From 41734b630ed86c5aa0814cb331f4f8e94e0bf2a2 Mon Sep 17 00:00:00 2001 From: Gert Goet Date: Thu, 29 Oct 2015 14:13:30 +0100 Subject: [PATCH 01/80] Ensure variable is evalled --- app/views/notify/project_was_moved_email.text.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/notify/project_was_moved_email.text.erb b/app/views/notify/project_was_moved_email.text.erb index d8a23dabf4..b2c5f71e46 100644 --- a/app/views/notify/project_was_moved_email.text.erb +++ b/app/views/notify/project_was_moved_email.text.erb @@ -1,4 +1,4 @@ -Project #{@old_path_with_namespace} was moved to another location +Project <%= @old_path_with_namespace %> was moved to another location The project is now located under <%= namespace_project_url(@project.namespace, @project) %> From 2c13723150b9095bb5b1482c62bab7817fd9a49e Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Fri, 13 Nov 2015 12:58:43 -0500 Subject: [PATCH 02/80] Update doc/install/installation.md for 8-2-stable [ci skip] --- doc/install/installation.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/install/installation.md b/doc/install/installation.md index 8028e51dbc..698f54cabc 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -211,9 +211,9 @@ We recommend using a PostgreSQL database. For MySQL check [MySQL setup guide](da ### Clone the Source # Clone GitLab repository - sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ce.git -b 8-1-stable gitlab + sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ce.git -b 8-2-stable gitlab -**Note:** You can change `8-1-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server! +**Note:** You can change `8-2-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server! ### Configure It From b8ab012544e584210b8b41219f85babdab091f59 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Fri, 13 Nov 2015 12:59:03 -0500 Subject: [PATCH 03/80] Update doc/install/installation.md for gitlab-workhorse [ci skip] --- doc/install/installation.md | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/doc/install/installation.md b/doc/install/installation.md index 698f54cabc..1479bdcb76 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -128,11 +128,10 @@ Install the Bundler Gem: ## 3. Go -Since GitLab 8.0, Git HTTP requests are handled by gitlab-git-http-server. -This is a small daemon written in Go. -To install gitlab-git-http-server we need a Go compiler. -The instructions below assume you use 64-bit Linux. You can find -downloads for other platforms at the [Go download +Since GitLab 8.0, Git HTTP requests are handled by gitlab-workhorse (formerly +gitlab-git-http-server). This is a small daemon written in Go. To install +gitlab-workhorse we need a Go compiler. The instructions below assume you +use 64-bit Linux. You can find downloads for other platforms at the [Go download page](https://golang.org/dl). curl -O --progress https://storage.googleapis.com/golang/go1.5.1.linux-amd64.tar.gz @@ -323,16 +322,16 @@ GitLab Shell is an SSH access and repository management software developed speci **Note:** Make sure your hostname can be resolved on the machine itself by either a proper DNS record or an additional line in /etc/hosts ("127.0.0.1 hostname"). This might be necessary for example if you set up gitlab behind a reverse proxy. If the hostname cannot be resolved, the final installation check will fail with "Check GitLab API access: FAILED. code: 401" and pushing commits will be rejected with "[remote rejected] master -> master (hook declined)". -### Install gitlab-git-http-server +### Install gitlab-workhorse cd /home/git - sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-git-http-server.git - cd gitlab-git-http-server - sudo -u git -H git checkout 0.3.0 + sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-workhorse.git + cd gitlab-workhorse + sudo -u git -H git checkout 0.4.1 sudo -u git -H make ### Initialize Database and Activate Advanced Features - + # Go to Gitlab installation folder cd /home/git/gitlab From a060a8dad5b44d3da20485123937ddf89169f8c7 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Fri, 13 Nov 2015 13:06:52 -0500 Subject: [PATCH 04/80] Update doc/update/8.1-to-8.2.md [ci skip] --- doc/update/8.1-to-8.2.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/doc/update/8.1-to-8.2.md b/doc/update/8.1-to-8.2.md index 3772f624e9..73d899f9c2 100644 --- a/doc/update/8.1-to-8.2.md +++ b/doc/update/8.1-to-8.2.md @@ -2,7 +2,8 @@ **NOTE:** GitLab 8.0 introduced several significant changes related to installation and configuration which *are not duplicated here*. Be sure you're -already running a working version of 8.0 before proceeding with this guide. +already running a working version of at least 8.0 before proceeding with this +guide. ### 0. Double-check your Git version @@ -67,7 +68,7 @@ sudo -u git -H git checkout 8-2-stable-ee ```bash cd /home/git/gitlab-shell sudo -u git -H git fetch -sudo -u git -H git checkout v2.6.5 +sudo -u git -H git checkout v2.6.6 ``` ### 5. Replace gitlab-git-http-server with gitlab-workhorse @@ -80,7 +81,7 @@ from GitLab 8.1. cd /home/git sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-workhorse.git cd gitlab-workhorse -sudo -u git -H git checkout 0.3.1 +sudo -u git -H git checkout 0.4.1 sudo -u git -H make ``` @@ -165,12 +166,12 @@ To make sure you didn't miss anything run a more thorough check: If all items are green, then congratulations, the upgrade is complete! -## Things went south? Revert to previous version (8.0) +## Things went south? Revert to previous version (8.1) ### 1. Revert the code to the previous version -Follow the [upgrade guide from 7.14 to 8.0](7.14-to-8.0.md), except for the database migration -(The backup is already migrated to the previous version) +Follow the [upgrade guide from 8.0 to 8.1](8.0-to-8.1.md), except for the +database migration (the backup is already migrated to the previous version). ### 2. Restore from the backup From 47b4b91ecd26066a04cc4b506dd62ccaed67bbdf Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Fri, 13 Nov 2015 13:10:34 -0500 Subject: [PATCH 05/80] Reorder monthly release tasks for RC1 day It didn't make sense to merge CE master into EE master, and *then* do the RC1 tasks (e.g., install/update docs) because then the RC1 won't have the updated docs. --- doc/release/monthly.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/release/monthly.md b/doc/release/monthly.md index 4925816daa..d347f58ba0 100644 --- a/doc/release/monthly.md +++ b/doc/release/monthly.md @@ -37,9 +37,9 @@ template are explained below: ### Xth: (6 working days before the 22nd) -- [ ] Merge CE `master` into EE `master` via merge request (#LINK) - [ ] Determine QA person and notify this person - [ ] Check the tasks in [how to rc1 guide](https://dev.gitlab.org/gitlab/gitlabhq/blob/master/doc/release/howto_rc1.md) and delegate tasks if necessary +- [ ] Merge CE `master` into EE `master` via merge request (#LINK) - [ ] Create CE and EE RC1 versions (#LINK) - [ ] Build RC1 packages From 05335a3c8584c48a9317bd0919eccee6948de742 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 13 Nov 2015 16:07:27 +0100 Subject: [PATCH 06/80] Create milestones in the group Signed-off-by: Dmitriy Zaporozhets --- .../groups/milestones_controller.rb | 36 +++++++++++++-- app/views/groups/milestones/index.html.haml | 12 +++-- app/views/groups/milestones/new.html.haml | 46 +++++++++++++++++++ config/routes.rb | 2 +- features/groups.feature | 9 +++- features/steps/groups.rb | 22 +++++++++ features/steps/shared/paths.rb | 4 ++ 7 files changed, 121 insertions(+), 10 deletions(-) create mode 100644 app/views/groups/milestones/new.html.haml diff --git a/app/controllers/groups/milestones_controller.rb b/app/controllers/groups/milestones_controller.rb index 669f7f3126..8779376d93 100644 --- a/app/controllers/groups/milestones_controller.rb +++ b/app/controllers/groups/milestones_controller.rb @@ -1,16 +1,34 @@ class Groups::MilestonesController < Groups::ApplicationController before_action :authorize_group_milestone!, only: :update + before_action :group def index - project_milestones = case params[:state] - when 'all'; state - when 'closed'; state('closed') - else state('active') - end + project_milestones = + case params[:state] + when 'all'; state + when 'closed'; state('closed') + else state('active') + end + @group_milestones = Milestones::GroupService.new(project_milestones).execute @group_milestones = Kaminari.paginate_array(@group_milestones).page(params[:page]).per(PER_PAGE) end + def new + @group_milestone = OpenStruct.new(title: nil, description: nil) + end + + def create + project_ids = params[:milestone][:project_ids] + title = milestone_params[:title] + + @group.projects.where(id: project_ids).each do |project| + Milestones::CreateService.new(project, current_user, milestone_params).execute + end + + redirect_to group_milestone_path(@group, title.parameterize, title: title) + end + def show project_milestones = Milestone.where(project_id: group.projects).order("due_date ASC") @group_milestone = Milestones::GroupService.new(project_milestones).milestone(title) @@ -51,4 +69,12 @@ class Groups::MilestonesController < Groups::ApplicationController def authorize_group_milestone! return render_404 unless can?(current_user, :admin_group, group) end + + def milestone_params + params.require(:milestone).permit( + :title, + :description, + :due_date + ) + end end diff --git a/app/views/groups/milestones/index.html.haml b/app/views/groups/milestones/index.html.haml index 2bbcad5fdf..ded4f3713f 100644 --- a/app/views/groups/milestones/index.html.haml +++ b/app/views/groups/milestones/index.html.haml @@ -3,9 +3,15 @@ = render 'shared/milestones_filter' .gray-content-block - Only milestones from - %strong #{@group.name} - group are listed here. + .pull-right + %span.pull-right.hidden-xs + = link_to new_group_milestone_path(@group), class: "btn btn-new" do + New Milestone + + .oneline + Only milestones from + %strong #{@group.name} + group are listed here. .milestones %ul.content-list - if @group_milestones.blank? diff --git a/app/views/groups/milestones/new.html.haml b/app/views/groups/milestones/new.html.haml new file mode 100644 index 0000000000..287f89a707 --- /dev/null +++ b/app/views/groups/milestones/new.html.haml @@ -0,0 +1,46 @@ +%h3.page-title + New Milestone + +%p.light + This will create milestone in every selected project +%hr + += form_for @group_milestone, as: :milestone, url: group_milestones_path(@group), html: { class: 'form-horizontal milestone-form gfm-form js-requires-input' } do |f| + .row + .col-md-6 + .form-group + = f.label :title, "Title", class: "control-label" + .col-sm-10 + = f.text_field :title, maxlength: 255, class: "form-control js-quick-submit", required: true + %p.hint Required + .form-group.milestone-description + = f.label :description, "Description", class: "control-label" + .col-sm-10 + = render layout: 'projects/md_preview', locals: { preview_class: "md-preview" } do + = render 'projects/zen', f: f, attr: :description, classes: 'description form-control js-quick-submit' + = render 'projects/notes/hints' + .clearfix + .error-alert + .form-group + = f.label :projects, "Projects", class: "control-label" + .col-sm-10 + = f.collection_select :project_ids, @group.projects, :id, :name, + { selected: @group.projects.map(&:id) }, multiple: true, class: 'select2' + + .col-md-6 + .form-group + = f.label :due_date, "Due Date", class: "control-label" + .col-sm-10= f.hidden_field :due_date + .col-sm-10 + .datepicker + + .form-actions + = f.submit 'Create Milestone', class: "btn-create btn" + = link_to "Cancel", group_milestones_path(@group), class: "btn btn-cancel" + + +:javascript + $( ".datepicker" ).datepicker({ + dateFormat: "yy-mm-dd", + onSelect: function(dateText, inst) { $("#milestone_due_date").val(dateText) } + }).datepicker("setDate", $.datepicker.parseDate('yy-mm-dd', $('#milestone_due_date').val())); diff --git a/config/routes.rb b/config/routes.rb index bd85f4e3c6..c0077ab1a9 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -368,7 +368,7 @@ Gitlab::Application.routes.draw do end resource :avatar, only: [:destroy] - resources :milestones, only: [:index, :show, :update] + resources :milestones, only: [:index, :show, :update, :new, :create] end end diff --git a/features/groups.feature b/features/groups.feature index db37fa3b37..615eff6a33 100644 --- a/features/groups.feature +++ b/features/groups.feature @@ -153,6 +153,13 @@ Feature: Groups Then I should see group milestone with descriptions and expiry date And I should see group milestone with all issues and MRs assigned to that milestone + Scenario: Create multiple milestones with one form + Given I visit group "Owned" milestones page + And I click new milestone button + And I fill milestone name + When I press create mileston button + Then milestone in each project should be created + # Group projects in settings Scenario: I should see all projects in the project list in settings Given Group "Owned" has archived project @@ -169,4 +176,4 @@ Feature: Groups When I visit group "Owned" page Then I should see group "Owned" Then I should see project "Public-project" - + diff --git a/features/steps/groups.rb b/features/steps/groups.rb index 70388c18fc..a8fba2406a 100644 --- a/features/steps/groups.rb +++ b/features/steps/groups.rb @@ -255,6 +255,28 @@ class Spinach::Features::Groups < Spinach::FeatureSteps expect(page).to have_xpath("//span[@class='label label-warning']", text: 'archived') end + step 'I fill milestone name' do + fill_in 'milestone_title', with: 'v2.9.0' + end + + step 'I click new milestone button' do + click_link "New Milestone" + end + + step 'I press create mileston button' do + click_button "Create Milestone" + end + + step 'milestone in each project should be created' do + group = Group.find_by(name: 'Owned') + expect(page).to have_content "Milestone v2.9.0" + expect(group.projects).to be_present + + group.projects.each do |project| + expect(page).to have_content project.name + end + end + protected def assigned_to_me(key) diff --git a/features/steps/shared/paths.rb b/features/steps/shared/paths.rb index eb978620da..c74a5fd3bc 100644 --- a/features/steps/shared/paths.rb +++ b/features/steps/shared/paths.rb @@ -31,6 +31,10 @@ module SharedPaths visit merge_requests_group_path(Group.find_by(name: "Owned")) end + step 'I visit group "Owned" milestones page' do + visit group_milestones_path(Group.find_by(name: "Owned")) + end + step 'I visit group "Owned" members page' do visit group_group_members_path(Group.find_by(name: "Owned")) end From 986695e136a8f6afa326048b30be77a9265d3bf7 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 13 Nov 2015 19:20:48 +0100 Subject: [PATCH 07/80] Refactor global and group milestones logic Signed-off-by: Dmitriy Zaporozhets --- app/controllers/concerns/global_milestones.rb | 19 ++++++ .../dashboard/milestones_controller.rb | 29 ++------- .../groups/application_controller.rb | 11 +++- app/controllers/groups/avatars_controller.rb | 2 - .../groups/group_members_controller.rb | 5 -- .../groups/milestones_controller.rb | 65 ++++++------------- app/finders/milestones_finder.rb | 13 ++++ app/helpers/labels_helper.rb | 2 +- app/helpers/milestones_helper.rb | 2 +- app/models/global_label.rb | 17 +++++ ...group_milestone.rb => global_milestone.rb} | 18 +++-- app/models/group_label.rb | 9 --- app/services/labels/group_service.rb | 26 -------- ...group_service.rb => collection_service.rb} | 2 +- .../dashboard/milestones/index.html.haml | 6 +- app/views/dashboard/milestones/show.html.haml | 36 +++++----- app/views/groups/milestones/index.html.haml | 6 +- app/views/groups/milestones/new.html.haml | 2 +- app/views/groups/milestones/show.html.haml | 42 ++++++------ 19 files changed, 146 insertions(+), 166 deletions(-) create mode 100644 app/controllers/concerns/global_milestones.rb create mode 100644 app/finders/milestones_finder.rb create mode 100644 app/models/global_label.rb rename app/models/{group_milestone.rb => global_milestone.rb} (78%) delete mode 100644 app/models/group_label.rb delete mode 100644 app/services/labels/group_service.rb rename app/services/milestones/{group_service.rb => collection_service.rb} (90%) diff --git a/app/controllers/concerns/global_milestones.rb b/app/controllers/concerns/global_milestones.rb new file mode 100644 index 0000000000..b428249acd --- /dev/null +++ b/app/controllers/concerns/global_milestones.rb @@ -0,0 +1,19 @@ +module GlobalMilestones + extend ActiveSupport::Concern + + def milestones + @milestones = MilestonesFinder.new.execute(@projects, params) + @milestones = GlobalMilestone.build_collection(@milestones) + @milestones = Kaminari.paginate_array(@milestones).page(params[:page]).per(ApplicationController::PER_PAGE) + end + + def milestone + milestones = Milestone.of_projects(@projects).where(title: params[:title]) + + if milestones.present? + @milestone = GlobalMilestone.new(params[:title], milestones) + else + render_404 + end + end +end diff --git a/app/controllers/dashboard/milestones_controller.rb b/app/controllers/dashboard/milestones_controller.rb index 53896d4f2c..2bdce0f8a0 100644 --- a/app/controllers/dashboard/milestones_controller.rb +++ b/app/controllers/dashboard/milestones_controller.rb @@ -1,34 +1,19 @@ class Dashboard::MilestonesController < Dashboard::ApplicationController - before_action :load_projects + include GlobalMilestones + + before_action :projects + before_action :milestones, only: [:index] + before_action :milestone, only: [:show] def index - project_milestones = case params[:state] - when 'all'; state - when 'closed'; state('closed') - else state('active') - end - @dashboard_milestones = Milestones::GroupService.new(project_milestones).execute - @dashboard_milestones = Kaminari.paginate_array(@dashboard_milestones).page(params[:page]).per(PER_PAGE) end def show - project_milestones = Milestone.where(project_id: @projects).order("due_date ASC") - @dashboard_milestone = Milestones::GroupService.new(project_milestones).milestone(title) end private - def load_projects - @projects = current_user.authorized_projects.sorted_by_activity.non_archived - end - - def title - params[:title] - end - - def state(state = nil) - conditions = { project_id: @projects } - conditions.reverse_merge!(state: state) if state - Milestone.where(conditions).order("title ASC") + def projects + @projects ||= current_user.authorized_projects.sorted_by_activity.non_archived end end diff --git a/app/controllers/groups/application_controller.rb b/app/controllers/groups/application_controller.rb index 6878d4bc07..be801858ea 100644 --- a/app/controllers/groups/application_controller.rb +++ b/app/controllers/groups/application_controller.rb @@ -1,8 +1,13 @@ class Groups::ApplicationController < ApplicationController layout 'group' + before_action :group private - + + def group + @group ||= Group.find_by(path: params[:group_id]) + end + def authorize_read_group! unless @group and can?(current_user, :read_group, @group) if current_user.nil? @@ -12,13 +17,13 @@ class Groups::ApplicationController < ApplicationController end end end - + def authorize_admin_group! unless can?(current_user, :admin_group, group) return render_404 end end - + def authorize_admin_group_member! unless can?(current_user, :admin_group_member, group) return render_403 diff --git a/app/controllers/groups/avatars_controller.rb b/app/controllers/groups/avatars_controller.rb index 6aa64222f7..f390705dc6 100644 --- a/app/controllers/groups/avatars_controller.rb +++ b/app/controllers/groups/avatars_controller.rb @@ -1,8 +1,6 @@ class Groups::AvatarsController < ApplicationController def destroy - @group = Group.find_by(path: params[:group_id]) @group.remove_avatar! - @group.save redirect_to edit_group_path(@group) diff --git a/app/controllers/groups/group_members_controller.rb b/app/controllers/groups/group_members_controller.rb index 91518c44a9..b25957a06e 100644 --- a/app/controllers/groups/group_members_controller.rb +++ b/app/controllers/groups/group_members_controller.rb @@ -1,6 +1,5 @@ class Groups::GroupMembersController < Groups::ApplicationController skip_before_action :authenticate_user!, only: [:index] - before_action :group # Authorize before_action :authorize_read_group! @@ -80,10 +79,6 @@ class Groups::GroupMembersController < Groups::ApplicationController protected - def group - @group ||= Group.find_by(path: params[:group_id]) - end - def member_params params.require(:group_member).permit(:access_level, :user_id) end diff --git a/app/controllers/groups/milestones_controller.rb b/app/controllers/groups/milestones_controller.rb index 8779376d93..6833a550c9 100644 --- a/app/controllers/groups/milestones_controller.rb +++ b/app/controllers/groups/milestones_controller.rb @@ -1,21 +1,16 @@ class Groups::MilestonesController < Groups::ApplicationController - before_action :authorize_group_milestone!, only: :update - before_action :group + include GlobalMilestones + + before_action :projects + before_action :milestones, only: [:index] + before_action :milestone, only: [:show, :update] + before_action :authorize_group_milestone!, only: [:create, :update] def index - project_milestones = - case params[:state] - when 'all'; state - when 'closed'; state('closed') - else state('active') - end - - @group_milestones = Milestones::GroupService.new(project_milestones).execute - @group_milestones = Kaminari.paginate_array(@group_milestones).page(params[:page]).per(PER_PAGE) end def new - @group_milestone = OpenStruct.new(title: nil, description: nil) + @milestone = Milestone.new end def create @@ -26,55 +21,35 @@ class Groups::MilestonesController < Groups::ApplicationController Milestones::CreateService.new(project, current_user, milestone_params).execute end - redirect_to group_milestone_path(@group, title.parameterize, title: title) + redirect_to milestone_path(title) end def show - project_milestones = Milestone.where(project_id: group.projects).order("due_date ASC") - @group_milestone = Milestones::GroupService.new(project_milestones).milestone(title) end def update - project_milestones = Milestone.where(project_id: group.projects).order("due_date ASC") - @group_milestones = Milestones::GroupService.new(project_milestones).milestone(title) - - @group_milestones.milestones.each do |milestone| - Milestones::UpdateService.new(milestone.project, current_user, params[:milestone]).execute(milestone) + @milestone.milestones.each do |milestone| + Milestones::UpdateService.new(milestone.project, current_user, milestone_params).execute(milestone) end - respond_to do |format| - format.js - format.html do - redirect_to group_milestones_path(group) - end - end + redirect_back_or_default(default: milestone_path(@milestone.title)) end private - def group - @group ||= Group.find_by(path: params[:group_id]) - end - - def title - params[:title] - end - - def state(state = nil) - conditions = { project_id: group.projects } - conditions.reverse_merge!(state: state) if state - Milestone.where(conditions).order("title ASC") - end - def authorize_group_milestone! return render_404 unless can?(current_user, :admin_group, group) end def milestone_params - params.require(:milestone).permit( - :title, - :description, - :due_date - ) + params.require(:milestone).permit(:title, :description, :due_date, :state_event) + end + + def milestone_path(title) + group_milestone_path(@group, title.parameterize, title: title) + end + + def projects + @projects ||= @group.projects end end diff --git a/app/finders/milestones_finder.rb b/app/finders/milestones_finder.rb new file mode 100644 index 0000000000..71f207ca03 --- /dev/null +++ b/app/finders/milestones_finder.rb @@ -0,0 +1,13 @@ +class MilestonesFinder + def execute(projects, params) + milestones = Milestone.of_projects(projects) + milestones = milestones.order("due_date ASC") + + case params[:state] + when 'closed' then milestones.closed + when 'all' then milestones + else milestones.active + end + end +end + diff --git a/app/helpers/labels_helper.rb b/app/helpers/labels_helper.rb index ee04ace35d..795fb439f2 100644 --- a/app/helpers/labels_helper.rb +++ b/app/helpers/labels_helper.rb @@ -100,7 +100,7 @@ module LabelsHelper Label.where(project_id: @projects) end - grouped_labels = Labels::GroupService.new(labels).execute + grouped_labels = GlobalLabel.build_collection(labels) grouped_labels.unshift(Label::None) grouped_labels.unshift(Label::Any) diff --git a/app/helpers/milestones_helper.rb b/app/helpers/milestones_helper.rb index 37a5b58cce..ad43892b63 100644 --- a/app/helpers/milestones_helper.rb +++ b/app/helpers/milestones_helper.rb @@ -28,7 +28,7 @@ module MilestonesHelper Milestone.where(project_id: @projects) end.active - grouped_milestones = Milestones::GroupService.new(milestones).execute + grouped_milestones = GlobalMilestone.build_collection(milestones) grouped_milestones.unshift(Milestone::None) grouped_milestones.unshift(Milestone::Any) diff --git a/app/models/global_label.rb b/app/models/global_label.rb new file mode 100644 index 0000000000..0171f7d54b --- /dev/null +++ b/app/models/global_label.rb @@ -0,0 +1,17 @@ +class GlobalLabel + attr_accessor :title, :labels + alias_attribute :name, :title + + def self.build_collection(labels) + labels = labels.group_by(&:title) + + labels.map do |title, label| + new(title, label) + end + end + + def initialize(title, labels) + @title = title + @labels = labels + end +end diff --git a/app/models/group_milestone.rb b/app/models/global_milestone.rb similarity index 78% rename from app/models/group_milestone.rb rename to app/models/global_milestone.rb index 91844da62e..f96e9d41c9 100644 --- a/app/models/group_milestone.rb +++ b/app/models/global_milestone.rb @@ -1,7 +1,15 @@ -class GroupMilestone +class GlobalMilestone attr_accessor :title, :milestones alias_attribute :name, :title + def self.build_collection(milestones) + milestones = milestones.group_by(&:title) + + milestones.map do |title, milestones| + new(title, milestones) + end + end + def initialize(title, milestones) @title = title @milestones = milestones @@ -10,7 +18,7 @@ class GroupMilestone def safe_title @title.parameterize end - + def projects milestones.map { |milestone| milestone.project } end @@ -60,15 +68,15 @@ class GroupMilestone end def issues - @group_issues ||= milestones.map(&:issues).flatten.group_by(&:state) + @issues ||= milestones.map(&:issues).flatten.group_by(&:state) end def merge_requests - @group_merge_requests ||= milestones.map(&:merge_requests).flatten.group_by(&:state) + @merge_requests ||= milestones.map(&:merge_requests).flatten.group_by(&:state) end def participants - @group_participants ||= milestones.map(&:participants).flatten.compact.uniq + @participants ||= milestones.map(&:participants).flatten.compact.uniq end def opened_issues diff --git a/app/models/group_label.rb b/app/models/group_label.rb deleted file mode 100644 index 0fc39cb877..0000000000 --- a/app/models/group_label.rb +++ /dev/null @@ -1,9 +0,0 @@ -class GroupLabel - attr_accessor :title, :labels - alias_attribute :name, :title - - def initialize(title, labels) - @title = title - @labels = labels - end -end diff --git a/app/services/labels/group_service.rb b/app/services/labels/group_service.rb deleted file mode 100644 index b26cee24d5..0000000000 --- a/app/services/labels/group_service.rb +++ /dev/null @@ -1,26 +0,0 @@ -module Labels - class GroupService < ::BaseService - def initialize(project_labels) - @project_labels = project_labels.group_by(&:title) - end - - def execute - build(@project_labels) - end - - def label(title) - if title - group_label = @project_labels[title].group_by(&:title) - build(group_label).first - else - nil - end - end - - private - - def build(label) - label.map { |title, labels| GroupLabel.new(title, labels) } - end - end -end diff --git a/app/services/milestones/group_service.rb b/app/services/milestones/collection_service.rb similarity index 90% rename from app/services/milestones/group_service.rb rename to app/services/milestones/collection_service.rb index 11d702f1e7..2eefec99e7 100644 --- a/app/services/milestones/group_service.rb +++ b/app/services/milestones/collection_service.rb @@ -1,5 +1,5 @@ module Milestones - class GroupService < Milestones::BaseService + class CollectionService < Milestones::BaseService def initialize(project_milestones) @project_milestones = project_milestones.group_by(&:title) end diff --git a/app/views/dashboard/milestones/index.html.haml b/app/views/dashboard/milestones/index.html.haml index 21b25c3986..635251e237 100644 --- a/app/views/dashboard/milestones/index.html.haml +++ b/app/views/dashboard/milestones/index.html.haml @@ -10,10 +10,10 @@ .milestones %ul.content-list - - if @dashboard_milestones.blank? + - if @milestones.blank? %li .nothing-here-block No milestones to show - else - - @dashboard_milestones.each do |milestone| + - @milestones.each do |milestone| = render 'milestone', milestone: milestone - = paginate @dashboard_milestones, theme: "gitlab" + = paginate @milestones, theme: "gitlab" diff --git a/app/views/dashboard/milestones/show.html.haml b/app/views/dashboard/milestones/show.html.haml index 2fe14c6388..580db613ed 100644 --- a/app/views/dashboard/milestones/show.html.haml +++ b/app/views/dashboard/milestones/show.html.haml @@ -1,14 +1,14 @@ -- page_title @dashboard_milestone.title, "Milestones" +- page_title @milestone.title, "Milestones" %h4.page-title - .issue-box{ class: "issue-box-#{@dashboard_milestone.closed? ? 'closed' : 'open'}" } - - if @dashboard_milestone.closed? + .issue-box{ class: "issue-box-#{@milestone.closed? ? 'closed' : 'open'}" } + - if @milestone.closed? Closed - else Open - Milestone #{@dashboard_milestone.title} + Milestone #{@milestone.title} %hr -- if (@dashboard_milestone.total_items_count == @dashboard_milestone.closed_items_count) && @dashboard_milestone.active? +- if (@milestone.total_items_count == @milestone.closed_items_count) && @milestone.active? .alert.alert-success %span All issues for this milestone are closed. You may close the milestone now. @@ -22,7 +22,7 @@ %th Open issues %th State %th Due date - - @dashboard_milestone.milestones.each do |milestone| + - @milestone.milestones.each do |milestone| %tr %td = link_to "#{milestone.project.name_with_namespace}", namespace_project_milestone_path(milestone.project.namespace, milestone.project, milestone) @@ -39,46 +39,46 @@ .context %p.lead Progress: - #{@dashboard_milestone.closed_items_count} closed + #{@milestone.closed_items_count} closed – - #{@dashboard_milestone.open_items_count} open - = milestone_progress_bar(@dashboard_milestone) + #{@milestone.open_items_count} open + = milestone_progress_bar(@milestone) %ul.nav.nav-tabs %li.active = link_to '#tab-issues', 'data-toggle' => 'tab' do Issues - %span.badge= @dashboard_milestone.issue_count + %span.badge= @milestone.issue_count %li = link_to '#tab-merge-requests', 'data-toggle' => 'tab' do Merge Requests - %span.badge= @dashboard_milestone.merge_requests_count + %span.badge= @milestone.merge_requests_count %li = link_to '#tab-participants', 'data-toggle' => 'tab' do Participants - %span.badge= @dashboard_milestone.participants.count + %span.badge= @milestone.participants.count .pull-right - = link_to 'Browse Issues', issues_dashboard_path(milestone_title: @dashboard_milestone.title), class: "btn edit-milestone-link btn-grouped" + = link_to 'Browse Issues', issues_dashboard_path(milestone_title: @milestone.title), class: "btn edit-milestone-link btn-grouped" .tab-content .tab-pane.active#tab-issues .row .col-md-6 - = render 'issues', title: "Open", issues: @dashboard_milestone.opened_issues + = render 'issues', title: "Open", issues: @milestone.opened_issues .col-md-6 - = render 'issues', title: "Closed", issues: @dashboard_milestone.closed_issues + = render 'issues', title: "Closed", issues: @milestone.closed_issues .tab-pane#tab-merge-requests .row .col-md-6 - = render 'merge_requests', title: "Open", merge_requests: @dashboard_milestone.opened_merge_requests + = render 'merge_requests', title: "Open", merge_requests: @milestone.opened_merge_requests .col-md-6 - = render 'merge_requests', title: "Closed", merge_requests: @dashboard_milestone.closed_merge_requests + = render 'merge_requests', title: "Closed", merge_requests: @milestone.closed_merge_requests .tab-pane#tab-participants %ul.bordered-list - - @dashboard_milestone.participants.each do |user| + - @milestone.participants.each do |user| %li = link_to user, title: user.name, class: "darken" do = image_tag avatar_icon(user, 32), class: "avatar s32" diff --git a/app/views/groups/milestones/index.html.haml b/app/views/groups/milestones/index.html.haml index ded4f3713f..ffd7dd3fc0 100644 --- a/app/views/groups/milestones/index.html.haml +++ b/app/views/groups/milestones/index.html.haml @@ -14,10 +14,10 @@ group are listed here. .milestones %ul.content-list - - if @group_milestones.blank? + - if @milestones.blank? %li .nothing-here-block No milestones to show - else - - @group_milestones.each do |milestone| + - @milestones.each do |milestone| = render 'milestone', milestone: milestone - = paginate @group_milestones, theme: "gitlab" + = paginate @milestones, theme: "gitlab" diff --git a/app/views/groups/milestones/new.html.haml b/app/views/groups/milestones/new.html.haml index 287f89a707..4c490d8ccb 100644 --- a/app/views/groups/milestones/new.html.haml +++ b/app/views/groups/milestones/new.html.haml @@ -5,7 +5,7 @@ This will create milestone in every selected project %hr -= form_for @group_milestone, as: :milestone, url: group_milestones_path(@group), html: { class: 'form-horizontal milestone-form gfm-form js-requires-input' } do |f| += form_for @milestone, url: group_milestones_path(@group), html: { class: 'form-horizontal milestone-form gfm-form js-requires-input' } do |f| .row .col-md-6 .form-group diff --git a/app/views/groups/milestones/show.html.haml b/app/views/groups/milestones/show.html.haml index a92ad5d751..e609abca08 100644 --- a/app/views/groups/milestones/show.html.haml +++ b/app/views/groups/milestones/show.html.haml @@ -1,22 +1,22 @@ -- page_title @group_milestone.title, "Milestones" +- page_title @milestone.title, "Milestones" = render "header_title" %h4.page-title - .issue-box{ class: "issue-box-#{@group_milestone.closed? ? 'closed' : 'open'}" } - - if @group_milestone.closed? + .issue-box{ class: "issue-box-#{@milestone.closed? ? 'closed' : 'open'}" } + - if @milestone.closed? Closed - else Open - Milestone #{@group_milestone.title} + Milestone #{@milestone.title} .pull-right - if can?(current_user, :admin_group, @group) - - if @group_milestone.active? - = link_to 'Close Milestone', group_milestone_path(@group, @group_milestone.safe_title, title: @group_milestone.title, milestone: {state_event: :close }), method: :put, class: "btn btn-sm btn-close" + - if @milestone.active? + = link_to 'Close Milestone', group_milestone_path(@group, @milestone.safe_title, title: @milestone.title, milestone: {state_event: :close }), method: :put, class: "btn btn-sm btn-close" - else - = link_to 'Reopen Milestone', group_milestone_path(@group, @group_milestone.safe_title, title: @group_milestone.title, milestone: {state_event: :activate }), method: :put, class: "btn btn-sm btn-grouped btn-reopen" + = link_to 'Reopen Milestone', group_milestone_path(@group, @milestone.safe_title, title: @milestone.title, milestone: {state_event: :activate }), method: :put, class: "btn btn-sm btn-grouped btn-reopen" %hr -- if (@group_milestone.total_items_count == @group_milestone.closed_items_count) && @group_milestone.active? +- if (@milestone.total_items_count == @milestone.closed_items_count) && @milestone.active? .alert.alert-success %span All issues for this milestone are closed. You may close the milestone now. @@ -30,7 +30,7 @@ %th Open issues %th State %th Due date - - @group_milestone.milestones.each do |milestone| + - @milestone.milestones.each do |milestone| %tr %td = link_to "#{milestone.project.name}", namespace_project_milestone_path(milestone.project.namespace, milestone.project, milestone) @@ -47,46 +47,46 @@ .context %p.lead Progress: - #{@group_milestone.closed_items_count} closed + #{@milestone.closed_items_count} closed – - #{@group_milestone.open_items_count} open - = milestone_progress_bar(@group_milestone) + #{@milestone.open_items_count} open + = milestone_progress_bar(@milestone) %ul.nav.nav-tabs %li.active = link_to '#tab-issues', 'data-toggle' => 'tab' do Issues - %span.badge= @group_milestone.issue_count + %span.badge= @milestone.issue_count %li = link_to '#tab-merge-requests', 'data-toggle' => 'tab' do Merge Requests - %span.badge= @group_milestone.merge_requests_count + %span.badge= @milestone.merge_requests_count %li = link_to '#tab-participants', 'data-toggle' => 'tab' do Participants - %span.badge= @group_milestone.participants.count + %span.badge= @milestone.participants.count .pull-right - = link_to 'Browse Issues', issues_group_path(@group, milestone_title: @group_milestone.title), class: "btn edit-milestone-link btn-grouped" + = link_to 'Browse Issues', issues_group_path(@group, milestone_title: @milestone.title), class: "btn edit-milestone-link btn-grouped" .tab-content .tab-pane.active#tab-issues .row .col-md-6 - = render 'issues', title: "Open", issues: @group_milestone.opened_issues + = render 'issues', title: "Open", issues: @milestone.opened_issues .col-md-6 - = render 'issues', title: "Closed", issues: @group_milestone.closed_issues + = render 'issues', title: "Closed", issues: @milestone.closed_issues .tab-pane#tab-merge-requests .row .col-md-6 - = render 'merge_requests', title: "Open", merge_requests: @group_milestone.opened_merge_requests + = render 'merge_requests', title: "Open", merge_requests: @milestone.opened_merge_requests .col-md-6 - = render 'merge_requests', title: "Closed", merge_requests: @group_milestone.closed_merge_requests + = render 'merge_requests', title: "Closed", merge_requests: @milestone.closed_merge_requests .tab-pane#tab-participants %ul.bordered-list - - @group_milestone.participants.each do |user| + - @milestone.participants.each do |user| %li = link_to user, title: user.name, class: "darken" do = image_tag avatar_icon(user, 32), class: "avatar s32" From c79d801bf58c58ec21e64cb782176d6dc879a60f Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 13 Nov 2015 19:31:02 +0100 Subject: [PATCH 08/80] Fix a bug when milestone/label filter was empty for dashboard issues page Signed-off-by: Dmitriy Zaporozhets --- CHANGELOG | 1 + app/controllers/dashboard_controller.rb | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 9806666833..dd4306ed0c 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -42,6 +42,7 @@ v 8.2.0 (unreleased) - Ability to add release notes (markdown text and attachments) to git tags (aka Releases) - Relative links from a repositories README.md now link to the default branch - Fix trailing whitespace issue in merge request/issue title + - Fix bug when milestone/label filter was empty for dashboard issues page v 8.1.4 - Fix bug where manually merged branches in a MR would end up with an empty diff (Stan Hu) diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb index 4ebb3d7276..b2c1fa4230 100644 --- a/app/controllers/dashboard_controller.rb +++ b/app/controllers/dashboard_controller.rb @@ -1,5 +1,6 @@ class DashboardController < Dashboard::ApplicationController before_action :event_filter, only: :activity + before_action :projects, only: [:issues, :merge_requests] respond_to :html @@ -47,4 +48,8 @@ class DashboardController < Dashboard::ApplicationController @events = @event_filter.apply_filter(@events).with_associations @events = @events.limit(20).offset(params[:offset] || 0) end + + def projects + @projects ||= current_user.authorized_projects.sorted_by_activity.non_archived + end end From 98d6d491b5187945b2d86db20af411240716980a Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 16 Nov 2015 14:38:34 +0100 Subject: [PATCH 09/80] Move global milestone specs Signed-off-by: Dmitriy Zaporozhets --- app/services/milestones/collection_service.rb | 26 ------- spec/models/global_milestone_spec.rb | 65 +++++++++++++++++ .../services/milestones/group_service_spec.rb | 70 ------------------- 3 files changed, 65 insertions(+), 96 deletions(-) delete mode 100644 app/services/milestones/collection_service.rb create mode 100644 spec/models/global_milestone_spec.rb delete mode 100644 spec/services/milestones/group_service_spec.rb diff --git a/app/services/milestones/collection_service.rb b/app/services/milestones/collection_service.rb deleted file mode 100644 index 2eefec99e7..0000000000 --- a/app/services/milestones/collection_service.rb +++ /dev/null @@ -1,26 +0,0 @@ -module Milestones - class CollectionService < Milestones::BaseService - def initialize(project_milestones) - @project_milestones = project_milestones.group_by(&:title) - end - - def execute - build(@project_milestones) - end - - def milestone(title) - if title - group_milestone = @project_milestones[title].group_by(&:title) - build(group_milestone).first - else - nil - end - end - - private - - def build(milestone) - milestone.map{ |title, milestones| GroupMilestone.new(title, milestones) } - end - end -end diff --git a/spec/models/global_milestone_spec.rb b/spec/models/global_milestone_spec.rb new file mode 100644 index 0000000000..6eeff30b20 --- /dev/null +++ b/spec/models/global_milestone_spec.rb @@ -0,0 +1,65 @@ +require 'spec_helper' + +describe GlobalMilestone do + let(:user) { create(:user) } + let(:user2) { create(:user) } + let(:group) { create(:group) } + let(:project1) { create(:project, group: group) } + let(:project2) { create(:project, path: 'gitlab-ci', group: group) } + let(:project3) { create(:project, path: 'cookbook-gitlab', group: group) } + let(:milestone1_project1) { create(:milestone, title: "Milestone v1.2", project: project1) } + let(:milestone1_project2) { create(:milestone, title: "Milestone v1.2", project: project2) } + let(:milestone1_project3) { create(:milestone, title: "Milestone v1.2", project: project3) } + let(:milestone2_project1) { create(:milestone, title: "VD-123", project: project1) } + let(:milestone2_project2) { create(:milestone, title: "VD-123", project: project2) } + let(:milestone2_project3) { create(:milestone, title: "VD-123", project: project3) } + + describe :build_collection do + before do + milestones = + [ + milestone1_project1, + milestone1_project2, + milestone1_project3, + milestone2_project1, + milestone2_project2, + milestone2_project3 + ] + + @global_milestones = GlobalMilestone.build_collection(milestones) + end + + it 'should have all project milestones' do + expect(@global_milestones.count).to eq(2) + end + + it 'should have all project milestones titles' do + expect(@global_milestones.map(&:title)).to match_array(['Milestone v1.2', 'VD-123']) + end + + it 'should have all project milestones' do + expect(@global_milestones.map { |group_milestone| group_milestone.milestones.count }.sum).to eq(6) + end + end + + describe :initialize do + before do + milestones = + [ + milestone1_project1, + milestone1_project2, + milestone1_project3, + ] + + @global_milestone = GlobalMilestone.new(milestone1_project1.title, milestones) + end + + it 'should have exactly one group milestone' do + expect(@global_milestone.title).to eq('Milestone v1.2') + end + + it 'should have all project milestones with the same title' do + expect(@global_milestone.milestones.count).to eq(3) + end + end +end diff --git a/spec/services/milestones/group_service_spec.rb b/spec/services/milestones/group_service_spec.rb deleted file mode 100644 index 74eb0f99e0..0000000000 --- a/spec/services/milestones/group_service_spec.rb +++ /dev/null @@ -1,70 +0,0 @@ -require 'spec_helper' - -describe Milestones::GroupService do - let(:user) { create(:user) } - let(:user2) { create(:user) } - let(:group) { create(:group) } - let(:project1) { create(:project, group: group) } - let(:project2) { create(:project, path: 'gitlab-ci', group: group) } - let(:project3) { create(:project, path: 'cookbook-gitlab', group: group) } - let(:milestone1_project1) { create(:milestone, title: "Milestone v1.2", project: project1) } - let(:milestone1_project2) { create(:milestone, title: "Milestone v1.2", project: project2) } - let(:milestone1_project3) { create(:milestone, title: "Milestone v1.2", project: project3) } - let(:milestone2_project1) { create(:milestone, title: "VD-123", project: project1) } - let(:milestone2_project2) { create(:milestone, title: "VD-123", project: project2) } - let(:milestone2_project3) { create(:milestone, title: "VD-123", project: project3) } - - describe 'execute' do - context 'with valid projects' do - before do - milestones = - [ - milestone1_project1, - milestone1_project2, - milestone1_project3, - milestone2_project1, - milestone2_project2, - milestone2_project3 - ] - @group_milestones = Milestones::GroupService.new(milestones).execute - end - - it 'should have all project milestones' do - expect(@group_milestones.count).to eq(2) - end - - it 'should have all project milestones titles' do - expect(@group_milestones.map { |group_milestone| group_milestone.title }).to match_array(['Milestone v1.2', 'VD-123']) - end - - it 'should have all project milestones' do - expect(@group_milestones.map { |group_milestone| group_milestone.milestones.count }.sum).to eq(6) - end - end - end - - describe 'milestone' do - context 'with valid title' do - before do - milestones = - [ - milestone1_project1, - milestone1_project2, - milestone1_project3, - milestone2_project1, - milestone2_project2, - milestone2_project3 - ] - @group_milestones = Milestones::GroupService.new(milestones).milestone('Milestone v1.2') - end - - it 'should have exactly one group milestone' do - expect(@group_milestones.title).to eq('Milestone v1.2') - end - - it 'should have all project milestones with the same title' do - expect(@group_milestones.milestones.count).to eq(3) - end - end - end -end From 8a03cb87442a42c8fc1630ab356dfd35dbb476f7 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 16 Nov 2015 14:39:19 +0100 Subject: [PATCH 10/80] Lets add more tests to Milestones services Signed-off-by: Dmitriy Zaporozhets --- app/finders/milestones_finder.rb | 1 - .../services/milestones/close_service_spec.rb | 28 +++++++++++++++++++ .../milestones/create_service_spec.rb | 24 ++++++++++++++++ 3 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 spec/services/milestones/close_service_spec.rb create mode 100644 spec/services/milestones/create_service_spec.rb diff --git a/app/finders/milestones_finder.rb b/app/finders/milestones_finder.rb index 71f207ca03..b704e87890 100644 --- a/app/finders/milestones_finder.rb +++ b/app/finders/milestones_finder.rb @@ -10,4 +10,3 @@ class MilestonesFinder end end end - diff --git a/spec/services/milestones/close_service_spec.rb b/spec/services/milestones/close_service_spec.rb new file mode 100644 index 0000000000..034c0f22e1 --- /dev/null +++ b/spec/services/milestones/close_service_spec.rb @@ -0,0 +1,28 @@ +require 'spec_helper' + +describe Milestones::CloseService do + let(:user) { create(:user) } + let(:project) { create(:project) } + let(:milestone) { create(:milestone, title: "Milestone v1.2", project: project) } + + before do + project.team << [user, :master] + end + + describe :execute do + before do + Milestones::CloseService.new(project, user, {}).execute(milestone) + end + + it { expect(milestone).to be_valid } + it { expect(milestone).to be_closed } + + describe :event do + let(:event) { Event.first } + + it { expect(event.milestone).to be_truthy } + it { expect(event.target).to eq(milestone) } + it { expect(event.action_name).to eq('closed') } + end + end +end diff --git a/spec/services/milestones/create_service_spec.rb b/spec/services/milestones/create_service_spec.rb new file mode 100644 index 0000000000..757c9a226d --- /dev/null +++ b/spec/services/milestones/create_service_spec.rb @@ -0,0 +1,24 @@ +require 'spec_helper' + +describe Milestones::CreateService do + let(:project) { create(:empty_project) } + let(:user) { create(:user) } + + describe :execute do + context "valid params" do + before do + project.team << [user, :master] + + opts = { + title: 'v2.1.9', + description: 'Patch release to fix security issue' + } + + @milestone = Milestones::CreateService.new(project, user, opts).execute + end + + it { expect(@milestone).to be_valid } + it { expect(@milestone.title).to eq('v2.1.9') } + end + end +end From 8630d476e419ba524cb5f23e25772bcf2223195d Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 16 Nov 2015 14:45:20 +0100 Subject: [PATCH 11/80] Add header and page title to new milestone page Signed-off-by: Dmitriy Zaporozhets --- app/views/groups/milestones/new.html.haml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/views/groups/milestones/new.html.haml b/app/views/groups/milestones/new.html.haml index 4c490d8ccb..d4284af8a0 100644 --- a/app/views/groups/milestones/new.html.haml +++ b/app/views/groups/milestones/new.html.haml @@ -1,3 +1,6 @@ +- page_title "Milestones" +- header_title group_title(@group, "Milestones", group_milestones_path(@group)) + %h3.page-title New Milestone From f16f315115e732493d976a9c866af351253ecf61 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 16 Nov 2015 15:07:16 +0100 Subject: [PATCH 12/80] Few changes to Group Milestone feature: * Group attachments are not supported so I removed attach file link * Added changelog item * Add markdown hint to project milestone form Signed-off-by: Dmitriy Zaporozhets --- CHANGELOG | 1 + app/assets/javascripts/dispatcher.js.coffee | 2 ++ app/views/groups/milestones/new.html.haml | 3 +-- app/views/projects/milestones/_form.html.haml | 6 ++---- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index dd4306ed0c..27ce7f3668 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -43,6 +43,7 @@ v 8.2.0 (unreleased) - Relative links from a repositories README.md now link to the default branch - Fix trailing whitespace issue in merge request/issue title - Fix bug when milestone/label filter was empty for dashboard issues page + - Add ability to create milestone in group projects from single form v 8.1.4 - Fix bug where manually merged branches in a MR would end up with an empty diff (Stan Hu) diff --git a/app/assets/javascripts/dispatcher.js.coffee b/app/assets/javascripts/dispatcher.js.coffee index 951173af5d..4059fc39c6 100644 --- a/app/assets/javascripts/dispatcher.js.coffee +++ b/app/assets/javascripts/dispatcher.js.coffee @@ -28,6 +28,8 @@ class Dispatcher when 'projects:milestones:new', 'projects:milestones:edit' new ZenMode() new DropzoneInput($('.milestone-form')) + when 'groups:milestones:new' + new ZenMode() when 'projects:compare:show' new Diff() when 'projects:issues:new','projects:issues:edit' diff --git a/app/views/groups/milestones/new.html.haml b/app/views/groups/milestones/new.html.haml index d4284af8a0..800bac4ef0 100644 --- a/app/views/groups/milestones/new.html.haml +++ b/app/views/groups/milestones/new.html.haml @@ -21,7 +21,6 @@ .col-sm-10 = render layout: 'projects/md_preview', locals: { preview_class: "md-preview" } do = render 'projects/zen', f: f, attr: :description, classes: 'description form-control js-quick-submit' - = render 'projects/notes/hints' .clearfix .error-alert .form-group @@ -43,7 +42,7 @@ :javascript - $( ".datepicker" ).datepicker({ + $(".datepicker").datepicker({ dateFormat: "yy-mm-dd", onSelect: function(dateText, inst) { $("#milestone_due_date").val(dateText) } }).datepicker("setDate", $.datepicker.parseDate('yy-mm-dd', $('#milestone_due_date').val())); diff --git a/app/views/projects/milestones/_form.html.haml b/app/views/projects/milestones/_form.html.haml index 255ddab479..24879b19d2 100644 --- a/app/views/projects/milestones/_form.html.haml +++ b/app/views/projects/milestones/_form.html.haml @@ -23,9 +23,7 @@ .col-sm-10 = render layout: 'projects/md_preview', locals: { preview_class: "md-preview" } do = render 'projects/zen', f: f, attr: :description, classes: 'description form-control js-quick-submit' - .hint - .pull-left Milestones are parsed with #{link_to "GitLab Flavored Markdown", help_page_path("markdown", "markdown"), target: '_blank'}. - .pull-left Attach files by dragging & dropping or #{link_to "selecting them", '#', class: 'markdown-selector' }. + = render 'projects/notes/hints' .clearfix .error-alert .col-md-6 @@ -45,7 +43,7 @@ :javascript - $( ".datepicker" ).datepicker({ + $(".datepicker").datepicker({ dateFormat: "yy-mm-dd", onSelect: function(dateText, inst) { $("#milestone_due_date").val(dateText) } }).datepicker("setDate", $.datepicker.parseDate('yy-mm-dd', $('#milestone_due_date').val())); From f445d3d1f317d8addbe60cf31fa15ca592ba0d19 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Mon, 16 Nov 2015 15:36:14 +0100 Subject: [PATCH 13/80] unique is for indexes. --- db/schema.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/schema.rb b/db/schema.rb index a8e8dfe6bb..4870fe3fc4 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -423,7 +423,7 @@ ActiveRecord::Schema.define(version: 20151114113410) do add_index "labels", ["project_id"], name: "index_labels_on_project_id", using: :btree create_table "lfs_objects", force: true do |t| - t.string "oid", null: false, unique: true + t.string "oid", null: false t.integer "size", null: false t.datetime "created_at" t.datetime "updated_at" From 78d542fcd811b6e18209fb97f126fd6291bd411b Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 16 Nov 2015 15:56:50 +0100 Subject: [PATCH 14/80] Add milestones documentation to workflow Signed-off-by: Dmitriy Zaporozhets --- doc/workflow/README.md | 1 + doc/workflow/milestones.md | 13 +++++++++++++ doc/workflow/milestones/form.png | Bin 0 -> 88591 bytes doc/workflow/milestones/group_form.png | Bin 0 -> 77087 bytes 4 files changed, 14 insertions(+) create mode 100644 doc/workflow/milestones.md create mode 100644 doc/workflow/milestones/form.png create mode 100644 doc/workflow/milestones/group_form.png diff --git a/doc/workflow/README.md b/doc/workflow/README.md index a2653704c3..c1a4f64981 100644 --- a/doc/workflow/README.md +++ b/doc/workflow/README.md @@ -14,5 +14,6 @@ - [Protected branches](protected_branches.md) - [Web Editor](web_editor.md) - [Releases](releases.md) +- [Milestones](milestones.md) - [Merge Requests](merge_requests.md) - ["Work In Progress" Merge Requests](wip_merge_requests.md) diff --git a/doc/workflow/milestones.md b/doc/workflow/milestones.md new file mode 100644 index 0000000000..1cd1f0f2fc --- /dev/null +++ b/doc/workflow/milestones.md @@ -0,0 +1,13 @@ +# Milestones + +Milestone allows you to group issues and set due date for it. +Milestone is created per project. + +![milestone form](milestones/form.png) + +## Groups and milestones + +You can create milestone with single form for several projects that belongs to the same group. +On the group milestones page you will be able to see this milestones grouped together by name. + +![group milestone form](milestones/group_form.png) diff --git a/doc/workflow/milestones/form.png b/doc/workflow/milestones/form.png new file mode 100644 index 0000000000000000000000000000000000000000..de44c1ffc1a44c21e7d6eff77ff8752d84b6ea8f GIT binary patch literal 88591 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

7chsg28F&v6Qs`*;tr3Ve?{d?nB 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 literal 0 HcmV?d00001 diff --git a/doc/workflow/milestones/group_form.png b/doc/workflow/milestones/group_form.png new file mode 100644 index 0000000000000000000000000000000000000000..38862dcca6895c28a09c6173fc8a2d7b1552b528 GIT binary patch literal 77087 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

hub?d7kLqUFo_P#LClu2 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

AZ-_IvsYe~ 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 IAzhvEA5O_fNB{r; literal 0 HcmV?d00001 From 84c71e5d827f1a0b225b7f6e9eeabe00a9c3eadd Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Mon, 16 Nov 2015 15:59:15 +0100 Subject: [PATCH 15/80] Add unique to oid index for lfs object. --- db/migrate/20151116144118_add_unique_for_lfs_oid_index.rb | 7 +++++++ db/schema.rb | 5 ++--- 2 files changed, 9 insertions(+), 3 deletions(-) create mode 100644 db/migrate/20151116144118_add_unique_for_lfs_oid_index.rb diff --git a/db/migrate/20151116144118_add_unique_for_lfs_oid_index.rb b/db/migrate/20151116144118_add_unique_for_lfs_oid_index.rb new file mode 100644 index 0000000000..41b93da0a8 --- /dev/null +++ b/db/migrate/20151116144118_add_unique_for_lfs_oid_index.rb @@ -0,0 +1,7 @@ +class AddUniqueForLfsOidIndex < ActiveRecord::Migration + def change + remove_index :lfs_objects, :oid + remove_index :lfs_objects, [:oid, :size] + add_index :lfs_objects, :oid, unique: true + end +end diff --git a/db/schema.rb b/db/schema.rb index 4870fe3fc4..aa76cef9fe 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20151114113410) do +ActiveRecord::Schema.define(version: 20151116144118) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -430,8 +430,7 @@ ActiveRecord::Schema.define(version: 20151114113410) do t.string "file" end - add_index "lfs_objects", ["oid", "size"], name: "index_lfs_objects_on_oid_and_size", using: :btree - add_index "lfs_objects", ["oid"], name: "index_lfs_objects_on_oid", using: :btree + add_index "lfs_objects", ["oid"], name: "index_lfs_objects_on_oid", unique: true, using: :btree create_table "lfs_objects_projects", force: true do |t| t.integer "lfs_object_id", null: false From 929ab909c88e9ac5d87acacb376a39dcfa6a639c Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 16 Nov 2015 16:14:19 +0100 Subject: [PATCH 16/80] Group masters should be able to create/close milestones Signed-off-by: Dmitriy Zaporozhets --- app/controllers/groups/milestones_controller.rb | 2 +- app/models/ability.rb | 1 + app/views/groups/milestones/_milestone.html.haml | 2 +- app/views/groups/milestones/index.html.haml | 9 +++++---- app/views/groups/milestones/show.html.haml | 2 +- 5 files changed, 9 insertions(+), 7 deletions(-) diff --git a/app/controllers/groups/milestones_controller.rb b/app/controllers/groups/milestones_controller.rb index 6833a550c9..10233222ee 100644 --- a/app/controllers/groups/milestones_controller.rb +++ b/app/controllers/groups/milestones_controller.rb @@ -38,7 +38,7 @@ class Groups::MilestonesController < Groups::ApplicationController private def authorize_group_milestone! - return render_404 unless can?(current_user, :admin_group, group) + return render_404 unless can?(current_user, :admin_milestones, group) end def milestone_params diff --git a/app/models/ability.rb b/app/models/ability.rb index 5ae28d5133..d01b3ae6f0 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -233,6 +233,7 @@ class Ability if group.has_master?(user) || group.has_owner?(user) || user.admin? rules.push(*[ :create_projects, + :admin_milestones ]) end diff --git a/app/views/groups/milestones/_milestone.html.haml b/app/views/groups/milestones/_milestone.html.haml index 41dffdd2fb..a20bf75bc3 100644 --- a/app/views/groups/milestones/_milestone.html.haml +++ b/app/views/groups/milestones/_milestone.html.haml @@ -22,7 +22,7 @@ %span.label.label-gray = milestone.project.name .col-sm-6 - - if can?(current_user, :admin_group, @group) + - if can?(current_user, :admin_milestones, @group) - if milestone.closed? = link_to 'Reopen Milestone', group_milestone_path(@group, milestone.safe_title, title: milestone.title, milestone: {state_event: :activate }), method: :put, class: "btn btn-xs btn-grouped btn-reopen" - else diff --git a/app/views/groups/milestones/index.html.haml b/app/views/groups/milestones/index.html.haml index ffd7dd3fc0..84ec77c618 100644 --- a/app/views/groups/milestones/index.html.haml +++ b/app/views/groups/milestones/index.html.haml @@ -3,10 +3,11 @@ = render 'shared/milestones_filter' .gray-content-block - .pull-right - %span.pull-right.hidden-xs - = link_to new_group_milestone_path(@group), class: "btn btn-new" do - New Milestone + - if can?(current_user, :admin_milestones, @group) + .pull-right + %span.pull-right.hidden-xs + = link_to new_group_milestone_path(@group), class: "btn btn-new" do + New Milestone .oneline Only milestones from diff --git a/app/views/groups/milestones/show.html.haml b/app/views/groups/milestones/show.html.haml index e609abca08..716e93f558 100644 --- a/app/views/groups/milestones/show.html.haml +++ b/app/views/groups/milestones/show.html.haml @@ -9,7 +9,7 @@ Open Milestone #{@milestone.title} .pull-right - - if can?(current_user, :admin_group, @group) + - if can?(current_user, :admin_milestones, @group) - if @milestone.active? = link_to 'Close Milestone', group_milestone_path(@group, @milestone.safe_title, title: @milestone.title, milestone: {state_event: :close }), method: :put, class: "btn btn-sm btn-close" - else From 32f1a7196817b1073327c607905ee40b9140e6df Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 16 Nov 2015 17:24:14 +0100 Subject: [PATCH 17/80] Fix removing avatar for group Signed-off-by: Dmitriy Zaporozhets --- app/controllers/groups/avatars_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/groups/avatars_controller.rb b/app/controllers/groups/avatars_controller.rb index f390705dc6..76c87366ba 100644 --- a/app/controllers/groups/avatars_controller.rb +++ b/app/controllers/groups/avatars_controller.rb @@ -1,4 +1,4 @@ -class Groups::AvatarsController < ApplicationController +class Groups::AvatarsController < Groups::ApplicationController def destroy @group.remove_avatar! @group.save From b22feb9fc7e77fd7c2920030d7833a1e8f38a8c3 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Mon, 16 Nov 2015 11:47:31 -0500 Subject: [PATCH 18/80] Version 8.2.0.rc1 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index a2264f05f5..88b48676b1 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.1.0.pre +8.2.0.rc1 \ No newline at end of file From 0ca55d100068b126deb38b1c5b78719fdaf8a68f Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Mon, 16 Nov 2015 11:48:31 -0500 Subject: [PATCH 19/80] Version 8.2.0.rc1-ee --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 948ae913cd..5b1adc255f 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.1.0.pre-ee +8.2.0.rc1-ee \ No newline at end of file From c8e53d4467e1e8cce4db04aafba00d55f014e283 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Sun, 15 Nov 2015 15:30:05 -0500 Subject: [PATCH 20/80] Revert "Merge pull request #9820 from huacnlee/avoid-render-form-in-notes-list" This reverts commit 63144cd062f6d259f1f30b6e06eb92a16caa8dec, reversing changes made to 8ab5df9d872414b2cca3ebd16d57b89e2f19e06a. --- app/assets/javascripts/notes.js.coffee | 13 +++++++------ app/controllers/projects/notes_controller.rb | 7 +------ app/views/projects/notes/_note.html.haml | 5 ++++- app/views/projects/notes/_notes_with_form.html.haml | 2 +- app/views/projects/notes/edit.js.erb | 2 -- config/routes.rb | 2 +- features/steps/project/issues/issues.rb | 2 +- spec/features/notes_on_merge_requests_spec.rb | 6 ++++++ spec/features/task_lists_spec.rb | 3 +++ 9 files changed, 24 insertions(+), 18 deletions(-) delete mode 100644 app/views/projects/notes/edit.js.erb diff --git a/app/assets/javascripts/notes.js.coffee b/app/assets/javascripts/notes.js.coffee index b0682f1684..ea75c656bc 100644 --- a/app/assets/javascripts/notes.js.coffee +++ b/app/assets/javascripts/notes.js.coffee @@ -29,6 +29,7 @@ class @Notes $(document).on "ajax:success", "form.edit_note", @updateNote # Edit note link + $(document).on "click", ".js-note-edit", @showEditForm $(document).on "click", ".note-edit-cancel", @cancelEdit # Reopen and close actions for Issue/MR combined with note form submit @@ -66,6 +67,7 @@ class @Notes $(document).off "ajax:success", ".js-main-target-form" $(document).off "ajax:success", ".js-discussion-note-form" $(document).off "ajax:success", "form.edit_note" + $(document).off "click", ".js-note-edit" $(document).off "click", ".note-edit-cancel" $(document).off "click", ".js-note-delete" $(document).off "click", ".js-note-attachment-delete" @@ -285,14 +287,13 @@ class @Notes Adds a hidden div with the original content of the note to fill the edit note form with if the user cancels ### - showEditForm: (note, formHTML) -> - nodeText = note.find(".note-text"); - nodeText.hide() - note.find('.note-edit-form').remove() - nodeText.after(formHTML) + showEditForm: (e) -> + e.preventDefault() + note = $(this).closest(".note") note.find(".note-body > .note-text").hide() note.find(".note-header").hide() - form = note.find(".note-edit-form") + base_form = note.find(".note-edit-form") + form = base_form.clone().insertAfter(base_form) form.addClass('current-note-edit-form gfm-form') form.find('.div-dropzone').remove() diff --git a/app/controllers/projects/notes_controller.rb b/app/controllers/projects/notes_controller.rb index 0c98e2f1bf..41cd08c93c 100644 --- a/app/controllers/projects/notes_controller.rb +++ b/app/controllers/projects/notes_controller.rb @@ -3,7 +3,7 @@ class Projects::NotesController < Projects::ApplicationController before_action :authorize_read_note! before_action :authorize_create_note!, only: [:create] before_action :authorize_admin_note!, only: [:update, :destroy] - before_action :find_current_user_notes, except: [:destroy, :edit, :delete_attachment] + before_action :find_current_user_notes, except: [:destroy, :delete_attachment] def index current_fetched_at = Time.now.to_i @@ -29,11 +29,6 @@ class Projects::NotesController < Projects::ApplicationController end end - def edit - @note = note - render layout: false - end - def update @note = Notes::UpdateService.new(project, current_user, note_params).execute(note) diff --git a/app/views/projects/notes/_note.html.haml b/app/views/projects/notes/_note.html.haml index 8a3292f7da..8880830198 100644 --- a/app/views/projects/notes/_note.html.haml +++ b/app/views/projects/notes/_note.html.haml @@ -7,7 +7,7 @@ .note-header - if note_editable?(note) .note-actions - = link_to edit_namespace_project_note_path(note.project.namespace, note.project, note), title: 'Edit comment', remote: true, class: 'js-note-edit' do + = link_to '#', title: 'Edit comment', class: 'js-note-edit' do = icon('pencil-square-o') = link_to namespace_project_note_path(note.project.namespace, note.project, note), title: 'Remove comment', method: :delete, data: { confirm: 'Are you sure you want to remove this comment?' }, remote: true, class: 'js-note-delete danger' do @@ -59,6 +59,9 @@ .note-text = preserve do = markdown(note.note, {no_header_anchors: true}) + - unless note.system? + -# System notes can't be edited + = render 'projects/notes/edit_form', note: note - if note.attachment.url .note-attachment diff --git a/app/views/projects/notes/_notes_with_form.html.haml b/app/views/projects/notes/_notes_with_form.html.haml index 91cefa6d14..04222b8f7c 100644 --- a/app/views/projects/notes/_notes_with_form.html.haml +++ b/app/views/projects/notes/_notes_with_form.html.haml @@ -7,4 +7,4 @@ = render "projects/notes/form", view: params[:view] :javascript - window._notes = new Notes("#{namespace_project_notes_path(namespace_id: @project.namespace, target_id: @noteable.id, target_type: @noteable.class.name.underscore)}", #{@notes.map(&:id).to_json}, #{Time.now.to_i}, "#{params[:view]}") + new Notes("#{namespace_project_notes_path(namespace_id: @project.namespace, target_id: @noteable.id, target_type: @noteable.class.name.underscore)}", #{@notes.map(&:id).to_json}, #{Time.now.to_i}, "#{params[:view]}") diff --git a/app/views/projects/notes/edit.js.erb b/app/views/projects/notes/edit.js.erb deleted file mode 100644 index 2599bad5d6..0000000000 --- a/app/views/projects/notes/edit.js.erb +++ /dev/null @@ -1,2 +0,0 @@ -$note = $('.note-row-<%= @note.id %>:visible'); -_notes.showEditForm($note, '<%= escape_javascript(render('edit_form', note: @note)) %>'); diff --git a/config/routes.rb b/config/routes.rb index bd85f4e3c6..696136d964 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -660,7 +660,7 @@ Gitlab::Application.routes.draw do end end - resources :notes, constraints: { id: /\d+/ } do + resources :notes, only: [:index, :create, :destroy, :update], constraints: { id: /\d+/ } do member do delete :delete_attachment end diff --git a/features/steps/project/issues/issues.rb b/features/steps/project/issues/issues.rb index be134b9c2b..af2da41bad 100644 --- a/features/steps/project/issues/issues.rb +++ b/features/steps/project/issues/issues.rb @@ -219,7 +219,7 @@ class Spinach::Features::ProjectIssues < Spinach::FeatureSteps end step 'The code block should be unchanged' do - expect(page).to have_content("Command [1]: /usr/local/bin/git , see [text](doc/text)") + expect(page).to have_content("```\nCommand [1]: /usr/local/bin/git , see [text](doc/text)\n```") end step 'project \'Shop\' has issue \'Bugfix1\' with description: \'Description for issue1\'' do diff --git a/spec/features/notes_on_merge_requests_spec.rb b/spec/features/notes_on_merge_requests_spec.rb index 16d5a03e88..d7cb3b2e86 100644 --- a/spec/features/notes_on_merge_requests_spec.rb +++ b/spec/features/notes_on_merge_requests_spec.rb @@ -65,6 +65,12 @@ describe 'Comments', feature: true do end describe 'when editing a note', js: true do + it 'should contain the hidden edit form' do + page.within("#note_#{note.id}") do + is_expected.to have_css('.note-edit-form', visible: false) + end + end + describe 'editing the note' do before do find('.note').hover diff --git a/spec/features/task_lists_spec.rb b/spec/features/task_lists_spec.rb index 6cbe685a93..fca3c77fc6 100644 --- a/spec/features/task_lists_spec.rb +++ b/spec/features/task_lists_spec.rb @@ -51,6 +51,7 @@ feature 'Task Lists', feature: true do expect(page).to have_selector(container) expect(page).to have_selector("#{container} .wiki .task-list .task-list-item .task-list-item-checkbox") + expect(page).to have_selector("#{container} .js-task-list-field") expect(page).to have_selector('form.js-issuable-update') expect(page).to have_selector('a.btn-close') end @@ -89,6 +90,7 @@ feature 'Task Lists', feature: true do expect(page).to have_selector('.note .js-task-list-container') expect(page).to have_selector('.note .js-task-list-container .task-list .task-list-item .task-list-item-checkbox') + expect(page).to have_selector('.note .js-task-list-container .js-task-list-field') end it 'is only editable by author' do @@ -125,6 +127,7 @@ feature 'Task Lists', feature: true do expect(page).to have_selector(container) expect(page).to have_selector("#{container} .wiki .task-list .task-list-item .task-list-item-checkbox") + expect(page).to have_selector("#{container} .js-task-list-field") expect(page).to have_selector('form.js-issuable-update') expect(page).to have_selector('a.btn-close') end From ccb0c40c54d913fe140231c88f4adcd2d41c5b87 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Sun, 15 Nov 2015 14:32:28 -0500 Subject: [PATCH 21/80] Make ProjectWiki touch Project#last_activity_at after wiki actions Closes #3026 --- app/models/project_wiki.rb | 10 ++++++++++ spec/models/project_wiki_spec.rb | 18 ++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/app/models/project_wiki.rb b/app/models/project_wiki.rb index 231973fa54..b5fec38378 100644 --- a/app/models/project_wiki.rb +++ b/app/models/project_wiki.rb @@ -86,6 +86,8 @@ class ProjectWiki commit = commit_details(:created, message, title) wiki.write_page(title, format, content, commit) + + update_project_activity rescue Gollum::DuplicatePageError => e @error_message = "Duplicate page: #{e.message}" return false @@ -95,10 +97,14 @@ class ProjectWiki commit = commit_details(:updated, message, page.title) wiki.update_page(page, page.name, format, content, commit) + + update_project_activity end def delete_page(page, message = nil) wiki.delete_page(page, commit_details(:deleted, message, page.title)) + + update_project_activity end def page_title_and_dir(title) @@ -146,4 +152,8 @@ class ProjectWiki def path_to_repo @path_to_repo ||= File.join(Gitlab.config.gitlab_shell.repos_path, "#{path_with_namespace}.git") end + + def update_project_activity + @project.touch(:last_activity_at) + end end diff --git a/spec/models/project_wiki_spec.rb b/spec/models/project_wiki_spec.rb index 9f6cdeeaa9..3b88914444 100644 --- a/spec/models/project_wiki_spec.rb +++ b/spec/models/project_wiki_spec.rb @@ -184,6 +184,12 @@ describe ProjectWiki do subject.create_page("test page", "some content", :markdown, "commit message") expect(subject.pages.first.page.version.message).to eq("commit message") end + + it 'updates project activity' do + expect(subject).to receive(:update_project_activity) + + subject.create_page('Test Page', 'This is content') + end end describe "#update_page" do @@ -205,6 +211,12 @@ describe ProjectWiki do it "sets the correct commit message" do expect(@page.version.message).to eq("updated page") end + + it 'updates project activity' do + expect(subject).to receive(:update_project_activity) + + subject.update_page(@gollum_page, 'Yet more content', :markdown, 'Updated page again') + end end describe "#delete_page" do @@ -217,6 +229,12 @@ describe ProjectWiki do subject.delete_page(@page) expect(subject.pages.count).to eq(0) end + + it 'updates project activity' do + expect(subject).to receive(:update_project_activity) + + subject.delete_page(@page) + end end private From b093f50986b6dcd0e4caf33d3c96831155e71db8 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 16 Nov 2015 19:55:58 +0100 Subject: [PATCH 22/80] Some code and doc improvements Signed-off-by: Dmitriy Zaporozhets --- app/models/global_milestone.rb | 4 ++++ app/views/dashboard/milestones/show.html.haml | 2 +- app/views/groups/milestones/show.html.haml | 2 +- doc/workflow/milestones.md | 8 ++++---- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/app/models/global_milestone.rb b/app/models/global_milestone.rb index f96e9d41c9..1321ccd963 100644 --- a/app/models/global_milestone.rb +++ b/app/models/global_milestone.rb @@ -94,4 +94,8 @@ class GlobalMilestone def closed_merge_requests merge_requests.values_at("closed", "merged", "locked").compact.flatten end + + def complete? + total_items_count == closed_items_count + end end diff --git a/app/views/dashboard/milestones/show.html.haml b/app/views/dashboard/milestones/show.html.haml index 580db613ed..83077a398b 100644 --- a/app/views/dashboard/milestones/show.html.haml +++ b/app/views/dashboard/milestones/show.html.haml @@ -8,7 +8,7 @@ Milestone #{@milestone.title} %hr -- if (@milestone.total_items_count == @milestone.closed_items_count) && @milestone.active? +- if @milestone.complete? && @milestone.active? .alert.alert-success %span All issues for this milestone are closed. You may close the milestone now. diff --git a/app/views/groups/milestones/show.html.haml b/app/views/groups/milestones/show.html.haml index 716e93f558..d161259e4a 100644 --- a/app/views/groups/milestones/show.html.haml +++ b/app/views/groups/milestones/show.html.haml @@ -16,7 +16,7 @@ = link_to 'Reopen Milestone', group_milestone_path(@group, @milestone.safe_title, title: @milestone.title, milestone: {state_event: :activate }), method: :put, class: "btn btn-sm btn-grouped btn-reopen" %hr -- if (@milestone.total_items_count == @milestone.closed_items_count) && @milestone.active? +- if @milestone.complete? && @milestone.active? .alert.alert-success %span All issues for this milestone are closed. You may close the milestone now. diff --git a/doc/workflow/milestones.md b/doc/workflow/milestones.md index 1cd1f0f2fc..dff36899ae 100644 --- a/doc/workflow/milestones.md +++ b/doc/workflow/milestones.md @@ -1,13 +1,13 @@ # Milestones -Milestone allows you to group issues and set due date for it. -Milestone is created per project. +Milestones allow you to organize issues and merge requests into a cohesive group, optionally setting a due date. +A common use is keeping track of an upcoming software version. Milestones are created per-project. ![milestone form](milestones/form.png) ## Groups and milestones -You can create milestone with single form for several projects that belongs to the same group. -On the group milestones page you will be able to see this milestones grouped together by name. +You can create a milestone for several projects in the same group simultaneously. +On the group's milestones page, you will be able to see the status of that milestone across all of the selected projects. ![group milestone form](milestones/group_form.png) From 3300db70ff53699732672824859186cd083623fa Mon Sep 17 00:00:00 2001 From: Alex Jordan Date: Mon, 16 Nov 2015 02:01:26 -0800 Subject: [PATCH 23/80] Rewrite HTTP links to force TLS, where possible --- CONTRIBUTING.md | 8 ++++---- app/views/admin/users/_profile.html.haml | 4 ++-- app/views/users/show.html.haml | 4 ++-- doc/ci/docker/using_docker_build.md | 4 ++-- doc/ci/quick_start/README.md | 6 +++--- doc/customization/libravatar.md | 6 +++--- doc/development/architecture.md | 2 +- doc/hooks/custom_hooks.md | 2 +- doc/install/database_mysql.md | 2 +- doc/install/installation.md | 4 ++-- doc/integration/ldap.md | 4 ++-- doc/legal/corporate_contributor_license_agreement.md | 2 +- .../individual_contributor_license_agreement.md | 2 +- doc/markdown/markdown.md | 12 ++++++------ doc/operations/unicorn.md | 4 ++-- doc/release/security.md | 4 ++-- doc/ssh/README.md | 2 +- doc/update/6.x-or-7.x-to-7.14.md | 2 +- doc/workflow/gitlab_flow.md | 12 ++++++------ doc/workflow/importing/migrating_from_svn.md | 4 ++-- 20 files changed, 45 insertions(+), 45 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9f79ff413a..5d85c9f3fc 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -10,7 +10,7 @@ By submitting code as an individual you agree to the [individual contributor lic ## Security vulnerability disclosure -Please report suspected security vulnerabilities in private to support@gitlab.com, also see the [disclosure section on the GitLab.com website](http://about.gitlab.com/disclosure/). Please do NOT create publicly viewable issues for suspected security vulnerabilities. +Please report suspected security vulnerabilities in private to support@gitlab.com, also see the [disclosure section on the GitLab.com website](https://about.gitlab.com/disclosure/). Please do NOT create publicly viewable issues for suspected security vulnerabilities. ## Closing policy for issues and merge requests @@ -35,7 +35,7 @@ The [GitLab CE issue tracker on GitLab.com](https://gitlab.com/gitlab-org/gitlab Do not use the issue tracker for feature requests. We have a specific [feature request forum](http://feedback.gitlab.com) for this purpose. Please keep feature requests as small and simple as possible, complex ones might be edited to make them small and simple. -Please send a merge request with a tested solution or a merge request with a failing test instead of opening an issue if you can. If you're unsure where to post, post to the [mailing list](https://groups.google.com/forum/#!forum/gitlabhq) or [Stack Overflow](http://stackoverflow.com/questions/tagged/gitlab) first. There are a lot of helpful GitLab users there who may be able to help you quickly. If your particular issue turns out to be a bug, it will find its way from there. +Please send a merge request with a tested solution or a merge request with a failing test instead of opening an issue if you can. If you're unsure where to post, post to the [mailing list](https://groups.google.com/forum/#!forum/gitlabhq) or [Stack Overflow](https://stackoverflow.com/questions/tagged/gitlab) first. There are a lot of helpful GitLab users there who may be able to help you quickly. If your particular issue turns out to be a bug, it will find its way from there. ### Issue tracker guidelines @@ -72,7 +72,7 @@ If you can, please submit a merge request with the fix or improvements including 1. Write [tests](https://gitlab.com/gitlab-org/gitlab-development-kit#running-the-tests) and code 1. Add your changes to the [CHANGELOG](CHANGELOG) 1. If you are changing the README, some documentation or other things which have no effect on the tests, add `[ci skip]` somewhere in the commit message -1. If you have multiple commits please combine them into one commit by [squashing them](http://git-scm.com/book/en/Git-Tools-Rewriting-History#Squashing-Commits) +1. If you have multiple commits please combine them into one commit by [squashing them](https://git-scm.com/book/en/Git-Tools-Rewriting-History#Squashing-Commits) 1. Push the commit to your fork 1. Submit a merge request (MR) to the master branch 1. The MR title should describe the change you want to make @@ -181,4 +181,4 @@ This code of conduct applies both within project spaces and in public spaces whe Instances of abusive, harassing, or otherwise unacceptable behavior can be reported by emailing contact@gitlab.com -This Code of Conduct is adapted from the [Contributor Covenant](http:contributor-covenant.org), version 1.1.0, available at [http://contributor-covenant.org/version/1/1/0/](http://contributor-covenant.org/version/1/1/0/) +This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.1.0, available at [http://contributor-covenant.org/version/1/1/0/](http://contributor-covenant.org/version/1/1/0/) diff --git a/app/views/admin/users/_profile.html.haml b/app/views/admin/users/_profile.html.haml index 90d9980c85..7d11edc79e 100644 --- a/app/views/admin/users/_profile.html.haml +++ b/app/views/admin/users/_profile.html.haml @@ -16,11 +16,11 @@ - unless user.linkedin.blank? %li %span.light LinkedIn: - %strong= link_to user.linkedin, "http://www.linkedin.com/in/#{user.linkedin}" + %strong= link_to user.linkedin, "https://www.linkedin.com/in/#{user.linkedin}" - unless user.twitter.blank? %li %span.light Twitter: - %strong= link_to user.twitter, "http://www.twitter.com/#{user.twitter}" + %strong= link_to user.twitter, "https://twitter.com/#{user.twitter}" - unless user.website_url.blank? %li %span.light Website: diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml index 3099241218..d5a92cb816 100644 --- a/app/views/users/show.html.haml +++ b/app/views/users/show.html.haml @@ -32,11 +32,11 @@ = icon('skype') - unless @user.linkedin.blank? .profile-link-holder - = link_to "http://www.linkedin.com/in/#{@user.linkedin}", title: "LinkedIn" do + = link_to "https://www.linkedin.com/in/#{@user.linkedin}", title: "LinkedIn" do = icon('linkedin-square') - unless @user.twitter.blank? .profile-link-holder - = link_to "http://www.twitter.com/#{@user.twitter}", title: "Twitter" do + = link_to "https://twitter.com/#{@user.twitter}", title: "Twitter" do = icon('twitter-square') - unless @user.website_url.blank? .profile-link-holder diff --git a/doc/ci/docker/using_docker_build.md b/doc/ci/docker/using_docker_build.md index 5af27470d2..4b1788a9af 100644 --- a/doc/ci/docker/using_docker_build.md +++ b/doc/ci/docker/using_docker_build.md @@ -35,7 +35,7 @@ GitLab Runner then executes build scripts as `gitlab-runner` user. ```bash $ sudo gitlab-runner register -n \ - --url http://gitlab.com/ci \ + --url https://gitlab.com/ci \ --token RUNNER_TOKEN \ --executor shell --description "My Runner" @@ -84,7 +84,7 @@ In order to do that follow the steps: ```bash $ sudo gitlab-runner register -n \ - --url http://gitlab.com/ci \ + --url https://gitlab.com/ci \ --token RUNNER_TOKEN \ --executor docker \ --description "My Docker Runner" \ diff --git a/doc/ci/quick_start/README.md b/doc/ci/quick_start/README.md index a87a1f806f..d69064a91f 100644 --- a/doc/ci/quick_start/README.md +++ b/doc/ci/quick_start/README.md @@ -6,7 +6,7 @@ To start building projects with GitLab CI a few steps needs to be done. First you need to have a working GitLab and GitLab CI instance. -You can omit this step if you use [GitLab.com](http://GitLab.com/). +You can omit this step if you use [GitLab.com](https://GitLab.com/). ## 2. Create repository on GitLab @@ -16,7 +16,7 @@ Push your application to that repository. ## 3. Add project to CI The next part is to login to GitLab CI. -Point your browser to the URL you have set GitLab or use [gitlab.com/ci](http://gitlab.com/ci/). +Point your browser to the URL you have set GitLab or use [gitlab.com/ci](https://gitlab.com/ci/). On the first screen you will see a list of GitLab's projects that you have access to: @@ -97,7 +97,7 @@ If you do it correctly your runner should be shown under **Runners activated for ### Shared runners -If you use [gitlab.com/ci](http://gitlab.com/ci/) you can use **Shared runners** provided by GitLab Inc. +If you use [gitlab.com/ci](https://gitlab.com/ci/) you can use **Shared runners** provided by GitLab Inc. These are special virtual machines that are run on GitLab's infrastructure that can build any project. To enable **Shared runners** you have to go to **Runners** and click **Enable shared runners** for this project. diff --git a/doc/customization/libravatar.md b/doc/customization/libravatar.md index 54c1780c3a..bd2c242afc 100644 --- a/doc/customization/libravatar.md +++ b/doc/customization/libravatar.md @@ -2,7 +2,7 @@ GitLab by default supports [Gravatar](https://gravatar.com) avatar service. Libravatar is a service which delivers your avatar (profile picture) to other websites and their API is -[heavily based on gravatar](http://wiki.libravatar.org/api/). +[heavily based on gravatar](https://wiki.libravatar.org/api/). This means that it is not complicated to switch to Libravatar avatar service or even self hosted Libravatar server. @@ -31,7 +31,7 @@ the configuration options as follows: ## Self-hosted -If you are [running your own libravatar service](http://wiki.libravatar.org/running_your_own/) the URL will be different in the configuration +If you are [running your own libravatar service](https://wiki.libravatar.org/running_your_own/) the URL will be different in the configuration but the important part is to provide the same placeholders so GitLab can parse the URL correctly. For example, you host a service on `http://libravatar.example.com` the `plain_url` you need to supply in `gitlab.yml` is @@ -63,7 +63,7 @@ Run `sudo gitlab-ctl reconfigure` for changes to take effect. ## Default URL for missing images -[Libravatar supports different sets](http://wiki.libravatar.org/api/) of `missing images` for emails not found on the Libravatar service. +[Libravatar supports different sets](https://wiki.libravatar.org/api/) of `missing images` for emails not found on the Libravatar service. In order to use a different set other than `identicon`, replace `&d=identicon` portion of the URL with another supported set. For example, you can use `retro` set in which case the URL would look like: `plain_url: "http://cdn.libravatar.org/avatar/%{hash}?s=%{size}&d=retro"` diff --git a/doc/development/architecture.md b/doc/development/architecture.md index c00d290371..6101a71a8d 100644 --- a/doc/development/architecture.md +++ b/doc/development/architecture.md @@ -146,7 +146,7 @@ nginx Apache httpd -- [Explanation of Apache logs](http://httpd.apache.org/docs/2.2/logs.html). +- [Explanation of Apache logs](https://httpd.apache.org/docs/2.2/logs.html). - `/var/log/apache2/` contains error and output logs (on Ubuntu). - `/var/log/httpd/` contains error and output logs (on RHEL). diff --git a/doc/hooks/custom_hooks.md b/doc/hooks/custom_hooks.md index 548c484bc0..0f2665a3bf 100644 --- a/doc/hooks/custom_hooks.md +++ b/doc/hooks/custom_hooks.md @@ -7,7 +7,7 @@ Please explore webhooks as an option if you do not have filesystem access. For a Git natively supports hooks that are executed on different actions. Examples of server-side git hooks include pre-receive, post-receive, and update. See -[Git SCM Server-Side Hooks](http://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks#Server-Side-Hooks) +[Git SCM Server-Side Hooks](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks#Server-Side-Hooks) for more information about each hook type. As of gitlab-shell version 2.2.0 (which requires GitLab 7.5+), GitLab diff --git a/doc/install/database_mysql.md b/doc/install/database_mysql.md index c565e90da2..513ad69ec2 100644 --- a/doc/install/database_mysql.md +++ b/doc/install/database_mysql.md @@ -2,7 +2,7 @@ ## Note -We do not recommend using MySQL due to various issues. For example, case [(in)sensitivity](https://dev.mysql.com/doc/refman/5.0/en/case-sensitivity.html) and [problems](http://bugs.mysql.com/bug.php?id=65830) that [suggested](http://bugs.mysql.com/bug.php?id=50909) [fixes](http://bugs.mysql.com/bug.php?id=65830) [have](http://bugs.mysql.com/bug.php?id=63164). +We do not recommend using MySQL due to various issues. For example, case [(in)sensitivity](https://dev.mysql.com/doc/refman/5.0/en/case-sensitivity.html) and [problems](https://bugs.mysql.com/bug.php?id=65830) that [suggested](https://bugs.mysql.com/bug.php?id=50909) [fixes](https://bugs.mysql.com/bug.php?id=65830) [have](https://bugs.mysql.com/bug.php?id=63164). ## MySQL diff --git a/doc/install/installation.md b/doc/install/installation.md index 8028e51dbc..193db10e4d 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -106,7 +106,7 @@ Then select 'Internet Site' and press enter to confirm the hostname. ## 2. Ruby -The use of Ruby version managers such as [RVM](http://rvm.io/), [rbenv](https://github.com/sstephenson/rbenv) or [chruby](https://github.com/postmodern/chruby) with GitLab in production frequently leads to hard to diagnose problems. For example, GitLab Shell is called from OpenSSH and having a version manager can prevent pushing and pulling over SSH. Version managers are not supported and we strongly advise everyone to follow the instructions below to use a system Ruby. +The use of Ruby version managers such as [RVM](https://rvm.io/), [rbenv](https://github.com/sstephenson/rbenv) or [chruby](https://github.com/postmodern/chruby) with GitLab in production frequently leads to hard to diagnose problems. For example, GitLab Shell is called from OpenSSH and having a version manager can prevent pushing and pulling over SSH. Version managers are not supported and we strongly advise everyone to follow the instructions below to use a system Ruby. Remove the old Ruby 1.8 if present @@ -298,7 +298,7 @@ We recommend using a PostgreSQL database. For MySQL check [MySQL setup guide](da ### Install Gems -**Note:** As of bundler 1.5.2, you can invoke `bundle install -jN` (where `N` the number of your processor cores) and enjoy the parallel gems installation with measurable difference in completion time (~60% faster). Check the number of your cores with `nproc`. For more information check this [post](http://robots.thoughtbot.com/parallel-gem-installing-using-bundler). First make sure you have bundler >= 1.5.2 (run `bundle -v`) as it addresses some [issues](https://devcenter.heroku.com/changelog-items/411) that were [fixed](https://github.com/bundler/bundler/pull/2817) in 1.5.2. +**Note:** As of bundler 1.5.2, you can invoke `bundle install -jN` (where `N` the number of your processor cores) and enjoy the parallel gems installation with measurable difference in completion time (~60% faster). Check the number of your cores with `nproc`. For more information check this [post](https://robots.thoughtbot.com/parallel-gem-installing-using-bundler). First make sure you have bundler >= 1.5.2 (run `bundle -v`) as it addresses some [issues](https://devcenter.heroku.com/changelog-items/411) that were [fixed](https://github.com/bundler/bundler/pull/2817) in 1.5.2. # For PostgreSQL (note, the option says "without ... mysql") sudo -u git -H bundle install --deployment --without development test mysql aws kerberos diff --git a/doc/integration/ldap.md b/doc/integration/ldap.md index 9b7d8fa396..7e2920b886 100644 --- a/doc/integration/ldap.md +++ b/doc/integration/ldap.md @@ -71,7 +71,7 @@ main: # 'main' is the GitLab 'provider ID' of this LDAP server # Filter LDAP users # - # Format: RFC 4515 http://tools.ietf.org/search/rfc4515 + # Format: RFC 4515 https://tools.ietf.org/search/rfc4515 # Ex. (employeeType=developer) # # Note: GitLab does not support omniauth-ldap's custom filter syntax. @@ -145,7 +145,7 @@ If multiple LDAP email attributes are present, e.g. `mail: foo@bar.com` and `ema ## Using an LDAP filter to limit access to your GitLab server If you want to limit all GitLab access to a subset of the LDAP users on your LDAP server you can set up an LDAP user filter. -The filter must comply with [RFC 4515](http://tools.ietf.org/search/rfc4515). +The filter must comply with [RFC 4515](https://tools.ietf.org/search/rfc4515). ```ruby # For omnibus packages; new LDAP server syntax diff --git a/doc/legal/corporate_contributor_license_agreement.md b/doc/legal/corporate_contributor_license_agreement.md index 13bf15fcf4..7b94506c29 100644 --- a/doc/legal/corporate_contributor_license_agreement.md +++ b/doc/legal/corporate_contributor_license_agreement.md @@ -22,4 +22,4 @@ You accept and agree to the following terms and conditions for Your present and 8. It is your responsibility to notify GitLab B.V. when any change is required to the list of designated employees authorized to submit Contributions on behalf of the Corporation, or to the Corporation's Point of Contact with GitLab B.V.. -This text is licensed under the [Creative Commons Attribution 3.0 License](http://creativecommons.org/licenses/by/3.0/) and the original source is the Google Open Source Programs Office. +This text is licensed under the [Creative Commons Attribution 3.0 License](https://creativecommons.org/licenses/by/3.0/) and the original source is the Google Open Source Programs Office. diff --git a/doc/legal/individual_contributor_license_agreement.md b/doc/legal/individual_contributor_license_agreement.md index 72b01433dd..f97c252fd7 100644 --- a/doc/legal/individual_contributor_license_agreement.md +++ b/doc/legal/individual_contributor_license_agreement.md @@ -22,4 +22,4 @@ You accept and agree to the following terms and conditions for Your present and 8. You agree to notify GitLab B.V. of any facts or circumstances of which you become aware that would make these representations inaccurate in any respect. -This text is licensed under the [Creative Commons Attribution 3.0 License](http://creativecommons.org/licenses/by/3.0/) and the original source is the Google Open Source Programs Office. +This text is licensed under the [Creative Commons Attribution 3.0 License](https://creativecommons.org/licenses/by/3.0/) and the original source is the Google Open Source Programs Office. diff --git a/doc/markdown/markdown.md b/doc/markdown/markdown.md index ac3851f8c9..bc8e7d155e 100644 --- a/doc/markdown/markdown.md +++ b/doc/markdown/markdown.md @@ -43,7 +43,7 @@ You can also use other rich text files in GitLab. You might have to install a de ## Newlines -GFM honors the markdown specification in how [paragraphs and line breaks are handled](http://daringfireball.net/projects/markdown/syntax#p). +GFM honors the markdown specification in how [paragraphs and line breaks are handled](https://daringfireball.net/projects/markdown/syntax#p). A paragraph is simply one or more consecutive lines of text, separated by one or more blank lines. Line-breaks, or softreturns, are rendered if you end a line with two or more spaces @@ -72,14 +72,14 @@ do_this_and_do_that_and_another_thing GFM will autolink almost any URL you copy and paste into your text. - * http://www.google.com + * https://www.google.com * https://google.com/ * ftp://ftp.us.debian.org/debian/ * smb://foo/bar/baz * irc://irc.freenode.net/gitlab * http://localhost:3000 -* http://www.google.com +* https://www.google.com * https://google.com/ * ftp://ftp.us.debian.org/debian/ * smb://foo/bar/baz @@ -390,7 +390,7 @@ There are two ways to create links, inline-style and reference-style. [arbitrary case-insensitive reference text]: https://www.mozilla.org [1]: http://slashdot.org - [link text itself]: http://www.reddit.com + [link text itself]: https://www.reddit.com [I'm an inline-style link](https://www.google.com) @@ -406,7 +406,7 @@ Some text to show that the reference links can follow later. [arbitrary case-insensitive reference text]: https://www.mozilla.org [1]: http://slashdot.org -[link text itself]: http://www.reddit.com +[link text itself]: https://www.reddit.com **Note** @@ -583,5 +583,5 @@ By including colons in the header row, you can align the text within that column ## References - This document leveraged heavily from the [Markdown-Cheatsheet](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet). -- The [Markdown Syntax Guide](http://daringfireball.net/projects/markdown/syntax) at Daring Fireball is an excellent resource for a detailed explanation of standard markdown. +- The [Markdown Syntax Guide](https://daringfireball.net/projects/markdown/syntax) at Daring Fireball is an excellent resource for a detailed explanation of standard markdown. - [Dillinger.io](http://dillinger.io) is a handy tool for testing standard markdown. diff --git a/doc/operations/unicorn.md b/doc/operations/unicorn.md index 3998da01f0..bad61151bd 100644 --- a/doc/operations/unicorn.md +++ b/doc/operations/unicorn.md @@ -52,7 +52,7 @@ leak memory, probably because it does not handle user requests.) To make these memory leaks manageable, GitLab comes with the [unicorn-worker-killer gem](https://github.com/kzk/unicorn-worker-killer). This -gem [monkey-patches](http://en.wikipedia.org/wiki/Monkey_patch) the Unicorn +gem [monkey-patches](https://en.wikipedia.org/wiki/Monkey_patch) the Unicorn workers to do a memory self-check after every 16 requests. If the memory of the Unicorn worker exceeds a pre-set limit then the worker process exits. The Unicorn master then automatically replaces the worker process. @@ -83,4 +83,4 @@ is a normal value for our current GitLab.com setup and traffic. The high frequency of Unicorn memory restarts on some GitLab sites can be a source of confusion for administrators. Usually they are a [red -herring](http://en.wikipedia.org/wiki/Red_herring). +herring](https://en.wikipedia.org/wiki/Red_herring). diff --git a/doc/release/security.md b/doc/release/security.md index 60bcfbb6da..b1a62b333e 100644 --- a/doc/release/security.md +++ b/doc/release/security.md @@ -8,7 +8,7 @@ Do a security release when there is a critical issue that needs to be addresses ## Security vulnerability disclosure -Please report suspected security vulnerabilities in private to , also see the [disclosure section on the GitLab.com website](http://about.gitlab.com/disclosure/). Please do NOT create publicly viewable issues for suspected security vulnerabilities. +Please report suspected security vulnerabilities in private to , also see the [disclosure section on the GitLab.com website](https://about.gitlab.com/disclosure/). Please do NOT create publicly viewable issues for suspected security vulnerabilities. ## Release Procedure @@ -25,7 +25,7 @@ Please report suspected security vulnerabilities in private to Date: Tue, 17 Nov 2015 13:08:11 +0200 Subject: [PATCH 24/80] Fix md syntax in doc/api/commits.md --- doc/api/commits.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/api/commits.md b/doc/api/commits.md index 8e4a0ee1b8..93d62b751e 100644 --- a/doc/api/commits.md +++ b/doc/api/commits.md @@ -188,7 +188,7 @@ Parameters: "target_url": "http://jenkins/project/url", "description": "Jenkins success", "created_at": "2015-10-12T09:47:16.250Z", - "started_at": "2015-10-12T09:47:16.250Z"", + "started_at": "2015-10-12T09:47:16.250Z", "finished_at": "2015-10-12T09:47:16.262Z", "author": { "id": 1, @@ -228,7 +228,7 @@ POST /projects/:id/statuses/:sha "target_url": "http://jenkins/project/url", "description": "Jenkins success", "created_at": "2015-10-12T09:47:16.250Z", - "started_at": "2015-10-12T09:47:16.250Z"", + "started_at": "2015-10-12T09:47:16.250Z", "finished_at": "2015-10-12T09:47:16.262Z", "author": { "id": 1, From 3ae1dee475dbeb9bdf62ed139292cba09b6c98bb Mon Sep 17 00:00:00 2001 From: Jason Lee Date: Mon, 16 Nov 2015 12:00:37 +0800 Subject: [PATCH 25/80] Avoid render edit_form when visitor can't edit them. Reverted #9820, github/task_list need a form, textarea for update. --- app/views/projects/notes/_note.html.haml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/views/projects/notes/_note.html.haml b/app/views/projects/notes/_note.html.haml index 8880830198..efa7dd01cc 100644 --- a/app/views/projects/notes/_note.html.haml +++ b/app/views/projects/notes/_note.html.haml @@ -59,8 +59,7 @@ .note-text = preserve do = markdown(note.note, {no_header_anchors: true}) - - unless note.system? - -# System notes can't be edited + - if note_editable?(note) = render 'projects/notes/edit_form', note: note - if note.attachment.url From 4597f8ef209b832538c3aa8524c197ef505d625e Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Tue, 17 Nov 2015 10:44:01 -0500 Subject: [PATCH 26/80] Update monthly release template [ci skip] --- doc/release/monthly.md | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/doc/release/monthly.md b/doc/release/monthly.md index d347f58ba0..c9ab87671d 100644 --- a/doc/release/monthly.md +++ b/doc/release/monthly.md @@ -54,21 +54,25 @@ template are explained below: - [ ] Update GitLab.com with RC1 - [ ] Create the regression issue in the CE issue tracker: - > This is a meta issue to index possible regressions in this monthly release - > and any patch versions. - > - > Please do not raise or discuss issues directly in this issue but link to - > issues that might warrant a patch release. If there is a Merge Request - > that fixes the issue, please link to that as well. - > - > Please only post one regression issue and/or merge request per comment. - > Comments will be updated by the release manager as they are addressed. + ``` + This is a meta issue to index possible regressions in this monthly release + and any patch versions. + + Please do not raise or discuss issues directly in this issue but link to + issues that might warrant a patch release. If there is a Merge Request + that fixes the issue, please link to that as well. + + Please only post one regression issue and/or merge request per comment. + Comments will be updated by the release manager as they are addressed. + ``` - [ ] Tweet about RC1 release: - > GitLab x.y.0.rc1 is available: https://packages.gitlab.com/gitlab/unstable - > Use at your own risk. Please link regressions issues from - > LINK_TO_REGRESSION_ISSUE + ``` + GitLab x.y.0.rc1 is available: https://packages.gitlab.com/gitlab/unstable + Use at your own risk. Please link regressions issues from + LINK_TO_REGRESSION_ISSUE + ``` ### Xth: (3 working days before the 22nd) From 85102d094f44741e6fbf53910df1bed363a020bb Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Tue, 17 Nov 2015 11:02:11 -0500 Subject: [PATCH 27/80] Update CHANGELOG [ci skip] --- CHANGELOG | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 3c22df7c9a..ca09d9c09f 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,8 @@ Please view this file on the master branch, on stable branches it's out of date. -v 8.2.0 (unreleased) +v 8.3.0 (unreleased) + +v 8.2.0 - Remove CSS property preventing hard tabs from rendering in Chromium 45 (Stan Hu) - Fix Drone CI service template not saving properly (Stan Hu) - Fix avatars not showing in Atom feeds and project issues when Gravatar disabled (Stan Hu) From 1ec7cea59751b83c364116e9c20260537e14fd58 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Tue, 17 Nov 2015 11:43:47 -0500 Subject: [PATCH 28/80] Merge branch 'param-view' into 'master' See merge request !1816 --- app/helpers/diff_helper.rb | 8 ++++++-- app/views/projects/commit/show.html.haml | 2 +- app/views/projects/diffs/_diffs.html.haml | 2 +- app/views/projects/diffs/_file.html.haml | 3 +-- app/views/projects/notes/_form.html.haml | 2 +- app/views/projects/notes/_notes_with_form.html.haml | 4 ++-- 6 files changed, 12 insertions(+), 9 deletions(-) diff --git a/app/helpers/diff_helper.rb b/app/helpers/diff_helper.rb index b889fb2897..f47d5c4c74 100644 --- a/app/helpers/diff_helper.rb +++ b/app/helpers/diff_helper.rb @@ -1,4 +1,8 @@ module DiffHelper + def diff_view + params[:view] == 'parallel' ? 'parallel' : 'inline' + end + def allowed_diff_size if diff_hard_limit_enabled? Commit::DIFF_HARD_LIMIT_FILES @@ -137,7 +141,7 @@ module DiffHelper # Always use HTML to handle case where JSON diff rendered this button params_copy.delete(:format) - link_to url_for(params_copy), id: "inline-diff-btn", class: (params[:view] != 'parallel' ? 'btn active' : 'btn') do + link_to url_for(params_copy), id: "inline-diff-btn", class: (diff_view == 'inline' ? 'btn active' : 'btn') do 'Inline' end end @@ -148,7 +152,7 @@ module DiffHelper # Always use HTML to handle case where JSON diff rendered this button params_copy.delete(:format) - link_to url_for(params_copy), id: "parallel-diff-btn", class: (params[:view] == 'parallel' ? 'btn active' : 'btn') do + link_to url_for(params_copy), id: "parallel-diff-btn", class: (diff_view == 'parallel' ? 'btn active' : 'btn') do 'Side-by-side' end end diff --git a/app/views/projects/commit/show.html.haml b/app/views/projects/commit/show.html.haml index 30a3973828..85e203cbe5 100644 --- a/app/views/projects/commit/show.html.haml +++ b/app/views/projects/commit/show.html.haml @@ -3,4 +3,4 @@ = render "commit_box" = render "ci_menu" if @ci_commit = render "projects/diffs/diffs", diffs: @diffs, project: @project -= render "projects/notes/notes_with_form", view: params[:view] += render "projects/notes/notes_with_form" diff --git a/app/views/projects/diffs/_diffs.html.haml b/app/views/projects/diffs/_diffs.html.haml index e46bf1ab1e..416fb4da07 100644 --- a/app/views/projects/diffs/_diffs.html.haml +++ b/app/views/projects/diffs/_diffs.html.haml @@ -1,4 +1,4 @@ -- if params[:view] == 'parallel' +- if diff_view == 'parallel' - fluid_layout true - diff_files = safe_diff_files(diffs) diff --git a/app/views/projects/diffs/_file.html.haml b/app/views/projects/diffs/_file.html.haml index 410ff6abb4..c745b4e69b 100644 --- a/app/views/projects/diffs/_file.html.haml +++ b/app/views/projects/diffs/_file.html.haml @@ -33,7 +33,7 @@ -# Skipp all non non-supported blobs - return unless blob.respond_to?('text?') - if blob.text? - - if params[:view] == 'parallel' + - if diff_view == 'parallel' = render "projects/diffs/parallel_view", diff_file: diff_file, project: project, blob: blob, index: i - else = render "projects/diffs/text_file", diff_file: diff_file, index: i @@ -42,4 +42,3 @@ = render "projects/diffs/image", diff_file: diff_file, old_file: old_file, file: blob, index: i - else .nothing-here-block No preview for this file type - diff --git a/app/views/projects/notes/_form.html.haml b/app/views/projects/notes/_form.html.haml index 13dfa0a1bb..5dd84317e3 100644 --- a/app/views/projects/notes/_form.html.haml +++ b/app/views/projects/notes/_form.html.haml @@ -1,5 +1,5 @@ = form_for [@project.namespace.becomes(Namespace), @project, @note], remote: true, html: { :'data-type' => 'json', multipart: true, id: nil, class: "new_note js-new-note-form common-note-form gfm-form" }, authenticity_token: true do |f| - = hidden_field_tag :view, params[:view] + = hidden_field_tag :view, diff_view = hidden_field_tag :line_type = note_target_fields(@note) = f.hidden_field :commit_id diff --git a/app/views/projects/notes/_notes_with_form.html.haml b/app/views/projects/notes/_notes_with_form.html.haml index 04222b8f7c..99c1b0fa43 100644 --- a/app/views/projects/notes/_notes_with_form.html.haml +++ b/app/views/projects/notes/_notes_with_form.html.haml @@ -4,7 +4,7 @@ .js-main-target-form - if can? current_user, :create_note, @project - = render "projects/notes/form", view: params[:view] + = render "projects/notes/form", view: diff_view :javascript - new Notes("#{namespace_project_notes_path(namespace_id: @project.namespace, target_id: @noteable.id, target_type: @noteable.class.name.underscore)}", #{@notes.map(&:id).to_json}, #{Time.now.to_i}, "#{params[:view]}") + new Notes("#{namespace_project_notes_path(namespace_id: @project.namespace, target_id: @noteable.id, target_type: @noteable.class.name.underscore)}", #{@notes.map(&:id).to_json}, #{Time.now.to_i}, "#{diff_view}") From 8a1cafeb9decf2738311ea45a15d8fef0489b7da Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Tue, 17 Nov 2015 18:23:27 +0000 Subject: [PATCH 29/80] Merge branch 'james11/gitlab-ce-removable-group-owner' into 'master' Prevent the last owner of a group from being able to delete themselves by 'adding' themselves as a master Replaces !1708. Fixes #1111. See merge request !1815 --- CHANGELOG | 1 + .../groups/group_members_controller.rb | 30 +++++----- .../projects/project_members_controller.rb | 34 ++++++----- app/models/ability.rb | 58 +++++++++++++------ app/models/group.rb | 7 +-- app/models/member.rb | 38 +++++++++--- app/models/project.rb | 2 +- .../group_members/_group_member.html.haml | 6 +- .../groups/group_members/index.html.haml | 6 +- .../project_members/_project_member.html.haml | 11 ++-- .../projects/project_members/_team.html.haml | 4 +- .../projects/project_members/update.js.haml | 3 +- features/groups.feature | 8 +++ features/steps/groups.rb | 18 ++++++ 14 files changed, 149 insertions(+), 77 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index ca09d9c09f..cc9fcf1992 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -47,6 +47,7 @@ v 8.2.0 - Fix trailing whitespace issue in merge request/issue title - Fix bug when milestone/label filter was empty for dashboard issues page - Add ability to create milestone in group projects from single form + - Prevent the last owner of a group from being able to delete themselves by 'adding' themselves as a master (James Lopez) v 8.1.4 - Fix bug where manually merged branches in a MR would end up with an empty diff (Stan Hu) diff --git a/app/controllers/groups/group_members_controller.rb b/app/controllers/groups/group_members_controller.rb index b25957a06e..0e902c4bb4 100644 --- a/app/controllers/groups/group_members_controller.rb +++ b/app/controllers/groups/group_members_controller.rb @@ -3,8 +3,7 @@ class Groups::GroupMembersController < Groups::ApplicationController # Authorize before_action :authorize_read_group! - before_action :authorize_admin_group!, except: [:index, :leave] - before_action :authorize_admin_group_member!, only: [:create, :resend_invite] + before_action :authorize_admin_group_member!, except: [:index, :leave] def index @project = @group.projects.find(params[:project_id]) if params[:project_id] @@ -17,7 +16,8 @@ class Groups::GroupMembersController < Groups::ApplicationController end @members = @members.order('access_level DESC').page(params[:page]).per(50) - @group_member = GroupMember.new + + @group_member = @group.group_members.new end def create @@ -27,24 +27,23 @@ class Groups::GroupMembersController < Groups::ApplicationController end def update - @member = @group.group_members.find(params[:id]) + @group_member = @group.group_members.find(params[:id]) - return render_403 unless can?(current_user, :update_group_member, @member) + return render_403 unless can?(current_user, :update_group_member, @group_member) - @member.update_attributes(member_params) + @group_member.update_attributes(member_params) end def destroy @group_member = @group.group_members.find(params[:id]) - if can?(current_user, :destroy_group_member, @group_member) # May fail if last owner. - @group_member.destroy - respond_to do |format| - format.html { redirect_to group_group_members_path(@group), notice: 'User was successfully removed from group.' } - format.js { render nothing: true } - end - else - return render_403 + return render_403 unless can?(current_user, :destroy_group_member, @group_member) + + @group_member.destroy + + respond_to do |format| + format.html { redirect_to group_group_members_path(@group), notice: 'User was successfully removed from group.' } + format.js { render nothing: true } end end @@ -63,10 +62,11 @@ class Groups::GroupMembersController < Groups::ApplicationController end def leave - @group_member = @group.group_members.where(user_id: current_user.id).first + @group_member = @group.group_members.find_by(user_id: current_user) if can?(current_user, :destroy_group_member, @group_member) @group_member.destroy + redirect_to(dashboard_groups_path, notice: "You left #{group.name} group.") else if @group.last_owner?(current_user) diff --git a/app/controllers/projects/project_members_controller.rb b/app/controllers/projects/project_members_controller.rb index 9de5269cd2..07eb94e4f4 100644 --- a/app/controllers/projects/project_members_controller.rb +++ b/app/controllers/projects/project_members_controller.rb @@ -1,6 +1,6 @@ class Projects::ProjectMembersController < Projects::ApplicationController # Authorize - before_action :authorize_admin_project!, except: :leave + before_action :authorize_admin_project_member!, except: :leave def index @project_members = @project.project_members @@ -29,10 +29,6 @@ class Projects::ProjectMembersController < Projects::ApplicationController @project_member = @project.project_members.new end - def new - @project_member = @project.project_members.new - end - def create @project.team.add_users(params[:user_ids].split(','), params[:access_level], current_user) @@ -41,11 +37,17 @@ class Projects::ProjectMembersController < Projects::ApplicationController def update @project_member = @project.project_members.find(params[:id]) + + return render_403 unless can?(current_user, :update_project_member, @project_member) + @project_member.update_attributes(member_params) end def destroy @project_member = @project.project_members.find(params[:id]) + + return render_403 unless can?(current_user, :destroy_project_member, @project_member) + @project_member.destroy respond_to do |format| @@ -71,16 +73,22 @@ class Projects::ProjectMembersController < Projects::ApplicationController end def leave - if @project.namespace == current_user.namespace - message = 'You can not leave your own project. Transfer or delete the project.' - return redirect_back_or_default(default: { action: 'index' }, options: { alert: message }) - end + @project_member = @project.project_members.find_by(user_id: current_user) - @project.project_members.find_by(user_id: current_user).destroy + if can?(current_user, :destroy_project_member, @project_member) + @project_member.destroy - respond_to do |format| - format.html { redirect_to dashboard_projects_path } - format.js { render nothing: true } + respond_to do |format| + format.html { redirect_to dashboard_projects_path, notice: "You left the project." } + format.js { render nothing: true } + end + else + if current_user == @project.owner + message = 'You can not leave your own project. Transfer or delete the project.' + redirect_back_or_default(default: { action: 'index' }, options: { alert: message }) + else + render_403 + end end end diff --git a/app/models/ability.rb b/app/models/ability.rb index d01b3ae6f0..500af08d20 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -15,6 +15,7 @@ class Ability when "Group" then group_abilities(user, subject) when "Namespace" then namespace_abilities(user, subject) when "GroupMember" then group_member_abilities(user, subject) + when "ProjectMember" then project_member_abilities(user, subject) else [] end.concat(global_abilities(user)) end @@ -231,19 +232,19 @@ class Ability # Only group masters and group owners can create new projects in group if group.has_master?(user) || group.has_owner?(user) || user.admin? - rules.push(*[ + rules += [ :create_projects, :admin_milestones - ]) + ] end # Only group owner and administrators can admin group if group.has_owner?(user) || user.admin? - rules.push(*[ + rules += [ :admin_group, :admin_namespace, :admin_group_member - ]) + ] end rules.flatten @@ -254,16 +255,15 @@ class Ability # Only namespace owner and administrators can admin it if namespace.owner == user || user.admin? - rules.push(*[ + rules += [ :create_projects, :admin_namespace - ]) + ] end rules.flatten end - [:issue, :merge_request].each do |name| define_method "#{name}_abilities" do |user, subject| rules = [] @@ -304,15 +304,39 @@ class Ability rules = [] target_user = subject.user group = subject.group - can_manage = group_abilities(user, group).include?(:admin_group_member) - if can_manage && (user != target_user) - rules << :update_group_member - rules << :destroy_group_member + unless group.last_owner?(target_user) + can_manage = group_abilities(user, group).include?(:admin_group_member) + + if can_manage && user != target_user + rules << :update_group_member + rules << :destroy_group_member + end + + if user == target_user + rules << :destroy_group_member + end end - if !group.last_owner?(user) && (can_manage || (user == target_user)) - rules << :destroy_group_member + rules + end + + def project_member_abilities(user, subject) + rules = [] + target_user = subject.user + project = subject.project + + unless target_user == project.owner + can_manage = project_abilities(user, project).include?(:admin_project_member) + + if can_manage && user != target_user + rules << :update_project_member + rules << :destroy_project_member + end + + if user == target_user + rules << :destroy_project_member + end end rules @@ -320,10 +344,10 @@ class Ability def abilities @abilities ||= begin - abilities = Six.new - abilities << self - abilities - end + abilities = Six.new + abilities << self + abilities + end end private diff --git a/app/models/group.rb b/app/models/group.rb index 793a3b5ef2..2c9e75496b 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -20,8 +20,9 @@ require 'file_size_validator' class Group < Namespace include Gitlab::ConfigHelper include Referable - + has_many :group_members, dependent: :destroy, as: :source, class_name: 'GroupMember' + alias_method :members, :group_members has_many :users, through: :group_members validate :avatar_type, if: ->(user) { user.avatar.present? && user.avatar_changed? } @@ -110,10 +111,6 @@ class Group < Namespace has_owner?(user) && owners.size == 1 end - def members - group_members - end - def avatar_type unless self.avatar.image? self.errors.add :avatar, "only images allowed" diff --git a/app/models/member.rb b/app/models/member.rb index cae8caa23f..28aee2e379 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -30,13 +30,22 @@ class Member < ActiveRecord::Base validates :user, presence: true, unless: :invite? validates :source, presence: true - validates :user_id, uniqueness: { scope: [:source_type, :source_id], + validates :user_id, uniqueness: { scope: [:source_type, :source_id], message: "already exists in source", allow_nil: true } validates :access_level, inclusion: { in: Gitlab::Access.all_values }, presence: true - validates :invite_email, presence: { if: :invite? }, - email: { strict_mode: true, allow_nil: true }, - uniqueness: { scope: [:source_type, :source_id], allow_nil: true } + validates :invite_email, + presence: { + if: :invite? + }, + email: { + strict_mode: true, + allow_nil: true + }, + uniqueness: { + scope: [:source_type, :source_id], + allow_nil: true + } scope :invite, -> { where(user_id: nil) } scope :non_invite, -> { where("user_id IS NOT NULL") } @@ -73,7 +82,7 @@ class Member < ActiveRecord::Base def add_user(members, user_id, access_level, current_user = nil) user = user_for_id(user_id) - + # `user` can be either a User object or an email to be invited if user.is_a?(User) member = members.find_or_initialize_by(user_id: user.id) @@ -82,10 +91,21 @@ class Member < ActiveRecord::Base member.invite_email = user end - member.created_by ||= current_user - member.access_level = access_level + if can_update_member?(current_user, member) + member.created_by ||= current_user + member.access_level = access_level - member.save + member.save + end + end + + private + + def can_update_member?(current_user, member) + # There is no current user for bulk actions, in which case anything is allowed + !current_user || + current_user.can?(:update_group_member, member) || + current_user.can?(:update_project_member, member) end end @@ -95,7 +115,7 @@ class Member < ActiveRecord::Base def accept_invite!(new_user) return false unless invite? - + self.invite_token = nil self.invite_accepted_at = Time.now.utc diff --git a/app/models/project.rb b/app/models/project.rb index 9ea0d15497..a099a67cf6 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -42,7 +42,7 @@ class Project < ActiveRecord::Base include Sortable include AfterCommitQueue include CaseSensitivity - + extend Gitlab::ConfigHelper extend Enumerize diff --git a/app/views/groups/group_members/_group_member.html.haml b/app/views/groups/group_members/_group_member.html.haml index 3c19381321..be94b1abc1 100644 --- a/app/views/groups/group_members/_group_member.html.haml +++ b/app/views/groups/group_members/_group_member.html.haml @@ -1,6 +1,5 @@ - user = member.user - return unless user || member.invite? -- show_roles = true if show_roles.nil? %li{class: "#{dom_class(member)} js-toggle-container", id: dom_id(member)} %span{class: ("list-item-name" if show_controls)} @@ -25,11 +24,11 @@ = link_to member.created_by.name, user_path(member.created_by) = time_ago_with_tooltip(member.created_at) - - if show_controls && can?(current_user, :admin_group_member, member) + - if show_controls && can?(current_user, :admin_group_member, @group) = link_to resend_invite_group_group_member_path(@group, member), method: :post, class: "btn-xs btn", title: 'Resend invite' do Resend invite - - if show_roles + - if should_user_see_group_roles?(current_user, @group) %span.pull-right %strong= member.human_access - if show_controls @@ -37,6 +36,7 @@ = button_tag class: "btn-xs btn js-toggle-button", title: 'Edit access level', type: 'button' do %i.fa.fa-pencil-square-o + - if can?(current_user, :destroy_group_member, member)   - if current_user == user diff --git a/app/views/groups/group_members/index.html.haml b/app/views/groups/group_members/index.html.haml index 15d289471c..d4ad33a8bf 100644 --- a/app/views/groups/group_members/index.html.haml +++ b/app/views/groups/group_members/index.html.haml @@ -1,8 +1,6 @@ - page_title "Members" - header_title group_title(@group, "Members", group_group_members_path(@group)) -- show_roles = should_user_see_group_roles?(current_user, @group) - -- if show_roles +- if should_user_see_group_roles?(current_user, @group) %p.light Members of group have access to all group projects. Read more about permissions @@ -32,7 +30,7 @@ (#{@members.total_count}) %ul.well-list - @members.each do |member| - = render 'groups/group_members/group_member', member: member, show_roles: show_roles, show_controls: true + = render 'groups/group_members/group_member', member: member, show_controls: true = paginate @members, theme: 'gitlab' diff --git a/app/views/projects/project_members/_project_member.html.haml b/app/views/projects/project_members/_project_member.html.haml index 76c46d1d80..f07cd97e63 100644 --- a/app/views/projects/project_members/_project_member.html.haml +++ b/app/views/projects/project_members/_project_member.html.haml @@ -24,18 +24,19 @@ = link_to member.created_by.name, user_path(member.created_by) = time_ago_with_tooltip(member.created_at) - - if current_user_can_admin_project + - if can?(current_user, :admin_project_member, @project) = link_to resend_invite_namespace_project_project_member_path(@project.namespace, @project, member), method: :post, class: "btn-xs btn", title: 'Resend invite' do Resend invite - - if current_user_can_admin_project - - unless @project.personal? && user == current_user - .pull-right - %strong= member.human_access + - if can?(current_user, :admin_project_member, @project) + .pull-right + %strong= member.human_access + - if can?(current_user, :update_project_member, member) = button_tag class: "btn-xs btn js-toggle-button", title: 'Edit access level', type: 'button' do %i.fa.fa-pencil-square-o + - if can?(current_user, :destroy_project_member, member)   - if current_user == user = link_to leave_namespace_project_project_members_path(@project.namespace, @project), data: { confirm: leave_project_message(@project) }, method: :delete, class: "btn-xs btn btn-remove", title: 'Leave project' do diff --git a/app/views/projects/project_members/_team.html.haml b/app/views/projects/project_members/_team.html.haml index 615c425e59..b807fb2cc9 100644 --- a/app/views/projects/project_members/_team.html.haml +++ b/app/views/projects/project_members/_team.html.haml @@ -1,5 +1,3 @@ -- can_admin_project = can?(current_user, :admin_project, @project) - .panel.panel-default.prepend-top-20 .panel-heading %strong #{@project.name} @@ -8,4 +6,4 @@ (#{members.count}) %ul.well-list - members.each do |project_member| - = render 'project_member', member: project_member, current_user_can_admin_project: can_admin_project + = render 'project_member', member: project_member diff --git a/app/views/projects/project_members/update.js.haml b/app/views/projects/project_members/update.js.haml index 811b185882..2fb3a41d54 100644 --- a/app/views/projects/project_members/update.js.haml +++ b/app/views/projects/project_members/update.js.haml @@ -1,3 +1,2 @@ -- can_admin_project = can?(current_user, :admin_project, @project) :plain - $("##{dom_id(@project_member)}").replaceWith('#{escape_javascript(render("project_member", member: @project_member, current_user_can_admin_project: can_admin_project))}'); + $("##{dom_id(@project_member)}").replaceWith('#{escape_javascript(render("project_member", member: @project_member))}'); diff --git a/features/groups.feature b/features/groups.feature index 615eff6a33..abf3769a84 100644 --- a/features/groups.feature +++ b/features/groups.feature @@ -59,6 +59,14 @@ Feature: Groups When I select "Mike" as "Reporter" Then I should see "Mike" in team list as "Reporter" + @javascript + Scenario: Ignore add user to group when is already Owner + Given gitlab user "Mike" + When I visit group "Owned" members page + And I click link "Add members" + When I select "Mike" as "Reporter" + Then I should see "Mike" in team list as "Owner" + @javascript Scenario: Invite user to group When I visit group "Owned" members page diff --git a/features/steps/groups.rb b/features/steps/groups.rb index a8fba2406a..9c0313537b 100644 --- a/features/steps/groups.rb +++ b/features/steps/groups.rb @@ -48,6 +48,17 @@ class Spinach::Features::Groups < Spinach::FeatureSteps click_button "Add users to group" end + step 'I select "Mike" as "Master"' do + user = User.find_by(name: "Mike") + + page.within ".users-group-form" do + select2(user.id, from: "#user_ids", multiple: true) + select "Master", from: "access_level" + end + + click_button "Add users to group" + end + step 'I should see "Mike" in team list as "Reporter"' do page.within '.well-list' do expect(page).to have_content('Mike') @@ -55,6 +66,13 @@ class Spinach::Features::Groups < Spinach::FeatureSteps end end + step 'I should see "Mike" in team list as "Owner"' do + page.within '.well-list' do + expect(page).to have_content('Mike') + expect(page).to have_content('Owner') + end + end + step 'I select "sjobs@apple.com" as "Reporter"' do page.within ".users-group-form" do select2("sjobs@apple.com", from: "#user_ids", multiple: true) From c9f032470116e0cda23e605a66eceaad928b3e02 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Tue, 17 Nov 2015 18:28:09 +0000 Subject: [PATCH 30/80] Merge branch 'adamliesko/gitlab-ce-notification-upon-unassignment' into 'master' Add notification to the former assignee upon unassignment Replaces !1769 Fixes #3395 See merge request !1818 --- CHANGELOG | 1 + app/services/notification_service.rb | 12 ++++++++---- spec/services/issues/update_service_spec.rb | 12 ++++++++---- spec/services/merge_requests/update_service_spec.rb | 11 +++++++---- 4 files changed, 24 insertions(+), 12 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index cc9fcf1992..8e31d2a043 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -34,6 +34,7 @@ v 8.2.0 - Add "added", "modified" and "removed" properties to commit object in webhook - Rename "Back to" links to "Go to" because its not always a case it point to place user come from - Allow groups to appear in the search results if the group owner allows it + - Add email notification to former assignee upon unassignment (Adam Lieskovský) - New design for project graphs page - Remove deprecated dumped yaml file generated from previous job definitions - Fix incoming email config defaults diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index a6b2234865..6ed6ebca58 100644 --- a/app/services/notification_service.rb +++ b/app/services/notification_service.rb @@ -361,11 +361,13 @@ class NotificationService end def reassign_resource_email(target, project, current_user, method) - assignee_id_was = previous_record(target, "assignee_id") - recipients = build_recipients(target, project, current_user) + previous_assignee_id = previous_record(target, "assignee_id") + previous_assignee = User.find_by(id: previous_assignee_id) if previous_assignee_id + + recipients = build_recipients(target, project, current_user, [previous_assignee]) recipients.each do |recipient| - mailer.send(method, recipient.id, target.id, assignee_id_was, current_user.id) + mailer.send(method, recipient.id, target.id, previous_assignee_id, current_user.id) end end @@ -377,9 +379,11 @@ class NotificationService end end - def build_recipients(target, project, current_user) + def build_recipients(target, project, current_user, extra_recipients = nil) recipients = target.participants(current_user) + recipients = recipients.concat(extra_recipients).compact.uniq if extra_recipients + recipients = add_project_watchers(recipients, project) recipients = reject_mention_users(recipients, project) recipients = reject_muted_users(recipients, project) diff --git a/spec/services/issues/update_service_spec.rb b/spec/services/issues/update_service_spec.rb index a91be3b447..f55527ee9a 100644 --- a/spec/services/issues/update_service_spec.rb +++ b/spec/services/issues/update_service_spec.rb @@ -3,13 +3,15 @@ require 'spec_helper' describe Issues::UpdateService do let(:user) { create(:user) } let(:user2) { create(:user) } - let(:issue) { create(:issue, title: 'Old title') } + let(:user3) { create(:user) } + let(:issue) { create(:issue, title: 'Old title', assignee_id: user3.id) } let(:label) { create(:label) } let(:project) { issue.project } before do project.team << [user, :master] project.team << [user2, :developer] + project.team << [user3, :developer] end describe 'execute' do @@ -34,9 +36,11 @@ describe Issues::UpdateService do it { expect(@issue.labels.count).to eq(1) } it { expect(@issue.labels.first.title).to eq('Bug') } - it 'should send email to user2 about assign of new issue' do - email = ActionMailer::Base.deliveries.last - expect(email.to.first).to eq(user2.email) + it 'should send email to user2 about assign of new issue and email to user3 about issue unassignment' do + deliveries = ActionMailer::Base.deliveries + email = deliveries.last + recipients = deliveries.last(2).map(&:to).flatten + expect(recipients).to include(user2.email, user3.email) expect(email.subject).to include(issue.title) end diff --git a/spec/services/merge_requests/update_service_spec.rb b/spec/services/merge_requests/update_service_spec.rb index c75173c145..2ed51d223b 100644 --- a/spec/services/merge_requests/update_service_spec.rb +++ b/spec/services/merge_requests/update_service_spec.rb @@ -3,7 +3,8 @@ require 'spec_helper' describe MergeRequests::UpdateService do let(:user) { create(:user) } let(:user2) { create(:user) } - let(:merge_request) { create(:merge_request, :simple, title: 'Old title') } + let(:user3) { create(:user) } + let(:merge_request) { create(:merge_request, :simple, title: 'Old title', assignee_id: user3.id) } let(:project) { merge_request.project } let(:label) { create(:label) } @@ -47,9 +48,11 @@ describe MergeRequests::UpdateService do with(@merge_request, 'update') end - it 'should send email to user2 about assign of new merge_request' do - email = ActionMailer::Base.deliveries.last - expect(email.to.first).to eq(user2.email) + it 'should send email to user2 about assign of new merge request and email to user3 about merge request unassignment' do + deliveries = ActionMailer::Base.deliveries + email = deliveries.last + recipients = deliveries.last(2).map(&:to).flatten + expect(recipients).to include(user2.email, user3.email) expect(email.subject).to include(merge_request.title) end From 17a0cd46ccdad003b3bf36061fb16caa24a977a1 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Tue, 17 Nov 2015 13:48:28 -0500 Subject: [PATCH 31/80] Merge branch 'contributor-graph-by-email' into 'master' See merge request !1705 --- CHANGELOG | 4 +++- .../javascripts/stat_graph_contributors_util.js.coffee | 5 ++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 8e31d2a043..56072e10ef 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -3,6 +3,8 @@ Please view this file on the master branch, on stable branches it's out of date. v 8.3.0 (unreleased) v 8.2.0 +v 8.2.0 (unreleased) + - Fix grouping of contributors by email in graph. - Remove CSS property preventing hard tabs from rendering in Chromium 45 (Stan Hu) - Fix Drone CI service template not saving properly (Stan Hu) - Fix avatars not showing in Atom feeds and project issues when Gravatar disabled (Stan Hu) @@ -1955,4 +1957,4 @@ v 0.8.0 - stability - security fixes - increased test coverage - - email notification + - email notification \ No newline at end of file diff --git a/app/assets/javascripts/stat_graph_contributors_util.js.coffee b/app/assets/javascripts/stat_graph_contributors_util.js.coffee index cfe5508290..f5584bcfe4 100644 --- a/app/assets/javascripts/stat_graph_contributors_util.js.coffee +++ b/app/assets/javascripts/stat_graph_contributors_util.js.coffee @@ -6,7 +6,7 @@ window.ContributorsStatGraphUtil = for entry in log @add_date(entry.date, total) unless total[entry.date]? - data = by_author[entry.author_name] #|| by_email[entry.author_email] + data = by_author[entry.author_name] || by_email[entry.author_email] data ?= @add_author(entry, by_author, by_email) @add_date(entry.date, data) unless data[entry.date] @@ -95,5 +95,4 @@ window.ContributorsStatGraphUtil = if date_range is null || date_range[0] <= new Date(date) <= date_range[1] true else - false - + false \ No newline at end of file From ea5a10b065e6f2d02b627790832424729ed578ce Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Tue, 17 Nov 2015 18:51:40 +0000 Subject: [PATCH 32/80] Merge branch 'compare-first-commit' into 'master' Correctly set comparison first commit when range includes a merge commit Fixes #3207. See merge request !1814 --- app/controllers/projects/compare_controller.rb | 4 ++-- app/helpers/diff_helper.rb | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/controllers/projects/compare_controller.rb b/app/controllers/projects/compare_controller.rb index 55134e11d1..5200d609cc 100644 --- a/app/controllers/projects/compare_controller.rb +++ b/app/controllers/projects/compare_controller.rb @@ -20,8 +20,8 @@ class Projects::CompareController < Projects::ApplicationController if compare_result @commits = Commit.decorate(compare_result.commits, @project) @diffs = compare_result.diffs - @commit = @commits.last - @first_commit = @commits.first + @commit = @project.commit(head_ref) + @first_commit = @project.commit(base_ref) @line_notes = [] end end diff --git a/app/helpers/diff_helper.rb b/app/helpers/diff_helper.rb index f47d5c4c74..0fd5c98658 100644 --- a/app/helpers/diff_helper.rb +++ b/app/helpers/diff_helper.rb @@ -175,7 +175,7 @@ module DiffHelper def commit_for_diff(diff) if diff.deleted_file first_commit = @first_commit || @commit - first_commit.parent + first_commit.parent || @first_commit else @commit end From 8382fac7cc7f9c1ce31b57044c7930db72bbf71a Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Tue, 17 Nov 2015 15:19:20 -0500 Subject: [PATCH 33/80] Update CHANGELOG [ci skip] --- CHANGELOG | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 56072e10ef..94f07a3168 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -3,7 +3,6 @@ Please view this file on the master branch, on stable branches it's out of date. v 8.3.0 (unreleased) v 8.2.0 -v 8.2.0 (unreleased) - Fix grouping of contributors by email in graph. - Remove CSS property preventing hard tabs from rendering in Chromium 45 (Stan Hu) - Fix Drone CI service template not saving properly (Stan Hu) @@ -1957,4 +1956,4 @@ v 0.8.0 - stability - security fixes - increased test coverage - - email notification \ No newline at end of file + - email notification From 371e8505f813b434c72ac252a16e2618d3161f0d Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Wed, 18 Nov 2015 14:56:29 +0000 Subject: [PATCH 34/80] Merge branch 'ce-mirror-backport' into 'master' Backport relevant changes from gitlab-org/gitlab-ee!51 To do: - [x] Update gitlab-shell See merge request !1822 --- GITLAB_SHELL_VERSION | 2 +- app/assets/stylesheets/framework/common.scss | 4 ++ .../stylesheets/framework/tw_bootstrap.scss | 2 +- .../projects/imports_controller.rb | 4 +- app/helpers/projects_helper.rb | 8 --- app/models/project.rb | 18 +++-- app/models/repository.rb | 47 +++++++++----- app/services/projects/create_service.rb | 8 +-- app/views/projects/_home_panel.html.haml | 17 ++--- .../projects/buttons/_download.html.haml | 4 ++ .../projects/buttons/_dropdown.html.haml | 2 - app/views/projects/buttons/_fork.html.haml | 25 +++---- app/views/projects/buttons/_star.html.haml | 2 +- app/views/projects/imports/new.html.haml | 25 ++++--- app/views/projects/imports/show.html.haml | 2 +- app/views/projects/new.html.haml | 15 +---- app/views/shared/_clone_panel.html.haml | 5 +- app/views/shared/_import_form.html.haml | 16 +++++ app/workers/repository_fork_worker.rb | 14 ++-- app/workers/repository_import_worker.rb | 65 ++++++++++++------- ...51110125604_add_import_error_to_project.rb | 5 ++ db/schema.rb | 5 +- features/steps/dashboard/new_project.rb | 1 - lib/gitlab/backend/shell.rb | 7 +- spec/services/projects/fork_service_spec.rb | 17 ++--- spec/workers/repository_fork_worker_spec.rb | 1 - 26 files changed, 176 insertions(+), 145 deletions(-) create mode 100644 app/views/projects/buttons/_download.html.haml create mode 100644 app/views/shared/_import_form.html.haml create mode 100644 db/migrate/20151110125604_add_import_error_to_project.rb diff --git a/GITLAB_SHELL_VERSION b/GITLAB_SHELL_VERSION index 338a5b5d8f..e261122d5c 100644 --- a/GITLAB_SHELL_VERSION +++ b/GITLAB_SHELL_VERSION @@ -1 +1 @@ -2.6.6 +2.6.7 diff --git a/app/assets/stylesheets/framework/common.scss b/app/assets/stylesheets/framework/common.scss index ddbacd7fd4..40f4beb196 100644 --- a/app/assets/stylesheets/framework/common.scss +++ b/app/assets/stylesheets/framework/common.scss @@ -328,6 +328,10 @@ table { } } +.well { + margin-bottom: 0; +} + .search_box { @extend .well; text-align: center; diff --git a/app/assets/stylesheets/framework/tw_bootstrap.scss b/app/assets/stylesheets/framework/tw_bootstrap.scss index 99d028d122..50c0cf61f4 100644 --- a/app/assets/stylesheets/framework/tw_bootstrap.scss +++ b/app/assets/stylesheets/framework/tw_bootstrap.scss @@ -172,7 +172,7 @@ } .panel-body { - form { + form, pre { margin: 0; } diff --git a/app/controllers/projects/imports_controller.rb b/app/controllers/projects/imports_controller.rb index 066b66014f..fb8788f081 100644 --- a/app/controllers/projects/imports_controller.rb +++ b/app/controllers/projects/imports_controller.rb @@ -28,8 +28,8 @@ class Projects::ImportsController < Projects::ApplicationController if @project.import_finished? redirect_to(project_path(@project)) and return else - redirect_to new_namespace_project_import_path(@project.namespace, - @project) && return + redirect_to(new_namespace_project_import_path(@project.namespace, + @project)) and return end end end diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 690ae2090d..c9cd4a0d54 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -253,14 +253,6 @@ module ProjectsHelper filename_path(project, :version) end - def hidden_pass_url(original_url) - result = URI(original_url) - result.password = '*****' unless result.password.nil? - result - rescue - original_url - end - def project_wiki_path_with_version(proj, page, version, is_newest) url_params = is_newest ? {} : { version_id: version } namespace_project_wiki_path(proj.namespace, proj, page, url_params) diff --git a/app/models/project.rb b/app/models/project.rb index a099a67cf6..70a648e68a 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -310,15 +310,17 @@ class Project < ActiveRecord::Base def add_import_job if forked? - unless RepositoryForkWorker.perform_async(id, forked_from_project.path_with_namespace, self.namespace.path) - import_fail - end + RepositoryForkWorker.perform_async(self.id, forked_from_project.path_with_namespace, self.namespace.path) else - RepositoryImportWorker.perform_async(id) + RepositoryImportWorker.perform_async(self.id) end end def clear_import_data + update(import_error: nil) + + ProjectCacheWorker.perform_async(self.id) + self.import_data.destroy if self.import_data end @@ -346,6 +348,14 @@ class Project < ActiveRecord::Base import_status == 'finished' end + def safe_import_url + result = URI.parse(self.import_url) + result.password = '*****' unless result.password.nil? + result.to_s + rescue + original_url + end + def check_limit unless creator.can_create_project? or namespace.kind == 'group' errors[:limit_reached] << ("Your project limit is #{creator.projects_limit} projects! Please contact your administrator to increase it") diff --git a/app/models/repository.rb b/app/models/repository.rb index f76b770e86..c183610346 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -6,7 +6,7 @@ class Repository include Gitlab::ShellAdapter - attr_accessor :raw_repository, :path_with_namespace, :project + attr_accessor :path_with_namespace, :project def self.clean_old_archives repository_downloads_path = Gitlab.config.gitlab.repository_downloads_path @@ -19,14 +19,18 @@ class Repository def initialize(path_with_namespace, default_branch = nil, project = nil) @path_with_namespace = path_with_namespace @project = project + end - if path_with_namespace - @raw_repository = Gitlab::Git::Repository.new(path_to_repo) - @raw_repository.autocrlf = :input + def raw_repository + return nil unless path_with_namespace + + @raw_repository ||= begin + repo = Gitlab::Git::Repository.new(path_to_repo) + repo.autocrlf = :input + repo + rescue Gitlab::Git::Repository::NoRepository + nil end - - rescue Gitlab::Git::Repository::NoRepository - nil end # Return absolute path to repository @@ -105,29 +109,25 @@ class Repository end def add_branch(branch_name, ref) - cache.expire(:branch_names) - @branches = nil + expire_branches_cache gitlab_shell.add_branch(path_with_namespace, branch_name, ref) end def add_tag(tag_name, ref, message = nil) - cache.expire(:tag_names) - @tags = nil + expire_tags_cache gitlab_shell.add_tag(path_with_namespace, tag_name, ref, message) end def rm_branch(branch_name) - cache.expire(:branch_names) - @branches = nil + expire_branches_cache gitlab_shell.rm_branch(path_with_namespace, branch_name) end def rm_tag(tag_name) - cache.expire(:tag_names) - @tags = nil + expire_tags_cache gitlab_shell.rm_tag(path_with_namespace, tag_name) end @@ -169,6 +169,16 @@ class Repository end end + def expire_tags_cache + cache.expire(:tag_names) + @tags = nil + end + + def expire_branches_cache + cache.expire(:branch_names) + @branches = nil + end + def expire_cache cache_keys.each do |key| cache.expire(key) @@ -484,7 +494,7 @@ class Repository root_ref_commit = commit(root_ref) if branch_commit - rugged.merge_base(root_ref_commit.id, branch_commit.id) == branch_commit.id + is_ancestor?(branch_commit.id, root_ref_commit.id) else nil end @@ -494,6 +504,11 @@ class Repository rugged.merge_base(first_commit_id, second_commit_id) end + def is_ancestor?(ancestor_id, descendant_id) + merge_base(ancestor_id, descendant_id) == ancestor_id + end + + def search_files(query, ref) offset = 2 args = %W(#{Gitlab.config.git.bin_path} grep -i -n --before-context #{offset} --after-context #{offset} -e #{query} #{ref || root_ref}) diff --git a/app/services/projects/create_service.rb b/app/services/projects/create_service.rb index 5b84527ecc..700a1db04d 100644 --- a/app/services/projects/create_service.rb +++ b/app/services/projects/create_service.rb @@ -55,7 +55,9 @@ module Projects @project.save if @project.persisted? && !@project.import? - raise 'Failed to create repository' unless @project.create_repository + unless @project.create_repository + raise 'Failed to create repository' + end end end @@ -94,9 +96,7 @@ module Projects @project.team << [current_user, :master, current_user] end - if @project.import? - @project.import_start - end + @project.import_start if @project.import? end end end diff --git a/app/views/projects/_home_panel.html.haml b/app/views/projects/_home_panel.html.haml index 8c0980369f..88d54bf6f2 100644 --- a/app/views/projects/_home_panel.html.haml +++ b/app/views/projects/_home_panel.html.haml @@ -18,17 +18,12 @@ .project-repo-buttons .split-one = render 'projects/buttons/star' + = render 'projects/buttons/fork' - - unless empty_repo - = render 'projects/buttons/fork' - = render "shared/clone_panel" - .split-repo-buttons - - unless empty_repo - - if can? current_user, :download_code, @project - = link_to archive_namespace_project_repository_path(@project.namespace, @project, ref: @ref, format: 'zip'), class: 'btn', rel: 'nofollow' do - = icon('download fw') - - = render 'projects/buttons/dropdown' - = render 'projects/buttons/notifications' + .split-repo-buttons + = render "projects/buttons/download" + = render 'projects/buttons/dropdown' + + = render 'projects/buttons/notifications' diff --git a/app/views/projects/buttons/_download.html.haml b/app/views/projects/buttons/_download.html.haml new file mode 100644 index 0000000000..14ee2263b7 --- /dev/null +++ b/app/views/projects/buttons/_download.html.haml @@ -0,0 +1,4 @@ +- unless @project.empty_repo? + - if can? current_user, :download_code, @project + = link_to archive_namespace_project_repository_path(@project.namespace, @project, ref: @ref, format: 'zip'), class: 'btn has_tooltip', rel: 'nofollow', title: "Download ZIP" do + = icon('download') diff --git a/app/views/projects/buttons/_dropdown.html.haml b/app/views/projects/buttons/_dropdown.html.haml index 18cae8ef6d..b277b765b6 100644 --- a/app/views/projects/buttons/_dropdown.html.haml +++ b/app/views/projects/buttons/_dropdown.html.haml @@ -32,5 +32,3 @@ = link_to new_namespace_project_tag_path(@project.namespace, @project) do = icon('tags fw') New tag - - diff --git a/app/views/projects/buttons/_fork.html.haml b/app/views/projects/buttons/_fork.html.haml index 8f2f631eb7..2d3abf0905 100644 --- a/app/views/projects/buttons/_fork.html.haml +++ b/app/views/projects/buttons/_fork.html.haml @@ -1,12 +1,13 @@ -- if current_user && can?(current_user, :fork_project, @project) - - if current_user.already_forked?(@project) && current_user.manageable_namespaces.size < 2 - = link_to namespace_project_path(current_user, current_user.fork_of(@project)), title: 'Go to your fork', class: 'btn' do - = icon('code-fork fw') - Fork - %span.count - = @project.forks_count - - else - = link_to new_namespace_project_fork_path(@project.namespace, @project), title: "Fork project", class: 'btn' do - = icon('code-fork fw') - %span.count - = @project.forks_count +- unless @project.empty_repo? + - if current_user && can?(current_user, :fork_project, @project) + - if current_user.already_forked?(@project) && current_user.manageable_namespaces.size < 2 + = link_to namespace_project_path(current_user, current_user.fork_of(@project)), title: 'Go to your fork', class: 'btn has_tooltip' do + = icon('code-fork fw') + Fork + %span.count + = @project.forks_count + - else + = link_to new_namespace_project_fork_path(@project.namespace, @project), title: "Fork project", class: 'btn has_tooltip' do + = icon('code-fork fw') + %span.count + = @project.forks_count diff --git a/app/views/projects/buttons/_star.html.haml b/app/views/projects/buttons/_star.html.haml index 0658390203..41a3ec6d90 100644 --- a/app/views/projects/buttons/_star.html.haml +++ b/app/views/projects/buttons/_star.html.haml @@ -1,5 +1,5 @@ - if current_user - = link_to toggle_star_namespace_project_path(@project.namespace, @project), class: 'btn star-btn toggle-star', method: :post, remote: true do + = link_to toggle_star_namespace_project_path(@project.namespace, @project), class: 'btn star-btn toggle-star has_tooltip', method: :post, remote: true, title: "Star project" do = icon('star fw') %span.count = @project.star_count diff --git a/app/views/projects/imports/new.html.haml b/app/views/projects/imports/new.html.haml index 92a87690c5..6027fb2336 100644 --- a/app/views/projects/imports/new.html.haml +++ b/app/views/projects/imports/new.html.haml @@ -1,22 +1,19 @@ - page_title "Import repository" %h3.page-title - - if @project.import_failed? - Import failed. Retry? - - else - Import repository + Import repository %hr +- if @project.import_failed? + .panel.panel-danger + .panel-heading The repository could not be imported. + .panel-body + %pre + :preserve + #{@project.import_error.try(:strip)} + = form_for @project, url: namespace_project_import_path(@project.namespace, @project), method: :post, html: { class: 'form-horizontal' } do |f| - .form-group.import-url-data - = f.label :import_url, class: 'control-label' do - %span Import existing git repo - .col-sm-10 - = f.text_field :import_url, class: 'form-control', placeholder: 'https://github.com/randx/six.git' - .well.prepend-top-20 - This URL must be publicly accessible or you can add a username and password like this: https://username:password@gitlab.com/company/project.git. - %br - The import will time out after 4 minutes. For big repositories, use a clone/push combination. - For SVN repositories, check #{link_to "this migrating from SVN doc.", "http://doc.gitlab.com/ce/workflow/importing/migrating_from_svn.html"} + = render "shared/import_form", f: f + .form-actions = f.submit 'Start import', class: "btn btn-create", tabindex: 4 diff --git a/app/views/projects/imports/show.html.haml b/app/views/projects/imports/show.html.haml index 06886d215a..c0d1ce0d12 100644 --- a/app/views/projects/imports/show.html.haml +++ b/app/views/projects/imports/show.html.haml @@ -8,7 +8,7 @@ - else Import in progress. - unless @project.forked? - %p.monospace git clone --bare #{hidden_pass_url(@project.import_url)} + %p.monospace git clone --bare #{@project.safe_import_url} %p Please wait while we import the repository for you. Refresh at will. :javascript new ProjectImport(); diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml index a02c12f06a..c9d1fc3da2 100644 --- a/app/views/projects/new.html.haml +++ b/app/views/projects/new.html.haml @@ -23,7 +23,6 @@ = f.select :namespace_id, namespaces_options(params[:namespace_id] || :current_user), {}, {class: 'select2', tabindex: 2} - if import_sources_enabled? - .project-import.js-toggle-container .form-group %label.control-label Import project from @@ -82,19 +81,7 @@ %span Any repo by URL .js-toggle-content.hide - .form-group.import-url-data - = f.label :import_url, class: 'control-label' do - %span Git repository URL - .col-sm-10 - = f.text_field :import_url, class: 'form-control', placeholder: 'https://username:password@gitlab.company.com/group/project.git' - .well.prepend-top-20 - %ul - %li - The repository must be accessible over HTTP(S). If it is not publicly accessible, you can add authentication information to the URL: https://username:password@gitlab.company.com/group/project.git. - %li - The import will time out after 4 minutes. For big repositories, use a clone/push combination. - %li - To migrate an SVN repository, check out #{link_to "this document", "http://doc.gitlab.com/ce/workflow/importing/migrating_from_svn.html"}. + = render "shared/import_form", f: f .prepend-botton-10 diff --git a/app/views/shared/_clone_panel.html.haml b/app/views/shared/_clone_panel.html.haml index 2e4aab3630..8bcb24ae9d 100644 --- a/app/views/shared/_clone_panel.html.haml +++ b/app/views/shared/_clone_panel.html.haml @@ -21,7 +21,6 @@ = gitlab_config.protocol.upcase = text_field_tag :project_clone, default_url_to_repo(project), class: "js-select-on-focus form-control", readonly: true - if project.kind_of?(Project) - .input-group-addon - .visibility-level-label.has_tooltip{'data-title' => "#{visibility_level_label(project.visibility_level)} project" } + .input-group-addon.has_tooltip{title: "#{visibility_level_label(project.visibility_level)} project", data: { container: "body" } } + .visibility-level-label = visibility_level_icon(project.visibility_level) - diff --git a/app/views/shared/_import_form.html.haml b/app/views/shared/_import_form.html.haml new file mode 100644 index 0000000000..285af56ad7 --- /dev/null +++ b/app/views/shared/_import_form.html.haml @@ -0,0 +1,16 @@ +.form-group.import-url-data + = f.label :import_url, class: 'control-label' do + %span Git repository URL + .col-sm-10 + = f.text_field :import_url, class: 'form-control', placeholder: 'https://username:password@gitlab.company.com/group/project.git' + + .well.prepend-top-20 + %ul + %li + The repository must be accessible over http://, https:// or git://. + %li + If your HTTP repository is not publicly accessible, add authentication information to the URL: https://username:password@gitlab.company.com/group/project.git. + %li + The import will time out after 4 minutes. For big repositories, use a clone/push combination. + %li + To migrate an SVN repository, check out #{link_to "this document", "http://doc.gitlab.com/ce/workflow/importing/migrating_from_svn.html"}. diff --git a/app/workers/repository_fork_worker.rb b/app/workers/repository_fork_worker.rb index acd1c43f06..2f991c5233 100644 --- a/app/workers/repository_fork_worker.rb +++ b/app/workers/repository_fork_worker.rb @@ -13,22 +13,20 @@ class RepositoryForkWorker end result = gitlab_shell.fork_repository(source_path, target_path) - unless result logger.error("Unable to fork project #{project_id} for repository #{source_path} -> #{target_path}") + project.update(import_error: "The project could not be forked.") project.import_fail - project.save return end - if project.valid_repo? - ProjectCacheWorker.perform_async(project.id) - project.import_finish - else - project.import_fail + unless project.valid_repo? logger.error("Project #{id} had an invalid repository after fork") + project.update(import_error: "The forked repository is invalid.") + project.import_fail + return end - project.save + project.import_finish end end diff --git a/app/workers/repository_import_worker.rb b/app/workers/repository_import_worker.rb index ea2808045e..1de4916199 100644 --- a/app/workers/repository_import_worker.rb +++ b/app/workers/repository_import_worker.rb @@ -7,37 +7,52 @@ class RepositoryImportWorker def perform(project_id) project = Project.find(project_id) - unless project.import_url == Project::UNKNOWN_IMPORT_URL - import_result = gitlab_shell.send(:import_repository, - project.path_with_namespace, - project.import_url) - return project.import_fail unless import_result - else + if project.import_url == Project::UNKNOWN_IMPORT_URL + # In this case, we only want to import issues, not a repository. unless project.create_repository - return project.import_fail + project.update(import_error: "The repository could not be created.") + project.import_fail + return + end + else + begin + gitlab_shell.import_repository(project.path_with_namespace, project.import_url) + rescue Gitlab::Shell::Error => e + project.update(import_error: e.message) + project.import_fail + return end end - data_import_result = case project.import_type - when 'github' - Gitlab::GithubImport::Importer.new(project).execute - when 'gitlab' - Gitlab::GitlabImport::Importer.new(project).execute - when 'bitbucket' - Gitlab::BitbucketImport::Importer.new(project).execute - when 'google_code' - Gitlab::GoogleCodeImport::Importer.new(project).execute - when 'fogbugz' - Gitlab::FogbugzImport::Importer.new(project).execute - else - true - end - return project.import_fail unless data_import_result + data_import_result = + case project.import_type + when 'github' + Gitlab::GithubImport::Importer.new(project).execute + when 'gitlab' + Gitlab::GitlabImport::Importer.new(project).execute + when 'bitbucket' + Gitlab::BitbucketImport::Importer.new(project).execute + when 'google_code' + Gitlab::GoogleCodeImport::Importer.new(project).execute + when 'fogbugz' + Gitlab::FogbugzImport::Importer.new(project).execute + else + true + end - Gitlab::BitbucketImport::KeyDeleter.new(project).execute if project.import_type == 'bitbucket' + unless data_import_result + project.update(import_error: "The remote issue data could not be imported.") + project.import_fail + return + end + + if project.import_type == 'bitbucket' + Gitlab::BitbucketImport::KeyDeleter.new(project).execute + end project.import_finish - project.save - ProjectCacheWorker.perform_async(project.id) + + # Explicitly update mirror so that upstream remote is created and fetched + project.update_mirror end end diff --git a/db/migrate/20151110125604_add_import_error_to_project.rb b/db/migrate/20151110125604_add_import_error_to_project.rb new file mode 100644 index 0000000000..7fc990f8d0 --- /dev/null +++ b/db/migrate/20151110125604_add_import_error_to_project.rb @@ -0,0 +1,5 @@ +class AddImportErrorToProject < ActiveRecord::Migration + def change + add_column :projects, :import_error, :text + end +end diff --git a/db/schema.rb b/db/schema.rb index aa76cef9fe..440a33e200 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -640,7 +640,10 @@ ActiveRecord::Schema.define(version: 20151116144118) do t.integer "star_count", default: 0, null: false t.string "import_type" t.string "import_source" - t.integer "commit_count", default: 0 + t.integer "commit_count", default: 0 + t.boolean "merge_requests_ff_only_enabled", default: false + t.text "issues_template" + t.text "import_error" end add_index "projects", ["created_at", "id"], name: "index_projects_on_created_at_and_id", using: :btree diff --git a/features/steps/dashboard/new_project.rb b/features/steps/dashboard/new_project.rb index 44a4aa9844..a0aad66184 100644 --- a/features/steps/dashboard/new_project.rb +++ b/features/steps/dashboard/new_project.rb @@ -44,7 +44,6 @@ class Spinach::Features::NewProject < Spinach::FeatureSteps git_import_instructions = first('.js-toggle-content') expect(git_import_instructions).to be_visible expect(git_import_instructions).to have_content "Git repository URL" - expect(git_import_instructions).to have_content "The repository must be accessible over HTTP(S). If it is not publicly accessible, you can add authentication information to the URL:" end step 'I click on "Google Code"' do diff --git a/lib/gitlab/backend/shell.rb b/lib/gitlab/backend/shell.rb index 01b8bda05c..87ac30b5ff 100644 --- a/lib/gitlab/backend/shell.rb +++ b/lib/gitlab/backend/shell.rb @@ -1,6 +1,6 @@ module Gitlab class Shell - class AccessDenied < StandardError; end + class Error < StandardError; end class KeyAdder < Struct.new(:io) def add_key(id, key) @@ -36,8 +36,9 @@ module Gitlab # import_repository("gitlab/gitlab-ci", "https://github.com/randx/six.git") # def import_repository(name, url) - Gitlab::Utils.system_silent([gitlab_shell_projects_path, 'import-project', - "#{name}.git", url, '240']) + output, status = Popen::popen([gitlab_shell_projects_path, 'import-project', "#{name}.git", url, '240']) + raise Error, output unless status.zero? + true end # Move repository diff --git a/spec/services/projects/fork_service_spec.rb b/spec/services/projects/fork_service_spec.rb index e397b2b9b4..1feba6ce04 100644 --- a/spec/services/projects/fork_service_spec.rb +++ b/spec/services/projects/fork_service_spec.rb @@ -25,13 +25,6 @@ describe Projects::ForkService do end end - context 'fork project failure' do - it "fails due to transaction failure" do - @to_project = fork_project(@from_project, @to_user, false) - expect(@to_project.import_failed?) - end - end - context 'project already exists' do it "should fail due to validation, not transaction failure" do @existing_project = create(:project, creator_id: @to_user.id, name: @from_project.name, namespace: @to_namespace) @@ -66,7 +59,7 @@ describe Projects::ForkService do context 'fork project for group' do it 'group owner successfully forks project into the group' do - to_project = fork_project(@project, @group_owner, true, @opts) + to_project = fork_project(@project, @group_owner, @opts) expect(to_project.owner).to eq(@group) expect(to_project.namespace).to eq(@group) expect(to_project.name).to eq(@project.name) @@ -78,7 +71,7 @@ describe Projects::ForkService do context 'fork project for group when user not owner' do it 'group developer should fail to fork project into the group' do - to_project = fork_project(@project, @developer, true, @opts) + to_project = fork_project(@project, @developer, @opts) expect(to_project.errors[:namespace]).to eq(['is not valid']) end end @@ -87,7 +80,7 @@ describe Projects::ForkService do it 'should fail due to validation, not transaction failure' do existing_project = create(:project, name: @project.name, namespace: @group) - to_project = fork_project(@project, @group_owner, true, @opts) + to_project = fork_project(@project, @group_owner, @opts) expect(existing_project.persisted?).to be_truthy expect(to_project.errors[:name]).to eq(['has already been taken']) expect(to_project.errors[:path]).to eq(['has already been taken']) @@ -95,8 +88,8 @@ describe Projects::ForkService do end end - def fork_project(from_project, user, fork_success = true, params = {}) - allow(RepositoryForkWorker).to receive(:perform_async).and_return(fork_success) + def fork_project(from_project, user, params = {}) + allow(RepositoryForkWorker).to receive(:perform_async).and_return(true) Projects::ForkService.new(from_project, user, params).execute end end diff --git a/spec/workers/repository_fork_worker_spec.rb b/spec/workers/repository_fork_worker_spec.rb index aa03110696..245f066df1 100644 --- a/spec/workers/repository_fork_worker_spec.rb +++ b/spec/workers/repository_fork_worker_spec.rb @@ -12,7 +12,6 @@ describe RepositoryForkWorker do project.path_with_namespace, fork_project.namespace.path). and_return(true) - expect(ProjectCacheWorker).to receive(:perform_async) subject.perform(project.id, project.path_with_namespace, From 834e440f701daa9bb945fe42fe2504c4256aef67 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Wed, 18 Nov 2015 19:06:36 +0000 Subject: [PATCH 35/80] Merge branch 'mirror-repository' into 'master' Add option to mirror an upstream repository. Closes internal https://dev.gitlab.org/gitlab/gitlab-ee/issues/279 Depends on gitlab-org/gitlab-shell!29 To do: - [x] Decide on what user should be the author of the activity feed events. The initial project creator perhaps? That makes sense for personal projects, but less so for group projects, where it's even possible that the creator has since left the team. - [x] Write specs! - [x] Write documentation - [x] Port back relevant commits to CE: gitlab-org/gitlab-ce!1822 ---- ## Mirror status on project homepage ![Screen_Shot_2015-11-12_at_12.48.15](/uploads/39666b0e4a14723407b0f66e2aaddb46/Screen_Shot_2015-11-12_at_12.48.15.png) ## Settings navigation item ![Screen_Shot_2015-11-10_at_17.32.27](/uploads/116ece85f65681bbd3c7c5e282ab3b3c/Screen_Shot_2015-11-10_at_17.32.27.png) ## Mirroring settings ![Screen_Shot_2015-11-17_at_11.17.17](/uploads/ff57c89831524435ec6a063c3c470203/Screen_Shot_2015-11-17_at_11.17.17.png) ## Activity feed with new "pushes" (mirror updates) ![activity_feed](/uploads/04754251f2142fd06b1fddc2aae45232/activity_feed.png) I have yet to decide on what user should be the author of these events. The initial project creator perhaps? That makes sense for personal projects, but less so for group projects, where it's even possible that the creator has since left the team. ## Warning that branch has diverged from upstream ![diverged](/uploads/ecf7ae6c5709f626c750695f45ca521a/diverged.png) ## Commits heading after failed update ![commits_failure](/uploads/d1b3e1f6796431c839ee9e2f67499283/commits_failure.png) Link send user to the mirroring settings if they are a project admin. ## Mirroring settings after failed update ![Screen_Shot_2015-11-12_at_12.43.09](/uploads/ece68d5021c9a4c374bf6d973cf9fafa/Screen_Shot_2015-11-12_at_12.43.09.png) ## New project page ![new_project](/uploads/296beb6c7faf390a9b7e1facc9c1d4d6/new_project.png) ## Import form after failed import (Screenshot outdated) ![new_import_failure](/uploads/ac0ebfc8ec23232603126fe0a6e10171/new_import_failure.png) Shown when the initial import of a project fails, not when an update of an existing project fails. cc @dzaporozhets @sytses @JobV See merge request !51 --- CHANGELOG-EE | 5 +- app/assets/javascripts/dispatcher.js.coffee | 2 + app/assets/javascripts/users_select.js.coffee | 2 + app/assets/stylesheets/framework/common.scss | 4 + .../stylesheets/framework/tw_bootstrap.scss | 2 +- app/assets/stylesheets/pages/projects.scss | 14 ++- app/controllers/autocomplete_controller.rb | 6 +- .../projects/imports_controller.rb | 12 ++- .../projects/mirrors_controller.rb | 43 ++++++++ app/controllers/projects_controller.rb | 5 +- app/helpers/projects_helper.rb | 8 -- app/helpers/selects_helper.rb | 4 +- app/models/project.rb | 94 +++++++++++++++- app/models/repository.rb | 91 +++++++++++++--- app/services/projects/create_service.rb | 8 +- .../projects/update_mirror_service.rb | 75 +++++++++++++ .../layouts/nav/_project_settings.html.haml | 5 + app/views/projects/_home_panel.html.haml | 24 +++-- app/views/projects/branches/_branch.html.haml | 28 +++-- app/views/projects/branches/index.html.haml | 5 +- .../projects/buttons/_download.html.haml | 4 + .../projects/buttons/_dropdown.html.haml | 2 - app/views/projects/buttons/_fork.html.haml | 25 ++--- app/views/projects/buttons/_star.html.haml | 2 +- .../projects/buttons/_update_mirror.html.haml | 8 ++ .../projects/commits/_mirror_status.html.haml | 10 ++ app/views/projects/commits/show.html.haml | 2 + app/views/projects/imports/new.html.haml | 25 ++--- app/views/projects/imports/show.html.haml | 2 +- app/views/projects/mirrors/show.html.haml | 70 ++++++++++++ app/views/projects/new.html.haml | 15 +-- app/views/projects/tags/index.html.haml | 4 +- app/views/shared/_clone_panel.html.haml | 5 +- app/views/shared/_import_form.html.haml | 28 +++++ app/views/shared/_mirror_status.html.haml | 14 +++ .../shared/_mirror_update_button.html.haml | 9 ++ app/workers/repository_fork_worker.rb | 14 ++- app/workers/repository_import_worker.rb | 65 ++++++----- .../repository_update_mirror_worker.rb | 22 ++++ app/workers/update_all_mirrors_worker.rb | 10 ++ config/routes.rb | 5 + .../20151110125416_add_mirror_to_project.rb | 8 ++ ...51110125604_add_import_error_to_project.rb | 5 + db/schema.rb | 39 ++++--- doc/workflow/README.md | 1 + doc/workflow/repository_mirroring.md | 18 ++++ .../repository_mirroring/diverged_branch.png | Bin 0 -> 252687 bytes .../repository_mirroring/project_page.png | Bin 0 -> 138638 bytes .../repository_mirroring/settings.png | Bin 0 -> 290053 bytes features/steps/dashboard/new_project.rb | 1 - lib/gitlab/backend/shell.rb | 21 +++- spec/services/projects/fork_service_spec.rb | 17 +-- .../projects/update_mirror_service_spec.rb | 102 ++++++++++++++++++ spec/workers/repository_fork_worker_spec.rb | 1 - 54 files changed, 807 insertions(+), 184 deletions(-) create mode 100644 app/controllers/projects/mirrors_controller.rb create mode 100644 app/services/projects/update_mirror_service.rb create mode 100644 app/views/projects/buttons/_download.html.haml create mode 100644 app/views/projects/buttons/_update_mirror.html.haml create mode 100644 app/views/projects/commits/_mirror_status.html.haml create mode 100644 app/views/projects/mirrors/show.html.haml create mode 100644 app/views/shared/_import_form.html.haml create mode 100644 app/views/shared/_mirror_status.html.haml create mode 100644 app/views/shared/_mirror_update_button.html.haml create mode 100644 app/workers/repository_update_mirror_worker.rb create mode 100644 app/workers/update_all_mirrors_worker.rb create mode 100644 db/migrate/20151110125416_add_mirror_to_project.rb create mode 100644 db/migrate/20151110125604_add_import_error_to_project.rb create mode 100644 doc/workflow/repository_mirroring.md create mode 100644 doc/workflow/repository_mirroring/diverged_branch.png create mode 100644 doc/workflow/repository_mirroring/project_page.png create mode 100644 doc/workflow/repository_mirroring/settings.png create mode 100644 spec/services/projects/update_mirror_service_spec.rb diff --git a/CHANGELOG-EE b/CHANGELOG-EE index 57ff9af6ab..817e39099e 100644 --- a/CHANGELOG-EE +++ b/CHANGELOG-EE @@ -6,11 +6,14 @@ v 8.2.0 - Fix "Rebase onto master" - Ensure a comment is properly recorded in JIRA when a merge request is accepted - Allow groups to appear in the `Share with group` share if the group owner allows it + - Add option to mirror an upstream repository. v 8.1.0 (unreleased) - added an issues template (Hannes Rosenögger) v 8.1.0 + - Add documentation for "Share project with group" API call + - Added an issues template (Hannes Rosenögger) - Add documentation for "Share project with group" API call - Abiliy to disable 'Share with Group' feature (via UI and API) @@ -39,7 +42,7 @@ v 7.14.0 - Fix importing projects from GitHub Enterprise Edition. - Automatic approver suggestions (based on an authority of the code) - Add support for Jenkins unstable status - - Automatic approver suggestions (based on an authority of the code) + - Automatic approver suggestions (based on an authority of the code) - Support Kerberos ticket-based authentication for Git HTTP access v 7.13.3 diff --git a/app/assets/javascripts/dispatcher.js.coffee b/app/assets/javascripts/dispatcher.js.coffee index 45688c4f80..f5d29321f2 100644 --- a/app/assets/javascripts/dispatcher.js.coffee +++ b/app/assets/javascripts/dispatcher.js.coffee @@ -102,6 +102,8 @@ class Dispatcher new Activities() when 'projects:group_links:index' new GroupsSelect() + when 'projects:mirrors:show', 'projects:mirrors:update' + new UsersSelect() when 'admin:emails:show' new AdminEmailSelect() diff --git a/app/assets/javascripts/users_select.js.coffee b/app/assets/javascripts/users_select.js.coffee index bccdb2091f..f81c198665 100644 --- a/app/assets/javascripts/users_select.js.coffee +++ b/app/assets/javascripts/users_select.js.coffee @@ -8,6 +8,7 @@ class @UsersSelect @projectId = $(select).data('project-id') @groupId = $(select).data('group-id') @showCurrentUser = $(select).data('current-user') + @pushCodeToProtectedBranches = $(select).data('push-code-to-protected-branches') showNullUser = $(select).data('null-user') showAnyUser = $(select).data('any-user') showEmailUser = $(select).data('email-user') @@ -112,6 +113,7 @@ class @UsersSelect group_id: @groupId skip_ldap: @skipLdap current_user: @showCurrentUser + push_code_to_protected_branches: @pushCodeToProtectedBranches dataType: "json" ).done (users) -> callback(users) diff --git a/app/assets/stylesheets/framework/common.scss b/app/assets/stylesheets/framework/common.scss index c1ada58628..4afd27fff3 100644 --- a/app/assets/stylesheets/framework/common.scss +++ b/app/assets/stylesheets/framework/common.scss @@ -337,6 +337,10 @@ table { } } +.well { + margin-bottom: 0; +} + .search_box { @extend .well; text-align: center; diff --git a/app/assets/stylesheets/framework/tw_bootstrap.scss b/app/assets/stylesheets/framework/tw_bootstrap.scss index 99d028d122..50c0cf61f4 100644 --- a/app/assets/stylesheets/framework/tw_bootstrap.scss +++ b/app/assets/stylesheets/framework/tw_bootstrap.scss @@ -172,7 +172,7 @@ } .panel-body { - form { + form, pre { margin: 0; } diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss index d3b1004002..7596c078d4 100644 --- a/app/assets/stylesheets/pages/projects.scss +++ b/app/assets/stylesheets/pages/projects.scss @@ -106,13 +106,13 @@ .project-repo-buttons { margin-top: 12px; margin-bottom: 0px; + } - .btn { - @include btn-gray; + .btn { + @include btn-gray; - .count { - display: inline-block; - } + .count { + display: inline-block; } } } @@ -205,6 +205,10 @@ .dropdown-toggle { margin: -5px; } + + .update-mirror-button { + margin-right: -1px; + } } #notification-form { diff --git a/app/controllers/autocomplete_controller.rb b/app/controllers/autocomplete_controller.rb index 90efc37415..48e6451ba6 100644 --- a/app/controllers/autocomplete_controller.rb +++ b/app/controllers/autocomplete_controller.rb @@ -34,7 +34,11 @@ class AutocompleteController < ApplicationController @users = @users.search(params[:search]) if params[:search].present? @users = @users.active @users = @users.reorder(:name) - @users = @users.page(params[:page]).per(PER_PAGE) + if params[:push_code_to_protected_branches] && project + @users = @users.to_a.select { |user| user.can?(:push_code_to_protected_branches, project) }.take(PER_PAGE) + else + @users = @users.page(params[:page]).per(PER_PAGE) + end unless params[:search].present? # Include current user if available to filter by "Me" diff --git a/app/controllers/projects/imports_controller.rb b/app/controllers/projects/imports_controller.rb index 066b66014f..3dcc0d654c 100644 --- a/app/controllers/projects/imports_controller.rb +++ b/app/controllers/projects/imports_controller.rb @@ -8,9 +8,7 @@ class Projects::ImportsController < Projects::ApplicationController end def create - @project.import_url = params[:project][:import_url] - - if @project.save + if @project.update_attributes(import_params) @project.reload if @project.import_failed? @@ -28,8 +26,8 @@ class Projects::ImportsController < Projects::ApplicationController if @project.import_finished? redirect_to(project_path(@project)) and return else - redirect_to new_namespace_project_import_path(@project.namespace, - @project) && return + redirect_to(new_namespace_project_import_path(@project.namespace, + @project)) and return end end end @@ -48,4 +46,8 @@ class Projects::ImportsController < Projects::ApplicationController return end end + + def import_params + params.require(:project).permit(:import_url, :mirror, :mirror_user_id) + end end diff --git a/app/controllers/projects/mirrors_controller.rb b/app/controllers/projects/mirrors_controller.rb new file mode 100644 index 0000000000..fdb34bccec --- /dev/null +++ b/app/controllers/projects/mirrors_controller.rb @@ -0,0 +1,43 @@ +class Projects::MirrorsController < Projects::ApplicationController + # Authorize + before_action :require_non_empty_project + before_action :authorize_admin_project!, except: [:update_now] + before_action :authorize_push_code!, only: [:update_now] + + layout "project_settings" + + def show + + end + + def update + if @project.update_attributes(mirror_params) + if @project.mirror? + @project.update_mirror + + flash[:notice] = "Mirroring settings were successfully updated. The project is being updated." + elsif @project.mirror_changed? + flash[:notice] = "Mirroring was successfully disabled." + else + flash[:notice] = "Mirroring settings were successfully updated." + end + + redirect_to namespace_project_mirror_path(@project.namespace, @project) + else + render :show + end + end + + def update_now + @project.update_mirror + + flash[:notice] = "The repository is being updated..." + redirect_back_or_default(default: namespace_project_path(@project.namespace, @project)) + end + + private + + def mirror_params + params.require(:project).permit(:mirror, :import_url, :mirror_user_id) + end +end diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 947616af3e..d667c8cef8 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -88,7 +88,8 @@ class ProjectsController < ApplicationController end def show - if @project.import_in_progress? + # If we're importing while we do have a repository, we're simply updating the mirror. + if @project.import_in_progress? && !@project.updating_mirror? redirect_to namespace_project_import_path(@project.namespace, @project) return end @@ -235,6 +236,8 @@ class ProjectsController < ApplicationController :merge_requests_ff_only_enabled, :merge_requests_rebase_enabled, :merge_requests_template, + :mirror, + :mirror_user_id, :reset_approvals_on_push ) end diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 00795594ad..c66d8dee0c 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -253,14 +253,6 @@ module ProjectsHelper filename_path(project, :version) end - def hidden_pass_url(original_url) - result = URI(original_url) - result.password = '*****' unless result.password.nil? - result - rescue - original_url - end - def project_wiki_path_with_version(proj, page, version, is_newest) url_params = is_newest ? {} : { version_id: version } namespace_project_wiki_path(proj.namespace, proj, page, url_params) diff --git a/app/helpers/selects_helper.rb b/app/helpers/selects_helper.rb index c2ec6426c8..f99b97f060 100644 --- a/app/helpers/selects_helper.rb +++ b/app/helpers/selects_helper.rb @@ -13,6 +13,7 @@ module SelectsHelper first_user = opts[:first_user] && current_user ? current_user.username : false current_user = opts[:current_user] || false project = opts[:project] || @project + push_code_to_protected_branches = opts[:push_code_to_protected_branches] html = { class: css_class, @@ -21,7 +22,8 @@ module SelectsHelper 'data-any-user' => any_user, 'data-email-user' => email_user, 'data-first-user' => first_user, - 'data-current-user' => current_user + 'data-current-user' => current_user, + 'data-push-code-to-protected-branches' => push_code_to_protected_branches } unless opts[:scope] == :all diff --git a/app/models/project.rb b/app/models/project.rb index 0c0991c426..47d5ece506 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -76,6 +76,8 @@ class Project < ActiveRecord::Base has_one :git_hook, dependent: :destroy has_one :last_event, -> {order 'events.created_at DESC'}, class_name: 'Event', foreign_key: 'project_id' + belongs_to :mirror_user, foreign_key: 'mirror_user_id', class_name: 'User' + # Project services has_many :services has_one :gitlab_ci_service, dependent: :destroy @@ -161,6 +163,8 @@ class Project < ActiveRecord::Base validates :import_url, format: { with: /\A#{URI.regexp(%w(ssh git http https))}\z/, message: 'should be a valid url' }, if: :external_import? + validates :import_url, presence: true, if: :mirror? + validates :mirror_user, presence: true, if: :mirror? validates :star_count, numericality: { greater_than_or_equal_to: 0 } validate :check_limit, on: :create validate :avatar_type, @@ -185,6 +189,7 @@ class Project < ActiveRecord::Base scope :public_only, -> { where(visibility_level: Project::PUBLIC) } scope :public_and_internal_only, -> { where(visibility_level: Project.public_and_internal_levels) } scope :non_archived, -> { where(archived: false) } + scope :mirror, -> { where(mirror: true) } state_machine :import_status, initial: :none do event :import_start do @@ -209,6 +214,21 @@ class Project < ActiveRecord::Base after_transition any => :started, do: :schedule_add_import_job after_transition any => :finished, do: :clear_import_data + + after_transition started: :finished do |project, transaction| + if project.mirror? + timestamp = DateTime.now + project.mirror_last_update_at = timestamp + project.mirror_last_successful_update_at = timestamp + project.save + end + end + + after_transition started: :failed do |project, transaction| + if project.mirror? + project.update(mirror_last_update_at: DateTime.now) + end + end end class << self @@ -316,16 +336,26 @@ class Project < ActiveRecord::Base end def add_import_job - if forked? - unless RepositoryForkWorker.perform_async(id, forked_from_project.path_with_namespace, self.namespace.path) - import_fail + if repository_exists? + if mirror? + RepositoryUpdateMirrorWorker.perform_async(self.id) end + + return + end + + if forked? + RepositoryForkWorker.perform_async(self.id, forked_from_project.path_with_namespace, self.namespace.path) else - RepositoryImportWorker.perform_async(id) + RepositoryImportWorker.perform_async(self.id) end end def clear_import_data + update(import_error: nil) + + ProjectCacheWorker.perform_async(self.id) + self.import_data.destroy if self.import_data end @@ -353,6 +383,62 @@ class Project < ActiveRecord::Base import_status == 'finished' end + def safe_import_url + result = URI.parse(self.import_url) + result.password = '*****' unless result.password.nil? + result.to_s + rescue + original_url + end + + def mirror_updated? + mirror? && self.mirror_last_update_at + end + + def updating_mirror? + mirror? && import_in_progress? && !empty_repo? + end + + def mirror_last_update_status + return unless mirror_updated? + + if self.mirror_last_update_at == self.mirror_last_successful_update_at + :success + else + :failed + end + end + + def mirror_last_update_success? + mirror_last_update_status == :success + end + + def mirror_last_update_failed? + mirror_last_update_status == :failed + end + + def mirror_ever_updated_successfully? + mirror_updated? && self.mirror_last_successful_update_at + end + + def update_mirror + return unless mirror? + + return if import_in_progress? + + if import_failed? + import_retry + else + import_start + end + end + + def fetch_mirror + return unless mirror? + + repository.fetch_upstream(self.import_url) + end + def check_limit unless creator.can_create_project? or namespace.kind == 'group' errors[:limit_reached] << ("Your project limit is #{creator.projects_limit} projects! Please contact your administrator to increase it") diff --git a/app/models/repository.rb b/app/models/repository.rb index 54e4ed5552..9017628022 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -4,9 +4,11 @@ class Repository class PreReceiveError < StandardError; end class CommitError < StandardError; end + MIRROR_REMOTE = "upstream" + include Gitlab::ShellAdapter - attr_accessor :raw_repository, :path_with_namespace, :project + attr_accessor :path_with_namespace, :project def self.clean_old_archives repository_downloads_path = Gitlab.config.gitlab.repository_downloads_path @@ -19,14 +21,18 @@ class Repository def initialize(path_with_namespace, default_branch = nil, project = nil) @path_with_namespace = path_with_namespace @project = project + end - if path_with_namespace - @raw_repository = Gitlab::Git::Repository.new(path_to_repo) - @raw_repository.autocrlf = :input + def raw_repository + return nil unless path_with_namespace + + @raw_repository ||= begin + repo = Gitlab::Git::Repository.new(path_to_repo) + repo.autocrlf = :input + repo + rescue Gitlab::Git::Repository::NoRepository + nil end - - rescue Gitlab::Git::Repository::NoRepository - nil end # Return absolute path to repository @@ -105,37 +111,47 @@ class Repository end def add_branch(branch_name, ref) - cache.expire(:branch_names) - @branches = nil + expire_branches_cache gitlab_shell.add_branch(path_with_namespace, branch_name, ref) end def add_tag(tag_name, ref, message = nil) - cache.expire(:tag_names) - @tags = nil + expire_tags_cache gitlab_shell.add_tag(path_with_namespace, tag_name, ref, message) end def rm_branch(branch_name) - cache.expire(:branch_names) - @branches = nil + expire_branches_cache gitlab_shell.rm_branch(path_with_namespace, branch_name) end def rm_tag(tag_name) - cache.expire(:tag_names) - @tags = nil + expire_tags_cache gitlab_shell.rm_tag(path_with_namespace, tag_name) end + def add_remote(name, url) + raw_repository.remote_add(name, url) + rescue Rugged::ConfigError + raw_repository.remote_update(name, url: url) + end + + def fetch_remote(remote) + gitlab_shell.fetch_remote(path_with_namespace, remote) + end + def branch_names cache.fetch(:branch_names) { raw_repository.branch_names } end + def branch_exists?(name) + branch_names.include?(name) + end + def tag_names cache.fetch(:tag_names) { raw_repository.tag_names } end @@ -169,6 +185,16 @@ class Repository end end + def expire_tags_cache + cache.expire(:tag_names) + @tags = nil + end + + def expire_branches_cache + cache.expire(:branch_names) + @branches = nil + end + def expire_cache cache_keys.each do |key| cache.expire(key) @@ -496,16 +522,49 @@ class Repository root_ref_commit = commit(root_ref) if branch_commit - rugged.merge_base(root_ref_commit.id, branch_commit.id) == branch_commit.id + is_ancestor?(branch_commit.id, root_ref_commit.id) else nil end end + def fetch_upstream(url) + add_remote(Repository::MIRROR_REMOTE, url) + fetch_remote(Repository::MIRROR_REMOTE) + end + + def upstream_branches + rugged.references.each("refs/remotes/#{Repository::MIRROR_REMOTE}/*").map do |ref| + name = ref.name.sub(/\Arefs\/remotes\/#{Repository::MIRROR_REMOTE}\//, "") + + begin + Gitlab::Git::Branch.new(name, ref.target) + rescue Rugged::ReferenceError + # Omit invalid branch + end + end.compact + end + + def diverged_from_upstream?(branch_name) + branch_commit = commit(branch_name) + upstream_commit = commit("refs/remotes/#{MIRROR_REMOTE}/#{branch_name}") + + if upstream_commit + !is_ancestor?(branch_commit.id, upstream_commit.id) + else + false + end + end + def merge_base(first_commit_id, second_commit_id) rugged.merge_base(first_commit_id, second_commit_id) end + def is_ancestor?(ancestor_id, descendant_id) + merge_base(ancestor_id, descendant_id) == ancestor_id + end + + def search_files(query, ref) offset = 2 args = %W(#{Gitlab.config.git.bin_path} grep -i -n --before-context #{offset} --after-context #{offset} -e #{query} #{ref || root_ref}) diff --git a/app/services/projects/create_service.rb b/app/services/projects/create_service.rb index cef76a51cb..fddd2a50b6 100644 --- a/app/services/projects/create_service.rb +++ b/app/services/projects/create_service.rb @@ -55,7 +55,9 @@ module Projects @project.save if @project.persisted? && !@project.import? - raise 'Failed to create repository' unless @project.create_repository + unless @project.create_repository + raise 'Failed to create repository' + end end end @@ -94,9 +96,7 @@ module Projects @project.team << [current_user, :master, current_user] end - if @project.import? - @project.import_start - end + @project.import_start if @project.import? predefined_git_hook = GitHook.find_by(is_sample: true) diff --git a/app/services/projects/update_mirror_service.rb b/app/services/projects/update_mirror_service.rb new file mode 100644 index 0000000000..1f3d3fd424 --- /dev/null +++ b/app/services/projects/update_mirror_service.rb @@ -0,0 +1,75 @@ +module Projects + class UpdateMirrorService < BaseService + class Error < StandardError; end + class UpdateError < Error; end + + def execute + return false unless project.mirror? + + unless current_user.can?(:push_code_to_protected_branches, project) + return error("The mirror user is not allowed to push code to all branches on this project.") + end + + update_tags do + project.fetch_mirror + end + + update_branches + + success + rescue Gitlab::Shell::Error, UpdateError => e + error(e.message) + end + + private + + def update_branches + local_branches = repository.branches.each_with_object({}) { |branch, branches| branches[branch.name] = branch } + + repository.upstream_branches.each do |upstream_branch| + name = upstream_branch.name + + local_branch = local_branches[name] + + if local_branch.nil? + result = CreateBranchService.new(project, current_user).execute(name, upstream_branch.target) + if result[:status] == :error + raise UpdateError, result[:message] + end + elsif local_branch.target == upstream_branch.target + # Already up to date + elsif repository.diverged_from_upstream?(name) + # Cannot be updated + else + begin + repository.ff_merge(current_user, upstream_branch.target, name) + rescue Repository::PreReceiveError, Repository::CommitError => e + raise UpdateError, e.message + end + end + end + end + + def update_tags(&block) + old_tags = repository.tags.each_with_object({}) { |tag, tags| tags[tag.name] = tag } + + fetch_result = block.call + return fetch_result unless fetch_result + + repository.expire_tags_cache + + tags = repository.tags + + tags.each do |tag| + old_tag = old_tags[tag.name] + old_tag_target = old_tag ? old_tag.target : Gitlab::Git::BLANK_SHA + + next if old_tag_target == tag.target + + GitTagPushService.new.execute(project, current_user, old_tag_target, tag.target, "#{Gitlab::Git::TAG_REF_PREFIX}#{tag.name}") + end + + fetch_result + end + end +end diff --git a/app/views/layouts/nav/_project_settings.html.haml b/app/views/layouts/nav/_project_settings.html.haml index d74a23650a..97fce1bf51 100644 --- a/app/views/layouts/nav/_project_settings.html.haml +++ b/app/views/layouts/nav/_project_settings.html.haml @@ -44,6 +44,11 @@ = icon('lock fw') %span Protected Branches + = nav_link(controller: :mirrors) do + = link_to namespace_project_mirror_path(@project.namespace, @project), title: 'Mirror Repository', data: {placement: 'right'} do + = icon('clone fw') + %span + Mirror Repository = nav_link(controller: :audit_events) do = link_to namespace_project_audit_events_path(@project.namespace, @project) do = icon('file-text-o fw') diff --git a/app/views/projects/_home_panel.html.haml b/app/views/projects/_home_panel.html.haml index 8c0980369f..aefda710aa 100644 --- a/app/views/projects/_home_panel.html.haml +++ b/app/views/projects/_home_panel.html.haml @@ -13,22 +13,24 @@ = link_to project_path(forked_from_project) do = forked_from_project.namespace.try(:name) + - if @project.mirror? + - import_url = @project.safe_import_url + %p + Mirrored from #{link_to import_url, import_url}. + + = render "shared/mirror_status" .project-repo-buttons .split-one = render 'projects/buttons/star' + = render 'projects/buttons/fork' - - unless empty_repo - = render 'projects/buttons/fork' - = render "shared/clone_panel" - .split-repo-buttons - - unless empty_repo - - if can? current_user, :download_code, @project - = link_to archive_namespace_project_repository_path(@project.namespace, @project, ref: @ref, format: 'zip'), class: 'btn', rel: 'nofollow' do - = icon('download fw') - - = render 'projects/buttons/dropdown' - = render 'projects/buttons/notifications' + .split-repo-buttons + = render "projects/buttons/update_mirror" + = render "projects/buttons/download" + = render 'projects/buttons/dropdown' + + = render 'projects/buttons/notifications' diff --git a/app/views/projects/branches/_branch.html.haml b/app/views/projects/branches/_branch.html.haml index cc0ec9483d..0b7608c260 100644 --- a/app/views/projects/branches/_branch.html.haml +++ b/app/views/projects/branches/_branch.html.haml @@ -3,17 +3,25 @@ %div = link_to namespace_project_tree_path(@project.namespace, @project, branch.name) do %strong.str-truncated= branch.name -   - - if branch.name == @repository.root_ref - %span.label.label-primary default - - elsif @repository.merged_to_root_ref? branch.name - %span.label.label-info.has_tooltip(title="Merged into #{@repository.root_ref}") - merged - - if @project.protected_branch? branch.name - %span.label.label-success - %i.fa.fa-lock - protected + - if branch.name == @repository.root_ref + %span.label.label-primary default + - elsif @repository.merged_to_root_ref? branch.name + %span.label.label-info.has_tooltip(title="Merged into #{@repository.root_ref}") + merged + + - if @project.protected_branch? branch.name + %span.label.label-success + = icon('lock') + protected + + - if @project.mirror_ever_updated_successfully? && @repository.diverged_from_upstream?(branch.name) + - tooltip_message = "The branch could not be updated automatically because it has diverged from its upstream counterpart." + - tooltip_message << "
To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above." if can?(current_user, :push_code, @project) + %span.label.label-danger.has_tooltip{data: { html: "true", title: tooltip_message }} + = icon('exclamation-triangle') + diverged from upstream + .controls.hidden-xs - if create_mr_button?(@repository.root_ref, branch.name) = link_to create_mr_path(@repository.root_ref, branch.name), class: 'btn btn-grouped btn-xs' do diff --git a/app/views/projects/branches/index.html.haml b/app/views/projects/branches/index.html.haml index 03ade02a0c..0f282c73be 100644 --- a/app/views/projects/branches/index.html.haml +++ b/app/views/projects/branches/index.html.haml @@ -5,7 +5,7 @@ .pull-right - if can? current_user, :push_code, @project = link_to new_namespace_project_branch_path(@project.namespace, @project), class: 'btn btn-create' do - %i.fa.fa-add-sign + = icon('plus') New branch   .dropdown.inline @@ -26,6 +26,9 @@ = sort_title_oldest_updated .oneline Protected branches can be managed in project settings + += render 'projects/commits/mirror_status' + - unless @branches.empty? %ul.content-list.all-branches - @branches.each do |branch| diff --git a/app/views/projects/buttons/_download.html.haml b/app/views/projects/buttons/_download.html.haml new file mode 100644 index 0000000000..14ee2263b7 --- /dev/null +++ b/app/views/projects/buttons/_download.html.haml @@ -0,0 +1,4 @@ +- unless @project.empty_repo? + - if can? current_user, :download_code, @project + = link_to archive_namespace_project_repository_path(@project.namespace, @project, ref: @ref, format: 'zip'), class: 'btn has_tooltip', rel: 'nofollow', title: "Download ZIP" do + = icon('download') diff --git a/app/views/projects/buttons/_dropdown.html.haml b/app/views/projects/buttons/_dropdown.html.haml index 18cae8ef6d..b277b765b6 100644 --- a/app/views/projects/buttons/_dropdown.html.haml +++ b/app/views/projects/buttons/_dropdown.html.haml @@ -32,5 +32,3 @@ = link_to new_namespace_project_tag_path(@project.namespace, @project) do = icon('tags fw') New tag - - diff --git a/app/views/projects/buttons/_fork.html.haml b/app/views/projects/buttons/_fork.html.haml index 8f2f631eb7..2d3abf0905 100644 --- a/app/views/projects/buttons/_fork.html.haml +++ b/app/views/projects/buttons/_fork.html.haml @@ -1,12 +1,13 @@ -- if current_user && can?(current_user, :fork_project, @project) - - if current_user.already_forked?(@project) && current_user.manageable_namespaces.size < 2 - = link_to namespace_project_path(current_user, current_user.fork_of(@project)), title: 'Go to your fork', class: 'btn' do - = icon('code-fork fw') - Fork - %span.count - = @project.forks_count - - else - = link_to new_namespace_project_fork_path(@project.namespace, @project), title: "Fork project", class: 'btn' do - = icon('code-fork fw') - %span.count - = @project.forks_count +- unless @project.empty_repo? + - if current_user && can?(current_user, :fork_project, @project) + - if current_user.already_forked?(@project) && current_user.manageable_namespaces.size < 2 + = link_to namespace_project_path(current_user, current_user.fork_of(@project)), title: 'Go to your fork', class: 'btn has_tooltip' do + = icon('code-fork fw') + Fork + %span.count + = @project.forks_count + - else + = link_to new_namespace_project_fork_path(@project.namespace, @project), title: "Fork project", class: 'btn has_tooltip' do + = icon('code-fork fw') + %span.count + = @project.forks_count diff --git a/app/views/projects/buttons/_star.html.haml b/app/views/projects/buttons/_star.html.haml index 0658390203..41a3ec6d90 100644 --- a/app/views/projects/buttons/_star.html.haml +++ b/app/views/projects/buttons/_star.html.haml @@ -1,5 +1,5 @@ - if current_user - = link_to toggle_star_namespace_project_path(@project.namespace, @project), class: 'btn star-btn toggle-star', method: :post, remote: true do + = link_to toggle_star_namespace_project_path(@project.namespace, @project), class: 'btn star-btn toggle-star has_tooltip', method: :post, remote: true, title: "Star project" do = icon('star fw') %span.count = @project.star_count diff --git a/app/views/projects/buttons/_update_mirror.html.haml b/app/views/projects/buttons/_update_mirror.html.haml new file mode 100644 index 0000000000..07eae0a029 --- /dev/null +++ b/app/views/projects/buttons/_update_mirror.html.haml @@ -0,0 +1,8 @@ +- if @project.mirror? && can?(current_user, :push_code, @project) + - size = nil unless defined?(size) && size + - if @project.updating_mirror? + %span.btn.disabled.update-mirror-button.has_tooltip{title: "Updating from upstream..."} + = icon('refresh') + - else + = link_to update_now_namespace_project_mirror_path(@project.namespace, @project), method: :post, class: "btn update-mirror-button has_tooltip", title: "Update from upstream" do + = icon('refresh') diff --git a/app/views/projects/commits/_mirror_status.html.haml b/app/views/projects/commits/_mirror_status.html.haml new file mode 100644 index 0000000000..6f249fcaed --- /dev/null +++ b/app/views/projects/commits/_mirror_status.html.haml @@ -0,0 +1,10 @@ +- if @project.mirror? + .gray-content-block.second-block + .pull-right + = render "shared/mirror_update_button" + + - import_url = @project.safe_import_url + .oneline + This project is mirrored from #{link_to import_url, import_url}. + + = render "shared/mirror_status" diff --git a/app/views/projects/commits/show.html.haml b/app/views/projects/commits/show.html.haml index 2dd99cc821..f9f68a9fcd 100644 --- a/app/views/projects/commits/show.html.haml +++ b/app/views/projects/commits/show.html.haml @@ -24,6 +24,8 @@ %ul.breadcrumb.repo-breadcrumb = commits_breadcrumbs += render 'projects/commits/mirror_status' + %div{id: dom_id(@project)} #commits-list= render "commits", project: @project .clear diff --git a/app/views/projects/imports/new.html.haml b/app/views/projects/imports/new.html.haml index 92a87690c5..6027fb2336 100644 --- a/app/views/projects/imports/new.html.haml +++ b/app/views/projects/imports/new.html.haml @@ -1,22 +1,19 @@ - page_title "Import repository" %h3.page-title - - if @project.import_failed? - Import failed. Retry? - - else - Import repository + Import repository %hr +- if @project.import_failed? + .panel.panel-danger + .panel-heading The repository could not be imported. + .panel-body + %pre + :preserve + #{@project.import_error.try(:strip)} + = form_for @project, url: namespace_project_import_path(@project.namespace, @project), method: :post, html: { class: 'form-horizontal' } do |f| - .form-group.import-url-data - = f.label :import_url, class: 'control-label' do - %span Import existing git repo - .col-sm-10 - = f.text_field :import_url, class: 'form-control', placeholder: 'https://github.com/randx/six.git' - .well.prepend-top-20 - This URL must be publicly accessible or you can add a username and password like this: https://username:password@gitlab.com/company/project.git. - %br - The import will time out after 4 minutes. For big repositories, use a clone/push combination. - For SVN repositories, check #{link_to "this migrating from SVN doc.", "http://doc.gitlab.com/ce/workflow/importing/migrating_from_svn.html"} + = render "shared/import_form", f: f + .form-actions = f.submit 'Start import', class: "btn btn-create", tabindex: 4 diff --git a/app/views/projects/imports/show.html.haml b/app/views/projects/imports/show.html.haml index 06886d215a..c0d1ce0d12 100644 --- a/app/views/projects/imports/show.html.haml +++ b/app/views/projects/imports/show.html.haml @@ -8,7 +8,7 @@ - else Import in progress. - unless @project.forked? - %p.monospace git clone --bare #{hidden_pass_url(@project.import_url)} + %p.monospace git clone --bare #{@project.safe_import_url} %p Please wait while we import the repository for you. Refresh at will. :javascript new ProjectImport(); diff --git a/app/views/projects/mirrors/show.html.haml b/app/views/projects/mirrors/show.html.haml new file mode 100644 index 0000000000..6b3e07a6d4 --- /dev/null +++ b/app/views/projects/mirrors/show.html.haml @@ -0,0 +1,70 @@ +- page_title "Mirror Repository" +.pull-right + - if @project.mirror_last_update_success? + Successfully updated #{time_ago_with_tooltip(@project.mirror_last_successful_update_at)}. + %span.prepend-left-10 + = render "shared/mirror_update_button" +%h3.page-title + Mirror Repository + +%p.light + Set up your project to automatically have its branches, tags, and commits updated from an upstream repository every hour. + +%hr.clearfix + +- if @project.mirror_last_update_failed? + .panel.panel-danger + .panel-heading + The repository failed to update #{time_ago_with_tooltip(@project.mirror_last_update_at)}. + - if @project.mirror_ever_updated_successfully? + Last successful update #{time_ago_with_tooltip(@project.mirror_last_successful_update_at)}. + .panel-body + %pre + :preserve + #{@project.import_error.try(:strip)} + += form_for @project, url: namespace_project_mirror_path(@project.namespace, @project), html: { class: 'form-horizontal' } do |f| + - if @project.errors.any? + .alert.alert-danger + - @project.errors.full_messages.each do |msg| + %p= msg + + .form-group + .col-sm-offset-2.col-sm-10 + .checkbox + = f.label :mirror do + = f.check_box :mirror + %strong + Mirror repository + .help-block + Automatically update this project's branches, tags, and commits from the upstream repository every hour. + + .form-group + = f.label :import_url, class: 'control-label' do + %span Git repository URL + .col-sm-10 + = f.text_field :import_url, class: 'form-control', placeholder: 'https://username:password@gitlab.company.com/group/project.git' + .well.prepend-top-20 + %ul + %li + The repository must be accessible over http://, https://, ssh:// or git://. + %li + If your HTTP repository is not publicly accessible, add authentication information to the URL: https://username:password@gitlab.company.com/group/project.git. + %li + If your SSH repository is not publicly accessible, add the public SSH key of the GitLab server to the remote repository. + %li + The update action will time out after 10 minutes. For big repositories, use a clone/push combination. + + .form-group + = f.label :mirror_user_id, class: 'control-label' do + Mirror user + .col-sm-10 + = users_select_tag("project[mirror_user_id]", class: 'input-large', selected: @project.mirror_user_id || current_user.id, + first_user: true, current_user: true, push_code_to_protected_branches: true) + .help-block + This user will be the author of all events in the activity feed that are the result of an update, + like new branches being created or new commits being pushed to existing branches. + They need to have at least master access to this project. + + .form-actions + = f.submit "Save Changes", class: "btn btn-create" diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml index a02c12f06a..c9d1fc3da2 100644 --- a/app/views/projects/new.html.haml +++ b/app/views/projects/new.html.haml @@ -23,7 +23,6 @@ = f.select :namespace_id, namespaces_options(params[:namespace_id] || :current_user), {}, {class: 'select2', tabindex: 2} - if import_sources_enabled? - .project-import.js-toggle-container .form-group %label.control-label Import project from @@ -82,19 +81,7 @@ %span Any repo by URL .js-toggle-content.hide - .form-group.import-url-data - = f.label :import_url, class: 'control-label' do - %span Git repository URL - .col-sm-10 - = f.text_field :import_url, class: 'form-control', placeholder: 'https://username:password@gitlab.company.com/group/project.git' - .well.prepend-top-20 - %ul - %li - The repository must be accessible over HTTP(S). If it is not publicly accessible, you can add authentication information to the URL: https://username:password@gitlab.company.com/group/project.git. - %li - The import will time out after 4 minutes. For big repositories, use a clone/push combination. - %li - To migrate an SVN repository, check out #{link_to "this document", "http://doc.gitlab.com/ce/workflow/importing/migrating_from_svn.html"}. + = render "shared/import_form", f: f .prepend-botton-10 diff --git a/app/views/projects/tags/index.html.haml b/app/views/projects/tags/index.html.haml index 85d76eae3b..75199e7f88 100644 --- a/app/views/projects/tags/index.html.haml +++ b/app/views/projects/tags/index.html.haml @@ -6,11 +6,13 @@ - if can? current_user, :push_code, @project .pull-right = link_to new_namespace_project_tag_path(@project.namespace, @project), class: 'btn btn-create new-tag-btn' do - %i.fa.fa-add-sign + = icon('plus') New tag .oneline Tags give the ability to mark specific points in history as being important += render 'projects/commits/mirror_status' + .tags - unless @tags.empty? %ul.content-list diff --git a/app/views/shared/_clone_panel.html.haml b/app/views/shared/_clone_panel.html.haml index 2e4aab3630..8bcb24ae9d 100644 --- a/app/views/shared/_clone_panel.html.haml +++ b/app/views/shared/_clone_panel.html.haml @@ -21,7 +21,6 @@ = gitlab_config.protocol.upcase = text_field_tag :project_clone, default_url_to_repo(project), class: "js-select-on-focus form-control", readonly: true - if project.kind_of?(Project) - .input-group-addon - .visibility-level-label.has_tooltip{'data-title' => "#{visibility_level_label(project.visibility_level)} project" } + .input-group-addon.has_tooltip{title: "#{visibility_level_label(project.visibility_level)} project", data: { container: "body" } } + .visibility-level-label = visibility_level_icon(project.visibility_level) - diff --git a/app/views/shared/_import_form.html.haml b/app/views/shared/_import_form.html.haml new file mode 100644 index 0000000000..2b5428caaf --- /dev/null +++ b/app/views/shared/_import_form.html.haml @@ -0,0 +1,28 @@ +.form-group.import-url-data + = f.label :import_url, class: 'control-label' do + %span Git repository URL + .col-sm-10 + = f.text_field :import_url, class: 'form-control', placeholder: 'https://username:password@gitlab.company.com/group/project.git' + + .well.prepend-top-20 + %ul + %li + The repository must be accessible over http://, https:// or git://. + %li + If your HTTP repository is not publicly accessible, add authentication information to the URL: https://username:password@gitlab.company.com/group/project.git. + %li + The import will time out after 4 minutes. For big repositories, use a clone/push combination. + %li + To migrate an SVN repository, check out #{link_to "this document", "http://doc.gitlab.com/ce/workflow/importing/migrating_from_svn.html"}. + +.form-group + .col-sm-offset-2.col-sm-10 + .checkbox + = f.label :mirror do + = f.check_box :mirror + %strong + Mirror repository + .help-block + Automatically update this project's branches and tags from the upstream repository every hour. + += f.hidden_field :mirror_user_id, value: current_user.id diff --git a/app/views/shared/_mirror_status.html.haml b/app/views/shared/_mirror_status.html.haml new file mode 100644 index 0000000000..2cf9cab5b7 --- /dev/null +++ b/app/views/shared/_mirror_status.html.haml @@ -0,0 +1,14 @@ +- case @project.mirror_last_update_status +- when :success + Updated #{time_ago_with_tooltip(@project.mirror_last_successful_update_at)}. +- when :failed + - if can?(current_user, :admin_project, @project) + = link_to namespace_project_mirror_path(@project.namespace, @project) do + = icon("exclamation-triangle") + Failed to update #{time_ago_with_tooltip(@project.mirror_last_update_at)}. + - else + = icon("exclamation-triangle") + Failed to update #{time_ago_with_tooltip(@project.mirror_last_update_at)}. + + - if @project.mirror_ever_updated_successfully? + Last successful update #{time_ago_with_tooltip(@project.mirror_last_successful_update_at)}. diff --git a/app/views/shared/_mirror_update_button.html.haml b/app/views/shared/_mirror_update_button.html.haml new file mode 100644 index 0000000000..0fb719d6b4 --- /dev/null +++ b/app/views/shared/_mirror_update_button.html.haml @@ -0,0 +1,9 @@ +- if @project.mirror? && can?(current_user, :push_code, @project) + - if @project.updating_mirror? + %span.btn.disabled + = icon('refresh') + Updating… + - else + = link_to update_now_namespace_project_mirror_path(@project.namespace, @project), method: :post, class: "btn" do + = icon('refresh') + Update Now diff --git a/app/workers/repository_fork_worker.rb b/app/workers/repository_fork_worker.rb index acd1c43f06..2f991c5233 100644 --- a/app/workers/repository_fork_worker.rb +++ b/app/workers/repository_fork_worker.rb @@ -13,22 +13,20 @@ class RepositoryForkWorker end result = gitlab_shell.fork_repository(source_path, target_path) - unless result logger.error("Unable to fork project #{project_id} for repository #{source_path} -> #{target_path}") + project.update(import_error: "The project could not be forked.") project.import_fail - project.save return end - if project.valid_repo? - ProjectCacheWorker.perform_async(project.id) - project.import_finish - else - project.import_fail + unless project.valid_repo? logger.error("Project #{id} had an invalid repository after fork") + project.update(import_error: "The forked repository is invalid.") + project.import_fail + return end - project.save + project.import_finish end end diff --git a/app/workers/repository_import_worker.rb b/app/workers/repository_import_worker.rb index ea2808045e..1de4916199 100644 --- a/app/workers/repository_import_worker.rb +++ b/app/workers/repository_import_worker.rb @@ -7,37 +7,52 @@ class RepositoryImportWorker def perform(project_id) project = Project.find(project_id) - unless project.import_url == Project::UNKNOWN_IMPORT_URL - import_result = gitlab_shell.send(:import_repository, - project.path_with_namespace, - project.import_url) - return project.import_fail unless import_result - else + if project.import_url == Project::UNKNOWN_IMPORT_URL + # In this case, we only want to import issues, not a repository. unless project.create_repository - return project.import_fail + project.update(import_error: "The repository could not be created.") + project.import_fail + return + end + else + begin + gitlab_shell.import_repository(project.path_with_namespace, project.import_url) + rescue Gitlab::Shell::Error => e + project.update(import_error: e.message) + project.import_fail + return end end - data_import_result = case project.import_type - when 'github' - Gitlab::GithubImport::Importer.new(project).execute - when 'gitlab' - Gitlab::GitlabImport::Importer.new(project).execute - when 'bitbucket' - Gitlab::BitbucketImport::Importer.new(project).execute - when 'google_code' - Gitlab::GoogleCodeImport::Importer.new(project).execute - when 'fogbugz' - Gitlab::FogbugzImport::Importer.new(project).execute - else - true - end - return project.import_fail unless data_import_result + data_import_result = + case project.import_type + when 'github' + Gitlab::GithubImport::Importer.new(project).execute + when 'gitlab' + Gitlab::GitlabImport::Importer.new(project).execute + when 'bitbucket' + Gitlab::BitbucketImport::Importer.new(project).execute + when 'google_code' + Gitlab::GoogleCodeImport::Importer.new(project).execute + when 'fogbugz' + Gitlab::FogbugzImport::Importer.new(project).execute + else + true + end - Gitlab::BitbucketImport::KeyDeleter.new(project).execute if project.import_type == 'bitbucket' + unless data_import_result + project.update(import_error: "The remote issue data could not be imported.") + project.import_fail + return + end + + if project.import_type == 'bitbucket' + Gitlab::BitbucketImport::KeyDeleter.new(project).execute + end project.import_finish - project.save - ProjectCacheWorker.perform_async(project.id) + + # Explicitly update mirror so that upstream remote is created and fetched + project.update_mirror end end diff --git a/app/workers/repository_update_mirror_worker.rb b/app/workers/repository_update_mirror_worker.rb new file mode 100644 index 0000000000..d991a5bcde --- /dev/null +++ b/app/workers/repository_update_mirror_worker.rb @@ -0,0 +1,22 @@ +class RepositoryUpdateMirrorWorker + include Sidekiq::Worker + include Gitlab::ShellAdapter + + sidekiq_options queue: :gitlab_shell + + attr_accessor :project, :repository, :current_user + + def perform(project_id) + @project = Project.find(project_id) + @current_user = @project.mirror_user || @project.creator + + result = Projects::UpdateMirrorService.new(@project, @current_user).execute + if result[:status] == :error + project.update(import_error: result[:message]) + project.import_fail + return + end + + project.import_finish + end +end diff --git a/app/workers/update_all_mirrors_worker.rb b/app/workers/update_all_mirrors_worker.rb new file mode 100644 index 0000000000..f46e2023f0 --- /dev/null +++ b/app/workers/update_all_mirrors_worker.rb @@ -0,0 +1,10 @@ +class UpdateAllMirrorsWorker + include Sidekiq::Worker + include Sidetiq::Schedulable + + recurrence { hourly } + + def perform + Project.mirror.each(&:update_mirror) + end +end diff --git a/config/routes.rb b/config/routes.rb index 5211596ad9..5eaee5d6bc 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -633,6 +633,11 @@ Gitlab::Application.routes.draw do end resources :protected_branches, only: [:index, :create, :update, :destroy], constraints: { id: Gitlab::Regex.git_reference_regex } + resource :mirror, only: [:show, :update] do + member do + post :update_now + end + end resources :git_hooks, constraints: { id: /\d+/ } resource :variables, only: [:show, :update] resources :triggers, only: [:index, :create, :destroy] diff --git a/db/migrate/20151110125416_add_mirror_to_project.rb b/db/migrate/20151110125416_add_mirror_to_project.rb new file mode 100644 index 0000000000..4b67e3aefb --- /dev/null +++ b/db/migrate/20151110125416_add_mirror_to_project.rb @@ -0,0 +1,8 @@ +class AddMirrorToProject < ActiveRecord::Migration + def change + add_column :projects, :mirror, :boolean, default: false, null: false + add_column :projects, :mirror_last_update_at, :datetime + add_column :projects, :mirror_last_successful_update_at, :datetime + add_column :projects, :mirror_user_id, :integer + end +end diff --git a/db/migrate/20151110125604_add_import_error_to_project.rb b/db/migrate/20151110125604_add_import_error_to_project.rb new file mode 100644 index 0000000000..7fc990f8d0 --- /dev/null +++ b/db/migrate/20151110125604_add_import_error_to_project.rb @@ -0,0 +1,5 @@ +class AddImportErrorToProject < ActiveRecord::Migration + def change + add_column :projects, :import_error, :text + end +end diff --git a/db/schema.rb b/db/schema.rb index fa53ded5ad..33319a8061 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -48,9 +48,9 @@ ActiveRecord::Schema.define(version: 20151114113410) do t.boolean "twitter_sharing_enabled", default: true t.text "help_text" t.text "restricted_visibility_levels" - t.boolean "version_check_enabled", default: true t.integer "max_attachment_size", default: 10, null: false t.integer "default_project_visibility" + t.boolean "version_check_enabled", default: true t.integer "default_snippet_visibility" t.text "restricted_signup_domains" t.boolean "user_oauth_applications", default: true @@ -700,31 +700,36 @@ ActiveRecord::Schema.define(version: 20151114113410) do t.datetime "created_at" t.datetime "updated_at" t.integer "creator_id" - t.boolean "issues_enabled", default: true, null: false - t.boolean "wall_enabled", default: true, null: false - t.boolean "merge_requests_enabled", default: true, null: false - t.boolean "wiki_enabled", default: true, null: false + t.boolean "issues_enabled", default: true, null: false + t.boolean "wall_enabled", default: true, null: false + t.boolean "merge_requests_enabled", default: true, null: false + t.boolean "wiki_enabled", default: true, null: false t.integer "namespace_id" - t.string "issues_tracker", default: "gitlab", null: false + t.string "issues_tracker", default: "gitlab", null: false t.string "issues_tracker_id" - t.boolean "snippets_enabled", default: true, null: false + t.boolean "snippets_enabled", default: true, null: false t.datetime "last_activity_at" t.string "import_url" - t.integer "visibility_level", default: 0, null: false - t.boolean "archived", default: false, null: false + t.integer "visibility_level", default: 0, null: false + t.boolean "archived", default: false, null: false t.string "avatar" t.string "import_status" - t.float "repository_size", default: 0.0 - t.text "merge_requests_template" - t.integer "star_count", default: 0, null: false - t.boolean "merge_requests_rebase_enabled", default: false + t.float "repository_size", default: 0.0 + t.integer "star_count", default: 0, null: false t.string "import_type" t.string "import_source" - t.integer "approvals_before_merge", default: 0, null: false - t.boolean "reset_approvals_on_push", default: true - t.integer "commit_count", default: 0 - t.boolean "merge_requests_ff_only_enabled", default: false + t.text "merge_requests_template" + t.boolean "merge_requests_rebase_enabled", default: false + t.integer "commit_count", default: 0 + t.integer "approvals_before_merge", default: 0, null: false + t.boolean "reset_approvals_on_push", default: true + t.boolean "merge_requests_ff_only_enabled", default: false t.text "issues_template" + t.text "import_error" + t.boolean "mirror", default: false, null: false + t.datetime "mirror_last_update_at" + t.datetime "mirror_last_successful_update_at" + t.integer "mirror_user_id" end add_index "projects", ["created_at", "id"], name: "index_projects_on_created_at_and_id", using: :btree diff --git a/doc/workflow/README.md b/doc/workflow/README.md index 823ee4a193..7c0a3a5ed0 100644 --- a/doc/workflow/README.md +++ b/doc/workflow/README.md @@ -24,3 +24,4 @@ - [Releases](releases.md) - [Merge Requests](merge_requests.md) - ["Work In Progress" Merge Requests](wip_merge_requests.md) +- [Repository Mirroring](repository_mirroring.md) diff --git a/doc/workflow/repository_mirroring.md b/doc/workflow/repository_mirroring.md new file mode 100644 index 0000000000..d93e8bb48e --- /dev/null +++ b/doc/workflow/repository_mirroring.md @@ -0,0 +1,18 @@ +# Repository Mirroring + +You can set up a project to automatically have its branches, tags, and commits updated from an upstream repository. +This is useful when a repository you're interested in is located on a different server, and you want to be able to browse its content and its activity using the familiar GitLab interface. + +Mirror repositories are updated every hour, and all new branches, tags, and commits will be visible in the project's activity feed. Users with at least developer access to the project can also force an immediate update. + +![Project page](repository_mirroring/project_page.png) + +Since the repository on GitLab functions as a mirror of the upstream repository, you are advised not to push commits directly to the repository on GitLab. Instead, any commits should be pushed to the upstream repository, and will end up in the GitLab repository automatically within an hour, or when a forced update is initiated. + +If you do manually update a branch in the GitLab repository, the branch will become diverged from upstream, and GitLab will no longer automatically update this branch to prevent any changes from being lost. + +![Diverged branch](repository_mirroring/diverged_branch.png) + +You can set up Repository Mirroring by navigating to Project Settings > Repository Mirroring. + +![Settings](repository_mirroring/settings.png) diff --git a/doc/workflow/repository_mirroring/diverged_branch.png b/doc/workflow/repository_mirroring/diverged_branch.png new file mode 100644 index 0000000000000000000000000000000000000000..09da78e345dfb5dbac38b3e2bbc2574383684640 GIT binary patch literal 252687 zcmeEuXE>Z)*EW(th>#$ng-Ap<2|;ush%R~?qW5mJQG!GgJw%TZz4tn!1Q9KI8Er<3 zIv8yX#_+kH_x;{G@Av(A?*EVDFvr-}UVHDgu66Bwu5+!+Crx!l3Ni*V0s;aGrB^St z2ncR?5D;ARCMCXVG2LA8Bp|qX*IrIeQ%O#aRnx=O#@@-AfZ)}q#AFf!?Y_G`>q#^( zUXZ_(QQlCCGtI}wcvanwC;0Y*ij>>i>UBqbHd|;;4i76?1t6|F9AtPMVn+4a(2$N? zSO@ut@aPm7goY%z?&4Q}iP~NWra}a-y=~!BVeNfMOVGQ#PWBMrnzDc6lj<0Y3~_H) zEcFxHYR~JLw{JgKWEp@N6Wm^?Opo-$*DeI}MKHPCVkCG(wqO3)-`%=!!P zb_B5Ff9L_Q2qHH$Bn1%3Jc<<6?Psu1PpZlP!67!rSVKu*#U0763XoC%nw8q4{@(BR z^*Fv$ru!@h>b)-8&+d|VQ2ypJH1vEhp#6Z6BRH7@v*7VqKriw)Y=LwwpopeC9i!``-nm30pxdqJjpA|YF`)ifZitITkszJ62cX? z)2EhcPn)1EY&{l{*Hdp>UKr4dj7w{Y4NrG`Z7JHHc5HSFQCcU2d>tZ-h}-Hx-tc&s zlRxXm^p3!F@mh+^bw_~|@-f0n&niEvpoE4K!n;(VI^O|nmPz{`pDU5GnC8kzosi$5 z`>p!JPsym6m2$RS)gWKrGmg!EFyW=u+rqe7H}E`#Plw#%r!%J<4nnXG&+T3#!z7 z_HB92Y4^@Kl8rf*p)^| zE&i$g4fC}7Q;o8B9Px=ykj8m0jfsDCF=DIB8kwrj&skb)f6|b$w~O?y4h_>vQz1P8 zP!ka0v>v%h6FTp(-hR_Co&T(V_`>_{qP5Vt`DOI7Mx}Z3Ea5De@?gxC*3FL z$t02q#ts%>8Kg{6gwK)PcW)f#37Z5wARs$m&?I({A>SaheE!(+4W-Fjl0ASdE7Qxc z>rWVm{26*fOV&f=--vP&vA>a=zRCUlRu$t!=(R;EJ7VX>XU{1s-txOq&wp^tWoaRh zTV%c`OZD#E2$fh)xZOkIkMtJN&)Hl)0`G*rWV`X|PJG1P?b|h^h9O^A^IrjK$cyEI zeWY%ygO^RBS@{^ zwZ6-J=ehT3i=*Y?oliG&ZjTa5rQi7Bwfth4VcFZ_;XX}u`m`d`r+o&?c-12OP1t> zyl&7xeyID&K^applowItSS&Q5Jpr2#dB!jpwma8wq<8)7i-7zd&A?dM~DYg zbG}EShnffcw`u=CFJmvHe>iD48JHl=8>}0oDXY+-*2BR^Lul7XilO< zlSR@pLw8_AGEElG=Px%C0}`JrzgLDO4sl{epF-~=(uWEvv(ewOacbXr ztPewAbKnM{=M-iM09O*X|!t!l^T

hU)TRTzEy_Q&> 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 Nf{dzk%?Fd<{|}yd4dws< literal 0 HcmV?d00001 diff --git a/doc/workflow/repository_mirroring/project_page.png b/doc/workflow/repository_mirroring/project_page.png new file mode 100644 index 0000000000000000000000000000000000000000..585d97d5560eaa3fc50ac8ddca3384c661d5c425 GIT binary patch literal 138638 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

ySnU99>FP@KtSFSm`M7 z9}2WTGk|#Bu}1CP9o*|rKKhy8zIWu&9qnP-5f%;Sf;}FtBh)W937VcMHBy!Q7+z6A za6_yZMC5d>l$0Sr3O;?fmmc574JKz-f1RtC`Z!+SNxnJCjWQ44hvb3a>qO`~&VKQ; zqK30Auc1cS@NdbyP@;x3@KHho_LLe2UBv`Qy2Ly8iwLy2%RKqmoaSr+zrY}qOiY2v zn#a*hmvdiXOL2NjU;9$jl1JqFD~@!}W&<(iQzI8nYVG8(Q0JN{nXopO=!sRM7`8w zx9LYaG;jcl?m~;1W71>09emMP&~)N@*H8peo^!SVUUl;o5i7kWZ=o(SX=s3(s(Vh6 z(^yf=ZAv2hLJu7W2VWvT_+B%Y!{(&O>jw8{wb>YHLwfeJ@o(i4LA{)+JYf+@6XDDgw^(dk#*?R=+`;vfVjODm;!w^1nb6-P3qDyAm?3a|2M&&5 z(;D+ioxBQoe^vh@IIUGj^BsoZykn)v$xY>$(@n^EmDV*8DI+&XivbA51{{vg{QY54 zn(V7K#~@U9nQ@v|zn76yzGC750hRZ0=MK76RsN6?*x0q%-nSU{fN$ z4danklRo}rl}#S|87P6>@Bn(gui`|(Kz#}5lPyJX(Tv9eI4Gda zcDjqH$~mBFdJPb}+8gF2TloIQ-ymhmsd@%>X;`!(-_hO0l$H%<`qY54U+Mu4(ie9} z9v&?3ml)K^&8hdr11&l-zUPi+&6zoTdS(WVyAtYMt4E&-q8)p9UW<)pic>i_M$F@awJ^G0>T8huK6x6DMqAFT#}ryFyp1uEKir;vMr3 zqenr{!#Ad?3MWV*P?RqsAp>Bv89IwvB+BJ?8ZSZik=C7(tcx)9qDKpvO!=7Gl~WP& z2Vd{j`|V5>macWp#Ylb7+yzTmo{+Av1%4D z_lAkgB*g%y?p>CRQMK7lX+nn&4iAS;yhEOT!^fpaUysYo$CD;6vz3s2WxZd!pM7{w zsrl7=1FZSQCTVK_rFVAf?5Xon+TP6Bwsdkr4@|UmlK$-vLkjKKQS$@>0pw+KD~`eG zWZQUwMxh{8DZ5B!Yy!jr-s^K}^?H%0uWho&KCk!^q9We8V|`Hgye=e3{xOpL$w0sn zO-dAdgj{K;cH?-IYbM>RC;h8XaS(gCCJ*mLhQJM-^0%yT=5HDdnrWp#{0(q-=|G_EnJFD90H5I_Q8HB|G3-Jn{%-tYX`!z&vh zTp!o)r#%y;o}jrq@S*W5gG7qJo;Krw?)AeDFVTLppY8u;n``6(d03XP}?cC9}LwAZXY?OW&g-Yf9E zB^7a|Wo1&#J6;KuZx5q=Pxz+UXO88geIr8?PasK#DrMV&*m+n&uY|b!L_p_^kHcqx z=8uGB{ryT+k?D`NrcZ)mO?WDTd!mg9x?EwIKLXa@x7$TUf1tPeUA#!5msCBn9GC-+ zst>*~lljb4M#R8IW0;u9?NJMNiuSnO4~gpm@d}%@NMqsI3>+NDw99bleedel8@!Mk z^?ZmnK$QJ4so23S&>n$Y5ZL5w5s*TP0SHord8%wDxut_ID5k_>T#I*SuadsnU+#bd zvtXqLGF4x@q!%V37WjBRI#bI4&w_&Z$s!q3aTQ-Tw|~_L|5%BE$oa>o46--0n^CfK zKKBNehlSl@_WRK5cw~Kvd}=DhO!)Mg1?oEYd2NBLBhtL_)xFLtTsQW5rTSQ*St38d zbg7~^=^jo3-EwXA~WGtwvc@^?pwnUyN3frK*$XndTFvs?bcl=eQX)~m`U`Gkm~ z^Anx-YL)5ex<(?OagBx62CcPYd)w=``^y{^b_o6zXP_C*WGZy^&9fpg=fcyKGzO>b zi!M|+t5(SqC~`{Hdc0t**u5O!12t6L(AkvGATNL7eCiq!LU&Z<2u@7ppLWFmJ$N%D5vb{tw zt;WbCmpxKwY0yV$!r{Sw<+x@xrGis8zszu-_SU#7dR(NGlt`xVb%uA{3}moU%-v9= z&wj8!_D-D&)P9oHoR3ZOiNO@!_yV{Iv~4(9X$5g6F5h@%-W{WSIFU@%u?J8B&)BHK z$r2UXf@Qt>TSNhLmR#K?*lt!UZKCcdfn3Q{XqPM`0DqSSHLU-Q~e=yoOtte zrxdm*^@6e zrxPyRGXH?@7L@_W#c9RYvhcR#Ljqis&soZTpvh75$dX+@D#c#cskTkfT3PTcZ?H?^@7oXd1ZB8Nyj#+06lvQM zWzph4muIq+!G6(BZ%EC)KwZ*C*KgJ7E%yNwPRO(7KvJ0o?;0wO&-3+jt&Lr-e53o$ z{Su{=jeA`zd8wI`NY4GbgUSs70Zi>=QoMgM$6JYcN;Hk3y-=eXQ@Kb7()2k8$sXFJ zJ%M|%5tO4-CUnDwVXFui*H{@ zXv)MLj+?f2ymPxssAl{WUjV0f*FCVfWN$IQ37( zSC_Pa7$E_NTxZ~vLjd*A$onMJ&8BQ@7kmyT{UrKB5Wp@x2lwE2hc^OxXrL%oSM-OQ zy4Z_w7SH%C#Eg@h<1`1oY*-|VT5hdMiYyVWyLD~tfCf}CD=9f@Hwi@ffJt*qsr=SwIHyKE6#S~$r4h-DLudl)N{%GAbqf&VH!>s(H zH1NeCNVzNpoY}bTunh{Sw2z%WOb2^5kX#CZQi<;$00bnF`B^sO&PygfV$xCgV->?B zRC^gcB2GVAU?~7;aTF2PD(8`~TX@LU0iYh=J>j^p6mR59MpSTvbFA1Jvt_W<;M}iV zZoAV^?rvYYd&WCEWG`G^0ooQ{bD9xy@`ZMCKh%jY0#GEehYD%z=)?Vk9X7<_84`{@Lm zvU&T_&1ZkZnG3&0H_6Lz!oc%DP-1bHDGpI-+$uwL&|Sz4#^40eabtnAWhYoh(M;FxA zUSvMgKW{9g^jjnPb|pfcx!rT(a^Uurf)@wMo(q~Z+YsZ7nb|UjOYzB^A0yZbZ642w z+SFfCx3WAB@^JT;vH6tiTAsy)xj(!~CHCG)f=p*#qMBWL?;M>LmY%jhy_erCLt;_Q zE@>5;a{sOa*nYA`{_4g)1I;z0qv+!ZJ^T$}DbH7)@gZ&oagH`aKhv&K*bHXYCVMO= z;K1yx#|m;*3Me`?FOWp_SVMhAN+73;N8^uN>g>qx$4R%6^t|vhVL*_GpkwiM){} zfYv9)nl981!K#+0xN8BM4`xeF=b|>&k>MP+7yBirYkA7-BW4J?a5V))= z_+kxPAgxlv6cgIZbK*RsW=<2-)V4Ack>-02Hop3NiI6z_jExzZ)4rk5#HvnZ#gD9U zkLdNwU9}lm&WJdV>UOS~)(k`KiHO~)1ndLGvC%5_Oaku)w06oz493K@O6!+dJsbz# zGBKOf63o^}nSFBc0o(vw@m8w)ExrwkOhs%#b3ybYqU6Q>k+bbRa+Uy2+edj`9K9PE zTIsm!6-;h}7e;pBK3c>Y{3p0A(`yu8@0?>D^UN0q>!7}SYnH9mZR^z{(P=(g(j+6I zdYrIIP(h*BUVb(;S%75)J5#@ygdFGCm5Qwu5J~C-t$vO&#|cWKPj=DfIQK7yUwX`) zYeaH3U#N~Q$1El}G@?i5NDCn5Y2Z2Y4l#8ke_w#&N8f||^IRN_@JkeZ zl*CUo`*g(`l|$(v30lDY#}mztWqO=?t5HhUTLW?Bo8Fg!;kXpgg_qx>W-y7Phbze* zch<$shuOdJ9$V0fV9jL&!pdh#e@GQpi`k!ePiUF^2qBelfl+>#R}L9nD4KKzHUNT; z#rC-t#^rulvUDD=@AH4Bb8E8mjD%n4e-rg6Fnmi*!96<^_9)HwC@6Vs4j4Z(ab+hR zt)cUMu!P^jKNjN6XZ?|MsB5cVizwzMM#vmNv3>{xgq&X|^$L=gjZdj8L~~tt7@tKr zN`!`f_mUAXgI^-MwnB3lZeCHmYwV7mKN#oWjZ(!5dIaD{5 z=GdhmjX~(?4Qsy_7UJbSt4B0G6J^G?OWP~vL=O+ta0CXV8{P->zw4+x+pafaR7riX z8>g#+PcsFQdj`AMS|7*=6y=@GxI29Bwgm1`{UCNoZQ309cJE;1b{DtaA&=A8#^P6> zI1N6*Rd_LzCXSK4Pu!;0Xu;@~nox-j#4nu-^c-2|+ExNnyeIL4%3MlY;gI0s)VRWL zYaGqAO}xt1E@^NJbAUjV6P znoqU1+e~HmR2AB6C|lm?NXYWqbVU4^lcFq;tUA>L@J;OndGiraBC5m3VvaAfFKIyC zK+$H{K=wO6d<{w4|IUrGo``qIgpy!+t;-WyDVA>_sm1K}Y?#yV7lTe8d(z=GGKOkg zp4|Q&)*}6!3W4NE|3kDucNo3I(Z=EHQo~v4i1zz$mnrJ6n=^e?SPy^ss*jRczvi>W zk9_)JOGOaB#m2X1o^#+*eUDK-WoTKxov}5S3%weE2_G zjv1Ac7dfNWO`UtO6&hF5i6{oPUwFLKWH-uZ@`|qGDf{{~uX>!*(VOWz2Qwh3z-pM{ zHaK5c8eQS6qdAH$ZS3}vn84(w`6fO@y^{t8cc*3_Y&!6*%v(hgMY&sXw_w~W7q!><(SBxqtj1)a4Z58juPA8)GdYU^L>+3E;kLTf~SJ%tO1I!@> zrO0*NT&UHsMQ4wWylYThnQD>yvr=Jr@<_HLeSS6-c$06xwR3O=ZQB);xaeK4Jz8hWj%ix?bo1h+CYojgYl3|Hk#)_dG@;%ccB&BW>^5E2 z{|YW%ZPBZ1$wx6@S_<+a^^{I}yFJ*$oKS9bkqaQD36xLY>C}jyE<$(%`Gz4W6z6Et zJ>C^azpxtQi55BBnt%RNw&V>Fdp*sc0;qcr!~>@y4eSxd+h1B_IUnd8wH+nip2Y3r zfFzigu&OifU|fpAmVOXWeCAh0S=z5nLS!d4taf)!bZec=J5asP-%-7vwl!b&)Lh}g z4O5E?T6b^kl)u4I=6fML`JFQ8B1h(M#~+M6nVy4T6PW<+lv)!K#t{NX0Kt-dsBI^+f>5)WJ} zWz;KJ66BrFKClrui02bjwAk61jnbFs($F$u03?Ex>@;)Dv;2}W1R9mfmWb{$r_Qv| z>u$kD{b4x5E`l7h^{-yWW;^F8v|=X{~vM*<+HWidhDC!%xK?2f}()TQ%* z_a})}Hg&%kAEQ*~MNmd@Yu%T=!i4uo6R}8bN!y~jLLO`4Ke+&EUC_O&3+^PJA;h_H zp_}s|T*`dM@PHt0o59Pq$f#~`b zF0r6)iIB@LUBY2wSY$C9jCD#{xiaVTcEF4BOzEo>P`W!z)>=aLv+>BFS6@>6kX77f zoo9x>dUr4%dAK9EjP^(c3iDoP;NpzZ6dNF8ST&~LixxT>*Ut$bc9*Mch#|^{sSIc1 z?K-p5z;0MT(E9G$(4n{0K)O_LG#Ry@eNCD0M9_KcK`FeRGtr})b5FZGof$r3ZopI57SO=H(@Y}%z5`*pgYSd( z+&My=c~Ty#2xinyd+LF?u7-jqXN}RXs>0nO*C-IVBHK+UpZiCHh6`eqN#bCgI+uin zcm6WfVD?T4wqX1b?T2HvE6EHU0up`BWv(`>$z(+bJrJ%=brSW8y)26#R+AOd&E9=@ zD2Y&NI{K@$4gDe>4wFTvGgBx8nBsgiTYfdyiEuW{e%Qry@ zy7%8s>IPDZxY=$ujv=jRfQk_+{CE%^cetNzl=4snBR1C;j|_Kne81Y!mC6uI86R)x zEdyC)#IH(8_fJp}J^2cHAXnT7Y#%x)c2kv3*y&RR>$vJi+oZ0kx>uIVJ92$)qYU`7 z!htx1qUUIRma?tlhW4}J6~lYklH8T56PR@m|9#PE345P0>ABc=qk_q+eFsgX`t(|YKk8uEqfc%+ z-wwQ3<2v?c`9ovZ(NXmA@Z4;rKq2v2RQMRaPa$K|8JElZ;e|>~QM>i1eZh zB0e>pOAlke>Dj^Ix<2Z9tx@*U;4#Fq|J9&tya4^x+eAfU>irIlC%O8dP1n;bPL_~F zqy|}`$mC60!PTmq=Rt&?b8I`GTyPqX6S+{4h#A*DU~1YwN)VSR#k;~~^h)Wh3C>&4 zAI3OCC7 zUEI^j9_?#5vHb5|8`ZgralO@lqEfUKD9eeJ<%WT2!CKZ><4aNOTr8WWunNb!^=vo0 zM)}f4tfu5ZygB#23dTZ|`>A=i`gTAQzS2SM$*CXFJVmmT7p&<=i1dMI)aG@KNFiXC z2d(1Y93*t?MXPf$!qR_eJXIi5*XZ^uE5LP9{)fJP>B!8*7rJ$ z?Xy8OoVQgN=)ErTO71Q)t;JV3xhmjg;3Cz$+k;~C+U{6bDZJz{>z@(Jr-fV~THi-W zes3-XaQHassZmwkwy@X*@cnq}f%sA5j*Q+U{u~XO;oF^uxD@BE01?PXmxrrtPl)Jm zM^sUrr^F5}(NE&XrHpVe1jk1__Y|Mz7}MD6paZj`y!Y*zQJ-(qH=uU68rD1xz1=TEEiX~64W6;PXwYsiJ-B<8d5%GK z8J#OwVYu^SXUP`wd*PLm{s4P~)zQaN^GYl;$F#4K}meGvLc!^TwGLAd3!|Oe$6Y10EZD36c=gk{E1U9 zfeeqrMkY6eYn{A0->t_EmGNR?O;HZkENpZXtelrdvA3URP|rW5VbaY>H>_LeO7@Ms zt&wOfz?@a1V6|w7o9$u`z1>%af1kvA{W4o7biL0R{@oRIaaA?>!OUv?fHhL;V|Ubu zWc>ofzC9p(Sf@N?vhgO`!V^7ar~EV;KS<|ot1^vcn!KA7B9-Y=eva*C`BYF=3f@gl zKnLRvQ2~VWPBATd9Wp;Cd#yjNxSzv0T#x;Gf#+ciNCUC5J2_T|Hs=+L<2`||Nu(Tt%DoVH@6v(;icrkDq zHBBew)mV(|fwjt$h~wCG)|D`%y!In<=QwY$R*}Srx(lj7LfSPG(I|7f)UOTUhMsE- zwaWcB>Zuy1Pc6>uhssJA3_?tkcq8$r3>wMNTjg0Z-|S&H3;8uaj54^vw-3lwyn?HL z`9HVt}ExJ4CeAA^;yC@Uw&>dk^^gv*R#`D9s0YIukcwOwq z^a*>TdvdZ*U;E1N!Lo`tR$}{kYG~HaG{2O}Msy$6b5J7Rivb!G#EX9pWS*S+EBzqZ zrJ9bLd9DK`ac4HKUpO_Jh9N!++U?jkmc66mD4vk^ytIsjb&>OFBRMl`C>t(@E4(I@ z%XIxh$wh9jrxK@dyC&}IST8sv^w?y`tIND)bHfis7CeOBtq%=g?#1v3M6h zPZ4=r{{WKZywW#M`YU*v43&0nNrqH?g#ZDJs$})x?7DNSbN%2vP~?orPdpTi*`07S zH3w?jICtH|&tjrgZrrm}*;|CO0RThfo%`Qkd@;fSzt-^7O&DAn*3I)_C{oL-o&cG! zU9MSvcMa7(mK$IEbTdf!o*?Aa3^Dd&rK{E`DjQO%Aj9?p?Iv@IEms`3;SDL*E7GEb zA{;@R3U8=@N#n2(*CP|SXX;bgDf7KuH7^hIt` zo|NHH+eunm2(ln$iODXETe9w+(`kd<{)aYO4-f*xWaH{mf zhb9lq&A3k&zTM0vQj${AF)r${>5}Ajskz9^bhXFvG_gp% zHVW)~FD%2)IiMHR)+p&eAVHPl_gswPr;Q^|h>i>ibV6F2tva+fF_*Xu0RGhS&>zJ- zA5U`FiycjKzYb!}o!#E!8WH`%-N!AhV^L{-$%t}I8LK`qRA#X#ej~=Rpc{Nc*aWiO zvc_n%T=jb20$!8-LM^edx?d4mbm9<7#%s{vzK2$Izy~qvrK<%I4qCn}JN?ukq3(O^ z7*n6fOUEO!pp{5+oiDI|7)4{eQ{?7PFA$@>Jr0nT6X4ODl8iej@*i4e@AXH|7=s6L zeM-)*(zT9yNJ2)62W(BP%*$^=y}$1!II^b|;FQJ14g}ljCGi(OFP@@~XHF}fA$T@> zJ!aTGt%aQEpu(BwV!J^NQm+*QJHQ}dvfPD=38F&t4t;L^qcOR84rhykv zEYnC3_e5x$Bo4A7q-wB17X66~rSEbnq51<5CVwN@r$8x@ecZsyKvJNmB>GIy_#Dq; zeJw9}wiM`T8=)4nem5XTvvL8#7=X~2vTQ$LkniO}zl6$2dLGk7mebOEfcd-)`#e?$ zVwrROyrN|DbY@IoWaDdyGtQaf-nBb9d9~FIqo&(cJ*+@~<6c2E>REkNp`E}^p=~Yq z6pc3>({YzC!2J8;b+051)@MuO?wlX&%u^4eOrq>GPNUzJDpr43Z|wBetlXrn4MWEC z_UIKko6yQJ@=9LRl$XLNt42;@D&lgzur$Sk<5st?gl38AqzATtzM0w|XvG@$6TVQ{ zkm+{^KwN%;Yha%p>^0@#8>f5QQXhZCc?UN>h=-&#)oBv~3D&PbHR86Nd_Q-_*j)dr z2`GJ{4HxsX4jC%yVCd8y?Bj(ADhP1AP3W>VC0&PEE%Db(z+{aj&ZF{|gUO z)~Rn_d(PBi!J`*&eWXA`LB&j*K3w!XqNh^CplU*%0)2<6ScE0ZfM0MpKJ7gaNMrMe zJ2L!IHukPPI8JhZdx>*7T=T#_Gk^Werkxw}Qd^&&`wg}0lUr>SCE1!c*D)dPTp9;Y ztafaet2U>A%6boy^O9e;y7hHi4A8KC$6B=|6jCyAE@kwqr~MbAXFaBPs%(Z5<7n;A zy7U@?m&DzF9{D)vg|c{&DaWkX?N?3dBE6)v#KPFzU2z5Y+c1lqeIW0IX03qGkCpBV zIMsPpE^Stw{fzE^cjdXNpNc+#Z%$Q)Y%V4HJtKp-mlGS`Ekh1{Idc8!w;Wn$+c!}0 zckiOVN;sWE=WcGQL;@?oy)?&{FBSXlt#4n+aYzGt~JKOD=^-^}U zN*o{|6UCwT-0~yg%s?jOn7<}0FwDkVjO+>jV)3%2_ zT^W16mCvV>{eFq18LzF_PjntHm4}lSiWHNCHE2B+2Z1h8+a?$v{XKmD=_fk~2Uwe# zb8%`9@%bL=sRLEhGFC{-i&=2e$_wj#(iV_gq&=%uL?#`J!FNa0QT{*d{dH8-dHV;9 z3)0xs0)i+a4N5myAR!qZ_ji8h zIp;a&`;TWFX6EzGD__^^Vkx%h9^qNSKLuJ@65UyfXE9@a4rg~&vSz4FOU7Jq&UC15 zcUe5veNtBL>Lq&%%f{`PQx$oNQmSve=`b>fF~Q2fU2G4Pbt>S-T?#_^AB`BG6e9YT zBq}I~hAzoD<5+Ak1fTbA@EXve-B2sxd*Ke_>5kzr?&-8yGB0!1z&0B|JfCfoUiIp! z<{?qP+SyBNge=ZXQ>hVLA=SGtX3%b=HwIJY7AM~41Yp&b-HceJBJyoL>Xs#;7?T@YiqN7hO7;DGLY}Jly9y#OGEq6 z2jE2-6}n?$=r5K(Ze6*|0I1*_Si019Wx4%dR#h@77jzw5+9~TFVyPYxc0`n}JzK5p z9HaDzjNYkP&Rl)9SD0e21GnjC*fV}4q*?}}7Q1KYT%31YnK;4OP&(`yd2%n*LWG1# zJ%zSI9zs~4&39D8x755h(8rdo>fpO8NWT`6hjw+r>iWtdwR*6mA6Aq0&l*-ZN>@y- z1*oAAdo=IV_Z^xlf_5uMQ&c)WK6jYg5+26%%&$G@AP3k>$%1yQ(VqX%F_IT1RB9n}nQET(zQd?}Nw)f~H8l!5K zlvVfpks}U^bBQj6L_DIeb_Z5J)2|n9K(-5p^{9|-rQ6}Q z>{!rI`U2%5!pbpPh(g_B;o+i*eRUh%?n$v@;RpE1Gm>&prIRu?iR@l05RWP7De9=I zA-^K0Ruc;8*~=fvtLEUFjV7GCVZSm?qbC-$l?5LsA>%Te6byP*2VVnWhf@P49+OXv zf#Vsr9YShM_m3w->Iz()w!RG8nSvG&Vmw>Q6!xbd+lgnH9rdYtR<3HYM0So%=BpGz zBoX%Jk58q2XAU#)QIhyF`j@ianK!ux%x1u{y?{Roqv-E)nmve6~rfMjLCcc=fT2U`e%7>tuaC4{fg5 zXOO((aNF@2FSbR*lkbe}kAJ-MIiU`jt2PZotc6avpFCx$-PVoS-s(L3B)o7%7x5Dh zXszosw^CMRuau|$baUw`Eh9Mj*}o-J@nWUpbAsJ$9UB z9rYQllDb{By8QuXN8)9l5hV*ZV?kmTLOy~R4__z0!!DXkdQKr z+KE{cE08!yVqHhXx!=09<2+cxsF&Yuq)Co+U&`u)2ZQz}-j~i!u@5%0Eobr%@a4ve zL1~;zuVF{*6vmbl^}9>aW5slc3Lg#@|IX8pvg$znmF*sHZl<8FHtv{t9^*1WfG^R2#qwCNG272{xKZ%Fsl zIA%>5Qe%21s9s353mtBlET)%7hwvW7+g^li-L*mEXXR5tC|tgBn59yb1_%VTEaRo{ z?ygy>Vpo9H#CP(ed9OdafX3e`c#Qb^VC+VAr^l&4WW>l`m^?_FWEF#khBZg9ws>B~ z$w3pSH1e|kU4uCHz2Z(o{!^^8iUHXiO8oUQsRWC{wgAhTgS6waLt$%=e)BGi-U;Wa zc2AajY8=835yn?MK1o26$nWGZw{pC%n@glM3@_;nvT=S~9$`?U31OmEp3;kZMpNyS zoMm5P;=$z_fR!@DQO0!0zg=-Nj&flaVP}9$#`H*V-4ws=@d<+D%OnBk@R>ezy)5^F-0Bp}e@I=+ zOWS35bKy$Iz3t^8_9R5zrCbgYrYfuYM^2zKRs4yb#*Qn;Hg$D!Stdly1V*FgvFbEu zGC8i)QMvrNKSD{9zUkJ4x;s*YYR@O*;%3cr-3bGa23Hq3%ue=m-;Z{>a1chdG#o z4C|;jmyl75JTBrei=@dHDk;$=x!=yKaNz#ASvL9cySN9orOQ2a6_ZK6021bh>7`sK zk_NEZKdX<65_kK5E2Qgi9~g)r!big0$VOStoEHc3=L9uMOiBpCwZz$-5B%L&f+*sS zHR-kT;-_&JJyHNfYy1wtcqY6ODw0>IKW^|RvW?_U2M)Hg-2pam!eZYK%nSQRJ(I64 zzh*p??GSzSWWLukz%zZpI;H!;nv%B8|UWO3WrkZD^ zoMr8Lq_yvaDnGbixr=@HhFv*#sAd@pCY{g`45E%aDs}IA$+vRia?VcGn8VKYskL9= zAHvB$((x+Qd0_}St_dDI?fe=)QH|(B2JjFu+;yuRt+4eu-Z;9o`RVPN{OB|14Vvm1 zWx>5CzPTcgPgqc8ZqrNowa6S7$!XxWUnk##t~Is{=7kJjd&`Q3-*E`q>FH6X%pgY) z4wfq=RIYXM&YZEFrfE=3_6B!{3WLvYuj_gc?Ns_3e1cEq*52GS(A*6w(>Xd_I=ix* zXfc##S+#++cJr;9w9Kg<9AY@W+*T@s5cilHb2#zGxTLnOhzJ|O48V8a%pZ4r;JB{6 zmX>5bA_uuuHd%OwOaM|#Ki3vBrKpogjk!(s)QUcXySl$G?+(e$im#BvZBjA?JGgBP zkK?#esj#C8>=!(G{sq$7Zw?b(Y(TH*pxfUOEC@_f0sCNo(hccfUxP!8vc8&)Vj$3v17p7Sw1@1SHS?J9aF$!=qz zJwp!i-I)RDF2z`UikSKpJfv_fCVtw>W$u9LiBY!on7NBA%Y#R&U(#Wh9dpaK(srUl z_F^3vYxDHm1{3uYYq)ykKRD&9oB*6hqQ}OJ=TubgT#=3zUwt80yw=6M*ju+o+PWfX zzJ88m&T&q!+Gres>pZsM=H%+B{Bkls)fo!u@{k#@Am}|hm{h#MaV;At>4Ek(W{Tm& z&=1+S98@!!9M4>z<6*>K&sqqOd|D?YY*D_E_SV~e#ZI5JZh5e;VoPOMQJ!XDyxIq} zpHOn%tNE-J7Fb5^O2;cdnehRN<|0{4UOWeL5;?dVi)BM1B^)JZWk?ltKN{5zJ!}B=GYz^PUd-l8ft&zEC zwf>6(*(6q)4I0Q<^RA?tBLyaQCuipv+;R8(M}R&6Rj{NyM^aQBF=TTxf9I`U{g z21OV)+aB-fHH2^jiGclH&L5=SPrS6dv{cJUd2mL zM4AeU$lIFXXhaJH{1w;p_GK_qxU|Y=ND~jxcU5teMklf2V8gClV=NFNhHzJ}0qJ{B zRoUQXsw;lQm)l6HMFJQ5xV%#x>)$BV_#v`&SI?Iiw|NqTG6lMtak3)IT2qO=4s+U>Tm4 zdIRb8@D5Y+EeAJ4=vCp<`zUSdio4IVBwo(b4G(~G1{>_g&TI22#fD9{eE z$LvQs)viv|$}ko68K;+Ab$T?Y6}7Sibj;h4+z*&Y<;c`fnowzz5tseNY!-(aVPfRk zV&K%_vS zct?z{c4f)7lecy0;|l&|``9!G@qwHdW0@bNP!b%*x4H2#81ZetCJ^ zuQc(qo5#Vx^;Up;bs4pOZZO}J$d_HQMMlP15$Kr&|lb-GmAnSJj$ z8UF|*kv@=&f*{Py;f2mjLClhgLl22*7t-fe)h+8*W_F)ikoNT@pyf$kE~^>4^rV!v zR`VcFnGOIfZ7QwW zaNfA3+qQoF`q6qje*4L1X{{_Rogw1 zY#`%51EP9Sn$;}!=yr0ZQFizT?c7?eO}E^>y>i*?t4o)U6I?U~eCiROuuHPTFCKAN zEzr?x3F&Ewi;j765Dyj@`?HHxtqo|Ew7$k(^Qc=G?_M>F%gan!tJu@5X6N1|x!Xf! zD=nIzxCAIc5y0M72X&b8L~-*E>#D zb$XdBBm&*&ug6_aWTC#f_jqOQuduFmY>VL3%4}lu4*5GJ1?zVf1op$1T*{1spW3LwXQMT_~ zxy%Kh%#@|s=Y%ZX+TJwX^taE4sTN8}bP8>yxI0MVDO`dLRI*T{#7w!L?Ced7)5EaK z>MOet8?$QFInU{daUR@}OB6pmB~4jNmZd2fh%Q;ETsp$QFi|P!>sQjG%*yh#CVs0Q zlX-{!{bIn53v;g9%|%Yiyp`^%0o_8avu-oXy>VeGbzAgCrGAz<80o%a+DU1_h5i9K zUUx(wD%KZ_mcRPyY=gS*)L{;P=O-W<&TJcmvX@VOGWTuj8~`eZ7aIAsGi!SNbbMHSKmP zK;HP`Y2RwaxZ{dqdqEMBoWvw4X1vScH3TNH;^m$(1GiDHN~~>_@NZL&auK>b*VaX3 z?N+qpI&-gmRX^2HmaDF9Xm}fRL>zhPWP8GaaCO)BN*&X+DD4a6ggSk+p zr-pS6Ik9%Ila_VyXwQEvW4abin9EdL#a}~qqEOF=M?>7CPH9}gX-B}ku%K2&9$6P1 zf3HBpQlwb!-bdRFUh^X(R&<=tiFNkXLp*}7^C)|h8`)6NY8>cN9zq(>;@lgUuzLIi zjWm)u9aN9RzW!!gaR$YH)E8a&f+$Exl|eD@E@#%jTSQWRfVm2iWh~EJjr6{@XPBx} zKGxEh-JZtKjco%pb6U@(zRaoRPEaod8Gap;Lj*Ao!69T(e^NB85MmQsp92y$KD6 zRfj~zz#9YpBHa=DfrOLKyQUd7sgSD5*+s^l(RY(>x^}Of1>dNOt@C6r0W75zysBbl zyOZGfu-LqO1sRv%`BpYxTn(wI1-Zd8-#YsxduJO_5~M5=IpUTQxJRNkz-#CbsTXv) z%70u_E&qzUxN0#@0vd8Rzgm>}F-+}_n;n2 zSsIY?WJ}Y(!F|Vpbtu_IX^w|DE1@)T#W8Vw?|BBFcT+;z+SZvM7uE98NadmH;g_>i zvTXyqL)O{X!)NtNJHlmdF(G;fv+Zge&Fl;48U1$km|qefobIG>-V932-*r0a7|H(v zkaYGe>R6VK3#FPdNUGjFadQ7c6UC>&C2GSoTyE`MS(`d0yVu>hJrJLiFA>4eN*yE= zne0__!(hVT75{P?)DY$(L!elc~=<_%=8 zQWb&Wa{MKIy50xtvt5^xsGBk+2x7hQ#IzgQgD3Ep`Wp-tNxifv+}Hr;*c{$D++)yU z)HwXD17zVojLfzJ z0|ASBpLfxGB$tpup$j*>!0h?n=$0o_ubDEj>@0?m@w)N{lGbZQU!Ro`Jl#%lA-a5% z?q#u2CD#Z#!|BnQ@KBjYE!K!B_wAh}EDXn#>>eh~W_UBR23!G9*Unb4EVDPZ-z71Z zKRvPx?6vc?Yc+j%2Wgiw)}`}MG?Qql#S+x*d`PsC?n6rZn1}cTRsW~bLX+%}~ znm%8aLZNOJG$f|K)F@~MxwG*0R%oSVNzw!w+1qHO3tMjK+;rzaaVc|AT9Zp7s{;7er!>+}>95-|7CPpHRMUdxrOjE#DihY!o9&zC!o}F!XTk*|3hix9S@hhEnO9&k zpLm%wx1T$pgs=hFEQ88y4(e^%MAr|3ZwdP+(?a12h&RRLgRC|Cx+fjPC+!*wBYI4) zMUHWTHyGV_F_|AymEojtPbr;_qJOsk&I9usci|IOZIw7bEIaWBwn(OYa_&}r{d(;U zWtMsCn&q)FnVOSbmvkp$j?EQ^PcwM!_Y7jf{ES4OnpTDdKEuwz&yyuhIUXT4D|8=o zrUf#fkgDLZ&y@p1nL(Y_YkD4qbjar!wb@^tMm*?aiFIU#MJMzthM*JDWI18=07RaPxx0w(C9 z4=S-rg=sx%AbY3&dpl~gc{Og9VJMompK+%QR!4;mJ{|6W5GQf^LL?2`Y{o9xCQE62U%l9#bQ$=wzKTq5? zqxyv^^EzOSB)Uyl^dr$^#Z&F}*pkhD?g{aztq$TPSeq7;S{u1#)l{I#KQEO!-= z;nZpuanKZN=70o?*SwU8HNR#zZQyhgy7elKwYIp7d)P}71ZOA;^ICx6e$A?I0zM~j zH0nQIg|ySBZ|`{W@B(xmlSwkxV1ZGqrmEQ3O;-d-9>+E9{T^<9WS_2!k2G^O3!7K^ zc%$Ma6?K!%Qb$p%(;Uy3GjV?#P?3EyWqKc6YtqQ6qL`IM5lM?6Y_eq-S0m%y?XW!f z)l~^+;Hec0wXW@V!SGGC&Z~;A*z%SSbFw&4wcm|xX;36$#TJ07Kl_cG(vrfS*Muym;{1wczh#SCbkVNFY(m?2fd)6Ar4V?yr2-^E=8>wo(!F6|Hryp?dciH^prKr%sO>$<^12+2+rm9`2D==xXay@qW7i5tmR zAA_oRxV$(JCE&Ex9Nj%tmBgC8vB=13TUj5FXFuD~j!w!O8P&Dw!n)x0LTdlU$`zz1bz)Pfyr zix`^IpDp}0=K%AdN&li((g0PjX7djwiZH*?CypCjQ6>tv|m$sQ|K_6NV4ELO_B zLggOWFY|3m(_VZ!V>)Wbj+Ukt-9wHJVY(kP@F<4_8)eB>z@%4F|P4QUo+B0qF%1BrZ_Y;J#Q?iEV!7mE-w-fcZ zui#4HZY}Q^uKee&eZO%3;~$YeK$ZLSdE+mV>7RX3WEVwyTYZ{C@xy8V+p%4Hs|p5} z@kRNEdw=e({MomgHBl6%1BoTy(+#NQ{|5tnfe)lBCn^3v{P_1@976Hy?j9D||KYm) z*|2_jkIDoL?!!I3f3XH4R4yo%P)!dc3Yh#)2l#{;46aX~>7Pyim!H+o2c^A3OP$02 z;s8N2z~KC112F%`uAE;I=rW4U*yTip|DVr?>RJgH+>5Znf3XHs!PVfL8srO`{zq{D zhy{=9zLnqb<3Py=1k^WFJqJV{t!Z-oLc94Fd(zB_eqh@k34i~ewGTGMU>aX4IE@l3 z8}xELh6*`tPUAYlOl1eVE}-q%ef2QMXsaXmA7|p5Iyl%o6AwAA{^zMZtdmz)Z%;Cw zyz?zjAzz;ny7!F>{`~K^+ZVORx@%gc|Dg?4r=P@fHMU@7of>%m*ypoXEgep@=MmZM zb^n2jf4kBm(x?qdU*#PR{Lk|0U@}F|b=_WBe2};{B8(_O{R$41)rx@vNyy%PhxpowkGSnt&1KE*C&U~NZ!rI+EZSSf*kgo zF*PB<)Z=R-bQmAgN{_2#69fFeeOR!HA zkDHBFar#(dwu=F>;c!NIRXn0L*x;u5h<&qg>uI~-pqX(S2A-+5HEzv7V_TRXP~nsI zpwry1B8&G$66h)!Dy+4uzc5kalAogiP#N%4?)Z?!+^gjKtpUzF-#R9Rf2xXb_g)?@Qk%E` zsQC2(Cz@A{T(6GmOI)C%6nk>8f0YGPFVQ1Yo84s$l)9o26vW3Rb|ccX>`h-ElLBC0 zZm1aGzB5UcBpP`CDL$&*O9^96oE@82vqMRBeE|3g3FEj|7F_%Q#q|cOc1(>QA^nps zrQ+&Dgn=HXzdr1Lyn>EW1&`OU+HB9hQNkYi&LI8I#5*nxII@pcq`9#E z>7#&;?~USl&|xhK{A~mO*Q;Pz6or1@s=nUuZt&mymx>z)ECl&3+yCDu^i6THm9-`q zu~x&V87GD~KL#ov-04o8mDGyAn~}&nf@gS#mA$5Wbu}j3)RtbTWyxjLoZ79hdUF^rAv( zwp68eGv{aZ`{M&u!1##iR^fl`ct&FVhvNbUzs@KK5Nm&@O;hd!zXXRK&`suHpdh-x ze)d`}I2zr44}{O%?el*x^PuJZFBib~Zw32_q&(EJAOeI1Hw4Z*{~{b<8c&lOs?LA? zw+H?5N`wKu8_TUi@%kU85rXoGGYPlOi^^X|`QM+(1aSwzn-V(7s^lehUTM930(9`R z@aW$z`|lSJ+?Hogsgl9a`~Ns})$a))E1ujKxj0QADf{lRU;fMM1^t=iCr}k~$q9gf z0HQ~Kq%;?|wi@Nz>%&Aq$>B6o%`)s|t{TccApP}MsPZsMEhi%LcEJr{;UY$Hh5q?| zQ;FAk)mT)0b>;zoheqSM9&e;$cr+-4xBU0>(0!t3mXjnJf{klJsRnIO^OW3-d|vtW4SC8_e`1@-Iy9AP=aNgegw!FOu!O@$ zQcr&v*dNT{KQ0Aynb2`2LMcT&?4Hg3x{lNQd!Om*z46wL*(cSjfbHc4fclXYsLypI zfQkueyq}tWG{LFTal88Uq(}6MQ9#l^nI|}^?=k#{nHTkw4gn3GeqY85xlFm#f{{H? zb<>hxd&&?7iZCq3DqknCMiMYdMyi3#{rr{Lw@uKC*jN~D6)TCnwvcy5!huhIn3@~` zSaVK_w7-^7!IqdzkG?#ZKTs}qrOK4BV3+h78vNncD@m!EgklyjR zLJNb?X>5cOdBQy_cDY0QKy4YqoQHu&__ffPW`F zM!?DDiaeWm4aOm;Cl&(6Q`yCI7lknqe#>jh+axo&=;Z3j3dslC-P zZ@ChriXp{T?b%7^B}#$8OE-D$ulODIwj~NrjJhAKh(45mn(EJ5Gq?=aOSE4muX=YF zGG6603j{wWJERSVR&YA_u@orLXa{4uwXJ5FTN1FDld=m=-tZ-IE~a_=vto;};hWZ< zucv`s5QRPlQL)RLDLax;3Zc;wgxLz2a`$65UjeK*=8Ev?elm)dJWwLJ=h$QaD>l1P z7nSX>ae53fvns{`I6aXIeVOw5*P}G-V=~psEM$q&H#Zwdw4z;BD`*Se1sL&v+d@{B znGUe5zgW;)t39h(0B99{bi!i#R|Y%cV@K6dOBRb}$>~Ga@o_ z0y@cYE#;PJcF8#Pmv6WdmQcXQXs__iQ`v$w##T&e5%-`L4S2hM1Th~ey}bL?{p1kS zsn=3O@n?oF(^=Vhcwz&5Fgv75y?gFT*5Z>}&hziBc$m*AlN=K$-q!3{RTU3@rkp|Y zH>r-|bASEac88lnRXMXs7|-xrNrl~AuMrmOf4N~h9U>-*o^~8_m4c5WgU=GUdTFKu zd9w@YiC3_=je9-|fC%)%x|X>_4@w2=45}Q*!}U*BKV6{ni1sok%$V_lkKT`HPEDdu z-Dm4xgJM(O2P_a(Dh^|I{iNbqk(;ZCH7>WqZQR4!9i$qhQ*bXJV9LR$+$%X8z!08i z;n{%t(^+sfxKaG}!cHlIWAK`@QK@K{#(a zYTXnAxLz3tg+g8rUYU9NP*u=nH{g=Z*2`-Hz%VwI7T9>Nnvc>yE-i2FpV-7a!1a-TP}BDQOuegODbQP<_U$hA=us`(_ltu3J)i99s{N zau87^hh`rqv2rKiANolZz^5YBEO61Ij+62m{7HP0U*;%xXN2dZOy*kM&2NYxOucXm zQ}>|vWOu|;^x-oJhI*-oCgMpQ%pETq$?FjBk zJ-c++!{bBgoWVO6Z#z2Aan9XPP6ak!uAC<1oI3fPRIJM)d8^b^u3hg%rJW8Y1sTwA z;FM33!e#FUeQutKbe9Zhl1DD4*8PNeXv7x*;jmvGyx&Y8U*AF;@hWwOL3SQg_;Vwc z;ga_!z}aKXIhBR7=Mm;J=9PcsupAf2u$L?9f-6*pHYx=NN<_+4f+VRl2iMIZ1m&rKpgFZoagA|qkSC`n9 z8l`Ds4{q=0EN(@)#I|Bh&{N6ue#I_!M6u|(GoEx87@Q2a29bZQSVeGg>6D+=(*e46 z*@7pS^#J+CcBy>RyO5=F{sUFUQ)-6bxmeRY+;sVZ!OV1+31M+~xWXePKo{U0noamq z$_!mKP?I59Xk|l?xTIPys6sW2aYv$6zO2!qo(C^Lj?-C!3^CO& zQd3rfmxQc08c49A?w~hIIVq2ob~z8`9=*tO<4>2lFG;xKV>>gW^s>Yw7w|Ffnyi|h zs|5;YDE$dhO#}^-eB{&d@8OGm_)c2&iy;LSK*ch!pFsX*H-s?MMP#jKQBl760WCCBhHCMJFc~3V z4BpH{DY17qGm%vEBJ?o*y+(4&C(fo6>h6$^cw?B`?ojhOfI^B^D%tsLMi;jM%w#k; zbd1VXSvM4e!_i08Wy2&i$T^H;mHAYKHe-q@{EB4uq3-Dk_OTUv<1XG8n3ZxfC2U6k z9+RLb&wQ0O;=^24eIFO-0?B_;kJ1P_^u`PB>>8i&URrq{VcDps)whc=gT}ZR`p9$@AG;Mh6NV-)L|dO!CBf|ghX#IpDDul zDCC?QLT3*BnAjU`|4v!xFM=w-=`s!WM3*=PH9y*cL;|nY>#+@scil^DW2Ax!Wv8(j z8!l@2#imPm9L^^PdDX?Pl#Z~_QAj@I$YQxaKn34tix7@znLh1XK|Vfsju-FONjTv3d~(jZ(!VX@tEHm-fZ?yF zmi4J=I@zK0DOriyeL$qjnpt+hYM_=whkVA%Ns-Eil)bjU9zyE|G{*aOf2X$ z$hK|-ST>MH-f@OiF|9(@+udS54}E|G%my$nft`^S=O*q!kG%}ik9yo&jua@=Nj7`wt%(320Au6-B+7YggR`#m<%>kyqubi_oDtO_t-1>nj+chV};aj zUYPh^8{tu)^BPt^DoJds3ETkA73kW2VNlr(5^m2WGz=6E@pd&&R8H;N&~#} zZH8z;Tb5wdv>eF2m_1!se9=X?nH) z*tM5kLAMO!?KxV-xXhKv=L{A#qwwMrq0@amTW}Sys}({cybjdmjLj_KQq|JlWTx=e z^2u^v#gqW;fSBeLF2HsPXv|$sGN-voFfvYuxz#EAPFKn%utwBcWvvoV!xg^8p?9!} z53LedR`0wlNC?k=&NXy*-#k_I-Ih3~fZ~~Yx+JIY;W@-bu>S=b_n8lk96y})ADo71 zl}Qk^!a>&o0pdiSIna?J_MtZxX+&N)i*Z$oQwEKOL6Kx7uJTpLMNJSKdV?zkf@~B{gkCJM2GZ|J|}t49afY~pq;`4yqog$PwHYr@ioed3Jh2K-=qV1~l-) z`+=LOI|{N&;fM7i2?yz;uQfR*F9jAq}^1y2sofk zK>OZAs-)-jdc#c${ZlA)S~}r=L{-N)cB%M8fh;a7R>3Zb!Ive$XXG7TbdOM0=x3Yf z7Mgek3?_-PCGj4|8$K^~f?BlXx^(gm=zJH_I-?bD`0J4VcGOat3aq~RF^m?qV*x~q z--Ev~s$g|lILDii#24AO_Br($FWENV_R;5{pw6v8cb|;P0ub$m^a1q%wyIeS_lU27 zkCFdfb*KQ|G}-=B#UQ6qoHi7((mA8{cX8Dp|4WAp5(^TKVhny4b^6=?I-!EMLD7Hn zAZX7uWzZAmIbiDWda9JAkjVkBV{47^9FZxW$N|yD8Kyn`A7bBkWv^rX&8X=n(7{>H za{}8c1x)AmcwXC1VZu1S0Go`mI^)NQQ6z?u zidkj~@n2$y&;R*{m4ezZ%VtA%Y!W=!f-ayNC}|%Cs2FhDPXE@loXQd%h}dRhO@*Ck z0&;@C4y6A+FL41ql@=tL08_jE-^}y(+eSqTw#PsIZ}cORPoUxH(yr#^VL2+7(YJ z0HC;zMj?rHX+Ph%E4T-P`u?lm7KZRf#(m4v&Q|=L_7B+Hg@5m8{9$P)ahcT1>y}!o zB5u^OmFY_T)y)3n04GTScVF=y*TtAW+k(G(kBtP}WLw6@zg~ggEeQB;%g-opLYF-l z_g@T;$`L2Xb*lUKZrjIS1N;e+dc z<+1)I%71+&>kRS(5imi?-(VW&fBDZxY;yz1!N1MeoSW8venLV9_|rW_hF|{0Vv0zE z!OeVbJRgzzO?mwJE0G1DD;1r0nf@|W{>QOhYZeECiyw@}`Sbby=_b+%qHMuV7|l7? z>95ble-@k<1s(i9OX#0jLgx=6G#*7V`L8b&)q3{!vI^V3xDdf%U~vB*xI_h5xS&|_ zw(`h~X%}Bn7O>c)wHqGX9{VZVvYCw@2F{*J2qd^qPYua_agN*T4FEM z=EF;$HeW@rz+ZRi7<)&rB#h>MHG6`~An=-q_RbBu>Z$F;ndV_ohvNh=N7+>XA^@P} zGom67iCd%caSp!q6pfm3vH8_85O+OzKOKZ~Gw9_8#9$XEJmW%B$c-6@PIk&5 z*eiXIO=$72+w`!jH*T{znrQK=ZIMKNp+(1;)~Lhs8b0$XW~1U*^MA(v_??)s)lWZ* zR9v6rk+a|;B4zeQKXz}K6um8(9SA1c50Qu8!5It+FSj({7O4Xxu)2XtjzZz|vXxB> zaN|dLV9w8he`fl8bTNk=9Va}euH}&%Lv)GR7cCluQ6xaQ89djnP-#^>QQgFJfBibZ zT7bdy2=m|}6**YkA)^N@=r6$HzPMU>tvMY$($$2G6+=SFbHaAvuxJ}jQ@8fs%={`q zCQ-6PIoM0-I`PT*lv!K4%oxj&*xE(38#U= zt>alF?@WXA7Wi#o_J9BF|0$dPE0{$ph{3+ATMD7Py8piUzh0T5fc~c6UK%F+=5ze1 z*gSWslhi@!j$$77t(d=zGA~2i5TZ>xBN-RQSJZggS!%ca2c1@c-jA5^1nWaQQ`|28Y#wv;kzc z4W<{#q@jz{G&PquU&?Jm0m-|oX3vg`VmNKn4gmh)d4nI(^ITQ_m@Gx^4x?cyQP9EO z169!c@x_29;sXkS_HotGA8D`~f2*yB#v`^Rf+5blY^1}ibSQ13yT_hYwV3XvCSXb` z0zeR-v7urnjmkb(kXV3xZVrJA_ZioxkSh#zapY)C+;rRShGd(lr6!E!SQ^HJP>aU; z5(snEo~?P*m-m|@?_+Zb)ZKiw{tyCC7SDK3xF@980eH7C6Er_i+1+D9R3*2GlADL~ zoOTMI>AtBxDOGVe+3~XGR`$4P+g2zRSAt}Ci+z@;aSECodz)8HcM7+oVRLcxXAeA! zp8ys2ZKnBvm4|)TgZZp{>K!M!nQX8YckN7TRNQ6m!Tazk(3>F^m*5_TlZ?7Z&fJ8@ z3956l@nU~2IVq^q7oPRL+K6?^z9Mi|I7Y6NYqC303o~|gq%ImO9eLWAp1h2M0^!aA z=o~jb@iC=-mPABg8$f{>dK@hg$9!?U8Rlnu31nh(KyFi7|E%9qq_zR%;0Bk=KfQza zP?TPEmlS85awq45E$&T)&c4^{Mye^Xj|{sxWapN?@|NQ=cyPR;W9%`q;j3}l@8J^H zd6A4OAV~MyR^VC96hRw|eWZ&0IH9>PM>Lmgb{-%t0dVN;O;e6s_Gf%T`&*}*t@N`+ zokI9&tc&F{YKL30ER-Lr!0I4?H+2BEz&?%Q7&l&h8=%)uC=VPmMQ~e;m z3A4eEuX2r;msJZ(PIYuwrdiR)nO@?)+}=ad#dQYSQhJ*Ph!fCa?a}i|uY#NfDiL4O z)T)7R&@(n+EYedQba-?WIxHWUZXGdNqA+8}FtP=!PKWQs@`j8CAYg|qW6u(}oMpLirH+}dS-j)<;5!8FDV_$SNqMW}ajeRxXBXb5P-N(DktgDXPV)bpU4~?y(yd{U9gF5e--PH z*Mxf}aJ@6goj`m~de!0mR`M!;5bvx}@O=j$8d*fn%Z0m?1ThKk@V8;% zuA4^;fmI84Kx4N5Q}!%{SQb1q(#!*D!My>BWHh;zi^L#Mk~UgN@9V4<*BtZ2-@@PM+rc<{)D^L3~9UcW6)G z7vxcaYv&j+=<8qCHZjI(J$|bQ;v7lOND@mKSPVhJm=yV$J3U8WAuG$`pthyG$yh&- zPPff7BCq@u#vQk9;uI&@aHr0Hvh^pGtIYxJ24AuMp*Z;8-c?lb|LwqW_&CLjf2V~9 z2j_ol96jRPlY8{;oMhU3zW>CpDeu+3`(xJ*zjY*(ML!+j2J^!qplE<;7Qy z$Gq}KO0wT<-ifW~RS3p!8Ubx4eSn-zRO&3TemVoCPA{!Dyo+L3^{BH7IwCPlbXvHf zyNVo~wn;9bo@ni~wm3R=qCjl7T|(erjUMdY$920*$gABQQB!o04J*FdwCABb4NYoh zBr0DV?ShY1HB4VrktNg0!IMjX?fIO0{PY(fHIM_CK>MMZIVV`#Tmfqe_nxi=abF?m z^z3JBLJa3>iQYkXEzl^hfB~$Zx#rea9Pf|Ye)s|hfx-f{137Q$;4jWf@4hSq_-Y+z zYE3@WIeMj%hDaAb(^IbbO87D*U37!h0VJVY|(XVcO;eyf`d-Ae)vHqUV@Ko8q}TpYfk}i7CTy!LrC&;%&q(SDm*-V*+L@M zfU`{>O~Ntk>x>Q*{+?sRWXjgzl+Wi;UDe z;Y;#Pf8mhtc&BZIP@H)xCwQ|}dU5x#j}kf;YV3eg62rcF@as(P7ilzl(g(jwy2mbQ zHJY4hJ)wBJ#QD}lS3scJXcSn;lwiZ9|XRN9%z z8M;sLyVb~qe;=K?W$iCMM=$zd@fayAw1%HtYo2YJuOtwcJs(sSmk~@|eU)_8=Sqdc zWX!FhrVAc@c3PwFr_p|AKmoDv>kCvhceEZBzt7k32&?P*^v5mtow=DKKyLlo(LeZ- zQ~n`+0s-i_OA%*25p!I3?m$=M_be)GY-jy@y!BzpBc%hd6c-JSIAT|Vu*Z+E)$u>l zYSK_%s`WIyG-9Y3><_c$-|rko(y1#@!}I^}3Tyh4*!F1<9P9}q&rS)fmUyXrr;xd= zf(_&4BZjkXNN}Cz1MzkZnC2J|@wpyN!=YBs_s8?zNss~w)6^-u`l;$Uo09z&^Z0DK z2g2s%&e*P`Sh&^Z5tw;%oVE%0!)4ZeOki0fgc6|`;cq{v{|bU?0t-@hl|2J>M|Y{% zeF_9YG7_95te!tg=!!1Q2}7@T=p{X3LZMQt%fvnqFE*bMNW(j}eAxS3>56bQ~4rW(_NHxu8VggM4gB4*zo47)t4@j+?CaGH z-PYO|p`g=_aj#YhOI{%XgU8u6ft^zG=7?3_>+7XOso!_G8{vRg-!1e=_24yO+JBa; z#W5ja^4|LOK3Uho`r{R@!Oy8WS{B(r*PgRfTiK(DLg@qqKkZ0m`%ibdV_N+ip){bs z+`GF_dU2Djxz&Ab@cNhsgTAzyWin;+rtMsBk%>%tvL}N>K8y250@?h!BQ=aa>Qs>G z%`lnqJgAwAcgs|q;iUmg;wwWC#W$q(A?L3JjE8>V z?ELusFj7RDY=O12qbjo&65srXzerhaAJTX;fjEHeQ^uF(H`*{_;fRJeBQWC<@`h%S!+hnT}C3*dq9et;6rE`Q+HRHcv7ix@8eL5?6 zh~{Wfli#+m!1ib+oNFL%8Gi$!x@Ou$R(U;Q%>AlKZuUc*=lXSCtALcjCMmcWN$nw7 z8hG9jbW&62vxHR{gToinP=opqYyOC(FJ$jiLP@9?94h-)eAiARJ zqDSB2O8)$2j+D7Z(pM$}jDWqsJ1ETnhpBU0t;o(k3GguA0nzVZH@TgXAeO4+-g_|v zXJmdw>ilrWm$-d|fvO)&-u2($j6!nD8K_8alW0l!4@uMd;~$)SL99L7(vs9NM{9xbdYreJdAd8v&xx@a{Q@K0Y(#|ap2!=8}4 zDS?_HGbA*F_VvHVc|3vveDwd;IN~B53(MD zxD` z{?j&Yznn|+C%RkIb~#2RaJ%I5SCW5k4`8Aiw7xm+{%5Lx-gTVCL*INmB1`qZk$}Xu zdjvamP^M5pf{^M20Krx8Dqv4-q|{HI;h>QRx}pw?S3e>W(AJZZGO=y;D%6%e^=C8a zUnYfbTup~x*4X!5Bd9q=-d^B@DuZ!@0?rkhMuo$`XB|El{yz5!8Rw_FSeYv`O*be| z8SiCyxqn3Y+4mjZe@$Eh7_zzEi$?_DG2Ah!%kvn&hKc)-10U)Y*l@eW{b>3qn>l~x zA}ri@_nB4>#*LdrN8FEI7|D5-SMgh0i^<@Q)UTt|{>&_W`SBsWd?mTl7DH#$s<2-5 z-!B@Cpa1Pg2X334y=6DDO7soyfCi4nRSuVJUWK)uR$i~oDCsWFL^Qd(@6j-N%7+S8=k^I2l!Yyw zB`;r3dMEvp>o$c>mgW+7QpXPf0hoQaiXv4|(hIk&QU1H-L2y5Q|N_l*@;tbM}r4R zPnZm^ALG1YLG2s281{yW6x*8dlH6>?`^u^=}g~Yee4F{H@u@l zT(+78Y&OWl`YD5?w%7K{P|2_LFsfq^^8YLV ziz(@+%--8akpiA5<{jdR?%&Ek<52kbGt{_vU7sc_h}n79-dVydy!sCfQyygd#pR- zVjF;TwavEFlukN+pknYHp1Ut}nC}GF&GeNny+}z?W{&xO)_6y<=)m}mcrBn;(b<3p zTd@%YBXxz(WAk~febpyaYL!~k$6=%3PNJH-dJpr3{mSU{;g_>SpTJ^F;Ez`he_FnJn%W+{){m@8|pw@3^@uL0vj7xgQ_Rd~qK@ zt7{Ih@!xmMsxCQ`uw0NZ9fI$BF%5ZpM%z&gMf6b(YbGR4>UGsgr^vT;)`JpG%FQWIk75Mue+0i`>AyBCj}zX1<%3G^W8gQlAwEfk2qe&! zIDxVel9zKHI-ODR=FKWCj3ay zlc2HGxKE_Nn-ISNt;ux5$pleJmsCzerFC$9HZz8xs7Q);n_F|ex_?E6WFMqn_Skg0 zXkU(EPu350mycmHL1eej7eV)DLu&3EMQMtEir!%ieHg@fnJ~Hn?=R~@?8JT@+~NNY zC4&7YGo5*(hW#D0BBl#SNAVVsMbWlNYKKp@lJ!)9-3Y%=CdWH`AL{6}8Ry&JT~Vv` zPr<)GI#Jqf{=83F>b*B$;*d4d(BV0LbNZ~f2dYKorvQ*lO^Jp=#+`+x_Xhmh_#m{U z4pu>~Y!l>XZ2Y+sn7wI#51%3qx{eN?IV1^PgenvYE%LZ*VpL<#;Zw`OE&$Mj#{-G^ z_kzmjmo$8a*-fe}hIiL#g{trJUPa#dJe+m^3nxE)M>$L+MigPm3X>7 zSjz&}a@CX>b~+WZ=QIo21ya|T(4<^6lp04bk(=MFKlu=Bj^=_}A8YM1bavOB3K_Qw z+18l%=uQB-fKQqjEyAeNye1ro)k9X-t%5V}mFQbP_9nI~w^(ms50Lx#QM`;}ZzB4v$vVIBJz&^!VJ(p2eLKwN0%v>=ZAsoJj_irfQ8G*v zq_xdTxSF@^@|)v&5-r`E6jl6}f;cYrtLVq|hXVs;&&~9-(yNZdieEtZ-v3^ZiFX0M zcZ7?|cYV6$O1<+*z-Tkk*|ZzRBDTg-Zwl%%WYZY%8sqSU;CzxW+}GKmsAbn3AO*U}SWFJR*PcDA*>s;Su7Ci9UJOWY=7ul2s8C1DZE5U+GIrpb;Hc}n& zC535ESPpAFW~CNcotsn!ei9j3_3x1KtH5rT8M-nSs-Ghuq%r_i*9VOg#}R04A|7zW z1E(gi<-Y&V>h~vpb)1du(qNi1Kd`7dO!1Og|E-nHNm=K=q8bVr|JbRaiEWf{V;hp1 z1`=-J9tflTY1R}p=CVq_`@!fZUHXfZ5Tru_biJ+IApsqx)McT<+`sgyy~!$Q+6Q%I zD-Usm%=&3EwVtP79Q2Op-!hM1w8CkG0ox?7 z!}&XZ0MPN`_kAxy=lr^BvT0YWgf(-y1epM1+ej7STh(}7uRUzvl&J~y62}c@T9>B^ z2@KS8CRkZWm=(`4DXY!uH?1Gn^A|oSR^CKQESm(Q7n__?a}a!;N9bpq81Cfxi2GBr z-YZ@<{NjPjLCL0tMs(`MKLImzYE{b|e&;Cl^O?Pes^)v1Y zm_P~o?5a01KOUc338rZ(9Fr^-FO2R0+V5`fo)0L^ch=Z5RyFYk4y~dP!4p;mR%BtC z90p#yx&Bp4UE7ZNrD#thjyDSO1U(=09_qJRW94vOg&Xu^Sv@-uBL&@<`nA@u*`{8a zco!(%&gM@W+YRefx>+_6W$5ZMLo@bvLG$OB__S&H6OAa3R>>b|4c|YZoXTnP{4EB>T*+J zxk>rfqt`6=tpXRh#e}b7iQ4|ZP7fhlo2w3KQFD!N7A$`| z<2szcLIt`n)Vj<9%Y0C&{fec5($>EHqj9e?cmIv)cj?k*A8VwxaUaXe831Bjwg|In z1(_Zzr24gcKMNm;Kto@n;0#%>g`zos0 zxtaqoP?;e;Y)!^{JS=XbiJ1*!e4HC-CLI$Ad>f?A0nD<0}rp1MpvMWguw}S zUKye^CIibQ`{4f>yPwwowGB*8Mo;}Ut_O1e?h$~Mf6&kIr~u^>(?GBvC~!cynp^2HkY{PP~<9gKiq^}Y<9O6RyYN;Q!Y@Lx5`~x@%TJ-LH|VFBL$;ao^-3i zgCrsF(}x`oY2T>&mVKWwRte^*+O$ZWf4#Ib`I6RAD)-ODi64uD)Ob&dI|pED|=urvHh{chOO_!e`qF!G$NxVEgAT`)(gY*GNoUkEClY4Yt2 zP=e>Pocyul#`g9CImRD_aEagdUhYqN6OnJF9iKzUb||=@Xl>t|R@6S>x^y>ir*vM< znzEvNN|@iRf#KJ2+gC7arK{ZX-JW@?Cj$uPMp*w{j|+$Hf8@`rSM16-zg~LAZMa&S z2noykGyzk}jo7n0B*i6Cc9P z&lfC~*&qKY`vXFScC+7l0QcvGA@BlM zr>hsrTZ|O!HT=@SfH3%IL1n;`{5)OX)O@9MvB&4A{S~xDhz>||Awt2BiEFrZ ze}TY1DWRp=_bItg8diTp8`XAzderF%YjoluL){Cv5}*bGbkOTJwmHq{;Y#L}HRrHS zvv2=0c?)l|b1`o;++Ipm`7bk4X%x=+BawrM0rbU*h4N9(W`gu%anvQ4dJ)cWS0uq5 z;d`ADC;3%^sR2`{d7E*oAV9o@WWI$5L;xrEnq#b_R7gbsR1+xcgMss_3h$<08Q-hZ z0~7-cdI~ z_SmB7?4s?<4YQ$j!*Hg%X8h$>6`x@;R&Nr|000q(G4Pa)ky_HRS0!fkWlA+o^*0{0 zo`$RWybE-1_eptXQ7|IocE`x*_lJmkLSZe1K>`Vv3@@$s$Y<_VcQlHN^h)Pz4XYxG zqW8^{-1+1r%#mCs`F8*m&YXXh(THY}kR3qOUrREx4Q^2yyLRh+!kvzce*%H_?rebS z;L-Mr{=DiyW$S@3Z8B+QV_BkaZ+((~-CRm+c`krvN^0C@>1b3kTsD+eH>jC(GvrUM z+5QcXua z9v~LM?)a}0l(beiS5c)CZ+cs=>oV4 z`^3MNUkqfBJ)#qNOTp2uNcD@nS-9VZ_9ONjfLrwaYykp_crTSV>7>O zZ&#E0ftfw`;E=GiY7HadxI4VvXE^wV{HtU~J;OtUZyl=9-%EA{colJl!mbtuKVX5E zD8VHhmuzWz`q;~Ym&{H+QL#ZbF6`X#R2(kBK}&UxL&IO^)c2U0vxYAUN|RnDI(k3; zF~F+qzv7A#%+=y44wi?R6s3OFwllsuNeiQaU2d!cG>8;;%p;=sbm#I3!%QRa^`+Io zca{cH`itfVTOUICnb>~5(lT-h2-X4v4ui@@zYgfzf-3V0Gs(7zS5zKL*9)pkV-6nW zxQsnmmlH5AD*3nFzP#AQYh7z0iJvV*da)pI1O|CTk0x(pscbVS| zE)ZdAnW9=uK*7q@)Ud9+*X{W z`O9>jk*yEz-6Ph`bN%4r2X;BTl+Bs}o)9k|+Ij;E=lhJ}CNF%8Da$t)l_HaA9TfOQ zRJCj+$gSb$>&>sG30;u_!0Ow!BB)7HU~_73U5_GI0q7Jom9P=Z0K2u7yv>1!F^RXW|_d`%7;EN*g z=hWN3<$APSi7#1^5(hz-xC9)UDZJ$Q)$^4z{6I|U{d&AbPL7IpzvHrVav)DHQ?`A{DlAkd}L)FC`LKF93bx8;V%E6JEupToB zcAy3XP9JJi!9z7Geuh?N?mjZh5cyxh+}t5cx7~>r2=O!;i3klE zl$xw@tt;aM?Ku86EDja4typ@GDWp1lBJB>Nbn9Hx!Cm^umDz=U;sMe8`5}35dj-ht z*SE4C$H>yRZYESc)4c@$!SaR_r3n;3$^s$hvx%il6({N7;~L<}eMPgF004uv6U?$+ zigtoDrxB_M2f+0y`cOHmxoQ+LL+sI!>1z|B@}b=S?Yb`Q{&uKGVg zO++KWS8-kX1a^Y+xOJdi@_751^H7s;F2L`> z7H|a9##ih5HHQyUy4%_V`2SfwuAVjth;fUHS=0t|Mo-6{6&FT`j1e-2E&+i@QC~rL z`OF>KV5F}2N5|-Of6x4wzQ2cxL-Ow$gZx%kwyxkD){RZUmIuNP;9NQ7!4QS{&z@_4 zk(s45Dkmf(`h-#K-_1amE2%a1B+uBJ*O|WSU%Pm6oBQ)}fu7TEQR;Pd^~z+gwdeQvm6`E^zm2Xh$e8K%8+cPwngl5E(8^#w{r6&35n-$9>WL zpL*drfPXBh9IdUMTxaGz4IPmKH2C2(7uxSawK^H&oi7q5KQrmfr46Nk!a_g(&R8XsJ zJK1k92Hvk8xXMP4{gUad1&ky_;1b%4NgM}USGP@Zt(y6*t8ay~0YuQfMY-3=fqO=h z%9%{|c+%+R_M8>E_mrdo{BCE<*B!;mTsV@IFfcs*MK7m>SlP2i@4wAE4Lfge#YIw`REYv-5X7~3+hr7aTKb=+D-KnK<$iK6xcl0uP{xIPP z>V}a1cz^OXqm#@b|9(bv<;UWnmhc&!oA`(FGXd9q{I+&Ly$^pcWcu+4UR=k~cR%5a zo$rfY<>#+DN-bvTxVZXV$H<4=SKO4(IQ)^0`y4HdUyBS$-&jQCDfXYDc114WBukBo zyO%^!3c&Yk*lZbJDNus;tTnogIWw%Lw=29`oI8uST!Nb}2-%6bdR0;_Yr${)NX8O`CIZjA5X@48gG_%+1Ew{N} z;%d+E+&-<##BU)?Yoz5wo!UgE4Y8a3_aE$zOuDm;&JIKh-M04XGTmF8T8|ml-6!Cz z(Z{o`CT&w6wfa&b`Q-GGSh!wBW{-lzagh1RS1v*M72IjXj04fl`Bi}7#r=XeA7!fa zQFq%V3*!2cmUY*rZ_QvO}`P~5@^xAO8XeI;rL{TFuLbwT9cwP`|^^Chq}b5m`i7LlJzZ?fbG8X{b}Dzc%)mdrzgsqdW!mH z`(oDg>Fr?q^tSnQ{M4nFi5}u0m-Ka%Ee}LUrB#;V54_%|&H~b!-kMMSajY+#9W5u*lA|Oz9z?4SR9m zc!Xjk10&xCrw%rr6-Mg(0T5(B!g1PpT3#sDny&`E56-DV^S7E?S-qSXZ!d04e<`v@ zJ6MH{a~kdz5GDWs+O6Se7z9SC8xP)ebQ+sK?PP%yt|5o1H8fB}Qb#PqracvdHqtk; z?G#>Dih!$be0@gx&r1e~#@P_Xs)hJF!GFEr;iaW676{gAzj#Z2tye8d^^mX{{h zCP6)g>Zo_&`rTT<1xkN5T1XbL_mt#giO4)k-v!>|OCe4B10dbrRM45@UjQ(Uy@`0T zwQUKz5}uxxdC0LEJzN*Ey_l)ayay{oQMNHgIkv*Je@Txq5HY7f%%u31l@nwIY5f_^ z_v_b)reE(}?Aul4k+v3a^FnMY@(;93^1?Fy7hJ?J_qRC&QC@U@`p#-``}+&mBOaV* zi4qkIUb~xOv~bb>*|pZ)^TlCDrIES&4y-EtK-XM%owkZ@VHH?&IuFT-Gy3X%W>(h;FxuLkCh)mK7wS$$=`)<|4 zaRlrkc<=R})ABi2l$RpsyNxGu=@Q`98y^gg@wGw5{y@tL=(Q4`N*>+MExcu@>4e=H7z zsrfD^Z!PXiM4rli)fs)ov~(VEs*kcykd}t8*SL`im~}((*)&!Tsx_+XFo8R6%Dt<++2WEE-1GX^+{ z`h>9l#ebw(jeg{?dp826xoea9BD6n*98jY@5(1i<-8IEni|%8IA+2M;F=ZdnTDdx+ zN*(+Bgak|)v3cX&7kDJCZR-Ix-5d*g!_p)tRYy0+NjLPV^U(es%i}{ln#5^6Jfh{t zPg&0R%%*msx-)yK>Hq9hRb@0NjA|i*8Ut(W)k&41QX}=)S>&i+0^N@>k8Tih*M<2y zf%$#Q#1o*ZMJpk6pP!cXLl)_~c^m$ygZz;0UrT|O;8Znn9J>5ZZvw*g56=asADh|S zZ%cyRz#iga!sSL?v4bns^lk6feljrysS2mAkoH)rj%LHODk6Ljx{1-R+zVuTG9I8| z*E920ntEgOb92I&2}~r{a{}DQxX+ScH32||W|>njxlGFsDMRJ%a3U z6YPKP9wIn#bDg1wcHqL>bA`lL=J1%Hy%1?V9nzTlK8IyzJt& zM6*4myw(tbCCq}%-Zn=lr=}w4IJk9pf!{>Ax~FNwD)Nk0E3Ke8g1^zn4f?J#nnQlt zW9`DZX3EH9q>-pEerE{J=wv!S<9?&9-Jy;Z@X0GTZ$LJUn%&A?d8dVUpM%8|>f?831)WO_7&j};o=sW}N745tr8W9WzQ3z@%g*x4cV+08 z3VHXQCL{|j8#F}gVCHOer2c*X*vk0ue?1e==c4W}KY`4F9V3;&TOE=0T$M$$HYL~_ ztwk2xf0a}qOmW4uXC)Q!uiMb_9iPK14(~JuF?$oqg@@mZW)J(7*KLuQ`Jmvb7ZRey z2Aq@W5t*ZVuhNBL545HG8RAvDU$l!SMMPS&a%C2EeIA@DZdi6%FNFsw1q32(=soxU zv46yWyYAB+#`07;E9Ni>_+FDzdYA#8oOmE(%8|M2y#R39`W3b$rbA-8jWqa0gWpu) zo`nIDsl5N>imp|;bBNuX`g&iFd3zf&9YK&?%{l(x(&Sk!##nbRv)p|RgWapDti(n;!0{@Vv4&{d0% zPWVf%Y`NIn?fdVkz(M=|5N>-{!G`!LGkI;GoWMF^kyXgp}9yyVe@V(KpHXfjzZ}tcaI)!k*t;Zys+SNAEFZ z3wAA?eV>2+!dJP!6?KL;XYjLTbgOCVBhFxWTACVT?H-v-hbJH!3^KVM%zk~u>O+=n zIQhA}8}~U$O=vwLN?_oE7<8fa@1;( zt!2U!qj4V54aQNm-5{A@xc8zoENKDNnn5YALJky*^Sfp3=e2YA_qi50G&=1J4*BF3 zsBWGsVB@G$9}Fs4Fj`mjGo*!#CzzYmG>%5btz+4=wMQ=@LYrh$AtEivY*Y5H%?9s@ zTBCAkPJbsK+IA3KF`K`nM9l)XWst9&)2mRv% z==@P}X6c-x(AA896YH~MWw4Hj*-p}s3>7O}gMNmS%`rqsTgs`3NdkQ1LTa8O=q+T& z!=plW3IlMhFz$a$O6k`*sT{Z9G{RJ#ht<*Z+Sh^ey%#MIn~gSO=Bv9i!PmcSe6mQJ zRf4h$Ig8D$^>B%dFQ2l47}3Or%~ScbP&jc@gsnj>BntcC_^s6A1`C9)=5z>5ozE~@ zAm~dgsp56y$igEXjAijC*zcei@J#ogx%WBuP|;`U?R0IL{xMb0jUiI%9iN~JbpUK? z_76hgX4IJ-3mL^z0iRi`v_ktSlZZK?`WrHW zhFr_}PJg$dB|WcN=%-!3b}gm2fjs9Vx|Em262+ae>)(8eBYx2{C$~up)LswFfuBNbsIbzk$z+gAaND>NVfJwwlKd_HyG3gM zho+edEH#SBfU{9qB(;d++{7u#_z1oyE{P99W}l~HWAsex4C_5cr3ApEtl}bfCX0xs z=z@SRhMPZ&lx`O5h{MuM_E=(rkA!D8S;v!78Ns(94~qF|BB376x^TRjg-Q2Ppyo4j zx8FYSY`gAO9=h_=0TvS&eNd8nPffTP5Z;@tI1j^30l2U%X5ykUL3?zNyd(l!;T67j zG%dGImd>n|j^8;x0uCD$05Lm%D!)hMnm{9Q_x-27q7}Q;IL&b~LVQUPCe^o-4~$EyTX_Eb zx9hxWbFB4p>%kH?gy?*&HDuWXgBwopGMez4bc;y+EUPDf3qCG>i6QH>@b-&wmpfLs z#fb8DHsoF(eMeXQOJv*IrZFBu=t7Ks6Wl+2z-bA?xJ=|poXS8s0>i-a(;zGgvHANnWQ@01+^I*THMzU!dweIqyx)hD z`l`=S9*_r%Iew_tU|X0RoZ$BBLAFZ3FKBkQUPHk4LgC4V?E00$qFT6QO0UQ|sC*A9 zf37d}(o;&D57B?fqfJ>||>HZ6VgS|&V9>KqpDVFf{;Wq+8B zA9~&XsjE@Fs-BV>I!hflVy97pZ=Zf+dVUSKm|RdSNd)X`u(FzKZ~FV>P07iR&ee-3 zAQd)B__P?NGUmpp+9!*p5KL&4^@@uX!wj$zvjpeGg)UaSIxryReaI+I?M6eJ)pmaO zB$Ps3mj#spS;gcgq5*pF*(u^8OLbHIVB|U#8-EuuQCRjTj5~jIyR^*ikBpV{Lm)3V z>4~dAZM+858puA)oK^=$u|=m2f~suI^zU*7%$@$ZT*w;a~k3#Nl& zq+S1B^=qd0CZj%7H89b|p?&A=-(_6=S?@4lUC-5N{xAU$Fz=KFDb9}iL05*@GCwk0 z`#D+E_qWMK5uX-l({y-P{cyU0u8L;!l~pP|+k9cv-tR~^)4S=Ewmhcj72;4wSbLuY z%q_nr>l~+~CVk*==?SvLm+c??S{t`+>F3x+-kQ<3datGvNUM4k(;165CMt!siNDxO z(Gq^K?SQ%jtt#`0+K>eE$=E(w*q-9>*EijsTwIX=J51Qq3l7*UDNTq+(gx!FZO9gf z)Ey{FXqMNcdi&+7o;c=s*Z2{=E^(8;OVz*@?LiBC;yi1g>!t@_5K~Wauapw>JS>%{ z!Phmp_)3Hh8O`GO;nw+6<&pex=ZJ#>Pl_d8QDgC?}k7 z^b`6{fBM#;x?kvT3k96G^ERB|av`X`z~nGX=lJS$vtia5)f38Vzn6U|o-ZpksP~Dr zYPT+?3G)~K?BBnuJW6gl{*z8v;P+^Iu}siXRSuqyikOh7|GH@(>l2pYJ7dHaA6g#I zJ~llXs_^JPXFEXi1E2z%>slLs(G`^^t%VOYZ!GIdn;!0xE}4{8I}Tp6Od!O9re8J| zU9I|I{SV-;n)T3CdU5&e$Y`sf%61z6u&m3>&^~7_z>c+xtjftAshS*Xe{-obhybm@ zO=W08`{c}X`}38f!v4BB0>=NaDhmKdR!6`_$D1R&c!b$dLM;5|kjFwYtAe z=*+$ULd~Y4Zf)v72EUzZ@B?+K3J_82#fu|&QHY0MjfuK_N%dTEBC3z^Ex=9xTj3-F zUk{$VMlSKHFrU3Es`^uZv_0c_O*Z49)M(KgF;M#>c|`DLojJ0mr^h#_-7BAC%F=0W17;eVD<<_v>!A-e9}Ib`{ZiW2}d!nV}hXFT!r;od>@cr?3|64`SkJ~ z5W`UD{UB_T({ooFn`i2E_Vm51PmA(2kwpd-bUyG+{irq2PtOn^P&#)&>Q~-47x@Sp za(RX2?FJ@H^}m4Z|!dNHIn_>aws7o1rg+1={~%&+fMk{2D?6~Jl*0W2y}_m7W!TnjGS)jlVkYgEuq$Z z2Q>sEE_xU!d~`bh^O}T+zd&evaC@0_fGOfyx$Ega-fs7R-~oOSQPBqwqTTHKVo!0b zc6F{P)^w&%25-W?&ALiq;hvg-?%9ATR6#30$yAlFaesfB!5l{Z<9YOPhqjr-R{GbS zdQBRDUp1mA zXDDab#g<-uv+XvTEK%qdOa)UP190)QJlx}kM?tGFJ0 zUZii<@UO)CTq*f*H7c>W1b*k$!#^s4CY9Zd7p`kfT>P1nJ3_4eI{f~={tNF4BpU;9 zi8^Lu2s)FpXN3ZsQNIcw5qAPePWm}qEo;3mdBn8D`sFmcvt$duSm?gvS)mCiB&h`NJyu$!mj$M7Ih%gc^f z;@SD1ViwhaeSP2|bwbJS0IN8<0l7X>mI4o^6uBHWZ?sGaheUrKYX& zsxUg5hM&fen3RSvMoo#G3T@3NXC({ZU=Nj0oNb>DUf^_xcru&C-?=yYgE7Pl5B!!t zS_*f!`7=OvKnakG6~D%KQ^P8~j(9+CT9kRB?a@mjTB zNC6}d(`EVc6SC4uP0K$I#BCQA$TxlR^!clIn8))~mt>hec8Py~d|LBh>T>JaPEW3P z!iPN|d4wv5gv6X#nRKTa5j2Up#>r+=Epc4w_Zt(-hVJqy4$R3>c?H>{v9ZI+G`6D{M@wS zm|yth6{UkSRDmUeVWXxZ#g{1=Y$&vA6i@Cv+JEJI@o0Bp_5HwUE?UJXCiL-<5K}8aEB< zW}Eb*>Vj|EJy1j?760>|B%M>Bnj`Kkq-%JcXVK=aLE49B_P#lL2V_`vl-RyRg!na$ zJKYU!ly#M)fQhg494xRFK(BABx*Rdc-CxS4Vz?why}9zJ&!sG!O8bQ>TMcyfFDf50 z!n_`Brs}GtT5}#Se7~Ia~dTLD{;bu(05-9>j;DXN-<>kUiK1`?A zIi=vewLwjkfEiU$b20vGnf}$|u7r-r)3KsPCu!dy^o=ysC7bE_^e+N1$%R>dw!f7h@Y>HmDBrwE zE`?jd%zm4fhqENZ+-7ER7pP)L$J~ed2NjIU4rWMizj@eH+_|H$7?iAp8s=1ZX)qIE zt*tk9>lYAk^pDLvS|n5y;-sm@DoY*?3Kqfsi|hww(Y3Mgr0!BI85;9z70EY3@Sv4 z_Zg~-0yhK4;8shy1OUl>d6g1Y>n>E~uK{*WiFMgp2wo*()%F_nIr$pSc~D#Nhw*;+ zkwNMHu+PxmVqNL(nz+LSen6YCEQn|&$d_ae^&Gr(Mb*rNn)yvTAYE=_Q$;p^B@OeI zvf9YI2O4XBRoTu}wL!JUq6j+&C0u!-v>cSIPjZd0FQy0WA2rk}A z^V*YNG`^Utyn24_FqQ<$x6U8auDET;C`TJLIV;98z5c}nQHVL#DHl2yBFgGyKoLd% z*WPtTHI;R33E*HGK#UOqMVtW9YPO$hqc~!-fzufoP2-2Uz1;V-Q2bBuFu)$oO|}puXNT%Q7E8o zL?Yx(3h(%-`P{XbR|Ke3{+$=q&V6ZE)kwb@CY6CDfK(*SFY04&56yrI0%?JIPb3yy zO%n6-ZGQWsd1VQxzR*aC)<&oU33rJR+|=(N$=SGCt5WN69O}rJm#vRX9>gw>nT?qx zoOCx&T(~oZnGnoIAYDUT1D)5v7Jt(wvZN99@#MUk61P){p7HcY!&|zKr`Jc;O?J)9 zL=n<4_g7a(++BaYUi{cD6=EV|QypA;sx45n0AEMp5%V{5PI7r984eSxQ^Blg9>1Jm zuN!w24*(0=sVib;b6rtP0J$dqX`;eF)i~JL*`^3TR31xxRJuC^zLLyM`?@fasM|b# z2Kz$J&`xEQwaz49`@I)79`w@pTE_$TPElr4NM_{t1@U!Q8Zo`yBu z4ddA3f$`}uK*T&(tVbVMi^4Q@1l%ZN*y&4j$?zH8#BK!*xHl?cbcb&HRGCf>I7JH; z@FrLnMh4Tx+vghG4}6HF=L;`F7b=!|3^S7hdl7IQv=O~{DzM7f{N~Yyy7v*J)O&|k zz1IY9wY)W>W|`yEpY{hYI0{X`aE!x^r3rTGEwZHwhBXam`114`Dm2l~q$@FB6Kya~ z=`pS%Sa2)>gBU{0R}GK|vX*`4@CxXy`en}sy$-1W`maf1d3IR$UJGAXO;c(fL0pDc z%1`&vXCJB!wKU@0yE{mW7<07UT$IJLqS3ciO05&lY3DrA$crzj<1@h{=Z{_}W-y`# z7~K=yr+5cu@4Nmmkg(8(^x&>f$FHE?E}XVPjhl{_cS0P|B6a~itPV~c3p=FT+1&ns zo0A=>286`^fRV?%r=Kn4j$=UotYUFgg#4>bhlcI6JD(8HGSDV&1CC|_x|Fn?y1MrlUWFYx2Jo$0^tfd)wjpGo%PJR^2c14W_7F0Cm{GW z>}Mem@^110X$}qu*V-9ASd~}rwV%ptjSlUT3t9U><)~IhLcLa@iO}?OYUvOOx0~Co zGGj4q{0piheMQM$(X+u)LN}R47Tq&IvYEU|5L4 zvP=m~PbSZ&b${nD@$mYdfZ{8tYSEZ|L)2sQJsX5Ra=C|4ha38(11suKuY%QBq-ql) z3Vb+~Sbw1A>Ofn2=`gHg+Wf`HoeAM4ui+%eEC~RB!77qVZMSAfr>wo!6H(gqmUQ@w z>-1B6P?6=n1tyW1;ae2Ty7PPc&jCiiRP7ydYs&ClIJFjAvj5b)6Dub9j;=7qf9Y{N zMyaIJ$9-v>8nfvf?%SXvoD&U`al0vEsJ1z1hkeAN8e)4!!HJpm+jG=2b+QNHS^>xF-Dux}r_sQXt(Pg?HtmX(taEQ$JPtk# zsiJx%3mB@LsB&#iEJO%*Y-Tz4eTx#Z)Jv3h+p7XM&uf{_{!p|s`E8l7(KEUd8^p}X zv8xg$B*uC~Evjcy2&1rD4Ho1|#gfmnlUX0r`XE zNLT)P9h_huKR_;@gEi5_o-A> zX)u&iXG6Sxtxncv^Q9#2*T-LRaZ0K2$;(n53R8U**49f>@d(G3$&Cx)Ami*u@m+gt zQPzNx?FU<`y7&C;vDaUCD@7M+J-IbCeX=&NcFt$yrQM~lSs59EdGEAa_X%OUg&yj+ z5h3HmW6WKQDVpzYk;UAed=Y);LlBUhyf(J)(G)`XbZ6+)>H7_kQp7(<6;hLT0j#>O zFKR{adH2=gjhOH9;^pw>vHCVW-2*yN*|9R^v;DMq>>`~QzKrvxzw3>D-^P>H6%Mi? zC7bf;XQyAM>i>38ro|WSfX?_^DbfLlF>|ICeX|c)H|k>qPr8}tS$DcQQ(a=~h0{w1Z9 zD+RQaF}kuG_%`_VdEP)u{oBGi>PsN zpp6UMK`M%yDD%U;w2@yy<+};^%kJF(Xkn)`w(*A4S9ZWhsRrt59SQk z3YrE`$LV(7Z9#=#q8W2VT;a#FGHN7UB?s^7~y zPABJC7U{^>p&S>iQ9HBp2bZHop%%y`!K+Jvo#%~^0n$vh%ffIo4b(nKbtSWwP)YAA z1^#$?=ZmmX2&sD9c+kT73UWKC|2y7+;GeKzwwz?*c)?b0z3@)D+JTBu4k!w1rF=_= z4f=qGu+4ou8{^~xW%fAIcxBEJW>?|~8vgx-`ToQb3&yw7g>~@y)9oEC51!G;19^`# zQBwYI?EN2Z7wtePhppJ=FgB$v*~_!>HUV|} zuf+QknNc#Z)uvD~C!5kbLqYLpsqBwzy22+cuoVlT_ye2LcAf^xG{2I>{~z(c?-Q@K zfUVZtU4CR!+Sg`4nR$4*lk6EwV++`dIq>-($KT0(|BsGu&6V|dJ2Vwt^^9lxG~my4 zIT;8qh{GYHxETIV-%wVRIr&TkIbo(Kl%CT{DU<-sOyfp8Y87*Sh22%%&k`>T<>Jxz z2>W^}J9|Y33`{)xuYo$@6hs&|nCP_cbBUbxKND2SKPx*%rR_Z^YINc(JZPz6WM72S zy@wkn$IM({q&@mSaWFn;^;qG2K644H*OY2Yx86K>H`pL6&&ejMGL#W5lWfev%egFOpQ-ZE0l5wgpGnWg4iXlVZXtZ<+>c)q|#C7M8o;V&m~tV^NXIn z32DuIVy}m`u1mj2FaK9#I^bRk5+Yy}w-{?)kJ11Vaw`^^2|o{|qwN=O>%a2lXz-fK zki%0TaS!$o=cH9QAgEvL-!T@SiI##fOP>csp1=)x%Zm^$@j{B1WDnYk%Rd9>ySt6j zs#RJv$t9ktVaumAOI=CiX-vOVp=UJE7+!c1|^dlJ8YS*ZSxlzD5K41BtjR>Kh8McNM25^ps*3O&Mk$gc7{84gH|Bq;o^R2H2n#%2&_0))GKl#@-w zI*SL8a^I`!>gk<)eg`6^+kl%P%idV`5Boc4@PA?aKidE9IQ)P2eaepsnkvGxWHPPu z>vJ78$34($gL15j^lGDo?gq#B=-<*}GZywgpggzU2&CmE)f9;1!vBEdO1D{FhkZL6Bt% zBu9SVzyE-&vq}J-?-d~&*_3wiCy*FPCQ2+n{ literal 0 HcmV?d00001 diff --git a/doc/workflow/repository_mirroring/settings.png b/doc/workflow/repository_mirroring/settings.png new file mode 100644 index 0000000000000000000000000000000000000000..4247abbe224fee21f0bbbf0c347f1af6e72988fb GIT binary patch literal 290053 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%0DicDXDz}5c zgsyKyGwvac6Gx1hG9?}S+9Q zeb^8O0O;taGpk3RA*hZ`U3n^TRsVM4o*swwev1%!-SdGB~`gLKRn{exSt1iG!TO6p%nio zZHs&P#-{EjqNTTjnhpeeC-Pd@?<1!G%bll(lIb zgj+YmKKge+p*LL>O<@l$buL)XduRDBu@K(|Fb6R4mEo+FB^0Wk)yk<38VO%zZkp4J zY$JzXWjoQ_@Gz5o&9KY8A6eE-rh=>Q!JunYSF24_@TPO&Eb+g#EWxQ4PP+wwQR@j* ze^BJVl@Q-*5UptbHb!{Ms1rvBt3_klWLnt=+sPkZea6s6t$jq#mK)bqpj%Zix?ViN znz?@B4iXoS*6=Un*2wgNz4YFk(*&tIg!Io%DDv!bCYKvlcwGo}c~)G_H!K5=CTJ@6 zM|_}}>&{W(&lM`97;+bOS@#^2ioAaZ$^U`-1L7>Uu1uN{2-{+R6+`e#kNMPL8)89M zs+(KfKYFk>tztR@q0M-i+BOFV-sd;ku=G4EY%V@6>FGI+ciK=(bm_6X71TxHs#b9! zWQHk5H=oo8Xg-{BcETI|4DE(8Y~S~GFYFCe3XPbOO$qCMC8PGaGLM{sc)x+-F&!5Q z1p3qlB2?$!D2Nr{h5ui1oZquuhd1*U+rf@KYywaeNtXwrJz9cfL{J<0oc zuTnPNqdYF(6~~7kDN7?_m3FFt7BoMn0Cz#c@$pEWk4=TLr}9HNq8G!b^y{%TLILhR zBa|}DN~e2_xaF$CfFH2e=>zX6A!nYOzX_QLgl3P^^DBjX&YGzJBpJ$j!PFU}mA|R; zxSBCkmjhf{aN>ilhR7SM$Kw^DgRTvZ$!a9Og}j>KKIj{0Uu7T&=F3XtOaS@RL7Il6 zyJ`k-DFJ`UMA{%8X+WI}m-1%iWT!%I^MWeSkG-(oi;@r zIUjhoB=PGnQ5Irh1$2rl1+W!>ZC1H}YJwQ18p0tu91S)qe6=EdqJW#gRgVhp^U%(| z6&)d5E8yHKeaisvG!-3-NXP;RWsEr7=`asCsCuQX&;-$k=mKg)cE~FYBZ;zSgmZ#k zFjFVblliA-;+1aprUxT7(*}94v!MD)yfop-HHko~ZTSI8WdSRo9Wcj2a{9cLXHM?5 zOWrtN_kf3ikgZX0dJ76`R_)MF;yd+-7)%_El0bqR<-Ru3Z5rrcH@IztYz}+iUsEtr zW@Dia0jx>kIYU}bx`#?QkL#vzE56CNr>!oKoR)DR(O$5AGw*Q-LK4>j2!DS_!2N>s z7pJUazoLe9!;Z8IEHuED+gfpsRq3Gx@JxjkW{Ejq*&qgu1HW?=?|bRO!;keLWZHa~ z)J%?`?1Q*uL;;%mt>;vOi<_qq9sXDlw*3^Q_7!lT zGEo@&ankj=@Kgf=yh3hl%I@^4iU2YjptAT#gj1%Nk=CyTa3^co3rc|#|87cctaPL# z-?O$sMzSAwz;@Ss&$PMTOCRJ^9-$y;1M%X%5#$omC*V-=fS`)7Z`MIe!TZz^x5+hk zXafFE{;6ObUd*zG($t6=StUGaS4PJxpHPoXY3;?9Aq;B~4Ia;iwc=gOzT7v%#!6{x@ev8hRpcR`@B;Sfg47&F2aW&m(QOEyKxp$qI)1e*a0 zDD~smQF=?%=Ysi3B5q-jDJ37*ep1#tX|AmFlDGM1 z@K@a?|2MGrDYz3B`^$Xc20ZVkfkKkgovCE^55LWc+YnY`y?;kqd=UUS(qUQ?OTTdb zirSRqLCoU~zsX5bh9T^qFdt1PHTdOn1iI7#sp0)trC+CGNQ9O9M(L*k zPqr+r3|%fMU)(IStsGRMfXd$A1idMfT&lYc0qigQTyr7*g%Rk@q*W-Ow&b|5xJ)C- znVO|@WYdb^^xLS|Y<; z>Rs$C;NED^4N@y0-tZ0FB{r=yB=k4E($BAoO0XStX!cU0GA)JW3ac+N+|9^|;Pc3$ z`hYTdqERJaqJbj}uD9 z|F){J>z7FtBwiTA_adGwO^bm!6%)_7hd9hQm=4BJHzM++4X0KEL{T!YI+XL;;Z54C zZ1u50l)qZeCPG#FOOK7!FH2pBe?~g5VOX|g91E$(*eCSIVkfx#eBA&sO=HqQ$8!IDR2293GNF5U#ZQ! zL}<$Vl|!jfGwFR9)&A@+N4#a_^-=C^2%ahfnf`VINoIhtppy_GGvCLIg1Skq5hHf< zH20P$1Abx$r@&k;onGtl(^!7b={TGh99m~O8FL=4eQVE)S$a|tKX$Om^bBIP5$}EK zK{slqbwG~~J`%kMX*IKXdDj=aK51={(k!wAS^P9O7xqX;lHR5)2IQM6bIkS`T=~9O z?PC8R>>ZrdWe&->5b1E;k&gpNSnN9m@fBqRb@|GL21TXB64mSSgTSXy9SY&{MyPTY zifhgVEY;ocWMQKm@t4Ne7_Y!4Zom8Wk*~B5&1ut=6H4#Vi z$u|`{+O)qgfxmFd|Hs%@hQ-w^TL%rn-DMbt;1FDbySuv++}(l&cMIKZm`U*}J>Cx_Z^BRbB7=IEn}e!KJK!rnmWJMEKFgXv2uPEi-yO z9%79S@5i0>vA87ocIB5A^NA)^$|=-vVsh8^B%~z5>L48=fTLYg{hd%%3DCI_Tb>e) zuCm)Ct^U~&2N%y$E{)5*wLrKs<)c4(W-+<$Hc+sR>RvLhlxHbbL4uTuar3X1k#Irv(&YCLm6AHAlf> zUizVQC1>I>xfM4HyPP<9vuyHSa9Rl5i_2F(L;=UFWruO(rF_EFm>Kf)FT8qRgmRE; zlQ085YE>x|hDcRZO&?-(qi$(xG&8^Z%oVlM8#-?k`u+wTLVqHuB2(X@r`M%%Jbjn+!aLVCT?jPsy#mOC zuQAiY)SVgSDYyz{&*n`=-@WYA3n5=rA?%SI%hHX&LVN5J>eEdfg&m#Y+PYNcb`}5$ zg_UnSqV}}C9(0-dtFjhpWP2p6I9emCoVKB65t=q#^_30`R;x^xz3G~Q6NLJt%-zlc ziODlHkzCgw`wKwBM_=dXyIczGm-nCI`%(wq4|BMa$Xq+JHeWxkvG`F`Oprq4lXd!c zHy0Z`zd_YsUEnyEiiD-5DfP}rR;IXm`nda8zEb%8Br|g6Y<2QIi<`W-Ct+zY=IBwy z$!%cudNK4?UiwsT@#jy(WXmMQrNXsyG6fwrjSZlNizeUxbalZ;vKZ2n8}U+P0E|h7 zyMG6wi=yt~x0qB1%4XmEI@Rx9=}z)e?P3m(0+FmFt>Cj1#_j3V8ks(yT1M{)@xXGC zYSG?S%RdFU1ZZ$xTN(rk>t=uH=lN*{eI^L1j1SK}giiRWhz>_PR!K~+%6FBz$0*L& z`qCG@Ljt)D`=MgZ!1(&GZXLRS((g@UpxqLbfX)f67z_)mFZV#5>x3Vt?O`Ij-VaXL0lwlx{iZMU^xMfOd_b4seaF`S= zsb6xnmwuwowx;c5(Cq`9>MGnYOgtXRF!@u;ETP>Rh~O)ToVmiiBRL_;rFOuOwVxij zJALY79|{$BgwI>;IsE9&=&az@T_K7LM~CEaAi6KGdE9+CKioRB9v zENO80!fi{f-of+r#`UF{luzbSl$|c1`e)f13fpkRx3M2&HAbfxH*R7=?AgNfge8DD zp*e8NTh!h9)lN1K=}I2V))puz5)daEwH^V|hGq(A*xT!>mBu?<85OnS!EZkHee6D= z#UO2aFOhHby%+d}mT&Rh>{oSQynio%Jc7|Oxe7j<6j(CcXro#Pk9?0iR+D|SEgufX z7&(`}D_V3W!HzKFANg0x9}s(6xI%`zyLfUoMQC4cFU57$NA3b*RJIp|pr_kziw?`B z8zZ?sz*FFpbXUE<3K-LS&DGiV`;q4K142Nd8&?Tkrc@bheYR^boRckQ^3Gtv?40)= zz|oS)qW-ugZW_xfaC3oLdiukXkUX2CC^ssd#YM5Ai^J)M61wWefiTHW9FM{n zB&ZTcg$2R|^pDgSoexW1qxnY$sNv4I|3!%SlQ{Kn->fY0n?FUK7DUtccXw?EeZvu> zJ&b5lERn9zY?9%VUOe|fh_=Vo2ZXc@1+(0cwKv!a zhU|rRyH=wXicldCjidDyMFUg7N$U_s(<);%^A&X_MSC(H|4}1yXY$xb;ikQCDH*hC zNEOXGA*&0`dppH0F-??|Ow0fodSdGG*{*W;o<$W%jW5NRR5V3q4HTpaSZ56kaSyLk zmIL>(E&5bY`OqlNtQ4zYZC@n&E?E~hA0X3xn;bzQ8Wa3eES}Aa$JRn7`+L6+F1AbOEeQ_3lPC0k> zTobFdpNb3tAnRXaM3e8dlDxIlfSibjTTmmffF+O~uta6uSCtEGuqwuRKK89!TIO^# zmjk=IqBrxYqCpiqc5PMX#(4d?mVO>pVLg|te(rmm7t$t9xf3gQeO7vwxdQp9(1*#Tbowu)gVpKOTTE5fH zI9oZ_@tJU-ABKBdL_g<0Gg+?r!J+ccyo{!#KTyfv+`T(e`No`fkr*!f{Bow=@pfs= zH6fA4l&WxahucQWA^h4@R=sWStBm(CpT%pRW{ZBO25ZR;a2JBTHQP+{<|TV+sqD^} zj+=g5v zoJ}*v-1G!5$y9Bhmb%k|%CZs0*Z70fVkjDplQs7bG0@^C@qD41Xp=IM{jJ=rH!~DQI|12(M2C%^@4ihe7jA& zOxQlGpO?C5Al65R5_1(A^^!u9irSMK=*p&1N?+}Ol+SkcH_X|)v&qEVP8$3@CQwG*&aH6A@_v!?(UAJGh@!=-njR8yS&b_BK*MNPH|3RljxLFsJP2~o5Barcy!{fOT6qipe zrEa2)J-vzuGFNY`8_u*A=5R5nnMtLeIkLNX>tiBpP^A^U{G$aOxS;w4lR?Ae=mN_G zi$PBdPvl_-FVfraeE9kz0EPm=&Id*{7Qs;t$X89dVyVT93ixMcTS)-ul0i z-G0NyxH8_|kdx!Xt8dG>%QM_9R&Dc?y-{g+rya zUieNm&?*R%U&NOl)HiRV0Sjjw+B_!Q{vOFXPYdeuy-z^^J~FRn*RUvM?RD@PYbZ6C zI#?`+%_WFM0r{pJu^B5NvU5f^Lj=RYK;v#C%W&vAS|To8`FLChsOafBz0ha!knmh^ zKWr5aYw@(tvPk{SAB)Y z>6Bm=!3fuRhet9#{SW-iskx*Xm|UeH{N(&X@d0KPj+u`1_!J$qa&*DtJ??MBi3W1g>xC-y33U{@2+3{*=X6EV z=lns-gKW+F%CX+#05a9}5{XY#8Y12ezxkiYq$<|5gYJpDS#P950yRnwQs)41X<39wF*qHJj?LB&SD$n}HKOsd;gm ztnNS+9bB=|+eGr+Wke7u4G*E=!Apo1iUt-hBbOd_O#R zVzw#dmD;8?%A1MeEw?MhSX6!;&w0i=w7u0DsqxNT1g7KtouT)Ki{ocOt#)@NjK52>qNQb{!mCJ=SI7Hvs%NJ0Jx;1JR#fOKY(5CHIav0=_kQi)%Q`Lw zRL`0)H0x?P^z|4Xs6>a5t9e8b=%yM+ntCFIv)*SZJ(K1ekMY`8?=7Fa%5(4@k!F)h zOw)XMOu(_Z%yyG^fQF;WgYUSZ{tRWKO85p{ZTB6rq!ADwjMk}|)ovupJz<7Fh^p}B zbaZ6Ec}p6`Z~iPkz zdffyd`ya`Wf5fI&E9xEs&fNIEBG_G*V5r!kAG$S+(0|e^gbp>Xm!&#qZ@Zwn-ypwR4DW|;Q5{|xdXfF#~$9OlLbiB4Ro^s=lml~5>JF{RpUSH3o273d zhooAkdTuKFIe#yw-R%UkUfldYAu@2C*;u=m`ZT%#S79L98*ZUuoD-b|MwiURhztd- zd}X%)&-L_V#QLI}&( zQp8dtYD9IPOOz)PTp`)_%B!1O;d*vG0BY?W@htF~#jY0hHGTpe;vaouwJDx+PP<#4 zv>{b2Aetnh*K>_!WgxE+?vF?kHp+slb%_J!DRr(~jnAQ}FvP8S1E`YFCD5QX>)B4m z8LInKRM0)sjdvW94mfOogo}gJ(xp zi~Q@@U-|(uzstW1YYiEwA4shkDlADNF$K>U06xlFstHjaRQ8oUVVatM@kg@HR`>Jd zrYt?l|Eist=t1YBa&_I|fMU9f5&ucTHedlUGriyeWT;@i3TBHVLoKyv)t;l}jqw_REN)#RQQr-31H*whSs9yYnz4 zbjXJzz4s2u0ok?{?pC?)$vA|U8ovWR5H5%$Yk<>7-j%X0qdL^Ht)Tl7mK;KX!(py1 zw+!RHlPw}Tt(*zl`wO$ICAo}YS9A$I)#h^Y#_ZXSgx7ny#ZtmW?q(%RES-EO>!JyS z&>u!Bb|(e)O~(%d&V;S;pCb0e9~`W_ql2iw*;Fs$Bx~w{eshgKI+K9jTl4rsVhpZm zDF&-%F6BFEbMEfELFXrKex}v<_8lWQ1Y~Zk^T9&U8*fWt=+NF4Ho|-KZM7~YKp65j z^becnNUc3g-7P;9=4`n7gPQ-$UD2G#&F|j_ln0xyn|znt${u0)|V_e-UOzOUQRIi>vOD-dJTc~32 z|J-q!a(jg6sxMMs zh;>lpatzHTJMCjPusRF1V+u%kl0sUIn=0%mSqGwi6i%h6oxsm73q-+AUnJ`6oQ?2a zaT!;`6TWDjIA_G1l1O-zp8`oM%A$n`WG_5~U)sRHCB4(o}!a`LZR+)*n?=3d)8O|6cEx zeF%7CA~H;RvQOhxn=e>?Y0ot`bTni;d#tz^py4wD z$pJ{F3V%a$BSiRJvy6z9MXjlKt8zkaM_bcjiYq33=E z`um|9W*d^hQfC8JRwBbHLi9gp7Z(FwP6P#FV@{J!AF^y$)4UyTPgh&7S6ic9$D;>M zS27lDO~*&ay*y>lfprJxCG(x@T4dHE7{eq4$^&XPsLiE`I6;Gvx|N4mpwJ!6X0Js_ zVOpz0A@o7+(B8z}-u23=JF{fMH zp6jYc0kn)M$~;}Q0qFV=;c6mFE7B8biEQm1%$YJl5>ZC>-Np>DHr1T&H$TwM<;v)D zaW&FuoTP*#h`H+BlR2)Y9cpfSL~3PltUaNw<7wjaD4Arg?y(wO(0BTs&^U|FJ|BOR zB0IsdSp5Nb0thB`-$>!K|eQzYSsHAx75-!^RvK4C^lxV9-GKix79(Y~_2j8UcuH z7mR5&5hn=0ldS4Odbf?eKiIZS%-ZX(zXCc^zTl+v85*#`IckZB<%@m+3+ek*XHiaH z8gx@vmFuktioRG{jEw2wab&;3uiDi+wFbL@wHhCHi$w0kC&ug=5OWA58c&AIXR zLJ3srij-Lb9|rl=B}kbBQfzL+k$B#ZWC4y}rgP&dCu=G= zq-Htz;p~87K3eALb3-xY@y8g|Trix??i2@KvoL76-@OrXx?+edtx`U|U)I`r&z>14&c6|`k5Kw_2p6tl7Fws3zKG*=*q<36wDA(@ zWU;{}k+wn|wMMp#8erGrIxCnm!wV$u*0E19lV}`BjGLX;hcTz1WsOTXb2G31xyCVhbU{rSd_HLi{nndfn~YBy#v`1>#>ym38-XCYu@AC57X->x4EJ** z-10+D=rpDh)Bd^)&mrp4%%3?5{fd=;K2p-78@@gY3QId7nm|A&-Mi0kw(ArpR;oNDrKx#$5h2=c$;tPRX-PED*mj9$ z3TIvMMYi-XAaZ&7C7Mbi-vh`DPN!;ggB!@y(=PRHGdubf9bo5AF$y>_d`lRtr; zH^;KMj{j61H$@0O4N5wy^uzoO_*54AjGZnu+20Cu$>Dz7jTymvB9{cOBoS3F2wO53 zTc99>MyI@y2msc zDE%hl9?_?arXh63h!vTN z({;(21#C${!|K4=qxxthDM`SGb%xyi`wTg1H}O?XT(XM%?0)ie{psopOQ^oo8>q;e zy2r6-n3r;BY%*Y&$|@QeXj#}(@dPhTQPuh#!81Vr5K_=2w$&Eh(~Kg99~24}8*Wa_ ze)u-mkY411Rr45m|1O`Dx~)b)maBF>QjPoocS?e@^o!Qk;8JxGrC@$*d#E?WGl9+Y zsQ*|;?K9U`hNTx|bG3#X^hJfIUqz7~0lezBGa+z{aW*@7wLR2uaLUyl3Nhl=cagk$ z_a~&rL-rY;`zjEP>lrLdy5l~1A`ABhhz;$i5R>IR$sC2F6E)zeo~~P%Uv?!&JQ`5! zHb{0hMtKBWED~d5;{2dzzfQq-kc(nSh2h*XePfg+9S+BLp2rpHOM;gW!-7WZ6t{YB zM1f?e2JjX*cxPb-pvcpE5ug_>F+t1$LZ+3Tze;M!fSWh) zcSr?QcVyS2tXwBg^XA|nJli|Bu0D{v>;Bq>b=cDF+;G+YF&*Yq$)_aDK0A{XzT#^M zS5tlZ+i&v!dTN1`%6g)ct z687_@2J2FvNPc?g?b8w+AzQ+CnIR=8&QIouWT!m z`WQ+~-CA>{%K7oGg^6clBe_gK2*K0@%d=r(uup|@vZo0_j7{nRY`KnxMjPY-v612r z@Lm?%UpriNi&J)XWEm5HLjRJu%hve?>vlO*$zbjZp=0f_yt=Wa&`i?0?Lteaceu5M zz){7^?K5AIgWmCmJAkoRvU9~Tr_-qXb7SU zq@Yqz2@ecg;AmXEI;n#7DTh=yrnUokvlKTTH_KuR!TZUZ3aCw{v6kgJZgk&R3G2-l zgESX(om6`Y{YdDWNH?8>6hV|)Pj5aHX6HmxeXQ(X4jcH+de@H|T@b+72nDYc6C!iR zv?lw@*|#tGG0eYlK4zRUa%zPH9ZT<+tTVq+>Mi#A@QvG7+9Gld*Qp-U(TuBO7lW%` zq zX@ggzn06%}4vD=*ajw3n>UD@$nx-Bm3r&~@ybBD-y=6sdw|OYwW3V|e`2d4-|4tF- zu;l5kGRY?5M^>rNhyJNed|KAT_fpoX{zyZTRVd;=7(yXNC(c^=Fjjq*9HQV&5a)8| zV@4EsC2Y4#H5d_k6Y^Icr6EJ+v(YW%7^z?ZYG!;o8Q^e^Hf>h17n1ZPu54pjVa8gsCPFM2& zd_%~0j8}q^kf~%|Og1Ih8H|;PdOnGxtZVA3lY+h!R=MYlli=YwI|AvgQF_VqK)%&B zGi_bc>4Heo>K%nJ$Und#$obHy(XZd9`Hu;-_Dnl}6#xFW>IZesFiGux<&_|9M zmokooyI6?bR2VJoJmR(c*hRsDxrgvLqBAC^q6lf{&-XaxKG_iBMS$wo#reYe6DYEf0Bbj~a!9#mpYx6uoUEJdGa*XGE zxR2Y*jh570>dQnWK!I+m3fZkl=#6TWDRpS@+;%(U1jnG0KKphR%hHQi1@jZOMLqTd zq9cQPo>E+e@Lj9S`{dcG(XALsE#d>b56A=2`^HV*X3z4<2B-&ofHGPrF6@}Svx5*u~dq?Znfwhpa0No@7ez=kgdX4^? z1yGG74z{`K>UmpR(AWWfmRu~ZdXTdNl1+D1)e4ZwbO^{a35&`0`AX*OlX?0_hluJ| zxfUJ_jiq(6HT9n}>q+4Rxr1Grk7Rh?OEaZ+}GR&651Q=d*6Xn?2$mEaRw1-bk90YMxBW zkpi8^4wEh|%E(Dr5-f})qN|uiI~1_DCy>@}LW38{LZVHJU1~o&ki*aJP_(nm>4`9B zNzP`8jLCGImWiJNiyBaym>YRX$wkHb(0%U97V;D2DluAX`;eg9q~BP-wje&+Pq!DijmN>uZQgjjM_;x_Zu#{@~#q8 zGPHD*9!4j)(OU2>+n8U8n08Y&q_CtC-K%~wi?)8bi7=V8?ysg1x5oF#z z6zOvPX{dMn*-FFMbFm?VHfd^Hv}CH_6F$*XI-d*iSE>KBe*w}r$)|T8ovFV+IQT)< z1;>Qdx~}<%HGiWK75iWh_&daFh~S5?hu(C*Fq{NnQg}BP1Vx4DOGQ2}KF?-Q7^_oa zcIqM{JAb|zEcygAX8dk@zfnm+62eDJu9T?_eEWQlRpq=7?vAhtCG=F#px?ux78zEe zhIkkSh}>>t8F$759rT(lJm2hPFV-Ff&jH_bYX7A9q^5Y6zy_tWC)Ybe{q0LQD+&t0 zVO8}&)AjnNr-SpEhw@UsV^s4^^}xD&mOW z_AQDuI2}OK=p%QR(LeIN>b|BN?=1|)fnM6+oZ@VA!$`C_rln@k(^=-e-rcY8 zT6@dOUvi5HCXv`*BN5rUNVPakTOTX z>H(Yr*s^R_nT8-J_5ho5LVUFQKs0eNxNNx-w{s|ai%aDD89OStIWO8+v_WZl&5;`$ z250FcAPi4@gPhF*IonM-t)z3C(spyLXh=cZEAOMgaYp@z9Dpz}&GPQUV31_6t9xad z^1=QHDr#xe(}P^d$J;iwpOWx{W({zJ+E3y0uS2f6ZjZC?D#a4PJht=(>*J*_eF{y} z<4TW;OHOyN|Coq4{M{I9rV5H4;_sJn_#o?I<*VI=^d?fyEN+cI=;1jS|7(oX0sIdY zSKn?!yDRX+i5SKtYCVk5ZkKD~r<`LPu$^8&%?}Tr85~a|@HNi81jajM`GXSlloK)G zD|sVxxK#Sn^<79{rZ;$S^q~dO=0AGo%yaFY{0P572o(QD-d4@;LG@0WpOcBjJr6SjC^Y&^f!b^y+(O?Ibkb%epoW5O9TRA_tn2yn&>YMKcID;f=v z)1Jt1_PdB0RNOS<85{y62G1pOhUerjh;lbR1Meaj*)nH)Yg_FnLih z{VvVo+3pz9CAm;o;*DjGk2j1AIJZlbR1)@oyg%mB6X%4ELd!w$ZNW7644|C8hIpP5 zaU@2#47j9_BXH9d&pSgfyCGu96yWoN>5#0t+B%niOWu8dFI;BE1XmwK)>(mwK*YXH z1&sQp((^(84)X7_{qLQc@e5eP%&=UriQ|tn)$dHaI*?yaqvsHsZGazoFo7o6N%S2(ShVm`i zxYbl~_M);d@xGam_plhJ6#5{=wyN$Z(ZEhEyYzH$M_`n<`ank4j z;a6uq>!7z5Pi~?#qJu+Sfl6An7|+Fw&8ySr&1D5(+H|Y&%aO%2VV->m!Y3RFNBO_o z#~(QlKTOg8ih@!+DHWUK;c;TW{fW>%k=d=k(HI8|{SJeSOcQ)xly)!;Vf|PvbbzM6 zw*3F%JpMQ7B6A2oD~%~Zs^*Bl&&j`TMh$>VFG3+WcRf`04^D@KfzP*~x;?~Oq7ZmZm{*NA_5Sq;`hox<(;Iqg z|3Ke=V4?jc3*lfv;tlPv{uAfp014u~OF<+4-k!-H+-Z7IXr{O!dd>BnDp!X7;T zKd$^Sw!h(T@d>zf9X=t|w##qLr&r6!cMJcc%+2pA?2YecoUUbN)}KNlP4lP#2emKd z8uSfCn|uGr*4BrfVuj3h)B*1qzj~PeB%l6!BKSQ-KhwDs>@Dt@{R0~RXO`(2fmA5?u$SMuCntr{X1AfXnc-@NP`8xH(-MaNv#go= zWhkCPq=axMs7jciqq1WN8lLT?>!Ze6_+A!3W{p>9+gG&CCYZ!-aEqM6kc> z5~#7fwNa=ON0UHR6A^hNV0Ot>zdX~lKV9Zzw11+UyF{R{R@iZ6Bt#mWeWG#L8=@19 z#0A!xO`IN1I*pbpt@-YzP(TrVdpg8XLy7+a`S{a7bVY2R!Nr>n={u&9h>A5Q)Y!on zBs{=y5*>!pj?_UnXsgs zX!2cfG$GnR6mh)7-b5Ayb&cuSs`uvc!Z$(G*JAY=LqD5CQO}O>la6I8B6bB@y_ZI> zx>6N-tacBctjZ5McYSJx{U5(=Uz!cYiAZN~%WjVowO8m_S(8?9Pb@f^k(VIsz~uCY zr+@U6O$R-@9IN}UPEL!D-`Kr8x%=5ikXr+)gZjVgdc)!d5wT=P7t80gofBBY36sSb zn)9v23tNO|qDP#IqceA(T%|B?_J+n+hU&O+2Q3tirG;j@>%sv~-;xXLCua|%hacQc z8pJ+G)paDLs~<1cYdw8)0F%@_qY1U(f4l{lFi??!QG=n_0zHQFl~E%`IVF=3Ve9r! zlfbBTd277$*N=7p9gNnv#}#>l$gp!R27BcaUZ{)$&gsI)wB8nH0^_tM0DTDL{YCh2 zB2AdX&L)ibXH$XBlbL3kvE--`t&>x88h&|K8r`KDFkN+HT5{#<$XKTl0R*3sffXMf zxH2CO+ixa)4dxM)j{k?djH&(YK~2tgm;drIfE3jEI`eP1EXIM-?dSE8!ogxB$U_I* z*1BFCW|{VMyu7m9SNtDq;}W(+3M zn5pCPo#W7H0(VDciW})Ovap?xw9%3}S^%Nq#^ffCQA7?R|3!2rZ1ko{OBXKM1K?>6R`XRPYq< z?HX}F`aZVK3q&`>Kg6NNu1QiohmItm|c8$Mh7_^N@1R{r6K1dIy_ta{&;<#$rl zlGD8F`gO_J1aw+)>8~6jR#&yu2!aZH-le z!2T;!ADiM*(q_PP=B_b{pZ1EC;zXT+IctCzvgSvWAxh#5U2Ob4(QW%o1=;w&{Um_x z_eNkfi;(=cjX)b1!|6Cx_ujIh+@MA-lY`V{I{6lrR-SLIK725l!8Rl)vRd3rKz};V z_x1afq#B5$<8_1L{Boi*4C2{ygrQYMz4QE==~!+Yx<)PNXN~=&lRuYAZ>3WMg^ghM ztDL$q4Gsx~YNaL}#)y>a3DYNI810#NiIX9&OtCCCdaz%8rne1kl+=HHdE~evSq02e z>wJ`vI}z}-;;rY;7L7bKoIOT~_{gce&si8Be>(JnF;Rhhl=xw^D* zW86n-!aG}W&F<=V2SIEcf!nuXk0d>lXL@Za^oX!(Gi(MRs}}`slR4zj%kCvEM>)^j zEl2QM+_Dy(%xl}c5NW~XyL=3zV=>HQncQ_9RSwV)ht0V(hNeH_y=lB`v6En1cyn-sVs@I1 z#d~U1S_b4;0>zkRhrN!bl@FyzCaZu38(gqmtLJs8`E`+-jD*-5iHetHiG*XJ6-Xu- z>rYWaa+P!)_Ize}P{)y}QL3#nz_1^#O9o>My8^c>o{hyyxA3uv%Zz8M-_&Sz+l0Mt zpQF*&GFn|idxDV(dg(jQpOx{;U22+yx+Yo;H0KEH^5*Nc7$A~wB{#R|(JC}osn@nX z6a}YE+-G@FzdSiMBVIgC@#U8-A75>}h0d=G-4Y8&B4CG)NuyCM2UH!sHfN|ge4L%! zas;3vc#m0s+)WMVfi}z`>LaEu(E?IjemwOo(GpAlcc8{^1q2_o=gV>EvHoyHU2q^W zNR4l%NMywzBNuZvbM+-nVFGnYV$fV7J4>tXbAkd1q$btxly*#^C%nM-?uIE;W$9CsJg7ZK+7yBZ-!m31oVzC*lMF=+3M(ZVd z*$m!{AMZnim7A))(|$}ZiByW5Cvq=-!mb4=gt6h!{P>br$DjR{B_ofoJg=e2^VTMX zVNt-#OM7rPKg{37^J1IoUddLk3$fiC+|!P__}Iwq$YFPMq5797fXgo}H!_Va)cf&< zplO4~H{X_GzjMBB?s3keTh^vaQD8VR977}=JJA5M!^M1oCtk&^-C9@@$GORUMAbgx z3jQ#cR^u`>Iy$_V`ReJ)3v;~G+iJc^;&%w4iC6BdA>;RgEwg+`Q1^Q!DR?e|;zhj* z$m|6MbYQFRwO?_n)Q zWvJCEDa#i>{E|d&N6=QQ(%fo7oID&e*AwdSxuV|{88$>M|CPgAp0C~PcD{Qw-D7hf zNs^>btt)>?k10@3=V<@A5o0BNj~8hO;k&DE8B}t6lT2KXa?F zoHi>zE(ON6M5H-6>?AtxWckQs9GwVf`Mx3Ryp&7~o+j&0qSI;&1Izsn*;AoJzQavk zR$oGL7^hqc?YX6U#zUKs=v1^Xcj8#KtkiCn9OnzirUPznZ5sdjWVC2r`{e2mSBcu{ zb7p!x_1GafF{T+f*RiWgGWfRPZo>AX>SZDwiy4>5*>pAT*_F=tNZZ^d+NV{*j+g4E zs?MD@n9Bod73$!z$CXNZN}lYA;7O9XA6)MaAuW*-Y1H7gwz{}&c*efVrgKoO*;Zvc zQ?)jSy;#}Ip|>@VHF_&Bnlcd#Z1)C}?VzIg0V5dWIq}mE(CX|2*=JT;0m8*2wH015{oTKMeT5Jf!6e{IM9i&+ldmlA z)-N=pZQEWppPmcDn+%x0%v z5~g+31mcm6jpkUjZqS<|duCb51YgEdSfn$NAYV z$M@K6S6{M-lj)0FpT}zXqVj$Fyx^ef%aiKHPm!zd$$IWOKKE6X2VzZkfqied1Ly~B zXTF|0#FP1Uco|OR*BH_o+}?)yM(6`_k8_bU;L7RSn7m8r(9oZE9!Y%S48}|naOz*L z8YaJfIQg~Tv#3LQNyuhZ*R|QI@rw|J=Z7qd`4mS!-PfLt#!Qq45Zk~53a&*A(iI0$ z);{2eXgRcc^G|jHHY?0$Sj2Y{vU9Ob2D6r=ei**R4gPyyRDu~gv_TzD7WV4$%V$6H zv~bVW4iC*T<0m3M#8X6J!N6~$ghubBaanUUe}2|!z$p7b4GH&!WIV-eK`z#Zue({X zAdI>xFHcua^+bUD;-{Kkc;lM;Ty0h&rGmE8*$pikT6pn#l9*28T#0uOm^?q7w88JD ze421<$1J9OJ|TI2T7KJSs(IBAr)Ar&QP+NitOZHD*?G4~lk|W9TCX(TfP!ZH=Jp*X zO^TuYDop)hfXUIJ7AYHLt}qgy^Fx;Rew+Dx^{wO8NIz%4&Xq}wU4lN8(IUb$-K7BT zeo^bvD(N+X&k+}o;%nD3pcAOnKt_dcXj@nUXM4u8i^-3G;h0S6UYhi;Dsrbtt~qA}{VpF?3?9z7K5gT;YK{HFkcddFIdZi=cTw zllxj^go*pA%Nx=Wz`j{ma))9ov=CAh$}biJ0c8jK;P1nvFK3@o#)=<~UHr z4j|f=BJg;$^<~zJvV7jrBxw@#GDi{f=$7j=@`4Z_j=p`Jo9p1-Zh6=+q5CfNQP4;C zA(y(yXXd;{Yk*Rzr4E7nhS83( zkq7uDd_>We4{Gl`%jZQpZ=tsuPxk#2Vbw*0TVXv5I?G{T!LFDd$HY2e^LCvnc6j>c4 z#jwl{&A`5TT8(n{q#3n(RfFp9h1+v_zRALj*92m;hq{8ZKaZgal9Ll;nxZ2|z6*(l zWqfp9fI(?JW%p6{A9DJRB&$9zkkKuek+HtI#Jq~s9EpS?LfpG+l;smZi{pWI@D@lE zNyI)>+rBX}cgpji8P|e}bA5GDW*gGDni-l!>Mz2Su+sLf0@5#?#cNyrVd^=%MHuvj zw!e85)*z=ZQvX|l(q3glK7Bq6P<~?dxquwnagnpuEIIiX)|nfy@F1Ul`O|!MN0%WL z^sMA4Lf-}KbMROjUou@XpMYRfLI-ga$YW_RmCjOJo)+@v;NxK2Owi}9`)hVHI4>+B znJX_{&l5V00o7iZ{7WER(iVd5x4WP0yI0FEs@5aG&cMs0A zh%XnkanIJD9wq0DHXS-zx+}2T`>PF*nz}|Xy5XPBY%{<9;*GFlKV1d3-Fx=RcBxBD zFQ+1ea=0E%Z0KHG_2oKr^(jq}By7@MS5TEvGOwt+MtC)K(F$wTLl->{*x8Ng0oH*> zta<~jmiey0az~{6=H~khv;(kzd3X60GyxNi-K>Yhmi#yO;)5!_cybvJKk#Ro2^Z{M zx|XAN#k_3-C1jE#7HZ8f%+nb+I=t8g_2m_0~y;aWBw5~*Kb!`ZZd z!V&XdC05N0EO`V#ZEqJz3ZCy8UO|GI=t;s@{)LMY*#m}@hzSz?gjzBDSz6RQ=k*J13DqsjIzCvwa5E zA=k8ONmvf}jvh&%F!6ST?vtL$NCKMg|D)_HqvBZCH3PvCAh-qhV2uQKcL^j|(1u{a z9U5pnxVsZ1xCVE3cX!ud!C@-r?!C{QnKiS{{nI~sQBBoXpFZ|JoY8_G-P?+ zH`?zP{izOBSG#(9gLDNNWhQn~teYt(ryQw3;uA4!KEs}4IK$R0QA?rQnf_Bk@DAk* zzcNHUjFu8H5Z0AxL@X(jxhFzCQ;anZms*QLgw&-8yeNy0Lvxu2arRY0cJ{ITvPeDe z<^z#KWahAY>%40O9=B(yqjvjgNvesRKW!Ooea7w*(`fD5p)M9;|LRiRU`dqlHRs2n z^zK}kNuXCt04kA$mzmviwMs^|`xx_k;~_Q&B&2*M>t^blh(9b#KBv#+m|{BQoVCC= zoLGp4%cAA}1aUmH2X%QN8BhCzPeaQzn!jD1nzA1O~0*ijsE zxbw6^Sz(maWA+Luy0nh$4l{hGBk@~Vpv&o+j<1_N3O(EbteCjHU#IeEdSh_D5ZDY% zCFGD^l{)-F5xVzIv8vXqHv2H^HS=_m@U3Bn6Yas9k_O=g4Q#9E+dQFNb%roLal>9%pffh3)A< z2*#|yI!rkz%5stDZH0e!nNIUyU4OyCVu-<;=XV%y7ndjF8NYLe9#9NeyW7`~NG4uW z6n8y{MyIp(I^PrKcvw6zq=M<{j6$?TqtCM39$J(DoBI8_Y}Jdc!<% z3<$Odt7%Y#Qj2S@u3D3uj;vZ<9FF>4Dz9T%Bq^k=n^1a3_S)lDyY^e=!na$m1c)D( zPE#>9TN19Bm>*@CxkkRD={KYJTw`iTcX8Cs>sA=#R@DT#361gNl=cr*?yNfYaO;F< zYtYZ0iiGKmuT%_g+b+&F9lW$}IdFDwdUiV6(HS{xQjg6!db&LVqR` zDYjiBDA$Gao_;ca%YnXFW1Saa`Ga6HIJr^uS%1aNwPbLMFT7GXf-@vyDHew{$KRp3 zl)BDRO5{=^c3zgE#E{JWgNMTQ@o#}8;Gll4Loc|Zv)Xx=WaW)_v4(ikn6T7^hm!&n zY`{&5b98iHV}~9|FFMLMLSf~mGN8Y6cOAj1wEqsn_xY1GA(Gi=_7AnUkL@juD}+sz zQfr}_S76sg!^BBbF5~U5X5oNKw((lN$t1Kg30?(n=@;X}217l|9l$MoV`N+R*4F_a z&RCw$2V>J&ptqLGT%XZq5R8T@kXtm-*B=xz)B>I)6~%9+$fq&_Xv4_YYDU?yfRN zk8MPW!JD|SK3$nG9#r2&wmnrJAr$H(sT0I7rR~%GK!j2iCOSO{bPwvQ;Wga0B9M`w zH&6&qUDY_)-<|k1?_!sk1$SxP3Oz)Hj87Q-x!xoLqbw>#L{;6ond4)dKOv{!CwwAh zr#kG9$iL@uJpBeHqWd85LGoMT<>Vo)TKyh_q0X3npXSiZbeq3wT(&+x^_IW!Yr4Na zCfI;I9pPJubiK!n-V5xr@pZgVs9M)81oWN<9ofgE(K#<30Bkz73B_mm=vpY&xzrvN3%0DwUKh0W3|$j!j`dqp*>%+ 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%0D*i_;&fkX{8T0OxUzXdqGeDVMUJv)f! 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 Date: Thu, 19 Nov 2015 14:41:44 +0000 Subject: [PATCH 36/80] Merge branch 'client-max-body-size' into 'master' Do not limit workhorse POST/PUT size in NGINX Limiting, if any, should happen in gitlab-workhorse. See merge request !1831 --- lib/support/nginx/gitlab | 4 +--- lib/support/nginx/gitlab-ssl | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/lib/support/nginx/gitlab b/lib/support/nginx/gitlab index 93f2ad07ae..f38e2e6209 100644 --- a/lib/support/nginx/gitlab +++ b/lib/support/nginx/gitlab @@ -114,7 +114,6 @@ server { } location ~ ^/[\w\.-]+/[\w\.-]+/gitlab-lfs/objects { - client_max_body_size 0; # 'Error' 418 is a hack to re-use the @gitlab-workhorse block error_page 418 = @gitlab-workhorse; return 418; @@ -140,7 +139,6 @@ server { # Build artifacts should be submitted to this location location ~ ^/[\w\.-]+/[\w\.-]+/builds/download { - client_max_body_size 0; # 'Error' 418 is a hack to re-use the @gitlab-workhorse block error_page 418 = @gitlab-workhorse; return 418; @@ -148,13 +146,13 @@ server { # Build artifacts should be submitted to this location location ~ /ci/api/v1/builds/[0-9]+/artifacts { - client_max_body_size 0; # 'Error' 418 is a hack to re-use the @gitlab-workhorse block error_page 418 = @gitlab-workhorse; return 418; } location @gitlab-workhorse { + client_max_body_size 0; ## If you use HTTPS make sure you disable gzip compression ## to be safe against BREACH attack. # gzip off; diff --git a/lib/support/nginx/gitlab-ssl b/lib/support/nginx/gitlab-ssl index 90749947fa..4cc6a17db0 100644 --- a/lib/support/nginx/gitlab-ssl +++ b/lib/support/nginx/gitlab-ssl @@ -161,7 +161,6 @@ server { } location ~ ^/[\w\.-]+/[\w\.-]+/gitlab-lfs/objects { - client_max_body_size 0; # 'Error' 418 is a hack to re-use the @gitlab-workhorse block error_page 418 = @gitlab-workhorse; return 418; @@ -187,7 +186,6 @@ server { # Build artifacts should be submitted to this location location ~ ^/[\w\.-]+/[\w\.-]+/builds/download { - client_max_body_size 0; # 'Error' 418 is a hack to re-use the @gitlab-workhorse block error_page 418 = @gitlab-workhorse; return 418; @@ -195,13 +193,13 @@ server { # Build artifacts should be submitted to this location location ~ /ci/api/v1/builds/[0-9]+/artifacts { - client_max_body_size 0; # 'Error' 418 is a hack to re-use the @gitlab-workhorse block error_page 418 = @gitlab-workhorse; return 418; } location @gitlab-workhorse { + client_max_body_size 0; ## If you use HTTPS make sure you disable gzip compression ## to be safe against BREACH attack. gzip off; From 71cb328b4aafcfb772801e50033f686cbc3755ed Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 19 Nov 2015 12:29:47 +0000 Subject: [PATCH 37/80] Merge branch 'update_nginx_deploy' into 'master' Deploy page should be shown for all pages not just root Related to change already merged to Omnibus - gitlab-org/omnibus-gitlab!540 This change makes it so the deploy page is shown on all GitLab pages if the page exists. Users will no longer receive the 502 when deploys are happening. See merge request !1828 --- lib/support/nginx/gitlab | 2 +- lib/support/nginx/gitlab-ssl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/support/nginx/gitlab b/lib/support/nginx/gitlab index f38e2e6209..0cf5292b29 100644 --- a/lib/support/nginx/gitlab +++ b/lib/support/nginx/gitlab @@ -67,7 +67,7 @@ server { location / { ## Serve static files from defined root folder. ## @gitlab is a named location for the upstream fallback, see below. - try_files $uri $uri/index.html $uri.html @gitlab; + try_files $uri /index.html $uri.html @gitlab; } ## We route uploads through GitLab to prevent XSS and enforce access control. diff --git a/lib/support/nginx/gitlab-ssl b/lib/support/nginx/gitlab-ssl index 4cc6a17db0..31a651c87f 100644 --- a/lib/support/nginx/gitlab-ssl +++ b/lib/support/nginx/gitlab-ssl @@ -112,7 +112,7 @@ server { location / { ## Serve static files from defined root folder. ## @gitlab is a named location for the upstream fallback, see below. - try_files $uri $uri/index.html $uri.html @gitlab; + try_files $uri /index.html $uri.html @gitlab; } ## We route uploads through GitLab to prevent XSS and enforce access control. From 32771f06f1c683c38ecea577cc39b064c5211f55 Mon Sep 17 00:00:00 2001 From: Job van der Voort Date: Wed, 18 Nov 2015 10:03:27 +0000 Subject: [PATCH 38/80] Merge branch 'add_lfs_doc' into 'master' Documentation for Git LFS Doc explaining how to use Git LFS, how to use Git LFS with GitLab, known issues and troubleshooting tips. See merge request !1813 --- doc/workflow/git_lfs.md | 136 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 doc/workflow/git_lfs.md diff --git a/doc/workflow/git_lfs.md b/doc/workflow/git_lfs.md new file mode 100644 index 0000000000..4990a9b5aa --- /dev/null +++ b/doc/workflow/git_lfs.md @@ -0,0 +1,136 @@ +# Git LFS + +Managing large files such as audio, video and graphics files has always been one of the shortcomings of Git. +The general recommendation is to not have Git repositories larger than 1GB to preserve performance. + +GitLab already supports [managing large files with git annex](http://doc.gitlab.com/ee/workflow/git_annex.html) (EE only), however in certain +environments it is not always convenient to use different commands to differentiate between the large files and regular ones. + +Git LFS makes this simpler for the end user by removing the requirement to learn new commands. + + +## How it works + +Git LFS client talks with the GitLab server over HTTPS. It uses HTTP Basic Authentication to authorize client requests. +Once the request is authorized, Git LFS client receives instructions from where to fetch or where to push the large file. + +## Requirements + +* Git LFS is supported in GitLab starting with version 8.2 +* Git LFS client version 0.6.0 and up + +## GitLab and Git LFS + +### Configuration + +Git LFS objects can be large in size. By default, they are stored on the server GitLab is installed on. + +There are two configuration options to help GitLab server administrators: + +* Enabling/disabling Git LFS support +* Changing the location of LFS object storage + +#### Omnibus packages + +In `/etc/gitlab/gitlab.rb`: + +```ruby +gitlab_rails['lfs_enabled'] = false +gitlab_rails['lfs_storage_path'] = "/mnt/storage/lfs-objects" +``` + +#### Installations from source + +In `config/gitlab.yml`: + +```yaml + lfs: + enabled: false + storage_path: /mnt/storage/lfs-objects +``` + +## Known limitations + +* Git LFS v1 original API is not supported since it was deprecated early in LFS development, starting with Git LFS version 0.6.0 +* When SSH is set as a remote, Git LFS objects still go through HTTPS +* Any Git LFS request will ask for HTTPS credentials to be provided so good Git credentials store is recommended +* Currently, storing GitLab Git LFS objects on a non-local storage (like S3 buckets) is not supported +* Git LFS always assumes HTTPS so if you have GitLab server on HTTP you will have to add the url to Git config manually (see #troubleshooting-tips) + +## Using Git LFS + +Lets take a look at the workflow when you need to check large files into your Git repository with Git LFS: +For example, if you want to upload a very large file and check it into your Git repository: + +```bash +git clone git@gitlab.example.com:group/project.git +git lfs init # initialize the Git LFS project project +git lfs track "*.iso" # select the file extensions that you want to treat as large files +``` + +Once a certain file extension is marked for tracking as a LFS object you can use Git as usual without having to redo the command to track a file with the same extension: + +```bash +cp ~/tmp/debian.iso ./ # copy a large file into the current directory +git add . # add the large file to the project +git commit -am "Added Debian iso" # commit the file meta data +git push origin master # sync the git repo and large file to the GitLab server +``` + +Downloading a single large file is also very simple: + +```bash +git clone git@gitlab.example.com:group/project.git +git lfs fetch debian.iso # download the large file +``` + + +## Troubleshooting + +### error: Repository or object not found + +There are a couple of reasons why this error can occur: + +* Wrong version of LFS client used: + +Check the version of Git LFS on the client machine with `git lfs version`. Only version 0.6.0 and newer are supported. + +* Project is using deprecated LFS API + +Check the Git config of the project for traces of deprecated API with `git lfs -l`. If `batch = false` is set in the config, remove the line and try using Git LFS client newer than 0.6.0. + +### Invalid status for : 501 + +When attempting to push a LFS object to a GitLab server that doesn't have Git LFS support enabled, server will return status `error 501`. Check with your GitLab administrator why Git LFS is not enabled on the server. See [Configuration section](#configuration) for instructions on how to enable LFS support. + +### getsockopt: connection refused + +If you push a LFS object to a project and you receive an error similar to: `Post /info/lfs/objects/batch: dial tcp IP: getsockopt: connection refused`, +the LFS client is trying to reach GitLab through HTTPS. However, your GitLab instance is being served on HTTP. + +This behaviour is caused by Git LFS using HTTPS connections by default when a `lfsurl` is not set in the Git config. + +To prevent this from happening, set the lfs url in project Git config: + +```bash + +git config --add lfs.url "http://gitlab.example.com/group/project.git/info/lfs/objects/batch" +``` + +### Credentials are always required when pushing an object + +Given that Git LFS uses HTTP Basic Authentication to authenticate the user pushing the LFS object on every push for every object, user HTTPS credentials are required. + +By default, Git has support for remembering the credentials for each repository you use. This is described in [Git credentials man pages](https://git-scm.com/docs/gitcredentials). + +For example, you can tell Git to remember the password for a period of time in which you expect to push the objects: + +```bash +git config --global credential.helper 'cache --timeout=3600' +``` + +This will remember the credentials for an hour after which Git operations will require re-authentication. + +If you are using OS X you can use `osxkeychain` to store and encrypt your credentials. For Windows, `wincred` is available. + +More details about various methods of storing the user credentials can be found on [Git Credential Storage documentation](https://git-scm.com/book/en/v2/Git-Tools-Credential-Storage) \ No newline at end of file From 61c6e9697195b44a683e78d8b23c2d28eda15075 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 19 Nov 2015 10:00:58 +0000 Subject: [PATCH 39/80] Merge branch 'check_if_it_should_be_archived_in_backup' into 'master' Check which folders and archives should be packed before passing to tar command. If user uses backup task with SKIP and skips one of the archives listed(uploads, builds, artifacts) backup create will give an error: `Cannot stat: No such file or directory`. This MR fixes that by checking for skipped items. Additionally, compact everything to avoid `TypeError: no implicit conversion of nil into String` errors. See merge request !1824 --- lib/backup/manager.rb | 14 ++++++-------- spec/tasks/gitlab/backup_rake_spec.rb | 3 ++- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/lib/backup/manager.rb b/lib/backup/manager.rb index 9e15d5411a..e7eda7c6f4 100644 --- a/lib/backup/manager.rb +++ b/lib/backup/manager.rb @@ -150,17 +150,15 @@ module Backup private def backup_contents - folders_to_backup + ["uploads.tar.gz", "builds.tar.gz", "artifacts.tar.gz", "backup_information.yml"] + folders_to_backup + archives_to_backup + ["backup_information.yml"] + end + + def archives_to_backup + %w{uploads builds artifacts}.map{ |name| (name + ".tar.gz") unless skipped?(name) }.compact end def folders_to_backup - folders = %w{repositories db} - - if ENV["SKIP"] - return folders.reject{ |folder| ENV["SKIP"].include?(folder) } - end - - folders + %w{repositories db}.reject{ |name| skipped?(name) } end def settings diff --git a/spec/tasks/gitlab/backup_rake_spec.rb b/spec/tasks/gitlab/backup_rake_spec.rb index 06559c3925..fb5e74af64 100644 --- a/spec/tasks/gitlab/backup_rake_spec.rb +++ b/spec/tasks/gitlab/backup_rake_spec.rb @@ -149,7 +149,7 @@ describe 'gitlab:app namespace rake task' do # Redirect STDOUT and run the rake task orig_stdout = $stdout $stdout = StringIO.new - ENV["SKIP"] = "repositories" + ENV["SKIP"] = "repositories,uploads" run_rake_task('gitlab:backup:create') $stdout = orig_stdout @@ -180,6 +180,7 @@ describe 'gitlab:app namespace rake task' do expect(Rake::Task["gitlab:backup:db:restore"]).to receive :invoke expect(Rake::Task["gitlab:backup:repo:restore"]).not_to receive :invoke + expect(Rake::Task["gitlab:backup:uploads:restore"]).not_to receive :invoke expect(Rake::Task["gitlab:backup:builds:restore"]).to receive :invoke expect(Rake::Task["gitlab:backup:artifacts:restore"]).to receive :invoke expect(Rake::Task["gitlab:shell:setup"]).to receive :invoke From 506e0be36bcef746c3f2e469a5e1046380ca7d76 Mon Sep 17 00:00:00 2001 From: Job van der Voort Date: Thu, 19 Nov 2015 13:44:34 +0000 Subject: [PATCH 40/80] Merge branch 'lfs-client-doc' into 'master' Add link to git-lfs client [ci skip] See merge request !1832 --- doc/workflow/git_lfs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/workflow/git_lfs.md b/doc/workflow/git_lfs.md index 4990a9b5aa..e1064051fe 100644 --- a/doc/workflow/git_lfs.md +++ b/doc/workflow/git_lfs.md @@ -17,7 +17,7 @@ Once the request is authorized, Git LFS client receives instructions from where ## Requirements * Git LFS is supported in GitLab starting with version 8.2 -* Git LFS client version 0.6.0 and up +* Git LFS [client](https://git-lfs.github.com) version 0.6.0 and up ## GitLab and Git LFS From 9535d91e8db07cb32f408a62dcc169ba302566f4 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Thu, 19 Nov 2015 15:09:28 +0000 Subject: [PATCH 41/80] Merge branch 'update-gitlab-shell-doc' into 'master' Update gitlab-shell documentation to 2.6.7 See merge request !1836 --- doc/install/installation.md | 2 +- doc/update/8.1-to-8.2.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/install/installation.md b/doc/install/installation.md index 7ef46b0406..52ae30af80 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -312,7 +312,7 @@ We recommend using a PostgreSQL database. For MySQL check [MySQL setup guide](da GitLab Shell is an SSH access and repository management software developed specially for GitLab. # Run the installation task for gitlab-shell (replace `REDIS_URL` if needed): - sudo -u git -H bundle exec rake gitlab:shell:install[v2.6.6] REDIS_URL=unix:/var/run/redis/redis.sock RAILS_ENV=production + sudo -u git -H bundle exec rake gitlab:shell:install[v2.6.7] REDIS_URL=unix:/var/run/redis/redis.sock RAILS_ENV=production # By default, the gitlab-shell config is generated from your main GitLab config. # You can review (and modify) the gitlab-shell config as follows: diff --git a/doc/update/8.1-to-8.2.md b/doc/update/8.1-to-8.2.md index 73d899f9c2..261031442a 100644 --- a/doc/update/8.1-to-8.2.md +++ b/doc/update/8.1-to-8.2.md @@ -68,7 +68,7 @@ sudo -u git -H git checkout 8-2-stable-ee ```bash cd /home/git/gitlab-shell sudo -u git -H git fetch -sudo -u git -H git checkout v2.6.6 +sudo -u git -H git checkout v2.6.7 ``` ### 5. Replace gitlab-git-http-server with gitlab-workhorse From ed2a8ba6005d2fc83920c85df8e53677a2bfd97e Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Thu, 19 Nov 2015 10:33:18 -0500 Subject: [PATCH 42/80] Merge 8-2-stable into 8-2-stable-ee Conflicts remaining: - app/controllers/groups/group_members_controller.rb - app/controllers/projects/project_members_controller.rb - app/models/ability.rb - app/models/member.rb - app/models/project.rb --- CHANGELOG | 8 ++ CONTRIBUTING.md | 8 +- GITLAB_SHELL_VERSION | 2 +- VERSION | 2 +- app/assets/javascripts/dispatcher.js.coffee | 2 + app/assets/javascripts/notes.js.coffee | 13 +- .../stat_graph_contributors_util.js.coffee | 5 +- app/controllers/concerns/global_milestones.rb | 19 +++ .../dashboard/milestones_controller.rb | 29 +--- app/controllers/dashboard_controller.rb | 5 + .../groups/application_controller.rb | 1 + app/controllers/groups/avatars_controller.rb | 4 +- .../groups/group_members_controller.rb | 30 +++- .../groups/milestones_controller.rb | 73 +++++----- .../projects/compare_controller.rb | 4 +- app/controllers/projects/notes_controller.rb | 7 +- .../projects/project_members_controller.rb | 40 ++++-- app/finders/milestones_finder.rb | 12 ++ app/helpers/diff_helper.rb | 10 +- app/helpers/labels_helper.rb | 2 +- app/helpers/milestones_helper.rb | 2 +- app/models/ability.rb | 76 +++++++--- app/models/global_label.rb | 17 +++ ...group_milestone.rb => global_milestone.rb} | 22 ++- app/models/group.rb | 7 +- app/models/group_label.rb | 9 -- app/models/member.rb | 40 ++++-- app/models/project.rb | 8 +- app/models/project_wiki.rb | 10 ++ app/services/labels/group_service.rb | 26 ---- app/services/milestones/group_service.rb | 26 ---- app/services/notification_service.rb | 12 +- app/views/admin/users/_profile.html.haml | 4 +- .../dashboard/milestones/index.html.haml | 6 +- app/views/dashboard/milestones/show.html.haml | 36 ++--- .../group_members/_group_member.html.haml | 6 +- .../groups/group_members/index.html.haml | 6 +- .../groups/milestones/_milestone.html.haml | 2 +- app/views/groups/milestones/index.html.haml | 19 ++- app/views/groups/milestones/new.html.haml | 48 +++++++ app/views/groups/milestones/show.html.haml | 44 +++--- .../notify/project_was_moved_email.text.erb | 2 +- app/views/projects/commit/show.html.haml | 2 +- app/views/projects/diffs/_diffs.html.haml | 2 +- app/views/projects/diffs/_file.html.haml | 3 +- app/views/projects/milestones/_form.html.haml | 6 +- app/views/projects/notes/_form.html.haml | 2 +- app/views/projects/notes/_note.html.haml | 4 +- .../projects/notes/_notes_with_form.html.haml | 4 +- app/views/projects/notes/edit.js.erb | 2 - .../project_members/_project_member.html.haml | 11 +- .../projects/project_members/_team.html.haml | 4 +- .../projects/project_members/update.js.haml | 3 +- app/views/shared/_import_form.html.haml | 1 - app/views/users/show.html.haml | 4 +- config/routes.rb | 4 +- ...1116144118_add_unique_for_lfs_oid_index.rb | 7 + db/schema.rb | 15 +- doc/api/commits.md | 4 +- doc/ci/docker/using_docker_build.md | 4 +- doc/ci/quick_start/README.md | 6 +- doc/customization/libravatar.md | 6 +- doc/development/architecture.md | 2 +- doc/hooks/custom_hooks.md | 2 +- doc/install/database_mysql.md | 2 +- doc/install/installation.md | 29 ++-- doc/integration/ldap.md | 4 +- ...corporate_contributor_license_agreement.md | 2 +- ...ndividual_contributor_license_agreement.md | 2 +- doc/markdown/markdown.md | 12 +- doc/operations/unicorn.md | 4 +- doc/release/monthly.md | 30 ++-- doc/release/security.md | 4 +- doc/ssh/README.md | 2 +- doc/update/6.x-or-7.x-to-7.14.md | 2 +- doc/update/8.1-to-8.2.md | 13 +- doc/workflow/README.md | 1 + doc/workflow/git_lfs.md | 136 ++++++++++++++++++ doc/workflow/gitlab_flow.md | 12 +- doc/workflow/importing/migrating_from_svn.md | 4 +- doc/workflow/milestones.md | 13 ++ doc/workflow/milestones/form.png | Bin 0 -> 88591 bytes doc/workflow/milestones/group_form.png | Bin 0 -> 77087 bytes features/groups.feature | 19 ++- features/steps/groups.rb | 40 ++++++ features/steps/project/issues/issues.rb | 2 +- features/steps/shared/paths.rb | 4 + lib/backup/manager.rb | 14 +- lib/support/nginx/gitlab | 6 +- lib/support/nginx/gitlab-ssl | 6 +- spec/features/notes_on_merge_requests_spec.rb | 6 + spec/features/task_lists_spec.rb | 3 + spec/models/global_milestone_spec.rb | 65 +++++++++ spec/models/project_wiki_spec.rb | 18 +++ spec/services/issues/update_service_spec.rb | 12 +- .../merge_requests/update_service_spec.rb | 11 +- .../services/milestones/close_service_spec.rb | 28 ++++ .../milestones/create_service_spec.rb | 24 ++++ .../services/milestones/group_service_spec.rb | 70 --------- spec/tasks/gitlab/backup_rake_spec.rb | 3 +- 100 files changed, 931 insertions(+), 474 deletions(-) create mode 100644 app/controllers/concerns/global_milestones.rb create mode 100644 app/finders/milestones_finder.rb create mode 100644 app/models/global_label.rb rename app/models/{group_milestone.rb => global_milestone.rb} (76%) delete mode 100644 app/models/group_label.rb delete mode 100644 app/services/labels/group_service.rb delete mode 100644 app/services/milestones/group_service.rb create mode 100644 app/views/groups/milestones/new.html.haml delete mode 100644 app/views/projects/notes/edit.js.erb create mode 100644 db/migrate/20151116144118_add_unique_for_lfs_oid_index.rb create mode 100644 doc/workflow/git_lfs.md create mode 100644 doc/workflow/milestones.md create mode 100644 doc/workflow/milestones/form.png create mode 100644 doc/workflow/milestones/group_form.png create mode 100644 spec/models/global_milestone_spec.rb create mode 100644 spec/services/milestones/close_service_spec.rb create mode 100644 spec/services/milestones/create_service_spec.rb delete mode 100644 spec/services/milestones/group_service_spec.rb diff --git a/CHANGELOG b/CHANGELOG index 6528ca8c32..41104bc7fd 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -6,6 +6,10 @@ v 8.1.0 v 8.0.1 v 8.1.0 (unreleased) v 8.2.0 (unreleased) +v 8.3.0 (unreleased) + +v 8.2.0 + - Fix grouping of contributors by email in graph. - Remove CSS property preventing hard tabs from rendering in Chromium 45 (Stan Hu) - Fix Drone CI service template not saving properly (Stan Hu) - Fix avatars not showing in Atom feeds and project issues when Gravatar disabled (Stan Hu) @@ -37,6 +41,7 @@ v 8.2.0 (unreleased) - Add "added", "modified" and "removed" properties to commit object in webhook - Rename "Back to" links to "Go to" because its not always a case it point to place user come from - Allow groups to appear in the search results if the group owner allows it + - Add email notification to former assignee upon unassignment (Adam Lieskovský) - New design for project graphs page - Remove deprecated dumped yaml file generated from previous job definitions - Fix incoming email config defaults @@ -48,6 +53,9 @@ v 8.2.0 (unreleased) - Ability to add release notes (markdown text and attachments) to git tags (aka Releases) - Relative links from a repositories README.md now link to the default branch - Fix trailing whitespace issue in merge request/issue title + - Fix bug when milestone/label filter was empty for dashboard issues page + - Add ability to create milestone in group projects from single form + - Prevent the last owner of a group from being able to delete themselves by 'adding' themselves as a master (James Lopez) v 8.1.4 - Fix bug where manually merged branches in a MR would end up with an empty diff (Stan Hu) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9f79ff413a..5d85c9f3fc 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -10,7 +10,7 @@ By submitting code as an individual you agree to the [individual contributor lic ## Security vulnerability disclosure -Please report suspected security vulnerabilities in private to support@gitlab.com, also see the [disclosure section on the GitLab.com website](http://about.gitlab.com/disclosure/). Please do NOT create publicly viewable issues for suspected security vulnerabilities. +Please report suspected security vulnerabilities in private to support@gitlab.com, also see the [disclosure section on the GitLab.com website](https://about.gitlab.com/disclosure/). Please do NOT create publicly viewable issues for suspected security vulnerabilities. ## Closing policy for issues and merge requests @@ -35,7 +35,7 @@ The [GitLab CE issue tracker on GitLab.com](https://gitlab.com/gitlab-org/gitlab Do not use the issue tracker for feature requests. We have a specific [feature request forum](http://feedback.gitlab.com) for this purpose. Please keep feature requests as small and simple as possible, complex ones might be edited to make them small and simple. -Please send a merge request with a tested solution or a merge request with a failing test instead of opening an issue if you can. If you're unsure where to post, post to the [mailing list](https://groups.google.com/forum/#!forum/gitlabhq) or [Stack Overflow](http://stackoverflow.com/questions/tagged/gitlab) first. There are a lot of helpful GitLab users there who may be able to help you quickly. If your particular issue turns out to be a bug, it will find its way from there. +Please send a merge request with a tested solution or a merge request with a failing test instead of opening an issue if you can. If you're unsure where to post, post to the [mailing list](https://groups.google.com/forum/#!forum/gitlabhq) or [Stack Overflow](https://stackoverflow.com/questions/tagged/gitlab) first. There are a lot of helpful GitLab users there who may be able to help you quickly. If your particular issue turns out to be a bug, it will find its way from there. ### Issue tracker guidelines @@ -72,7 +72,7 @@ If you can, please submit a merge request with the fix or improvements including 1. Write [tests](https://gitlab.com/gitlab-org/gitlab-development-kit#running-the-tests) and code 1. Add your changes to the [CHANGELOG](CHANGELOG) 1. If you are changing the README, some documentation or other things which have no effect on the tests, add `[ci skip]` somewhere in the commit message -1. If you have multiple commits please combine them into one commit by [squashing them](http://git-scm.com/book/en/Git-Tools-Rewriting-History#Squashing-Commits) +1. If you have multiple commits please combine them into one commit by [squashing them](https://git-scm.com/book/en/Git-Tools-Rewriting-History#Squashing-Commits) 1. Push the commit to your fork 1. Submit a merge request (MR) to the master branch 1. The MR title should describe the change you want to make @@ -181,4 +181,4 @@ This code of conduct applies both within project spaces and in public spaces whe Instances of abusive, harassing, or otherwise unacceptable behavior can be reported by emailing contact@gitlab.com -This Code of Conduct is adapted from the [Contributor Covenant](http:contributor-covenant.org), version 1.1.0, available at [http://contributor-covenant.org/version/1/1/0/](http://contributor-covenant.org/version/1/1/0/) +This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.1.0, available at [http://contributor-covenant.org/version/1/1/0/](http://contributor-covenant.org/version/1/1/0/) diff --git a/GITLAB_SHELL_VERSION b/GITLAB_SHELL_VERSION index 338a5b5d8f..e261122d5c 100644 --- a/GITLAB_SHELL_VERSION +++ b/GITLAB_SHELL_VERSION @@ -1 +1 @@ -2.6.6 +2.6.7 diff --git a/VERSION b/VERSION index 5b1adc255f..e40da89725 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.2.0.rc1-ee \ No newline at end of file +8.2.0.rc1-ee diff --git a/app/assets/javascripts/dispatcher.js.coffee b/app/assets/javascripts/dispatcher.js.coffee index f5d29321f2..ff461e349c 100644 --- a/app/assets/javascripts/dispatcher.js.coffee +++ b/app/assets/javascripts/dispatcher.js.coffee @@ -28,6 +28,8 @@ class Dispatcher when 'projects:milestones:new', 'projects:milestones:edit' new ZenMode() new DropzoneInput($('.milestone-form')) + when 'groups:milestones:new' + new ZenMode() when 'projects:compare:show' new Diff() when 'projects:issues:new','projects:issues:edit' diff --git a/app/assets/javascripts/notes.js.coffee b/app/assets/javascripts/notes.js.coffee index b0682f1684..ea75c656bc 100644 --- a/app/assets/javascripts/notes.js.coffee +++ b/app/assets/javascripts/notes.js.coffee @@ -29,6 +29,7 @@ class @Notes $(document).on "ajax:success", "form.edit_note", @updateNote # Edit note link + $(document).on "click", ".js-note-edit", @showEditForm $(document).on "click", ".note-edit-cancel", @cancelEdit # Reopen and close actions for Issue/MR combined with note form submit @@ -66,6 +67,7 @@ class @Notes $(document).off "ajax:success", ".js-main-target-form" $(document).off "ajax:success", ".js-discussion-note-form" $(document).off "ajax:success", "form.edit_note" + $(document).off "click", ".js-note-edit" $(document).off "click", ".note-edit-cancel" $(document).off "click", ".js-note-delete" $(document).off "click", ".js-note-attachment-delete" @@ -285,14 +287,13 @@ class @Notes Adds a hidden div with the original content of the note to fill the edit note form with if the user cancels ### - showEditForm: (note, formHTML) -> - nodeText = note.find(".note-text"); - nodeText.hide() - note.find('.note-edit-form').remove() - nodeText.after(formHTML) + showEditForm: (e) -> + e.preventDefault() + note = $(this).closest(".note") note.find(".note-body > .note-text").hide() note.find(".note-header").hide() - form = note.find(".note-edit-form") + base_form = note.find(".note-edit-form") + form = base_form.clone().insertAfter(base_form) form.addClass('current-note-edit-form gfm-form') form.find('.div-dropzone').remove() diff --git a/app/assets/javascripts/stat_graph_contributors_util.js.coffee b/app/assets/javascripts/stat_graph_contributors_util.js.coffee index cfe5508290..f5584bcfe4 100644 --- a/app/assets/javascripts/stat_graph_contributors_util.js.coffee +++ b/app/assets/javascripts/stat_graph_contributors_util.js.coffee @@ -6,7 +6,7 @@ window.ContributorsStatGraphUtil = for entry in log @add_date(entry.date, total) unless total[entry.date]? - data = by_author[entry.author_name] #|| by_email[entry.author_email] + data = by_author[entry.author_name] || by_email[entry.author_email] data ?= @add_author(entry, by_author, by_email) @add_date(entry.date, data) unless data[entry.date] @@ -95,5 +95,4 @@ window.ContributorsStatGraphUtil = if date_range is null || date_range[0] <= new Date(date) <= date_range[1] true else - false - + false \ No newline at end of file diff --git a/app/controllers/concerns/global_milestones.rb b/app/controllers/concerns/global_milestones.rb new file mode 100644 index 0000000000..b428249acd --- /dev/null +++ b/app/controllers/concerns/global_milestones.rb @@ -0,0 +1,19 @@ +module GlobalMilestones + extend ActiveSupport::Concern + + def milestones + @milestones = MilestonesFinder.new.execute(@projects, params) + @milestones = GlobalMilestone.build_collection(@milestones) + @milestones = Kaminari.paginate_array(@milestones).page(params[:page]).per(ApplicationController::PER_PAGE) + end + + def milestone + milestones = Milestone.of_projects(@projects).where(title: params[:title]) + + if milestones.present? + @milestone = GlobalMilestone.new(params[:title], milestones) + else + render_404 + end + end +end diff --git a/app/controllers/dashboard/milestones_controller.rb b/app/controllers/dashboard/milestones_controller.rb index 53896d4f2c..2bdce0f8a0 100644 --- a/app/controllers/dashboard/milestones_controller.rb +++ b/app/controllers/dashboard/milestones_controller.rb @@ -1,34 +1,19 @@ class Dashboard::MilestonesController < Dashboard::ApplicationController - before_action :load_projects + include GlobalMilestones + + before_action :projects + before_action :milestones, only: [:index] + before_action :milestone, only: [:show] def index - project_milestones = case params[:state] - when 'all'; state - when 'closed'; state('closed') - else state('active') - end - @dashboard_milestones = Milestones::GroupService.new(project_milestones).execute - @dashboard_milestones = Kaminari.paginate_array(@dashboard_milestones).page(params[:page]).per(PER_PAGE) end def show - project_milestones = Milestone.where(project_id: @projects).order("due_date ASC") - @dashboard_milestone = Milestones::GroupService.new(project_milestones).milestone(title) end private - def load_projects - @projects = current_user.authorized_projects.sorted_by_activity.non_archived - end - - def title - params[:title] - end - - def state(state = nil) - conditions = { project_id: @projects } - conditions.reverse_merge!(state: state) if state - Milestone.where(conditions).order("title ASC") + def projects + @projects ||= current_user.authorized_projects.sorted_by_activity.non_archived end end diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb index 4ebb3d7276..b2c1fa4230 100644 --- a/app/controllers/dashboard_controller.rb +++ b/app/controllers/dashboard_controller.rb @@ -1,5 +1,6 @@ class DashboardController < Dashboard::ApplicationController before_action :event_filter, only: :activity + before_action :projects, only: [:issues, :merge_requests] respond_to :html @@ -47,4 +48,8 @@ class DashboardController < Dashboard::ApplicationController @events = @event_filter.apply_filter(@events).with_associations @events = @events.limit(20).offset(params[:offset] || 0) end + + def projects + @projects ||= current_user.authorized_projects.sorted_by_activity.non_archived + end end diff --git a/app/controllers/groups/application_controller.rb b/app/controllers/groups/application_controller.rb index 8c44f59ceb..be801858ea 100644 --- a/app/controllers/groups/application_controller.rb +++ b/app/controllers/groups/application_controller.rb @@ -1,5 +1,6 @@ class Groups::ApplicationController < ApplicationController layout 'group' + before_action :group private diff --git a/app/controllers/groups/avatars_controller.rb b/app/controllers/groups/avatars_controller.rb index 6aa64222f7..76c87366ba 100644 --- a/app/controllers/groups/avatars_controller.rb +++ b/app/controllers/groups/avatars_controller.rb @@ -1,8 +1,6 @@ -class Groups::AvatarsController < ApplicationController +class Groups::AvatarsController < Groups::ApplicationController def destroy - @group = Group.find_by(path: params[:group_id]) @group.remove_avatar! - @group.save redirect_to edit_group_path(@group) diff --git a/app/controllers/groups/group_members_controller.rb b/app/controllers/groups/group_members_controller.rb index 3f1c298545..5cadfaaded 100644 --- a/app/controllers/groups/group_members_controller.rb +++ b/app/controllers/groups/group_members_controller.rb @@ -1,11 +1,9 @@ class Groups::GroupMembersController < Groups::ApplicationController skip_before_action :authenticate_user!, only: [:index] - before_action :group # Authorize before_action :authorize_read_group! - before_action :authorize_admin_group!, except: [:index, :leave] - before_action :authorize_admin_group_member!, only: [:create, :resend_invite] + before_action :authorize_admin_group_member!, except: [:index, :leave] def index @project = @group.projects.find(params[:project_id]) if params[:project_id] @@ -18,7 +16,8 @@ class Groups::GroupMembersController < Groups::ApplicationController end @members = @members.order('access_level DESC').page(params[:page]).per(50) - @group_member = GroupMember.new + + @group_member = @group.group_members.new end def create @@ -36,20 +35,25 @@ class Groups::GroupMembersController < Groups::ApplicationController end def update - @member = @group.group_members.find(params[:id]) + @group_member = @group.group_members.find(params[:id]) - return render_403 unless can?(current_user, :update_group_member, @member) + return render_403 unless can?(current_user, :update_group_member, @group_member) +<<<<<<< HEAD old_access_level = @member.human_access if @member.update_attributes(member_params) log_audit_event(@member, action: :update, old_access_level: old_access_level) end +======= + @group_member.update_attributes(member_params) +>>>>>>> ce/8-2-stable end def destroy @group_member = @group.group_members.find(params[:id]) +<<<<<<< HEAD if can?(current_user, :destroy_group_member, @group_member) # May fail if last owner. @group_member.destroy log_audit_event(@group_member, action: :destroy) @@ -60,6 +64,15 @@ class Groups::GroupMembersController < Groups::ApplicationController end else return render_403 +======= + return render_403 unless can?(current_user, :destroy_group_member, @group_member) + + @group_member.destroy + + respond_to do |format| + format.html { redirect_to group_group_members_path(@group), notice: 'User was successfully removed from group.' } + format.js { render nothing: true } +>>>>>>> ce/8-2-stable end end @@ -78,11 +91,14 @@ class Groups::GroupMembersController < Groups::ApplicationController end def leave - @group_member = @group.group_members.where(user_id: current_user.id).first + @group_member = @group.group_members.find_by(user_id: current_user) if can?(current_user, :destroy_group_member, @group_member) @group_member.destroy +<<<<<<< HEAD log_audit_event(@group_member, action: :destroy) +======= +>>>>>>> ce/8-2-stable redirect_to(dashboard_groups_path, notice: "You left #{group.name} group.") else diff --git a/app/controllers/groups/milestones_controller.rb b/app/controllers/groups/milestones_controller.rb index 669f7f3126..10233222ee 100644 --- a/app/controllers/groups/milestones_controller.rb +++ b/app/controllers/groups/milestones_controller.rb @@ -1,54 +1,55 @@ class Groups::MilestonesController < Groups::ApplicationController - before_action :authorize_group_milestone!, only: :update + include GlobalMilestones + + before_action :projects + before_action :milestones, only: [:index] + before_action :milestone, only: [:show, :update] + before_action :authorize_group_milestone!, only: [:create, :update] def index - project_milestones = case params[:state] - when 'all'; state - when 'closed'; state('closed') - else state('active') - end - @group_milestones = Milestones::GroupService.new(project_milestones).execute - @group_milestones = Kaminari.paginate_array(@group_milestones).page(params[:page]).per(PER_PAGE) + end + + def new + @milestone = Milestone.new + end + + def create + project_ids = params[:milestone][:project_ids] + title = milestone_params[:title] + + @group.projects.where(id: project_ids).each do |project| + Milestones::CreateService.new(project, current_user, milestone_params).execute + end + + redirect_to milestone_path(title) end def show - project_milestones = Milestone.where(project_id: group.projects).order("due_date ASC") - @group_milestone = Milestones::GroupService.new(project_milestones).milestone(title) end def update - project_milestones = Milestone.where(project_id: group.projects).order("due_date ASC") - @group_milestones = Milestones::GroupService.new(project_milestones).milestone(title) - - @group_milestones.milestones.each do |milestone| - Milestones::UpdateService.new(milestone.project, current_user, params[:milestone]).execute(milestone) + @milestone.milestones.each do |milestone| + Milestones::UpdateService.new(milestone.project, current_user, milestone_params).execute(milestone) end - respond_to do |format| - format.js - format.html do - redirect_to group_milestones_path(group) - end - end + redirect_back_or_default(default: milestone_path(@milestone.title)) end private - def group - @group ||= Group.find_by(path: params[:group_id]) - end - - def title - params[:title] - end - - def state(state = nil) - conditions = { project_id: group.projects } - conditions.reverse_merge!(state: state) if state - Milestone.where(conditions).order("title ASC") - end - def authorize_group_milestone! - return render_404 unless can?(current_user, :admin_group, group) + return render_404 unless can?(current_user, :admin_milestones, group) + end + + def milestone_params + params.require(:milestone).permit(:title, :description, :due_date, :state_event) + end + + def milestone_path(title) + group_milestone_path(@group, title.parameterize, title: title) + end + + def projects + @projects ||= @group.projects end end diff --git a/app/controllers/projects/compare_controller.rb b/app/controllers/projects/compare_controller.rb index 55134e11d1..5200d609cc 100644 --- a/app/controllers/projects/compare_controller.rb +++ b/app/controllers/projects/compare_controller.rb @@ -20,8 +20,8 @@ class Projects::CompareController < Projects::ApplicationController if compare_result @commits = Commit.decorate(compare_result.commits, @project) @diffs = compare_result.diffs - @commit = @commits.last - @first_commit = @commits.first + @commit = @project.commit(head_ref) + @first_commit = @project.commit(base_ref) @line_notes = [] end end diff --git a/app/controllers/projects/notes_controller.rb b/app/controllers/projects/notes_controller.rb index 0c98e2f1bf..41cd08c93c 100644 --- a/app/controllers/projects/notes_controller.rb +++ b/app/controllers/projects/notes_controller.rb @@ -3,7 +3,7 @@ class Projects::NotesController < Projects::ApplicationController before_action :authorize_read_note! before_action :authorize_create_note!, only: [:create] before_action :authorize_admin_note!, only: [:update, :destroy] - before_action :find_current_user_notes, except: [:destroy, :edit, :delete_attachment] + before_action :find_current_user_notes, except: [:destroy, :delete_attachment] def index current_fetched_at = Time.now.to_i @@ -29,11 +29,6 @@ class Projects::NotesController < Projects::ApplicationController end end - def edit - @note = note - render layout: false - end - def update @note = Notes::UpdateService.new(project, current_user, note_params).execute(note) diff --git a/app/controllers/projects/project_members_controller.rb b/app/controllers/projects/project_members_controller.rb index bd2f76acd4..54165f867a 100644 --- a/app/controllers/projects/project_members_controller.rb +++ b/app/controllers/projects/project_members_controller.rb @@ -1,6 +1,6 @@ class Projects::ProjectMembersController < Projects::ApplicationController # Authorize - before_action :authorize_admin_project!, except: :leave + before_action :authorize_admin_project_member!, except: :leave def index @project_members = @project.project_members @@ -30,10 +30,6 @@ class Projects::ProjectMembersController < Projects::ApplicationController @project_group_links = @project.project_group_links end - def new - @project_member = @project.project_members.new - end - def create @project.team.add_users(params[:user_ids].split(','), params[:access_level], current_user) members = @project.project_members.where(user_id: params[:user_ids].split(',')) @@ -47,15 +43,25 @@ class Projects::ProjectMembersController < Projects::ApplicationController def update @project_member = @project.project_members.find(params[:id]) +<<<<<<< HEAD old_access_level = @project_member.human_access if @project_member.update_attributes(member_params) log_audit_event(@project_member, action: :update, old_access_level: old_access_level) end +======= + + return render_403 unless can?(current_user, :update_project_member, @project_member) + + @project_member.update_attributes(member_params) +>>>>>>> ce/8-2-stable end def destroy @project_member = @project.project_members.find(params[:id]) + + return render_403 unless can?(current_user, :destroy_project_member, @project_member) + @project_member.destroy log_audit_event(@project_member, action: :destroy) @@ -82,18 +88,28 @@ class Projects::ProjectMembersController < Projects::ApplicationController end def leave - if @project.namespace == current_user.namespace - message = 'You can not leave your own project. Transfer or delete the project.' - return redirect_back_or_default(default: { action: 'index' }, options: { alert: message }) - end + @project_member = @project.project_members.find_by(user_id: current_user) +<<<<<<< HEAD @project_member = @project.project_members.find_by(user_id: current_user) @project_member.destroy log_audit_event(@project_member, action: :destroy) +======= + if can?(current_user, :destroy_project_member, @project_member) + @project_member.destroy +>>>>>>> ce/8-2-stable - respond_to do |format| - format.html { redirect_to dashboard_projects_path } - format.js { render nothing: true } + respond_to do |format| + format.html { redirect_to dashboard_projects_path, notice: "You left the project." } + format.js { render nothing: true } + end + else + if current_user == @project.owner + message = 'You can not leave your own project. Transfer or delete the project.' + redirect_back_or_default(default: { action: 'index' }, options: { alert: message }) + else + render_403 + end end end diff --git a/app/finders/milestones_finder.rb b/app/finders/milestones_finder.rb new file mode 100644 index 0000000000..b704e87890 --- /dev/null +++ b/app/finders/milestones_finder.rb @@ -0,0 +1,12 @@ +class MilestonesFinder + def execute(projects, params) + milestones = Milestone.of_projects(projects) + milestones = milestones.order("due_date ASC") + + case params[:state] + when 'closed' then milestones.closed + when 'all' then milestones + else milestones.active + end + end +end diff --git a/app/helpers/diff_helper.rb b/app/helpers/diff_helper.rb index b889fb2897..0fd5c98658 100644 --- a/app/helpers/diff_helper.rb +++ b/app/helpers/diff_helper.rb @@ -1,4 +1,8 @@ module DiffHelper + def diff_view + params[:view] == 'parallel' ? 'parallel' : 'inline' + end + def allowed_diff_size if diff_hard_limit_enabled? Commit::DIFF_HARD_LIMIT_FILES @@ -137,7 +141,7 @@ module DiffHelper # Always use HTML to handle case where JSON diff rendered this button params_copy.delete(:format) - link_to url_for(params_copy), id: "inline-diff-btn", class: (params[:view] != 'parallel' ? 'btn active' : 'btn') do + link_to url_for(params_copy), id: "inline-diff-btn", class: (diff_view == 'inline' ? 'btn active' : 'btn') do 'Inline' end end @@ -148,7 +152,7 @@ module DiffHelper # Always use HTML to handle case where JSON diff rendered this button params_copy.delete(:format) - link_to url_for(params_copy), id: "parallel-diff-btn", class: (params[:view] == 'parallel' ? 'btn active' : 'btn') do + link_to url_for(params_copy), id: "parallel-diff-btn", class: (diff_view == 'parallel' ? 'btn active' : 'btn') do 'Side-by-side' end end @@ -171,7 +175,7 @@ module DiffHelper def commit_for_diff(diff) if diff.deleted_file first_commit = @first_commit || @commit - first_commit.parent + first_commit.parent || @first_commit else @commit end diff --git a/app/helpers/labels_helper.rb b/app/helpers/labels_helper.rb index ee04ace35d..795fb439f2 100644 --- a/app/helpers/labels_helper.rb +++ b/app/helpers/labels_helper.rb @@ -100,7 +100,7 @@ module LabelsHelper Label.where(project_id: @projects) end - grouped_labels = Labels::GroupService.new(labels).execute + grouped_labels = GlobalLabel.build_collection(labels) grouped_labels.unshift(Label::None) grouped_labels.unshift(Label::Any) diff --git a/app/helpers/milestones_helper.rb b/app/helpers/milestones_helper.rb index 37a5b58cce..ad43892b63 100644 --- a/app/helpers/milestones_helper.rb +++ b/app/helpers/milestones_helper.rb @@ -28,7 +28,7 @@ module MilestonesHelper Milestone.where(project_id: @projects) end.active - grouped_milestones = Milestones::GroupService.new(milestones).execute + grouped_milestones = GlobalMilestone.build_collection(milestones) grouped_milestones.unshift(Milestone::None) grouped_milestones.unshift(Milestone::Any) diff --git a/app/models/ability.rb b/app/models/ability.rb index 72b27daa76..df894be575 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -5,6 +5,7 @@ class Ability return [] unless user.kind_of?(User) return [] if user.blocked? +<<<<<<< HEAD abilities = case subject.class.name when "Project" then project_abilities(user, subject) @@ -33,6 +34,21 @@ class Ability :push_code, :push_code_to_protected_branches ] +======= + case subject.class.name + when "Project" then project_abilities(user, subject) + when "Issue" then issue_abilities(user, subject) + when "Note" then note_abilities(user, subject) + when "ProjectSnippet" then project_snippet_abilities(user, subject) + when "PersonalSnippet" then personal_snippet_abilities(user, subject) + when "MergeRequest" then merge_request_abilities(user, subject) + when "Group" then group_abilities(user, subject) + when "Namespace" then namespace_abilities(user, subject) + when "GroupMember" then group_member_abilities(user, subject) + when "ProjectMember" then project_member_abilities(user, subject) + else [] + end.concat(global_abilities(user)) +>>>>>>> ce/8-2-stable end # List of possible abilities @@ -247,22 +263,27 @@ class Ability # Only group masters and group owners can create new projects in group if group.has_master?(user) || group.has_owner?(user) || user.admin? - rules.push(*[ + rules += [ :create_projects, - ]) + :admin_milestones + ] end # Only group owner and administrators can admin group if group.has_owner?(user) || user.admin? - rules.push(*[ + rules += [ :admin_group, :admin_namespace, :admin_group_member +<<<<<<< HEAD ]) unless group.ldap_synced? rules << :admin_group_member end +======= + ] +>>>>>>> ce/8-2-stable end rules.flatten @@ -273,16 +294,15 @@ class Ability # Only namespace owner and administrators can admin it if namespace.owner == user || user.admin? - rules.push(*[ + rules += [ :create_projects, :admin_namespace - ]) + ] end rules.flatten end - [:issue, :merge_request].each do |name| define_method "#{name}_abilities" do |user, subject| rules = [] @@ -323,15 +343,39 @@ class Ability rules = [] target_user = subject.user group = subject.group - can_manage = group_abilities(user, group).include?(:admin_group_member) - if can_manage && (user != target_user) - rules << :update_group_member - rules << :destroy_group_member + unless group.last_owner?(target_user) + can_manage = group_abilities(user, group).include?(:admin_group_member) + + if can_manage && user != target_user + rules << :update_group_member + rules << :destroy_group_member + end + + if user == target_user + rules << :destroy_group_member + end end - if !group.last_owner?(user) && (can_manage || (user == target_user)) - rules << :destroy_group_member + rules + end + + def project_member_abilities(user, subject) + rules = [] + target_user = subject.user + project = subject.project + + unless target_user == project.owner + can_manage = project_abilities(user, project).include?(:admin_project_member) + + if can_manage && user != target_user + rules << :update_project_member + rules << :destroy_project_member + end + + if user == target_user + rules << :destroy_project_member + end end rules @@ -339,10 +383,10 @@ class Ability def abilities @abilities ||= begin - abilities = Six.new - abilities << self - abilities - end + abilities = Six.new + abilities << self + abilities + end end private diff --git a/app/models/global_label.rb b/app/models/global_label.rb new file mode 100644 index 0000000000..0171f7d54b --- /dev/null +++ b/app/models/global_label.rb @@ -0,0 +1,17 @@ +class GlobalLabel + attr_accessor :title, :labels + alias_attribute :name, :title + + def self.build_collection(labels) + labels = labels.group_by(&:title) + + labels.map do |title, label| + new(title, label) + end + end + + def initialize(title, labels) + @title = title + @labels = labels + end +end diff --git a/app/models/group_milestone.rb b/app/models/global_milestone.rb similarity index 76% rename from app/models/group_milestone.rb rename to app/models/global_milestone.rb index 91844da62e..1321ccd963 100644 --- a/app/models/group_milestone.rb +++ b/app/models/global_milestone.rb @@ -1,7 +1,15 @@ -class GroupMilestone +class GlobalMilestone attr_accessor :title, :milestones alias_attribute :name, :title + def self.build_collection(milestones) + milestones = milestones.group_by(&:title) + + milestones.map do |title, milestones| + new(title, milestones) + end + end + def initialize(title, milestones) @title = title @milestones = milestones @@ -10,7 +18,7 @@ class GroupMilestone def safe_title @title.parameterize end - + def projects milestones.map { |milestone| milestone.project } end @@ -60,15 +68,15 @@ class GroupMilestone end def issues - @group_issues ||= milestones.map(&:issues).flatten.group_by(&:state) + @issues ||= milestones.map(&:issues).flatten.group_by(&:state) end def merge_requests - @group_merge_requests ||= milestones.map(&:merge_requests).flatten.group_by(&:state) + @merge_requests ||= milestones.map(&:merge_requests).flatten.group_by(&:state) end def participants - @group_participants ||= milestones.map(&:participants).flatten.compact.uniq + @participants ||= milestones.map(&:participants).flatten.compact.uniq end def opened_issues @@ -86,4 +94,8 @@ class GroupMilestone def closed_merge_requests merge_requests.values_at("closed", "merged", "locked").compact.flatten end + + def complete? + total_items_count == closed_items_count + end end diff --git a/app/models/group.rb b/app/models/group.rb index 4c4f127ca6..6a47686069 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -20,8 +20,9 @@ require 'file_size_validator' class Group < Namespace include Gitlab::ConfigHelper include Referable - + has_many :group_members, dependent: :destroy, as: :source, class_name: 'GroupMember' + alias_method :members, :group_members has_many :users, through: :group_members has_many :project_group_links, dependent: :destroy has_many :shared_projects, through: :project_group_links, source: :project @@ -114,10 +115,6 @@ class Group < Namespace has_owner?(user) && owners.size == 1 end - def members - group_members - end - def avatar_type unless self.avatar.image? self.errors.add :avatar, "only images allowed" diff --git a/app/models/group_label.rb b/app/models/group_label.rb deleted file mode 100644 index 0fc39cb877..0000000000 --- a/app/models/group_label.rb +++ /dev/null @@ -1,9 +0,0 @@ -class GroupLabel - attr_accessor :title, :labels - alias_attribute :name, :title - - def initialize(title, labels) - @title = title - @labels = labels - end -end diff --git a/app/models/member.rb b/app/models/member.rb index c9cd984de7..54c4863a88 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -31,13 +31,22 @@ class Member < ActiveRecord::Base validates :user, presence: true, unless: :invite? validates :source, presence: true - validates :user_id, uniqueness: { scope: [:source_type, :source_id], + validates :user_id, uniqueness: { scope: [:source_type, :source_id], message: "already exists in source", allow_nil: true } validates :access_level, inclusion: { in: Gitlab::Access.all_values }, presence: true - validates :invite_email, presence: { if: :invite? }, - email: { strict_mode: true, allow_nil: true }, - uniqueness: { scope: [:source_type, :source_id], allow_nil: true } + validates :invite_email, + presence: { + if: :invite? + }, + email: { + strict_mode: true, + allow_nil: true + }, + uniqueness: { + scope: [:source_type, :source_id], + allow_nil: true + } scope :invite, -> { where(user_id: nil) } scope :non_invite, -> { where("user_id IS NOT NULL") } @@ -74,7 +83,7 @@ class Member < ActiveRecord::Base def add_user(members, user_id, access_level, current_user = nil, skip_notification: false) user = user_for_id(user_id) - + # `user` can be either a User object or an email to be invited if user.is_a?(User) member = members.find_or_initialize_by(user_id: user.id) @@ -83,12 +92,27 @@ class Member < ActiveRecord::Base member.invite_email = user end - member.created_by ||= current_user - member.access_level = access_level + if can_update_member?(current_user, member) + member.created_by ||= current_user + member.access_level = access_level + member.save + end + end + + private + +<<<<<<< HEAD member.skip_notification = skip_notification member.save +======= + def can_update_member?(current_user, member) + # There is no current user for bulk actions, in which case anything is allowed + !current_user || + current_user.can?(:update_group_member, member) || + current_user.can?(:update_project_member, member) +>>>>>>> ce/8-2-stable end end @@ -98,7 +122,7 @@ class Member < ActiveRecord::Base def accept_invite!(new_user) return false unless invite? - + self.invite_token = nil self.invite_accepted_at = Time.now.utc diff --git a/app/models/project.rb b/app/models/project.rb index 47d5ece506..e47c55ac7e 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -42,7 +42,7 @@ class Project < ActiveRecord::Base include Sortable include AfterCommitQueue include CaseSensitivity - + extend Gitlab::ConfigHelper extend Enumerize @@ -336,6 +336,7 @@ class Project < ActiveRecord::Base end def add_import_job +<<<<<<< HEAD if repository_exists? if mirror? RepositoryUpdateMirrorWorker.perform_async(self.id) @@ -344,6 +345,8 @@ class Project < ActiveRecord::Base return end +======= +>>>>>>> ce/8-2-stable if forked? RepositoryForkWorker.perform_async(self.id, forked_from_project.path_with_namespace, self.namespace.path) else @@ -391,6 +394,7 @@ class Project < ActiveRecord::Base original_url end +<<<<<<< HEAD def mirror_updated? mirror? && self.mirror_last_update_at end @@ -439,6 +443,8 @@ class Project < ActiveRecord::Base repository.fetch_upstream(self.import_url) end +======= +>>>>>>> ce/8-2-stable def check_limit unless creator.can_create_project? or namespace.kind == 'group' errors[:limit_reached] << ("Your project limit is #{creator.projects_limit} projects! Please contact your administrator to increase it") diff --git a/app/models/project_wiki.rb b/app/models/project_wiki.rb index 231973fa54..b5fec38378 100644 --- a/app/models/project_wiki.rb +++ b/app/models/project_wiki.rb @@ -86,6 +86,8 @@ class ProjectWiki commit = commit_details(:created, message, title) wiki.write_page(title, format, content, commit) + + update_project_activity rescue Gollum::DuplicatePageError => e @error_message = "Duplicate page: #{e.message}" return false @@ -95,10 +97,14 @@ class ProjectWiki commit = commit_details(:updated, message, page.title) wiki.update_page(page, page.name, format, content, commit) + + update_project_activity end def delete_page(page, message = nil) wiki.delete_page(page, commit_details(:deleted, message, page.title)) + + update_project_activity end def page_title_and_dir(title) @@ -146,4 +152,8 @@ class ProjectWiki def path_to_repo @path_to_repo ||= File.join(Gitlab.config.gitlab_shell.repos_path, "#{path_with_namespace}.git") end + + def update_project_activity + @project.touch(:last_activity_at) + end end diff --git a/app/services/labels/group_service.rb b/app/services/labels/group_service.rb deleted file mode 100644 index b26cee24d5..0000000000 --- a/app/services/labels/group_service.rb +++ /dev/null @@ -1,26 +0,0 @@ -module Labels - class GroupService < ::BaseService - def initialize(project_labels) - @project_labels = project_labels.group_by(&:title) - end - - def execute - build(@project_labels) - end - - def label(title) - if title - group_label = @project_labels[title].group_by(&:title) - build(group_label).first - else - nil - end - end - - private - - def build(label) - label.map { |title, labels| GroupLabel.new(title, labels) } - end - end -end diff --git a/app/services/milestones/group_service.rb b/app/services/milestones/group_service.rb deleted file mode 100644 index 11d702f1e7..0000000000 --- a/app/services/milestones/group_service.rb +++ /dev/null @@ -1,26 +0,0 @@ -module Milestones - class GroupService < Milestones::BaseService - def initialize(project_milestones) - @project_milestones = project_milestones.group_by(&:title) - end - - def execute - build(@project_milestones) - end - - def milestone(title) - if title - group_milestone = @project_milestones[title].group_by(&:title) - build(group_milestone).first - else - nil - end - end - - private - - def build(milestone) - milestone.map{ |title, milestones| GroupMilestone.new(title, milestones) } - end - end -end diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index a6b2234865..6ed6ebca58 100644 --- a/app/services/notification_service.rb +++ b/app/services/notification_service.rb @@ -361,11 +361,13 @@ class NotificationService end def reassign_resource_email(target, project, current_user, method) - assignee_id_was = previous_record(target, "assignee_id") - recipients = build_recipients(target, project, current_user) + previous_assignee_id = previous_record(target, "assignee_id") + previous_assignee = User.find_by(id: previous_assignee_id) if previous_assignee_id + + recipients = build_recipients(target, project, current_user, [previous_assignee]) recipients.each do |recipient| - mailer.send(method, recipient.id, target.id, assignee_id_was, current_user.id) + mailer.send(method, recipient.id, target.id, previous_assignee_id, current_user.id) end end @@ -377,9 +379,11 @@ class NotificationService end end - def build_recipients(target, project, current_user) + def build_recipients(target, project, current_user, extra_recipients = nil) recipients = target.participants(current_user) + recipients = recipients.concat(extra_recipients).compact.uniq if extra_recipients + recipients = add_project_watchers(recipients, project) recipients = reject_mention_users(recipients, project) recipients = reject_muted_users(recipients, project) diff --git a/app/views/admin/users/_profile.html.haml b/app/views/admin/users/_profile.html.haml index 90d9980c85..7d11edc79e 100644 --- a/app/views/admin/users/_profile.html.haml +++ b/app/views/admin/users/_profile.html.haml @@ -16,11 +16,11 @@ - unless user.linkedin.blank? %li %span.light LinkedIn: - %strong= link_to user.linkedin, "http://www.linkedin.com/in/#{user.linkedin}" + %strong= link_to user.linkedin, "https://www.linkedin.com/in/#{user.linkedin}" - unless user.twitter.blank? %li %span.light Twitter: - %strong= link_to user.twitter, "http://www.twitter.com/#{user.twitter}" + %strong= link_to user.twitter, "https://twitter.com/#{user.twitter}" - unless user.website_url.blank? %li %span.light Website: diff --git a/app/views/dashboard/milestones/index.html.haml b/app/views/dashboard/milestones/index.html.haml index 21b25c3986..635251e237 100644 --- a/app/views/dashboard/milestones/index.html.haml +++ b/app/views/dashboard/milestones/index.html.haml @@ -10,10 +10,10 @@ .milestones %ul.content-list - - if @dashboard_milestones.blank? + - if @milestones.blank? %li .nothing-here-block No milestones to show - else - - @dashboard_milestones.each do |milestone| + - @milestones.each do |milestone| = render 'milestone', milestone: milestone - = paginate @dashboard_milestones, theme: "gitlab" + = paginate @milestones, theme: "gitlab" diff --git a/app/views/dashboard/milestones/show.html.haml b/app/views/dashboard/milestones/show.html.haml index 2fe14c6388..83077a398b 100644 --- a/app/views/dashboard/milestones/show.html.haml +++ b/app/views/dashboard/milestones/show.html.haml @@ -1,14 +1,14 @@ -- page_title @dashboard_milestone.title, "Milestones" +- page_title @milestone.title, "Milestones" %h4.page-title - .issue-box{ class: "issue-box-#{@dashboard_milestone.closed? ? 'closed' : 'open'}" } - - if @dashboard_milestone.closed? + .issue-box{ class: "issue-box-#{@milestone.closed? ? 'closed' : 'open'}" } + - if @milestone.closed? Closed - else Open - Milestone #{@dashboard_milestone.title} + Milestone #{@milestone.title} %hr -- if (@dashboard_milestone.total_items_count == @dashboard_milestone.closed_items_count) && @dashboard_milestone.active? +- if @milestone.complete? && @milestone.active? .alert.alert-success %span All issues for this milestone are closed. You may close the milestone now. @@ -22,7 +22,7 @@ %th Open issues %th State %th Due date - - @dashboard_milestone.milestones.each do |milestone| + - @milestone.milestones.each do |milestone| %tr %td = link_to "#{milestone.project.name_with_namespace}", namespace_project_milestone_path(milestone.project.namespace, milestone.project, milestone) @@ -39,46 +39,46 @@ .context %p.lead Progress: - #{@dashboard_milestone.closed_items_count} closed + #{@milestone.closed_items_count} closed – - #{@dashboard_milestone.open_items_count} open - = milestone_progress_bar(@dashboard_milestone) + #{@milestone.open_items_count} open + = milestone_progress_bar(@milestone) %ul.nav.nav-tabs %li.active = link_to '#tab-issues', 'data-toggle' => 'tab' do Issues - %span.badge= @dashboard_milestone.issue_count + %span.badge= @milestone.issue_count %li = link_to '#tab-merge-requests', 'data-toggle' => 'tab' do Merge Requests - %span.badge= @dashboard_milestone.merge_requests_count + %span.badge= @milestone.merge_requests_count %li = link_to '#tab-participants', 'data-toggle' => 'tab' do Participants - %span.badge= @dashboard_milestone.participants.count + %span.badge= @milestone.participants.count .pull-right - = link_to 'Browse Issues', issues_dashboard_path(milestone_title: @dashboard_milestone.title), class: "btn edit-milestone-link btn-grouped" + = link_to 'Browse Issues', issues_dashboard_path(milestone_title: @milestone.title), class: "btn edit-milestone-link btn-grouped" .tab-content .tab-pane.active#tab-issues .row .col-md-6 - = render 'issues', title: "Open", issues: @dashboard_milestone.opened_issues + = render 'issues', title: "Open", issues: @milestone.opened_issues .col-md-6 - = render 'issues', title: "Closed", issues: @dashboard_milestone.closed_issues + = render 'issues', title: "Closed", issues: @milestone.closed_issues .tab-pane#tab-merge-requests .row .col-md-6 - = render 'merge_requests', title: "Open", merge_requests: @dashboard_milestone.opened_merge_requests + = render 'merge_requests', title: "Open", merge_requests: @milestone.opened_merge_requests .col-md-6 - = render 'merge_requests', title: "Closed", merge_requests: @dashboard_milestone.closed_merge_requests + = render 'merge_requests', title: "Closed", merge_requests: @milestone.closed_merge_requests .tab-pane#tab-participants %ul.bordered-list - - @dashboard_milestone.participants.each do |user| + - @milestone.participants.each do |user| %li = link_to user, title: user.name, class: "darken" do = image_tag avatar_icon(user, 32), class: "avatar s32" diff --git a/app/views/groups/group_members/_group_member.html.haml b/app/views/groups/group_members/_group_member.html.haml index 3c19381321..be94b1abc1 100644 --- a/app/views/groups/group_members/_group_member.html.haml +++ b/app/views/groups/group_members/_group_member.html.haml @@ -1,6 +1,5 @@ - user = member.user - return unless user || member.invite? -- show_roles = true if show_roles.nil? %li{class: "#{dom_class(member)} js-toggle-container", id: dom_id(member)} %span{class: ("list-item-name" if show_controls)} @@ -25,11 +24,11 @@ = link_to member.created_by.name, user_path(member.created_by) = time_ago_with_tooltip(member.created_at) - - if show_controls && can?(current_user, :admin_group_member, member) + - if show_controls && can?(current_user, :admin_group_member, @group) = link_to resend_invite_group_group_member_path(@group, member), method: :post, class: "btn-xs btn", title: 'Resend invite' do Resend invite - - if show_roles + - if should_user_see_group_roles?(current_user, @group) %span.pull-right %strong= member.human_access - if show_controls @@ -37,6 +36,7 @@ = button_tag class: "btn-xs btn js-toggle-button", title: 'Edit access level', type: 'button' do %i.fa.fa-pencil-square-o + - if can?(current_user, :destroy_group_member, member)   - if current_user == user diff --git a/app/views/groups/group_members/index.html.haml b/app/views/groups/group_members/index.html.haml index a943d10f46..6c35f614c8 100644 --- a/app/views/groups/group_members/index.html.haml +++ b/app/views/groups/group_members/index.html.haml @@ -1,8 +1,6 @@ - page_title "Members" - header_title group_title(@group, "Members", group_group_members_path(@group)) -- show_roles = should_user_see_group_roles?(current_user, @group) - -- if show_roles +- if should_user_see_group_roles?(current_user, @group) %p.light Members of group have access to all group projects. Read more about permissions @@ -49,7 +47,7 @@ (#{@members.total_count}) %ul.well-list - @members.each do |member| - = render 'groups/group_members/group_member', member: member, show_roles: show_roles, show_controls: true + = render 'groups/group_members/group_member', member: member, show_controls: true = paginate @members, theme: 'gitlab' diff --git a/app/views/groups/milestones/_milestone.html.haml b/app/views/groups/milestones/_milestone.html.haml index 41dffdd2fb..a20bf75bc3 100644 --- a/app/views/groups/milestones/_milestone.html.haml +++ b/app/views/groups/milestones/_milestone.html.haml @@ -22,7 +22,7 @@ %span.label.label-gray = milestone.project.name .col-sm-6 - - if can?(current_user, :admin_group, @group) + - if can?(current_user, :admin_milestones, @group) - if milestone.closed? = link_to 'Reopen Milestone', group_milestone_path(@group, milestone.safe_title, title: milestone.title, milestone: {state_event: :activate }), method: :put, class: "btn btn-xs btn-grouped btn-reopen" - else diff --git a/app/views/groups/milestones/index.html.haml b/app/views/groups/milestones/index.html.haml index 2bbcad5fdf..84ec77c618 100644 --- a/app/views/groups/milestones/index.html.haml +++ b/app/views/groups/milestones/index.html.haml @@ -3,15 +3,22 @@ = render 'shared/milestones_filter' .gray-content-block - Only milestones from - %strong #{@group.name} - group are listed here. + - if can?(current_user, :admin_milestones, @group) + .pull-right + %span.pull-right.hidden-xs + = link_to new_group_milestone_path(@group), class: "btn btn-new" do + New Milestone + + .oneline + Only milestones from + %strong #{@group.name} + group are listed here. .milestones %ul.content-list - - if @group_milestones.blank? + - if @milestones.blank? %li .nothing-here-block No milestones to show - else - - @group_milestones.each do |milestone| + - @milestones.each do |milestone| = render 'milestone', milestone: milestone - = paginate @group_milestones, theme: "gitlab" + = paginate @milestones, theme: "gitlab" diff --git a/app/views/groups/milestones/new.html.haml b/app/views/groups/milestones/new.html.haml new file mode 100644 index 0000000000..800bac4ef0 --- /dev/null +++ b/app/views/groups/milestones/new.html.haml @@ -0,0 +1,48 @@ +- page_title "Milestones" +- header_title group_title(@group, "Milestones", group_milestones_path(@group)) + +%h3.page-title + New Milestone + +%p.light + This will create milestone in every selected project +%hr + += form_for @milestone, url: group_milestones_path(@group), html: { class: 'form-horizontal milestone-form gfm-form js-requires-input' } do |f| + .row + .col-md-6 + .form-group + = f.label :title, "Title", class: "control-label" + .col-sm-10 + = f.text_field :title, maxlength: 255, class: "form-control js-quick-submit", required: true + %p.hint Required + .form-group.milestone-description + = f.label :description, "Description", class: "control-label" + .col-sm-10 + = render layout: 'projects/md_preview', locals: { preview_class: "md-preview" } do + = render 'projects/zen', f: f, attr: :description, classes: 'description form-control js-quick-submit' + .clearfix + .error-alert + .form-group + = f.label :projects, "Projects", class: "control-label" + .col-sm-10 + = f.collection_select :project_ids, @group.projects, :id, :name, + { selected: @group.projects.map(&:id) }, multiple: true, class: 'select2' + + .col-md-6 + .form-group + = f.label :due_date, "Due Date", class: "control-label" + .col-sm-10= f.hidden_field :due_date + .col-sm-10 + .datepicker + + .form-actions + = f.submit 'Create Milestone', class: "btn-create btn" + = link_to "Cancel", group_milestones_path(@group), class: "btn btn-cancel" + + +:javascript + $(".datepicker").datepicker({ + dateFormat: "yy-mm-dd", + onSelect: function(dateText, inst) { $("#milestone_due_date").val(dateText) } + }).datepicker("setDate", $.datepicker.parseDate('yy-mm-dd', $('#milestone_due_date').val())); diff --git a/app/views/groups/milestones/show.html.haml b/app/views/groups/milestones/show.html.haml index a92ad5d751..d161259e4a 100644 --- a/app/views/groups/milestones/show.html.haml +++ b/app/views/groups/milestones/show.html.haml @@ -1,22 +1,22 @@ -- page_title @group_milestone.title, "Milestones" +- page_title @milestone.title, "Milestones" = render "header_title" %h4.page-title - .issue-box{ class: "issue-box-#{@group_milestone.closed? ? 'closed' : 'open'}" } - - if @group_milestone.closed? + .issue-box{ class: "issue-box-#{@milestone.closed? ? 'closed' : 'open'}" } + - if @milestone.closed? Closed - else Open - Milestone #{@group_milestone.title} + Milestone #{@milestone.title} .pull-right - - if can?(current_user, :admin_group, @group) - - if @group_milestone.active? - = link_to 'Close Milestone', group_milestone_path(@group, @group_milestone.safe_title, title: @group_milestone.title, milestone: {state_event: :close }), method: :put, class: "btn btn-sm btn-close" + - if can?(current_user, :admin_milestones, @group) + - if @milestone.active? + = link_to 'Close Milestone', group_milestone_path(@group, @milestone.safe_title, title: @milestone.title, milestone: {state_event: :close }), method: :put, class: "btn btn-sm btn-close" - else - = link_to 'Reopen Milestone', group_milestone_path(@group, @group_milestone.safe_title, title: @group_milestone.title, milestone: {state_event: :activate }), method: :put, class: "btn btn-sm btn-grouped btn-reopen" + = link_to 'Reopen Milestone', group_milestone_path(@group, @milestone.safe_title, title: @milestone.title, milestone: {state_event: :activate }), method: :put, class: "btn btn-sm btn-grouped btn-reopen" %hr -- if (@group_milestone.total_items_count == @group_milestone.closed_items_count) && @group_milestone.active? +- if @milestone.complete? && @milestone.active? .alert.alert-success %span All issues for this milestone are closed. You may close the milestone now. @@ -30,7 +30,7 @@ %th Open issues %th State %th Due date - - @group_milestone.milestones.each do |milestone| + - @milestone.milestones.each do |milestone| %tr %td = link_to "#{milestone.project.name}", namespace_project_milestone_path(milestone.project.namespace, milestone.project, milestone) @@ -47,46 +47,46 @@ .context %p.lead Progress: - #{@group_milestone.closed_items_count} closed + #{@milestone.closed_items_count} closed – - #{@group_milestone.open_items_count} open - = milestone_progress_bar(@group_milestone) + #{@milestone.open_items_count} open + = milestone_progress_bar(@milestone) %ul.nav.nav-tabs %li.active = link_to '#tab-issues', 'data-toggle' => 'tab' do Issues - %span.badge= @group_milestone.issue_count + %span.badge= @milestone.issue_count %li = link_to '#tab-merge-requests', 'data-toggle' => 'tab' do Merge Requests - %span.badge= @group_milestone.merge_requests_count + %span.badge= @milestone.merge_requests_count %li = link_to '#tab-participants', 'data-toggle' => 'tab' do Participants - %span.badge= @group_milestone.participants.count + %span.badge= @milestone.participants.count .pull-right - = link_to 'Browse Issues', issues_group_path(@group, milestone_title: @group_milestone.title), class: "btn edit-milestone-link btn-grouped" + = link_to 'Browse Issues', issues_group_path(@group, milestone_title: @milestone.title), class: "btn edit-milestone-link btn-grouped" .tab-content .tab-pane.active#tab-issues .row .col-md-6 - = render 'issues', title: "Open", issues: @group_milestone.opened_issues + = render 'issues', title: "Open", issues: @milestone.opened_issues .col-md-6 - = render 'issues', title: "Closed", issues: @group_milestone.closed_issues + = render 'issues', title: "Closed", issues: @milestone.closed_issues .tab-pane#tab-merge-requests .row .col-md-6 - = render 'merge_requests', title: "Open", merge_requests: @group_milestone.opened_merge_requests + = render 'merge_requests', title: "Open", merge_requests: @milestone.opened_merge_requests .col-md-6 - = render 'merge_requests', title: "Closed", merge_requests: @group_milestone.closed_merge_requests + = render 'merge_requests', title: "Closed", merge_requests: @milestone.closed_merge_requests .tab-pane#tab-participants %ul.bordered-list - - @group_milestone.participants.each do |user| + - @milestone.participants.each do |user| %li = link_to user, title: user.name, class: "darken" do = image_tag avatar_icon(user, 32), class: "avatar s32" diff --git a/app/views/notify/project_was_moved_email.text.erb b/app/views/notify/project_was_moved_email.text.erb index d8a23dabf4..b2c5f71e46 100644 --- a/app/views/notify/project_was_moved_email.text.erb +++ b/app/views/notify/project_was_moved_email.text.erb @@ -1,4 +1,4 @@ -Project #{@old_path_with_namespace} was moved to another location +Project <%= @old_path_with_namespace %> was moved to another location The project is now located under <%= namespace_project_url(@project.namespace, @project) %> diff --git a/app/views/projects/commit/show.html.haml b/app/views/projects/commit/show.html.haml index 30a3973828..85e203cbe5 100644 --- a/app/views/projects/commit/show.html.haml +++ b/app/views/projects/commit/show.html.haml @@ -3,4 +3,4 @@ = render "commit_box" = render "ci_menu" if @ci_commit = render "projects/diffs/diffs", diffs: @diffs, project: @project -= render "projects/notes/notes_with_form", view: params[:view] += render "projects/notes/notes_with_form" diff --git a/app/views/projects/diffs/_diffs.html.haml b/app/views/projects/diffs/_diffs.html.haml index e46bf1ab1e..416fb4da07 100644 --- a/app/views/projects/diffs/_diffs.html.haml +++ b/app/views/projects/diffs/_diffs.html.haml @@ -1,4 +1,4 @@ -- if params[:view] == 'parallel' +- if diff_view == 'parallel' - fluid_layout true - diff_files = safe_diff_files(diffs) diff --git a/app/views/projects/diffs/_file.html.haml b/app/views/projects/diffs/_file.html.haml index 410ff6abb4..c745b4e69b 100644 --- a/app/views/projects/diffs/_file.html.haml +++ b/app/views/projects/diffs/_file.html.haml @@ -33,7 +33,7 @@ -# Skipp all non non-supported blobs - return unless blob.respond_to?('text?') - if blob.text? - - if params[:view] == 'parallel' + - if diff_view == 'parallel' = render "projects/diffs/parallel_view", diff_file: diff_file, project: project, blob: blob, index: i - else = render "projects/diffs/text_file", diff_file: diff_file, index: i @@ -42,4 +42,3 @@ = render "projects/diffs/image", diff_file: diff_file, old_file: old_file, file: blob, index: i - else .nothing-here-block No preview for this file type - diff --git a/app/views/projects/milestones/_form.html.haml b/app/views/projects/milestones/_form.html.haml index 255ddab479..24879b19d2 100644 --- a/app/views/projects/milestones/_form.html.haml +++ b/app/views/projects/milestones/_form.html.haml @@ -23,9 +23,7 @@ .col-sm-10 = render layout: 'projects/md_preview', locals: { preview_class: "md-preview" } do = render 'projects/zen', f: f, attr: :description, classes: 'description form-control js-quick-submit' - .hint - .pull-left Milestones are parsed with #{link_to "GitLab Flavored Markdown", help_page_path("markdown", "markdown"), target: '_blank'}. - .pull-left Attach files by dragging & dropping or #{link_to "selecting them", '#', class: 'markdown-selector' }. + = render 'projects/notes/hints' .clearfix .error-alert .col-md-6 @@ -45,7 +43,7 @@ :javascript - $( ".datepicker" ).datepicker({ + $(".datepicker").datepicker({ dateFormat: "yy-mm-dd", onSelect: function(dateText, inst) { $("#milestone_due_date").val(dateText) } }).datepicker("setDate", $.datepicker.parseDate('yy-mm-dd', $('#milestone_due_date').val())); diff --git a/app/views/projects/notes/_form.html.haml b/app/views/projects/notes/_form.html.haml index 13dfa0a1bb..5dd84317e3 100644 --- a/app/views/projects/notes/_form.html.haml +++ b/app/views/projects/notes/_form.html.haml @@ -1,5 +1,5 @@ = form_for [@project.namespace.becomes(Namespace), @project, @note], remote: true, html: { :'data-type' => 'json', multipart: true, id: nil, class: "new_note js-new-note-form common-note-form gfm-form" }, authenticity_token: true do |f| - = hidden_field_tag :view, params[:view] + = hidden_field_tag :view, diff_view = hidden_field_tag :line_type = note_target_fields(@note) = f.hidden_field :commit_id diff --git a/app/views/projects/notes/_note.html.haml b/app/views/projects/notes/_note.html.haml index 8a3292f7da..efa7dd01cc 100644 --- a/app/views/projects/notes/_note.html.haml +++ b/app/views/projects/notes/_note.html.haml @@ -7,7 +7,7 @@ .note-header - if note_editable?(note) .note-actions - = link_to edit_namespace_project_note_path(note.project.namespace, note.project, note), title: 'Edit comment', remote: true, class: 'js-note-edit' do + = link_to '#', title: 'Edit comment', class: 'js-note-edit' do = icon('pencil-square-o') = link_to namespace_project_note_path(note.project.namespace, note.project, note), title: 'Remove comment', method: :delete, data: { confirm: 'Are you sure you want to remove this comment?' }, remote: true, class: 'js-note-delete danger' do @@ -59,6 +59,8 @@ .note-text = preserve do = markdown(note.note, {no_header_anchors: true}) + - if note_editable?(note) + = render 'projects/notes/edit_form', note: note - if note.attachment.url .note-attachment diff --git a/app/views/projects/notes/_notes_with_form.html.haml b/app/views/projects/notes/_notes_with_form.html.haml index 91cefa6d14..99c1b0fa43 100644 --- a/app/views/projects/notes/_notes_with_form.html.haml +++ b/app/views/projects/notes/_notes_with_form.html.haml @@ -4,7 +4,7 @@ .js-main-target-form - if can? current_user, :create_note, @project - = render "projects/notes/form", view: params[:view] + = render "projects/notes/form", view: diff_view :javascript - window._notes = new Notes("#{namespace_project_notes_path(namespace_id: @project.namespace, target_id: @noteable.id, target_type: @noteable.class.name.underscore)}", #{@notes.map(&:id).to_json}, #{Time.now.to_i}, "#{params[:view]}") + new Notes("#{namespace_project_notes_path(namespace_id: @project.namespace, target_id: @noteable.id, target_type: @noteable.class.name.underscore)}", #{@notes.map(&:id).to_json}, #{Time.now.to_i}, "#{diff_view}") diff --git a/app/views/projects/notes/edit.js.erb b/app/views/projects/notes/edit.js.erb deleted file mode 100644 index 2599bad5d6..0000000000 --- a/app/views/projects/notes/edit.js.erb +++ /dev/null @@ -1,2 +0,0 @@ -$note = $('.note-row-<%= @note.id %>:visible'); -_notes.showEditForm($note, '<%= escape_javascript(render('edit_form', note: @note)) %>'); diff --git a/app/views/projects/project_members/_project_member.html.haml b/app/views/projects/project_members/_project_member.html.haml index 76c46d1d80..f07cd97e63 100644 --- a/app/views/projects/project_members/_project_member.html.haml +++ b/app/views/projects/project_members/_project_member.html.haml @@ -24,18 +24,19 @@ = link_to member.created_by.name, user_path(member.created_by) = time_ago_with_tooltip(member.created_at) - - if current_user_can_admin_project + - if can?(current_user, :admin_project_member, @project) = link_to resend_invite_namespace_project_project_member_path(@project.namespace, @project, member), method: :post, class: "btn-xs btn", title: 'Resend invite' do Resend invite - - if current_user_can_admin_project - - unless @project.personal? && user == current_user - .pull-right - %strong= member.human_access + - if can?(current_user, :admin_project_member, @project) + .pull-right + %strong= member.human_access + - if can?(current_user, :update_project_member, member) = button_tag class: "btn-xs btn js-toggle-button", title: 'Edit access level', type: 'button' do %i.fa.fa-pencil-square-o + - if can?(current_user, :destroy_project_member, member)   - if current_user == user = link_to leave_namespace_project_project_members_path(@project.namespace, @project), data: { confirm: leave_project_message(@project) }, method: :delete, class: "btn-xs btn btn-remove", title: 'Leave project' do diff --git a/app/views/projects/project_members/_team.html.haml b/app/views/projects/project_members/_team.html.haml index 615c425e59..b807fb2cc9 100644 --- a/app/views/projects/project_members/_team.html.haml +++ b/app/views/projects/project_members/_team.html.haml @@ -1,5 +1,3 @@ -- can_admin_project = can?(current_user, :admin_project, @project) - .panel.panel-default.prepend-top-20 .panel-heading %strong #{@project.name} @@ -8,4 +6,4 @@ (#{members.count}) %ul.well-list - members.each do |project_member| - = render 'project_member', member: project_member, current_user_can_admin_project: can_admin_project + = render 'project_member', member: project_member diff --git a/app/views/projects/project_members/update.js.haml b/app/views/projects/project_members/update.js.haml index 811b185882..2fb3a41d54 100644 --- a/app/views/projects/project_members/update.js.haml +++ b/app/views/projects/project_members/update.js.haml @@ -1,3 +1,2 @@ -- can_admin_project = can?(current_user, :admin_project, @project) :plain - $("##{dom_id(@project_member)}").replaceWith('#{escape_javascript(render("project_member", member: @project_member, current_user_can_admin_project: can_admin_project))}'); + $("##{dom_id(@project_member)}").replaceWith('#{escape_javascript(render("project_member", member: @project_member))}'); diff --git a/app/views/shared/_import_form.html.haml b/app/views/shared/_import_form.html.haml index 2b5428caaf..e363314be3 100644 --- a/app/views/shared/_import_form.html.haml +++ b/app/views/shared/_import_form.html.haml @@ -14,7 +14,6 @@ The import will time out after 4 minutes. For big repositories, use a clone/push combination. %li To migrate an SVN repository, check out #{link_to "this document", "http://doc.gitlab.com/ce/workflow/importing/migrating_from_svn.html"}. - .form-group .col-sm-offset-2.col-sm-10 .checkbox diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml index 3099241218..d5a92cb816 100644 --- a/app/views/users/show.html.haml +++ b/app/views/users/show.html.haml @@ -32,11 +32,11 @@ = icon('skype') - unless @user.linkedin.blank? .profile-link-holder - = link_to "http://www.linkedin.com/in/#{@user.linkedin}", title: "LinkedIn" do + = link_to "https://www.linkedin.com/in/#{@user.linkedin}", title: "LinkedIn" do = icon('linkedin-square') - unless @user.twitter.blank? .profile-link-holder - = link_to "http://www.twitter.com/#{@user.twitter}", title: "Twitter" do + = link_to "https://twitter.com/#{@user.twitter}", title: "Twitter" do = icon('twitter-square') - unless @user.website_url.blank? .profile-link-holder diff --git a/config/routes.rb b/config/routes.rb index 5eaee5d6bc..6189daf659 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -398,7 +398,7 @@ Gitlab::Application.routes.draw do end resource :avatar, only: [:destroy] - resources :milestones, only: [:index, :show, :update] + resources :milestones, only: [:index, :show, :update, :new, :create] end get "/audit_events" => "audit_events#group_log" @@ -712,7 +712,7 @@ Gitlab::Application.routes.draw do resources :group_links, only: [:index, :create, :destroy], constraints: { id: /\d+/ } - resources :notes, constraints: { id: /\d+/ } do + resources :notes, only: [:index, :create, :destroy, :update], constraints: { id: /\d+/ } do member do delete :delete_attachment end diff --git a/db/migrate/20151116144118_add_unique_for_lfs_oid_index.rb b/db/migrate/20151116144118_add_unique_for_lfs_oid_index.rb new file mode 100644 index 0000000000..41b93da0a8 --- /dev/null +++ b/db/migrate/20151116144118_add_unique_for_lfs_oid_index.rb @@ -0,0 +1,7 @@ +class AddUniqueForLfsOidIndex < ActiveRecord::Migration + def change + remove_index :lfs_objects, :oid + remove_index :lfs_objects, [:oid, :size] + add_index :lfs_objects, :oid, unique: true + end +end diff --git a/db/schema.rb b/db/schema.rb index 33319a8061..e979d764f8 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20151114113410) do +ActiveRecord::Schema.define(version: 20151116144118) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -48,9 +48,9 @@ ActiveRecord::Schema.define(version: 20151114113410) do t.boolean "twitter_sharing_enabled", default: true t.text "help_text" t.text "restricted_visibility_levels" + t.boolean "version_check_enabled", default: true t.integer "max_attachment_size", default: 10, null: false t.integer "default_project_visibility" - t.boolean "version_check_enabled", default: true t.integer "default_snippet_visibility" t.text "restricted_signup_domains" t.boolean "user_oauth_applications", default: true @@ -491,8 +491,7 @@ ActiveRecord::Schema.define(version: 20151114113410) do t.string "file" end - add_index "lfs_objects", ["oid", "size"], name: "index_lfs_objects_on_oid_and_size", using: :btree - add_index "lfs_objects", ["oid"], name: "index_lfs_objects_on_oid", using: :btree + add_index "lfs_objects", ["oid"], name: "index_lfs_objects_on_oid", unique: true, using: :btree create_table "lfs_objects_projects", force: true do |t| t.integer "lfs_object_id", null: false @@ -715,21 +714,21 @@ ActiveRecord::Schema.define(version: 20151114113410) do t.string "avatar" t.string "import_status" t.float "repository_size", default: 0.0 + t.text "merge_requests_template" t.integer "star_count", default: 0, null: false + t.boolean "merge_requests_rebase_enabled", default: false t.string "import_type" t.string "import_source" - t.text "merge_requests_template" - t.boolean "merge_requests_rebase_enabled", default: false - t.integer "commit_count", default: 0 t.integer "approvals_before_merge", default: 0, null: false t.boolean "reset_approvals_on_push", default: true + t.integer "commit_count", default: 0 t.boolean "merge_requests_ff_only_enabled", default: false t.text "issues_template" - t.text "import_error" t.boolean "mirror", default: false, null: false t.datetime "mirror_last_update_at" t.datetime "mirror_last_successful_update_at" t.integer "mirror_user_id" + t.text "import_error" end add_index "projects", ["created_at", "id"], name: "index_projects_on_created_at_and_id", using: :btree diff --git a/doc/api/commits.md b/doc/api/commits.md index 8e4a0ee1b8..93d62b751e 100644 --- a/doc/api/commits.md +++ b/doc/api/commits.md @@ -188,7 +188,7 @@ Parameters: "target_url": "http://jenkins/project/url", "description": "Jenkins success", "created_at": "2015-10-12T09:47:16.250Z", - "started_at": "2015-10-12T09:47:16.250Z"", + "started_at": "2015-10-12T09:47:16.250Z", "finished_at": "2015-10-12T09:47:16.262Z", "author": { "id": 1, @@ -228,7 +228,7 @@ POST /projects/:id/statuses/:sha "target_url": "http://jenkins/project/url", "description": "Jenkins success", "created_at": "2015-10-12T09:47:16.250Z", - "started_at": "2015-10-12T09:47:16.250Z"", + "started_at": "2015-10-12T09:47:16.250Z", "finished_at": "2015-10-12T09:47:16.262Z", "author": { "id": 1, diff --git a/doc/ci/docker/using_docker_build.md b/doc/ci/docker/using_docker_build.md index 5af27470d2..4b1788a9af 100644 --- a/doc/ci/docker/using_docker_build.md +++ b/doc/ci/docker/using_docker_build.md @@ -35,7 +35,7 @@ GitLab Runner then executes build scripts as `gitlab-runner` user. ```bash $ sudo gitlab-runner register -n \ - --url http://gitlab.com/ci \ + --url https://gitlab.com/ci \ --token RUNNER_TOKEN \ --executor shell --description "My Runner" @@ -84,7 +84,7 @@ In order to do that follow the steps: ```bash $ sudo gitlab-runner register -n \ - --url http://gitlab.com/ci \ + --url https://gitlab.com/ci \ --token RUNNER_TOKEN \ --executor docker \ --description "My Docker Runner" \ diff --git a/doc/ci/quick_start/README.md b/doc/ci/quick_start/README.md index a87a1f806f..d69064a91f 100644 --- a/doc/ci/quick_start/README.md +++ b/doc/ci/quick_start/README.md @@ -6,7 +6,7 @@ To start building projects with GitLab CI a few steps needs to be done. First you need to have a working GitLab and GitLab CI instance. -You can omit this step if you use [GitLab.com](http://GitLab.com/). +You can omit this step if you use [GitLab.com](https://GitLab.com/). ## 2. Create repository on GitLab @@ -16,7 +16,7 @@ Push your application to that repository. ## 3. Add project to CI The next part is to login to GitLab CI. -Point your browser to the URL you have set GitLab or use [gitlab.com/ci](http://gitlab.com/ci/). +Point your browser to the URL you have set GitLab or use [gitlab.com/ci](https://gitlab.com/ci/). On the first screen you will see a list of GitLab's projects that you have access to: @@ -97,7 +97,7 @@ If you do it correctly your runner should be shown under **Runners activated for ### Shared runners -If you use [gitlab.com/ci](http://gitlab.com/ci/) you can use **Shared runners** provided by GitLab Inc. +If you use [gitlab.com/ci](https://gitlab.com/ci/) you can use **Shared runners** provided by GitLab Inc. These are special virtual machines that are run on GitLab's infrastructure that can build any project. To enable **Shared runners** you have to go to **Runners** and click **Enable shared runners** for this project. diff --git a/doc/customization/libravatar.md b/doc/customization/libravatar.md index 54c1780c3a..bd2c242afc 100644 --- a/doc/customization/libravatar.md +++ b/doc/customization/libravatar.md @@ -2,7 +2,7 @@ GitLab by default supports [Gravatar](https://gravatar.com) avatar service. Libravatar is a service which delivers your avatar (profile picture) to other websites and their API is -[heavily based on gravatar](http://wiki.libravatar.org/api/). +[heavily based on gravatar](https://wiki.libravatar.org/api/). This means that it is not complicated to switch to Libravatar avatar service or even self hosted Libravatar server. @@ -31,7 +31,7 @@ the configuration options as follows: ## Self-hosted -If you are [running your own libravatar service](http://wiki.libravatar.org/running_your_own/) the URL will be different in the configuration +If you are [running your own libravatar service](https://wiki.libravatar.org/running_your_own/) the URL will be different in the configuration but the important part is to provide the same placeholders so GitLab can parse the URL correctly. For example, you host a service on `http://libravatar.example.com` the `plain_url` you need to supply in `gitlab.yml` is @@ -63,7 +63,7 @@ Run `sudo gitlab-ctl reconfigure` for changes to take effect. ## Default URL for missing images -[Libravatar supports different sets](http://wiki.libravatar.org/api/) of `missing images` for emails not found on the Libravatar service. +[Libravatar supports different sets](https://wiki.libravatar.org/api/) of `missing images` for emails not found on the Libravatar service. In order to use a different set other than `identicon`, replace `&d=identicon` portion of the URL with another supported set. For example, you can use `retro` set in which case the URL would look like: `plain_url: "http://cdn.libravatar.org/avatar/%{hash}?s=%{size}&d=retro"` diff --git a/doc/development/architecture.md b/doc/development/architecture.md index 39fa89aac2..ab9050f1c4 100644 --- a/doc/development/architecture.md +++ b/doc/development/architecture.md @@ -146,7 +146,7 @@ nginx Apache httpd -- [Explanation of Apache logs](http://httpd.apache.org/docs/2.2/logs.html). +- [Explanation of Apache logs](https://httpd.apache.org/docs/2.2/logs.html). - `/var/log/apache2/` contains error and output logs (on Ubuntu). - `/var/log/httpd/` contains error and output logs (on RHEL). diff --git a/doc/hooks/custom_hooks.md b/doc/hooks/custom_hooks.md index 548c484bc0..0f2665a3bf 100644 --- a/doc/hooks/custom_hooks.md +++ b/doc/hooks/custom_hooks.md @@ -7,7 +7,7 @@ Please explore webhooks as an option if you do not have filesystem access. For a Git natively supports hooks that are executed on different actions. Examples of server-side git hooks include pre-receive, post-receive, and update. See -[Git SCM Server-Side Hooks](http://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks#Server-Side-Hooks) +[Git SCM Server-Side Hooks](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks#Server-Side-Hooks) for more information about each hook type. As of gitlab-shell version 2.2.0 (which requires GitLab 7.5+), GitLab diff --git a/doc/install/database_mysql.md b/doc/install/database_mysql.md index c565e90da2..513ad69ec2 100644 --- a/doc/install/database_mysql.md +++ b/doc/install/database_mysql.md @@ -2,7 +2,7 @@ ## Note -We do not recommend using MySQL due to various issues. For example, case [(in)sensitivity](https://dev.mysql.com/doc/refman/5.0/en/case-sensitivity.html) and [problems](http://bugs.mysql.com/bug.php?id=65830) that [suggested](http://bugs.mysql.com/bug.php?id=50909) [fixes](http://bugs.mysql.com/bug.php?id=65830) [have](http://bugs.mysql.com/bug.php?id=63164). +We do not recommend using MySQL due to various issues. For example, case [(in)sensitivity](https://dev.mysql.com/doc/refman/5.0/en/case-sensitivity.html) and [problems](https://bugs.mysql.com/bug.php?id=65830) that [suggested](https://bugs.mysql.com/bug.php?id=50909) [fixes](https://bugs.mysql.com/bug.php?id=65830) [have](https://bugs.mysql.com/bug.php?id=63164). ## MySQL diff --git a/doc/install/installation.md b/doc/install/installation.md index 9ef38dd06c..3ad133c4d9 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -106,7 +106,7 @@ Then select 'Internet Site' and press enter to confirm the hostname. ## 2. Ruby -The use of Ruby version managers such as [RVM](http://rvm.io/), [rbenv](https://github.com/sstephenson/rbenv) or [chruby](https://github.com/postmodern/chruby) with GitLab in production frequently leads to hard to diagnose problems. For example, GitLab Shell is called from OpenSSH and having a version manager can prevent pushing and pulling over SSH. Version managers are not supported and we strongly advise everyone to follow the instructions below to use a system Ruby. +The use of Ruby version managers such as [RVM](https://rvm.io/), [rbenv](https://github.com/sstephenson/rbenv) or [chruby](https://github.com/postmodern/chruby) with GitLab in production frequently leads to hard to diagnose problems. For example, GitLab Shell is called from OpenSSH and having a version manager can prevent pushing and pulling over SSH. Version managers are not supported and we strongly advise everyone to follow the instructions below to use a system Ruby. Remove the old Ruby 1.8 if present @@ -128,11 +128,10 @@ Install the Bundler Gem: ## 3. Go -Since GitLab 8.0, Git HTTP requests are handled by gitlab-git-http-server. -This is a small daemon written in Go. -To install gitlab-git-http-server we need a Go compiler. -The instructions below assume you use 64-bit Linux. You can find -downloads for other platforms at the [Go download +Since GitLab 8.0, Git HTTP requests are handled by gitlab-workhorse (formerly +gitlab-git-http-server). This is a small daemon written in Go. To install +gitlab-workhorse we need a Go compiler. The instructions below assume you +use 64-bit Linux. You can find downloads for other platforms at the [Go download page](https://golang.org/dl). curl -O --progress https://storage.googleapis.com/golang/go1.5.1.linux-amd64.tar.gz @@ -211,9 +210,9 @@ We recommend using a PostgreSQL database. For MySQL check [MySQL setup guide](da ### Clone the Source # Clone GitLab repository - sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ce.git -b 8-1-stable-ee gitlab + sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ee.git -b 8-2-stable-ee gitlab -**Note:** You can change `8-1-stable-ee` to `master` if you want the *bleeding edge* version, but never install master on a production server! +**Note:** You can change `8-2-stable-ee` to `master` if you want the *bleeding edge* version, but never install master on a production server! ### Configure It @@ -298,7 +297,7 @@ We recommend using a PostgreSQL database. For MySQL check [MySQL setup guide](da ### Install Gems -**Note:** As of bundler 1.5.2, you can invoke `bundle install -jN` (where `N` the number of your processor cores) and enjoy the parallel gems installation with measurable difference in completion time (~60% faster). Check the number of your cores with `nproc`. For more information check this [post](http://robots.thoughtbot.com/parallel-gem-installing-using-bundler). First make sure you have bundler >= 1.5.2 (run `bundle -v`) as it addresses some [issues](https://devcenter.heroku.com/changelog-items/411) that were [fixed](https://github.com/bundler/bundler/pull/2817) in 1.5.2. +**Note:** As of bundler 1.5.2, you can invoke `bundle install -jN` (where `N` the number of your processor cores) and enjoy the parallel gems installation with measurable difference in completion time (~60% faster). Check the number of your cores with `nproc`. For more information check this [post](https://robots.thoughtbot.com/parallel-gem-installing-using-bundler). First make sure you have bundler >= 1.5.2 (run `bundle -v`) as it addresses some [issues](https://devcenter.heroku.com/changelog-items/411) that were [fixed](https://github.com/bundler/bundler/pull/2817) in 1.5.2. # For PostgreSQL (note, the option says "without ... mysql") sudo -u git -H bundle install --deployment --without development test mysql aws kerberos @@ -313,7 +312,7 @@ We recommend using a PostgreSQL database. For MySQL check [MySQL setup guide](da GitLab Shell is an SSH access and repository management software developed specially for GitLab. # Run the installation task for gitlab-shell (replace `REDIS_URL` if needed): - sudo -u git -H bundle exec rake gitlab:shell:install[v2.6.6] REDIS_URL=unix:/var/run/redis/redis.sock RAILS_ENV=production + sudo -u git -H bundle exec rake gitlab:shell:install[v2.6.7] REDIS_URL=unix:/var/run/redis/redis.sock RAILS_ENV=production # By default, the gitlab-shell config is generated from your main GitLab config. # You can review (and modify) the gitlab-shell config as follows: @@ -323,16 +322,16 @@ GitLab Shell is an SSH access and repository management software developed speci **Note:** Make sure your hostname can be resolved on the machine itself by either a proper DNS record or an additional line in /etc/hosts ("127.0.0.1 hostname"). This might be necessary for example if you set up gitlab behind a reverse proxy. If the hostname cannot be resolved, the final installation check will fail with "Check GitLab API access: FAILED. code: 401" and pushing commits will be rejected with "[remote rejected] master -> master (hook declined)". -### Install gitlab-git-http-server +### Install gitlab-workhorse cd /home/git - sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-git-http-server.git - cd gitlab-git-http-server - sudo -u git -H git checkout 0.3.0 + sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-workhorse.git + cd gitlab-workhorse + sudo -u git -H git checkout 0.4.1 sudo -u git -H make ### Initialize Database and Activate Advanced Features - + # Go to Gitlab installation folder cd /home/git/gitlab diff --git a/doc/integration/ldap.md b/doc/integration/ldap.md index adf692c8aa..f257c76a83 100644 --- a/doc/integration/ldap.md +++ b/doc/integration/ldap.md @@ -75,7 +75,7 @@ main: # 'main' is the GitLab 'provider ID' of this LDAP server # Filter LDAP users # - # Format: RFC 4515 http://tools.ietf.org/search/rfc4515 + # Format: RFC 4515 https://tools.ietf.org/search/rfc4515 # Ex. (employeeType=developer) # # Note: GitLab does not support omniauth-ldap's custom filter syntax. @@ -249,7 +249,7 @@ For installations from source, add the following setting in the 'ldap' section o ## Using an LDAP filter to limit access to your GitLab server If you want to limit all GitLab access to a subset of the LDAP users on your LDAP server you can set up an LDAP user filter. -The filter must comply with [RFC 4515](http://tools.ietf.org/search/rfc4515). +The filter must comply with [RFC 4515](https://tools.ietf.org/search/rfc4515). ```ruby # For omnibus packages; new LDAP server syntax diff --git a/doc/legal/corporate_contributor_license_agreement.md b/doc/legal/corporate_contributor_license_agreement.md index 13bf15fcf4..7b94506c29 100644 --- a/doc/legal/corporate_contributor_license_agreement.md +++ b/doc/legal/corporate_contributor_license_agreement.md @@ -22,4 +22,4 @@ You accept and agree to the following terms and conditions for Your present and 8. It is your responsibility to notify GitLab B.V. when any change is required to the list of designated employees authorized to submit Contributions on behalf of the Corporation, or to the Corporation's Point of Contact with GitLab B.V.. -This text is licensed under the [Creative Commons Attribution 3.0 License](http://creativecommons.org/licenses/by/3.0/) and the original source is the Google Open Source Programs Office. +This text is licensed under the [Creative Commons Attribution 3.0 License](https://creativecommons.org/licenses/by/3.0/) and the original source is the Google Open Source Programs Office. diff --git a/doc/legal/individual_contributor_license_agreement.md b/doc/legal/individual_contributor_license_agreement.md index 72b01433dd..f97c252fd7 100644 --- a/doc/legal/individual_contributor_license_agreement.md +++ b/doc/legal/individual_contributor_license_agreement.md @@ -22,4 +22,4 @@ You accept and agree to the following terms and conditions for Your present and 8. You agree to notify GitLab B.V. of any facts or circumstances of which you become aware that would make these representations inaccurate in any respect. -This text is licensed under the [Creative Commons Attribution 3.0 License](http://creativecommons.org/licenses/by/3.0/) and the original source is the Google Open Source Programs Office. +This text is licensed under the [Creative Commons Attribution 3.0 License](https://creativecommons.org/licenses/by/3.0/) and the original source is the Google Open Source Programs Office. diff --git a/doc/markdown/markdown.md b/doc/markdown/markdown.md index ac3851f8c9..bc8e7d155e 100644 --- a/doc/markdown/markdown.md +++ b/doc/markdown/markdown.md @@ -43,7 +43,7 @@ You can also use other rich text files in GitLab. You might have to install a de ## Newlines -GFM honors the markdown specification in how [paragraphs and line breaks are handled](http://daringfireball.net/projects/markdown/syntax#p). +GFM honors the markdown specification in how [paragraphs and line breaks are handled](https://daringfireball.net/projects/markdown/syntax#p). A paragraph is simply one or more consecutive lines of text, separated by one or more blank lines. Line-breaks, or softreturns, are rendered if you end a line with two or more spaces @@ -72,14 +72,14 @@ do_this_and_do_that_and_another_thing GFM will autolink almost any URL you copy and paste into your text. - * http://www.google.com + * https://www.google.com * https://google.com/ * ftp://ftp.us.debian.org/debian/ * smb://foo/bar/baz * irc://irc.freenode.net/gitlab * http://localhost:3000 -* http://www.google.com +* https://www.google.com * https://google.com/ * ftp://ftp.us.debian.org/debian/ * smb://foo/bar/baz @@ -390,7 +390,7 @@ There are two ways to create links, inline-style and reference-style. [arbitrary case-insensitive reference text]: https://www.mozilla.org [1]: http://slashdot.org - [link text itself]: http://www.reddit.com + [link text itself]: https://www.reddit.com [I'm an inline-style link](https://www.google.com) @@ -406,7 +406,7 @@ Some text to show that the reference links can follow later. [arbitrary case-insensitive reference text]: https://www.mozilla.org [1]: http://slashdot.org -[link text itself]: http://www.reddit.com +[link text itself]: https://www.reddit.com **Note** @@ -583,5 +583,5 @@ By including colons in the header row, you can align the text within that column ## References - This document leveraged heavily from the [Markdown-Cheatsheet](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet). -- The [Markdown Syntax Guide](http://daringfireball.net/projects/markdown/syntax) at Daring Fireball is an excellent resource for a detailed explanation of standard markdown. +- The [Markdown Syntax Guide](https://daringfireball.net/projects/markdown/syntax) at Daring Fireball is an excellent resource for a detailed explanation of standard markdown. - [Dillinger.io](http://dillinger.io) is a handy tool for testing standard markdown. diff --git a/doc/operations/unicorn.md b/doc/operations/unicorn.md index 3998da01f0..bad61151bd 100644 --- a/doc/operations/unicorn.md +++ b/doc/operations/unicorn.md @@ -52,7 +52,7 @@ leak memory, probably because it does not handle user requests.) To make these memory leaks manageable, GitLab comes with the [unicorn-worker-killer gem](https://github.com/kzk/unicorn-worker-killer). This -gem [monkey-patches](http://en.wikipedia.org/wiki/Monkey_patch) the Unicorn +gem [monkey-patches](https://en.wikipedia.org/wiki/Monkey_patch) the Unicorn workers to do a memory self-check after every 16 requests. If the memory of the Unicorn worker exceeds a pre-set limit then the worker process exits. The Unicorn master then automatically replaces the worker process. @@ -83,4 +83,4 @@ is a normal value for our current GitLab.com setup and traffic. The high frequency of Unicorn memory restarts on some GitLab sites can be a source of confusion for administrators. Usually they are a [red -herring](http://en.wikipedia.org/wiki/Red_herring). +herring](https://en.wikipedia.org/wiki/Red_herring). diff --git a/doc/release/monthly.md b/doc/release/monthly.md index 4925816daa..c9ab87671d 100644 --- a/doc/release/monthly.md +++ b/doc/release/monthly.md @@ -37,9 +37,9 @@ template are explained below: ### Xth: (6 working days before the 22nd) -- [ ] Merge CE `master` into EE `master` via merge request (#LINK) - [ ] Determine QA person and notify this person - [ ] Check the tasks in [how to rc1 guide](https://dev.gitlab.org/gitlab/gitlabhq/blob/master/doc/release/howto_rc1.md) and delegate tasks if necessary +- [ ] Merge CE `master` into EE `master` via merge request (#LINK) - [ ] Create CE and EE RC1 versions (#LINK) - [ ] Build RC1 packages @@ -54,21 +54,25 @@ template are explained below: - [ ] Update GitLab.com with RC1 - [ ] Create the regression issue in the CE issue tracker: - > This is a meta issue to index possible regressions in this monthly release - > and any patch versions. - > - > Please do not raise or discuss issues directly in this issue but link to - > issues that might warrant a patch release. If there is a Merge Request - > that fixes the issue, please link to that as well. - > - > Please only post one regression issue and/or merge request per comment. - > Comments will be updated by the release manager as they are addressed. + ``` + This is a meta issue to index possible regressions in this monthly release + and any patch versions. + + Please do not raise or discuss issues directly in this issue but link to + issues that might warrant a patch release. If there is a Merge Request + that fixes the issue, please link to that as well. + + Please only post one regression issue and/or merge request per comment. + Comments will be updated by the release manager as they are addressed. + ``` - [ ] Tweet about RC1 release: - > GitLab x.y.0.rc1 is available: https://packages.gitlab.com/gitlab/unstable - > Use at your own risk. Please link regressions issues from - > LINK_TO_REGRESSION_ISSUE + ``` + GitLab x.y.0.rc1 is available: https://packages.gitlab.com/gitlab/unstable + Use at your own risk. Please link regressions issues from + LINK_TO_REGRESSION_ISSUE + ``` ### Xth: (3 working days before the 22nd) diff --git a/doc/release/security.md b/doc/release/security.md index 60bcfbb6da..b1a62b333e 100644 --- a/doc/release/security.md +++ b/doc/release/security.md @@ -8,7 +8,7 @@ Do a security release when there is a critical issue that needs to be addresses ## Security vulnerability disclosure -Please report suspected security vulnerabilities in private to , also see the [disclosure section on the GitLab.com website](http://about.gitlab.com/disclosure/). Please do NOT create publicly viewable issues for suspected security vulnerabilities. +Please report suspected security vulnerabilities in private to , also see the [disclosure section on the GitLab.com website](https://about.gitlab.com/disclosure/). Please do NOT create publicly viewable issues for suspected security vulnerabilities. ## Release Procedure @@ -25,7 +25,7 @@ Please report suspected security vulnerabilities in private to + +## How it works + +Git LFS client talks with the GitLab server over HTTPS. It uses HTTP Basic Authentication to authorize client requests. +Once the request is authorized, Git LFS client receives instructions from where to fetch or where to push the large file. + +## Requirements + +* Git LFS is supported in GitLab starting with version 8.2 +* Git LFS [client](https://git-lfs.github.com) version 0.6.0 and up + +## GitLab and Git LFS + +### Configuration + +Git LFS objects can be large in size. By default, they are stored on the server GitLab is installed on. + +There are two configuration options to help GitLab server administrators: + +* Enabling/disabling Git LFS support +* Changing the location of LFS object storage + +#### Omnibus packages + +In `/etc/gitlab/gitlab.rb`: + +```ruby +gitlab_rails['lfs_enabled'] = false +gitlab_rails['lfs_storage_path'] = "/mnt/storage/lfs-objects" +``` + +#### Installations from source + +In `config/gitlab.yml`: + +```yaml + lfs: + enabled: false + storage_path: /mnt/storage/lfs-objects +``` + +## Known limitations + +* Git LFS v1 original API is not supported since it was deprecated early in LFS development, starting with Git LFS version 0.6.0 +* When SSH is set as a remote, Git LFS objects still go through HTTPS +* Any Git LFS request will ask for HTTPS credentials to be provided so good Git credentials store is recommended +* Currently, storing GitLab Git LFS objects on a non-local storage (like S3 buckets) is not supported +* Git LFS always assumes HTTPS so if you have GitLab server on HTTP you will have to add the url to Git config manually (see #troubleshooting-tips) + +## Using Git LFS + +Lets take a look at the workflow when you need to check large files into your Git repository with Git LFS: +For example, if you want to upload a very large file and check it into your Git repository: + +```bash +git clone git@gitlab.example.com:group/project.git +git lfs init # initialize the Git LFS project project +git lfs track "*.iso" # select the file extensions that you want to treat as large files +``` + +Once a certain file extension is marked for tracking as a LFS object you can use Git as usual without having to redo the command to track a file with the same extension: + +```bash +cp ~/tmp/debian.iso ./ # copy a large file into the current directory +git add . # add the large file to the project +git commit -am "Added Debian iso" # commit the file meta data +git push origin master # sync the git repo and large file to the GitLab server +``` + +Downloading a single large file is also very simple: + +```bash +git clone git@gitlab.example.com:group/project.git +git lfs fetch debian.iso # download the large file +``` + + +## Troubleshooting + +### error: Repository or object not found + +There are a couple of reasons why this error can occur: + +* Wrong version of LFS client used: + +Check the version of Git LFS on the client machine with `git lfs version`. Only version 0.6.0 and newer are supported. + +* Project is using deprecated LFS API + +Check the Git config of the project for traces of deprecated API with `git lfs -l`. If `batch = false` is set in the config, remove the line and try using Git LFS client newer than 0.6.0. + +### Invalid status for : 501 + +When attempting to push a LFS object to a GitLab server that doesn't have Git LFS support enabled, server will return status `error 501`. Check with your GitLab administrator why Git LFS is not enabled on the server. See [Configuration section](#configuration) for instructions on how to enable LFS support. + +### getsockopt: connection refused + +If you push a LFS object to a project and you receive an error similar to: `Post /info/lfs/objects/batch: dial tcp IP: getsockopt: connection refused`, +the LFS client is trying to reach GitLab through HTTPS. However, your GitLab instance is being served on HTTP. + +This behaviour is caused by Git LFS using HTTPS connections by default when a `lfsurl` is not set in the Git config. + +To prevent this from happening, set the lfs url in project Git config: + +```bash + +git config --add lfs.url "http://gitlab.example.com/group/project.git/info/lfs/objects/batch" +``` + +### Credentials are always required when pushing an object + +Given that Git LFS uses HTTP Basic Authentication to authenticate the user pushing the LFS object on every push for every object, user HTTPS credentials are required. + +By default, Git has support for remembering the credentials for each repository you use. This is described in [Git credentials man pages](https://git-scm.com/docs/gitcredentials). + +For example, you can tell Git to remember the password for a period of time in which you expect to push the objects: + +```bash +git config --global credential.helper 'cache --timeout=3600' +``` + +This will remember the credentials for an hour after which Git operations will require re-authentication. + +If you are using OS X you can use `osxkeychain` to store and encrypt your credentials. For Windows, `wincred` is available. + +More details about various methods of storing the user credentials can be found on [Git Credential Storage documentation](https://git-scm.com/book/en/v2/Git-Tools-Credential-Storage) \ No newline at end of file diff --git a/doc/workflow/gitlab_flow.md b/doc/workflow/gitlab_flow.md index 136b5ff3df..2682ee61f7 100644 --- a/doc/workflow/gitlab_flow.md +++ b/doc/workflow/gitlab_flow.md @@ -7,7 +7,7 @@ This allows a wide variety of branching strategies and workflows. Almost all of these are an improvement over the methods used before git. But many organizations end up with a workflow that is not clearly defined, overly complex or not integrated with issue tracking systems. Therefore we propose the GitLab flow as clearly defined set of best practices. -It combines [feature driven development](http://en.wikipedia.org/wiki/Feature-driven_development) and [feature branches](http://martinfowler.com/bliki/FeatureBranch.html) with issue tracking. +It combines [feature driven development](https://en.wikipedia.org/wiki/Feature-driven_development) and [feature branches](http://martinfowler.com/bliki/FeatureBranch.html) with issue tracking. Organizations coming to git from other version control systems frequently find it hard to develop an effective workflow. This article describes the GitLab flow that integrates the git workflow with an issue tracking system. @@ -91,7 +91,7 @@ This workflow where commits only flow downstream ensures that everything has bee If you need to cherry-pick a commit with a hotfix it is common to develop it on a feature branch and merge it into master with a merge request, do not delete the feature branch. If master is good to go (it should be if you a practicing [continuous delivery](http://martinfowler.com/bliki/ContinuousDelivery.html)) you then merge it to the other branches. If this is not possible because more manual testing is required you can send merge requests from the feature branch to the downstream branches. -An 'extreme' version of environment branches are setting up an environment for each feature branch as done by [Teatro](http://teatro.io/). +An 'extreme' version of environment branches are setting up an environment for each feature branch as done by [Teatro](https://teatro.io/). ## Release branches with GitLab flow @@ -104,7 +104,7 @@ By branching as late as possible you minimize the time you have to apply bug fix After a release branch is announced, only serious bug fixes are included in the release branch. If possible these bug fixes are first merged into master and then cherry-picked into the release branch. This way you can't forget to cherry-pick them into master and encounter the same bug on subsequent releases. -This is called an 'upstream first' policy that is also practiced by [Google](http://www.chromium.org/chromium-os/chromiumos-design-docs/upstream-first) and [Red Hat](http://www.redhat.com/about/news/archive/2013/5/a-community-for-using-openstack-with-red-hat-rdo). +This is called an 'upstream first' policy that is also practiced by [Google](https://www.chromium.org/chromium-os/chromiumos-design-docs/upstream-first) and [Red Hat](https://www.redhat.com/about/news/archive/2013/5/a-community-for-using-openstack-with-red-hat-rdo). Every time a bug-fix is included in a release branch the patch version is raised (to comply with [Semantic Versioning](http://semver.org/)) by setting a new tag. Some projects also have a stable branch that points to the same commit as the latest released branch. In this flow it is not common to have a production branch (or git flow master branch). @@ -200,7 +200,7 @@ And to understand a change in context one can always look at the merge commit th After you merge multiple commits from a feature branch into the master branch this is harder to undo. If you would have squashed all the commits into one you could have just reverted this commit but as we indicated you should not rebase commits after they are pushed. -Fortunately [reverting a merge made some time ago](http://git-scm.com/blog/2010/03/02/undoing-merges.html) can be done with git. +Fortunately [reverting a merge made some time ago](https://git-scm.com/blog/2010/03/02/undoing-merges.html) can be done with git. This however, requires having specific merge commits for the commits your want to revert. If you revert a merge and you change your mind, revert the revert instead of merging again since git will not allow you to merge the code again otherwise. @@ -215,7 +215,7 @@ With git you can also rebase your feature branch commits to order them after the This prevents creating a merge commit when merging master into your feature branch and creates a nice linear history. However, just like with squashing you should never rebase commits you have pushed to a remote server. This makes it impossible to rebase work in progress that you already shared with your team which is something we recommend. -When using rebase to keep your feature branch updated you [need to resolve similar conflicts again and again](http://blogs.atlassian.com/2013/10/git-team-workflows-merge-or-rebase/). +When using rebase to keep your feature branch updated you [need to resolve similar conflicts again and again](https://blogs.atlassian.com/2013/10/git-team-workflows-merge-or-rebase/). You can reuse recorded resolutions (rerere) sometimes, but without rebasing you only have to solve the conflicts one time and you’re set. There has to be a better way to avoid many merge commits. @@ -317,7 +317,7 @@ When initiating a feature branch, always start with an up to date master to bran If you know beforehand that your work absolutely depends on another branch you can also branch from there. If you need to merge in another branch after starting explain the reason in the merge commit. If you have not pushed your commits to a shared location yet you can also rebase on master or another feature branch. -Do not merge in upstream if your code will work and merge cleanly without doing so, Linus even says that [you should never merge in upstream at random points, only at major releases](http://lwn.net/Articles/328438/). +Do not merge in upstream if your code will work and merge cleanly without doing so, Linus even says that [you should never merge in upstream at random points, only at major releases](https://lwn.net/Articles/328438/). Merging only when needed prevents creating merge commits in your feature branch that later end up littering the master history. ## References diff --git a/doc/workflow/importing/migrating_from_svn.md b/doc/workflow/importing/migrating_from_svn.md index 485db4834e..1938ccd0c2 100644 --- a/doc/workflow/importing/migrating_from_svn.md +++ b/doc/workflow/importing/migrating_from_svn.md @@ -6,9 +6,9 @@ Git is a distributed version control system. There are some major differences between the two, for more information consult your favorite search engine. Git has tools for migrating SVN repositories to git, namely `git svn`. You can read more about this at -[git documentation pages](http://git-scm.com/book/en/Git-and-Other-Systems-Git-and-Subversion). +[git documentation pages](https://git-scm.com/book/en/Git-and-Other-Systems-Git-and-Subversion). -Apart from the [official git documentation](http://git-scm.com/book/en/Git-and-Other-Systems-Migrating-to-Git) there is also +Apart from the [official git documentation](https://git-scm.com/book/en/Git-and-Other-Systems-Migrating-to-Git) there is also user created step by step guide for migrating from SVN to GitLab. [Benjamin New](https://github.com/leftclickben) wrote [a guide that shows how to do a migration](https://gist.github.com/leftclickben/322b7a3042cbe97ed2af). Mirrors can be found [here](https://gitlab.com/snippets/2168) and [here](https://gist.github.com/maxlazio/f1b593b0d00aa966e9ca). diff --git a/doc/workflow/milestones.md b/doc/workflow/milestones.md new file mode 100644 index 0000000000..dff36899ae --- /dev/null +++ b/doc/workflow/milestones.md @@ -0,0 +1,13 @@ +# Milestones + +Milestones allow you to organize issues and merge requests into a cohesive group, optionally setting a due date. +A common use is keeping track of an upcoming software version. Milestones are created per-project. + +![milestone form](milestones/form.png) + +## Groups and milestones + +You can create a milestone for several projects in the same group simultaneously. +On the group's milestones page, you will be able to see the status of that milestone across all of the selected projects. + +![group milestone form](milestones/group_form.png) diff --git a/doc/workflow/milestones/form.png b/doc/workflow/milestones/form.png new file mode 100644 index 0000000000000000000000000000000000000000..de44c1ffc1a44c21e7d6eff77ff8752d84b6ea8f GIT binary patch literal 88591 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

7chsg28F&v6Qs`*;tr3Ve?{d?nB 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 literal 0 HcmV?d00001 diff --git a/doc/workflow/milestones/group_form.png b/doc/workflow/milestones/group_form.png new file mode 100644 index 0000000000000000000000000000000000000000..38862dcca6895c28a09c6173fc8a2d7b1552b528 GIT binary patch literal 77087 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

hub?d7kLqUFo_P#LClu2 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

AZ-_IvsYe~ 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 IAzhvEA5O_fNB{r; literal 0 HcmV?d00001 diff --git a/features/groups.feature b/features/groups.feature index de2e1c4968..69f48906fa 100644 --- a/features/groups.feature +++ b/features/groups.feature @@ -66,6 +66,14 @@ Feature: Groups When I select "Mike" as "Reporter" Then I should see "Mike" in team list as "Reporter" + @javascript + Scenario: Ignore add user to group when is already Owner + Given gitlab user "Mike" + When I visit group "Owned" members page + And I click link "Add members" + When I select "Mike" as "Reporter" + Then I should see "Mike" in team list as "Owner" + @javascript Scenario: Invite user to group When I visit group "Owned" members page @@ -171,7 +179,14 @@ Feature: Groups And I go to "Audit Events" Then I should see the audit event listed - # Group projects in settings + Scenario: Create multiple milestones with one form + Given I visit group "Owned" milestones page + And I click new milestone button + And I fill milestone name + When I press create mileston button + Then milestone in each project should be created + + # Group projects in settings Scenario: I should see all projects in the project list in settings Given Group "Owned" has archived project When I visit group "Owned" projects page @@ -187,4 +202,4 @@ Feature: Groups When I visit group "Owned" page Then I should see group "Owned" Then I should see project "Public-project" - + diff --git a/features/steps/groups.rb b/features/steps/groups.rb index 42372f4e32..e3b2805425 100644 --- a/features/steps/groups.rb +++ b/features/steps/groups.rb @@ -48,6 +48,17 @@ class Spinach::Features::Groups < Spinach::FeatureSteps click_button "Add users to group" end + step 'I select "Mike" as "Master"' do + user = User.find_by(name: "Mike") + + page.within ".users-group-form" do + select2(user.id, from: "#user_ids", multiple: true) + select "Master", from: "access_level" + end + + click_button "Add users to group" + end + step 'I should see "Mike" in team list as "Reporter"' do page.within '.well-list' do expect(page).to have_content('Mike') @@ -55,6 +66,13 @@ class Spinach::Features::Groups < Spinach::FeatureSteps end end + step 'I should see "Mike" in team list as "Owner"' do + page.within '.well-list' do + expect(page).to have_content('Mike') + expect(page).to have_content('Owner') + end + end + step 'I select "sjobs@apple.com" as "Reporter"' do page.within ".users-group-form" do select2("sjobs@apple.com", from: "#user_ids", multiple: true) @@ -293,6 +311,28 @@ class Spinach::Features::Groups < Spinach::FeatureSteps expect(page).to have_xpath("//span[@class='label label-warning']", text: 'archived') end + step 'I fill milestone name' do + fill_in 'milestone_title', with: 'v2.9.0' + end + + step 'I click new milestone button' do + click_link "New Milestone" + end + + step 'I press create mileston button' do + click_button "Create Milestone" + end + + step 'milestone in each project should be created' do + group = Group.find_by(name: 'Owned') + expect(page).to have_content "Milestone v2.9.0" + expect(group.projects).to be_present + + group.projects.each do |project| + expect(page).to have_content project.name + end + end + protected def assigned_to_me(key) diff --git a/features/steps/project/issues/issues.rb b/features/steps/project/issues/issues.rb index be134b9c2b..af2da41bad 100644 --- a/features/steps/project/issues/issues.rb +++ b/features/steps/project/issues/issues.rb @@ -219,7 +219,7 @@ class Spinach::Features::ProjectIssues < Spinach::FeatureSteps end step 'The code block should be unchanged' do - expect(page).to have_content("Command [1]: /usr/local/bin/git , see [text](doc/text)") + expect(page).to have_content("```\nCommand [1]: /usr/local/bin/git , see [text](doc/text)\n```") end step 'project \'Shop\' has issue \'Bugfix1\' with description: \'Description for issue1\'' do diff --git a/features/steps/shared/paths.rb b/features/steps/shared/paths.rb index 7cde1bef45..6275f566fa 100644 --- a/features/steps/shared/paths.rb +++ b/features/steps/shared/paths.rb @@ -35,6 +35,10 @@ module SharedPaths visit merge_requests_group_path(Group.find_by(name: "Owned")) end + step 'I visit group "Owned" milestones page' do + visit group_milestones_path(Group.find_by(name: "Owned")) + end + step 'I visit group "Owned" members page' do visit group_group_members_path(Group.find_by(name: "Owned")) end diff --git a/lib/backup/manager.rb b/lib/backup/manager.rb index 9e15d5411a..e7eda7c6f4 100644 --- a/lib/backup/manager.rb +++ b/lib/backup/manager.rb @@ -150,17 +150,15 @@ module Backup private def backup_contents - folders_to_backup + ["uploads.tar.gz", "builds.tar.gz", "artifacts.tar.gz", "backup_information.yml"] + folders_to_backup + archives_to_backup + ["backup_information.yml"] + end + + def archives_to_backup + %w{uploads builds artifacts}.map{ |name| (name + ".tar.gz") unless skipped?(name) }.compact end def folders_to_backup - folders = %w{repositories db} - - if ENV["SKIP"] - return folders.reject{ |folder| ENV["SKIP"].include?(folder) } - end - - folders + %w{repositories db}.reject{ |name| skipped?(name) } end def settings diff --git a/lib/support/nginx/gitlab b/lib/support/nginx/gitlab index 93f2ad07ae..0cf5292b29 100644 --- a/lib/support/nginx/gitlab +++ b/lib/support/nginx/gitlab @@ -67,7 +67,7 @@ server { location / { ## Serve static files from defined root folder. ## @gitlab is a named location for the upstream fallback, see below. - try_files $uri $uri/index.html $uri.html @gitlab; + try_files $uri /index.html $uri.html @gitlab; } ## We route uploads through GitLab to prevent XSS and enforce access control. @@ -114,7 +114,6 @@ server { } location ~ ^/[\w\.-]+/[\w\.-]+/gitlab-lfs/objects { - client_max_body_size 0; # 'Error' 418 is a hack to re-use the @gitlab-workhorse block error_page 418 = @gitlab-workhorse; return 418; @@ -140,7 +139,6 @@ server { # Build artifacts should be submitted to this location location ~ ^/[\w\.-]+/[\w\.-]+/builds/download { - client_max_body_size 0; # 'Error' 418 is a hack to re-use the @gitlab-workhorse block error_page 418 = @gitlab-workhorse; return 418; @@ -148,13 +146,13 @@ server { # Build artifacts should be submitted to this location location ~ /ci/api/v1/builds/[0-9]+/artifacts { - client_max_body_size 0; # 'Error' 418 is a hack to re-use the @gitlab-workhorse block error_page 418 = @gitlab-workhorse; return 418; } location @gitlab-workhorse { + client_max_body_size 0; ## If you use HTTPS make sure you disable gzip compression ## to be safe against BREACH attack. # gzip off; diff --git a/lib/support/nginx/gitlab-ssl b/lib/support/nginx/gitlab-ssl index 90749947fa..31a651c87f 100644 --- a/lib/support/nginx/gitlab-ssl +++ b/lib/support/nginx/gitlab-ssl @@ -112,7 +112,7 @@ server { location / { ## Serve static files from defined root folder. ## @gitlab is a named location for the upstream fallback, see below. - try_files $uri $uri/index.html $uri.html @gitlab; + try_files $uri /index.html $uri.html @gitlab; } ## We route uploads through GitLab to prevent XSS and enforce access control. @@ -161,7 +161,6 @@ server { } location ~ ^/[\w\.-]+/[\w\.-]+/gitlab-lfs/objects { - client_max_body_size 0; # 'Error' 418 is a hack to re-use the @gitlab-workhorse block error_page 418 = @gitlab-workhorse; return 418; @@ -187,7 +186,6 @@ server { # Build artifacts should be submitted to this location location ~ ^/[\w\.-]+/[\w\.-]+/builds/download { - client_max_body_size 0; # 'Error' 418 is a hack to re-use the @gitlab-workhorse block error_page 418 = @gitlab-workhorse; return 418; @@ -195,13 +193,13 @@ server { # Build artifacts should be submitted to this location location ~ /ci/api/v1/builds/[0-9]+/artifacts { - client_max_body_size 0; # 'Error' 418 is a hack to re-use the @gitlab-workhorse block error_page 418 = @gitlab-workhorse; return 418; } location @gitlab-workhorse { + client_max_body_size 0; ## If you use HTTPS make sure you disable gzip compression ## to be safe against BREACH attack. gzip off; diff --git a/spec/features/notes_on_merge_requests_spec.rb b/spec/features/notes_on_merge_requests_spec.rb index 16d5a03e88..d7cb3b2e86 100644 --- a/spec/features/notes_on_merge_requests_spec.rb +++ b/spec/features/notes_on_merge_requests_spec.rb @@ -65,6 +65,12 @@ describe 'Comments', feature: true do end describe 'when editing a note', js: true do + it 'should contain the hidden edit form' do + page.within("#note_#{note.id}") do + is_expected.to have_css('.note-edit-form', visible: false) + end + end + describe 'editing the note' do before do find('.note').hover diff --git a/spec/features/task_lists_spec.rb b/spec/features/task_lists_spec.rb index 6cbe685a93..fca3c77fc6 100644 --- a/spec/features/task_lists_spec.rb +++ b/spec/features/task_lists_spec.rb @@ -51,6 +51,7 @@ feature 'Task Lists', feature: true do expect(page).to have_selector(container) expect(page).to have_selector("#{container} .wiki .task-list .task-list-item .task-list-item-checkbox") + expect(page).to have_selector("#{container} .js-task-list-field") expect(page).to have_selector('form.js-issuable-update') expect(page).to have_selector('a.btn-close') end @@ -89,6 +90,7 @@ feature 'Task Lists', feature: true do expect(page).to have_selector('.note .js-task-list-container') expect(page).to have_selector('.note .js-task-list-container .task-list .task-list-item .task-list-item-checkbox') + expect(page).to have_selector('.note .js-task-list-container .js-task-list-field') end it 'is only editable by author' do @@ -125,6 +127,7 @@ feature 'Task Lists', feature: true do expect(page).to have_selector(container) expect(page).to have_selector("#{container} .wiki .task-list .task-list-item .task-list-item-checkbox") + expect(page).to have_selector("#{container} .js-task-list-field") expect(page).to have_selector('form.js-issuable-update') expect(page).to have_selector('a.btn-close') end diff --git a/spec/models/global_milestone_spec.rb b/spec/models/global_milestone_spec.rb new file mode 100644 index 0000000000..6eeff30b20 --- /dev/null +++ b/spec/models/global_milestone_spec.rb @@ -0,0 +1,65 @@ +require 'spec_helper' + +describe GlobalMilestone do + let(:user) { create(:user) } + let(:user2) { create(:user) } + let(:group) { create(:group) } + let(:project1) { create(:project, group: group) } + let(:project2) { create(:project, path: 'gitlab-ci', group: group) } + let(:project3) { create(:project, path: 'cookbook-gitlab', group: group) } + let(:milestone1_project1) { create(:milestone, title: "Milestone v1.2", project: project1) } + let(:milestone1_project2) { create(:milestone, title: "Milestone v1.2", project: project2) } + let(:milestone1_project3) { create(:milestone, title: "Milestone v1.2", project: project3) } + let(:milestone2_project1) { create(:milestone, title: "VD-123", project: project1) } + let(:milestone2_project2) { create(:milestone, title: "VD-123", project: project2) } + let(:milestone2_project3) { create(:milestone, title: "VD-123", project: project3) } + + describe :build_collection do + before do + milestones = + [ + milestone1_project1, + milestone1_project2, + milestone1_project3, + milestone2_project1, + milestone2_project2, + milestone2_project3 + ] + + @global_milestones = GlobalMilestone.build_collection(milestones) + end + + it 'should have all project milestones' do + expect(@global_milestones.count).to eq(2) + end + + it 'should have all project milestones titles' do + expect(@global_milestones.map(&:title)).to match_array(['Milestone v1.2', 'VD-123']) + end + + it 'should have all project milestones' do + expect(@global_milestones.map { |group_milestone| group_milestone.milestones.count }.sum).to eq(6) + end + end + + describe :initialize do + before do + milestones = + [ + milestone1_project1, + milestone1_project2, + milestone1_project3, + ] + + @global_milestone = GlobalMilestone.new(milestone1_project1.title, milestones) + end + + it 'should have exactly one group milestone' do + expect(@global_milestone.title).to eq('Milestone v1.2') + end + + it 'should have all project milestones with the same title' do + expect(@global_milestone.milestones.count).to eq(3) + end + end +end diff --git a/spec/models/project_wiki_spec.rb b/spec/models/project_wiki_spec.rb index 9f6cdeeaa9..3b88914444 100644 --- a/spec/models/project_wiki_spec.rb +++ b/spec/models/project_wiki_spec.rb @@ -184,6 +184,12 @@ describe ProjectWiki do subject.create_page("test page", "some content", :markdown, "commit message") expect(subject.pages.first.page.version.message).to eq("commit message") end + + it 'updates project activity' do + expect(subject).to receive(:update_project_activity) + + subject.create_page('Test Page', 'This is content') + end end describe "#update_page" do @@ -205,6 +211,12 @@ describe ProjectWiki do it "sets the correct commit message" do expect(@page.version.message).to eq("updated page") end + + it 'updates project activity' do + expect(subject).to receive(:update_project_activity) + + subject.update_page(@gollum_page, 'Yet more content', :markdown, 'Updated page again') + end end describe "#delete_page" do @@ -217,6 +229,12 @@ describe ProjectWiki do subject.delete_page(@page) expect(subject.pages.count).to eq(0) end + + it 'updates project activity' do + expect(subject).to receive(:update_project_activity) + + subject.delete_page(@page) + end end private diff --git a/spec/services/issues/update_service_spec.rb b/spec/services/issues/update_service_spec.rb index a91be3b447..f55527ee9a 100644 --- a/spec/services/issues/update_service_spec.rb +++ b/spec/services/issues/update_service_spec.rb @@ -3,13 +3,15 @@ require 'spec_helper' describe Issues::UpdateService do let(:user) { create(:user) } let(:user2) { create(:user) } - let(:issue) { create(:issue, title: 'Old title') } + let(:user3) { create(:user) } + let(:issue) { create(:issue, title: 'Old title', assignee_id: user3.id) } let(:label) { create(:label) } let(:project) { issue.project } before do project.team << [user, :master] project.team << [user2, :developer] + project.team << [user3, :developer] end describe 'execute' do @@ -34,9 +36,11 @@ describe Issues::UpdateService do it { expect(@issue.labels.count).to eq(1) } it { expect(@issue.labels.first.title).to eq('Bug') } - it 'should send email to user2 about assign of new issue' do - email = ActionMailer::Base.deliveries.last - expect(email.to.first).to eq(user2.email) + it 'should send email to user2 about assign of new issue and email to user3 about issue unassignment' do + deliveries = ActionMailer::Base.deliveries + email = deliveries.last + recipients = deliveries.last(2).map(&:to).flatten + expect(recipients).to include(user2.email, user3.email) expect(email.subject).to include(issue.title) end diff --git a/spec/services/merge_requests/update_service_spec.rb b/spec/services/merge_requests/update_service_spec.rb index c75173c145..2ed51d223b 100644 --- a/spec/services/merge_requests/update_service_spec.rb +++ b/spec/services/merge_requests/update_service_spec.rb @@ -3,7 +3,8 @@ require 'spec_helper' describe MergeRequests::UpdateService do let(:user) { create(:user) } let(:user2) { create(:user) } - let(:merge_request) { create(:merge_request, :simple, title: 'Old title') } + let(:user3) { create(:user) } + let(:merge_request) { create(:merge_request, :simple, title: 'Old title', assignee_id: user3.id) } let(:project) { merge_request.project } let(:label) { create(:label) } @@ -47,9 +48,11 @@ describe MergeRequests::UpdateService do with(@merge_request, 'update') end - it 'should send email to user2 about assign of new merge_request' do - email = ActionMailer::Base.deliveries.last - expect(email.to.first).to eq(user2.email) + it 'should send email to user2 about assign of new merge request and email to user3 about merge request unassignment' do + deliveries = ActionMailer::Base.deliveries + email = deliveries.last + recipients = deliveries.last(2).map(&:to).flatten + expect(recipients).to include(user2.email, user3.email) expect(email.subject).to include(merge_request.title) end diff --git a/spec/services/milestones/close_service_spec.rb b/spec/services/milestones/close_service_spec.rb new file mode 100644 index 0000000000..034c0f22e1 --- /dev/null +++ b/spec/services/milestones/close_service_spec.rb @@ -0,0 +1,28 @@ +require 'spec_helper' + +describe Milestones::CloseService do + let(:user) { create(:user) } + let(:project) { create(:project) } + let(:milestone) { create(:milestone, title: "Milestone v1.2", project: project) } + + before do + project.team << [user, :master] + end + + describe :execute do + before do + Milestones::CloseService.new(project, user, {}).execute(milestone) + end + + it { expect(milestone).to be_valid } + it { expect(milestone).to be_closed } + + describe :event do + let(:event) { Event.first } + + it { expect(event.milestone).to be_truthy } + it { expect(event.target).to eq(milestone) } + it { expect(event.action_name).to eq('closed') } + end + end +end diff --git a/spec/services/milestones/create_service_spec.rb b/spec/services/milestones/create_service_spec.rb new file mode 100644 index 0000000000..757c9a226d --- /dev/null +++ b/spec/services/milestones/create_service_spec.rb @@ -0,0 +1,24 @@ +require 'spec_helper' + +describe Milestones::CreateService do + let(:project) { create(:empty_project) } + let(:user) { create(:user) } + + describe :execute do + context "valid params" do + before do + project.team << [user, :master] + + opts = { + title: 'v2.1.9', + description: 'Patch release to fix security issue' + } + + @milestone = Milestones::CreateService.new(project, user, opts).execute + end + + it { expect(@milestone).to be_valid } + it { expect(@milestone.title).to eq('v2.1.9') } + end + end +end diff --git a/spec/services/milestones/group_service_spec.rb b/spec/services/milestones/group_service_spec.rb deleted file mode 100644 index 74eb0f99e0..0000000000 --- a/spec/services/milestones/group_service_spec.rb +++ /dev/null @@ -1,70 +0,0 @@ -require 'spec_helper' - -describe Milestones::GroupService do - let(:user) { create(:user) } - let(:user2) { create(:user) } - let(:group) { create(:group) } - let(:project1) { create(:project, group: group) } - let(:project2) { create(:project, path: 'gitlab-ci', group: group) } - let(:project3) { create(:project, path: 'cookbook-gitlab', group: group) } - let(:milestone1_project1) { create(:milestone, title: "Milestone v1.2", project: project1) } - let(:milestone1_project2) { create(:milestone, title: "Milestone v1.2", project: project2) } - let(:milestone1_project3) { create(:milestone, title: "Milestone v1.2", project: project3) } - let(:milestone2_project1) { create(:milestone, title: "VD-123", project: project1) } - let(:milestone2_project2) { create(:milestone, title: "VD-123", project: project2) } - let(:milestone2_project3) { create(:milestone, title: "VD-123", project: project3) } - - describe 'execute' do - context 'with valid projects' do - before do - milestones = - [ - milestone1_project1, - milestone1_project2, - milestone1_project3, - milestone2_project1, - milestone2_project2, - milestone2_project3 - ] - @group_milestones = Milestones::GroupService.new(milestones).execute - end - - it 'should have all project milestones' do - expect(@group_milestones.count).to eq(2) - end - - it 'should have all project milestones titles' do - expect(@group_milestones.map { |group_milestone| group_milestone.title }).to match_array(['Milestone v1.2', 'VD-123']) - end - - it 'should have all project milestones' do - expect(@group_milestones.map { |group_milestone| group_milestone.milestones.count }.sum).to eq(6) - end - end - end - - describe 'milestone' do - context 'with valid title' do - before do - milestones = - [ - milestone1_project1, - milestone1_project2, - milestone1_project3, - milestone2_project1, - milestone2_project2, - milestone2_project3 - ] - @group_milestones = Milestones::GroupService.new(milestones).milestone('Milestone v1.2') - end - - it 'should have exactly one group milestone' do - expect(@group_milestones.title).to eq('Milestone v1.2') - end - - it 'should have all project milestones with the same title' do - expect(@group_milestones.milestones.count).to eq(3) - end - end - end -end diff --git a/spec/tasks/gitlab/backup_rake_spec.rb b/spec/tasks/gitlab/backup_rake_spec.rb index 06559c3925..fb5e74af64 100644 --- a/spec/tasks/gitlab/backup_rake_spec.rb +++ b/spec/tasks/gitlab/backup_rake_spec.rb @@ -149,7 +149,7 @@ describe 'gitlab:app namespace rake task' do # Redirect STDOUT and run the rake task orig_stdout = $stdout $stdout = StringIO.new - ENV["SKIP"] = "repositories" + ENV["SKIP"] = "repositories,uploads" run_rake_task('gitlab:backup:create') $stdout = orig_stdout @@ -180,6 +180,7 @@ describe 'gitlab:app namespace rake task' do expect(Rake::Task["gitlab:backup:db:restore"]).to receive :invoke expect(Rake::Task["gitlab:backup:repo:restore"]).not_to receive :invoke + expect(Rake::Task["gitlab:backup:uploads:restore"]).not_to receive :invoke expect(Rake::Task["gitlab:backup:builds:restore"]).to receive :invoke expect(Rake::Task["gitlab:backup:artifacts:restore"]).to receive :invoke expect(Rake::Task["gitlab:shell:setup"]).to receive :invoke From 5bf300f2b9787254de76c819c202ed361a09db1d Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Thu, 19 Nov 2015 15:40:03 +0000 Subject: [PATCH 43/80] Merge branch 'new-tag-textarea' into 'master' Fix 'Attach a file' link in new tag form Also removed a little bit of code repetition :) See merge request !1834 --- app/views/projects/_zen.html.haml | 9 ++++++--- app/views/projects/releases/edit.html.haml | 3 +-- app/views/projects/tags/new.html.haml | 13 ++----------- 3 files changed, 9 insertions(+), 16 deletions(-) diff --git a/app/views/projects/_zen.html.haml b/app/views/projects/_zen.html.haml index 63ebfc9381..7e6301abde 100644 --- a/app/views/projects/_zen.html.haml +++ b/app/views/projects/_zen.html.haml @@ -2,9 +2,12 @@ %input#zen-toggle-comment.zen-toggle-comment(tabindex="-1" type="checkbox") .zen-backdrop - classes << ' js-gfm-input markdown-area' - = f.text_area attr, class: classes, placeholder: '' + - if defined?(f) && f + = f.text_area attr, class: classes, placeholder: '' + - else + = text_area_tag attr, nil, class: classes, placeholder: '' %a.zen-enter-link(tabindex="-1" href="#") - %i.fa.fa-expand + = icon('expand') Edit in fullscreen %a.zen-leave-link(href="#") - %i.fa.fa-compress + = icon('compress') diff --git a/app/views/projects/releases/edit.html.haml b/app/views/projects/releases/edit.html.haml index e7db09cdaa..f516b65ecd 100644 --- a/app/views/projects/releases/edit.html.haml +++ b/app/views/projects/releases/edit.html.haml @@ -11,10 +11,9 @@ .prepend-top-default = form_for(@release, method: :put, url: namespace_project_tag_release_path(@project.namespace, @project, @tag.name), html: { class: 'form-horizontal gfm-form release-form' }) do |f| = render layout: 'projects/md_preview', locals: { preview_class: "md-preview", referenced_users: true } do - = render 'projects/zen', f: f, attr: :description, classes: 'description js-quick-submit' + = render 'projects/zen', f: f, attr: :description, classes: 'description js-quick-submit form-control' = render 'projects/notes/hints' .error-alert .prepend-top-default = f.submit 'Save changes', class: 'btn btn-save' = link_to "Cancel", namespace_project_tag_path(@project.namespace, @project, @tag.name), class: "btn btn-default btn-cancel" - diff --git a/app/views/projects/tags/new.html.haml b/app/views/projects/tags/new.html.haml index e106be794f..86aa15dc5b 100644 --- a/app/views/projects/tags/new.html.haml +++ b/app/views/projects/tags/new.html.haml @@ -10,7 +10,7 @@ New git tag %hr -= form_tag namespace_project_tags_path, method: :post, id: "new-tag-form", class: "form-horizontal tag-form" do += form_tag namespace_project_tags_path, method: :post, id: "new-tag-form", class: "form-horizontal gfm-form tag-form" do .form-group = label_tag :tag_name, 'Name for new tag', class: 'control-label' .col-sm-10 @@ -30,16 +30,7 @@ = label_tag :release_description, 'Release notes', class: 'control-label' .col-sm-10 = render layout: 'projects/md_preview', locals: { preview_class: "md-preview", referenced_users: true } do - .zennable - %input#zen-toggle-comment.zen-toggle-comment(tabindex="-1" type="checkbox") - .zen-backdrop - = text_area_tag :release_description, nil, class: 'js-gfm-input markdown-area description js-quick-submit form-control', placeholder: '' - %a.zen-enter-link(tabindex="-1" href="#") - = icon('expand') - Edit in fullscreen - %a.zen-leave-link(href="#") - = icon('compress') - + = render 'projects/zen', attr: :release_description, classes: 'description js-quick-submit form-control' = render 'projects/notes/hints' .help-block (Optional) You can add release notes to your tag. It will be stored in the GitLab database and shown on the tags page .form-actions From 37fc82ace9b8ddf2aab52165d1344f6d6ecbc752 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Thu, 19 Nov 2015 16:47:34 +0100 Subject: [PATCH 44/80] Resolve conflicts --- .../groups/group_members_controller.rb | 29 +++-------- .../projects/project_members_controller.rb | 19 +++---- app/models/ability.rb | 49 ++++++------------- app/models/member.rb | 8 +-- app/models/project.rb | 8 +-- 5 files changed, 30 insertions(+), 83 deletions(-) diff --git a/app/controllers/groups/group_members_controller.rb b/app/controllers/groups/group_members_controller.rb index 5cadfaaded..7ce9b9a97c 100644 --- a/app/controllers/groups/group_members_controller.rb +++ b/app/controllers/groups/group_members_controller.rb @@ -39,40 +39,25 @@ class Groups::GroupMembersController < Groups::ApplicationController return render_403 unless can?(current_user, :update_group_member, @group_member) -<<<<<<< HEAD - old_access_level = @member.human_access + old_access_level = @group_member.human_access - if @member.update_attributes(member_params) - log_audit_event(@member, action: :update, old_access_level: old_access_level) + if @group_member.update_attributes(member_params) + log_audit_event(@group_member, action: :update, old_access_level: old_access_level) end -======= - @group_member.update_attributes(member_params) ->>>>>>> ce/8-2-stable end def destroy @group_member = @group.group_members.find(params[:id]) -<<<<<<< HEAD - if can?(current_user, :destroy_group_member, @group_member) # May fail if last owner. - @group_member.destroy - log_audit_event(@group_member, action: :destroy) - - respond_to do |format| - format.html { redirect_to group_group_members_path(@group), notice: 'User was successfully removed from group.' } - format.js { render nothing: true } - end - else - return render_403 -======= return render_403 unless can?(current_user, :destroy_group_member, @group_member) @group_member.destroy + log_audit_event(@group_member, action: :destroy) + respond_to do |format| format.html { redirect_to group_group_members_path(@group), notice: 'User was successfully removed from group.' } format.js { render nothing: true } ->>>>>>> ce/8-2-stable end end @@ -95,10 +80,8 @@ class Groups::GroupMembersController < Groups::ApplicationController if can?(current_user, :destroy_group_member, @group_member) @group_member.destroy -<<<<<<< HEAD + log_audit_event(@group_member, action: :destroy) -======= ->>>>>>> ce/8-2-stable redirect_to(dashboard_groups_path, notice: "You left #{group.name} group.") else diff --git a/app/controllers/projects/project_members_controller.rb b/app/controllers/projects/project_members_controller.rb index 54165f867a..9373e3efc5 100644 --- a/app/controllers/projects/project_members_controller.rb +++ b/app/controllers/projects/project_members_controller.rb @@ -43,18 +43,14 @@ class Projects::ProjectMembersController < Projects::ApplicationController def update @project_member = @project.project_members.find(params[:id]) -<<<<<<< HEAD + + return render_403 unless can?(current_user, :update_project_member, @project_member) + old_access_level = @project_member.human_access if @project_member.update_attributes(member_params) log_audit_event(@project_member, action: :update, old_access_level: old_access_level) end -======= - - return render_403 unless can?(current_user, :update_project_member, @project_member) - - @project_member.update_attributes(member_params) ->>>>>>> ce/8-2-stable end def destroy @@ -63,6 +59,7 @@ class Projects::ProjectMembersController < Projects::ApplicationController return render_403 unless can?(current_user, :destroy_project_member, @project_member) @project_member.destroy + log_audit_event(@project_member, action: :destroy) respond_to do |format| @@ -90,14 +87,10 @@ class Projects::ProjectMembersController < Projects::ApplicationController def leave @project_member = @project.project_members.find_by(user_id: current_user) -<<<<<<< HEAD - @project_member = @project.project_members.find_by(user_id: current_user) - @project_member.destroy - log_audit_event(@project_member, action: :destroy) -======= if can?(current_user, :destroy_project_member, @project_member) @project_member.destroy ->>>>>>> ce/8-2-stable + + log_audit_event(@project_member, action: :destroy) respond_to do |format| format.html { redirect_to dashboard_projects_path, notice: "You left the project." } diff --git a/app/models/ability.rb b/app/models/ability.rb index df894be575..cbeb33aa73 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -5,18 +5,18 @@ class Ability return [] unless user.kind_of?(User) return [] if user.blocked? -<<<<<<< HEAD - abilities = + abilities = case subject.class.name - when "Project" then project_abilities(user, subject) - when "Issue" then issue_abilities(user, subject) - when "Note" then note_abilities(user, subject) - when "ProjectSnippet" then project_snippet_abilities(user, subject) - when "PersonalSnippet" then personal_snippet_abilities(user, subject) - when "MergeRequest" then merge_request_abilities(user, subject) - when "Group" then group_abilities(user, subject) - when "Namespace" then namespace_abilities(user, subject) - when "GroupMember" then group_member_abilities(user, subject) + when "Project" then project_abilities(user, subject) + when "Issue" then issue_abilities(user, subject) + when "Note" then note_abilities(user, subject) + when "ProjectSnippet" then project_snippet_abilities(user, subject) + when "PersonalSnippet" then personal_snippet_abilities(user, subject) + when "MergeRequest" then merge_request_abilities(user, subject) + when "Group" then group_abilities(user, subject) + when "Namespace" then namespace_abilities(user, subject) + when "GroupMember" then group_member_abilities(user, subject) + when "ProjectMember" then project_member_abilities(user, subject) else [] end @@ -34,21 +34,6 @@ class Ability :push_code, :push_code_to_protected_branches ] -======= - case subject.class.name - when "Project" then project_abilities(user, subject) - when "Issue" then issue_abilities(user, subject) - when "Note" then note_abilities(user, subject) - when "ProjectSnippet" then project_snippet_abilities(user, subject) - when "PersonalSnippet" then personal_snippet_abilities(user, subject) - when "MergeRequest" then merge_request_abilities(user, subject) - when "Group" then group_abilities(user, subject) - when "Namespace" then namespace_abilities(user, subject) - when "GroupMember" then group_member_abilities(user, subject) - when "ProjectMember" then project_member_abilities(user, subject) - else [] - end.concat(global_abilities(user)) ->>>>>>> ce/8-2-stable end # List of possible abilities @@ -275,15 +260,11 @@ class Ability :admin_group, :admin_namespace, :admin_group_member -<<<<<<< HEAD - ]) - - unless group.ldap_synced? - rules << :admin_group_member - end -======= ] ->>>>>>> ce/8-2-stable + + if group.ldap_synced? + rules.delete(:admin_group_member) + end end rules.flatten diff --git a/app/models/member.rb b/app/models/member.rb index 54c4863a88..c616796b35 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -96,23 +96,19 @@ class Member < ActiveRecord::Base member.created_by ||= current_user member.access_level = access_level + member.skip_notification = skip_notification + member.save end end private -<<<<<<< HEAD - member.skip_notification = skip_notification - - member.save -======= def can_update_member?(current_user, member) # There is no current user for bulk actions, in which case anything is allowed !current_user || current_user.can?(:update_group_member, member) || current_user.can?(:update_project_member, member) ->>>>>>> ce/8-2-stable end end diff --git a/app/models/project.rb b/app/models/project.rb index e47c55ac7e..47d5ece506 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -42,7 +42,7 @@ class Project < ActiveRecord::Base include Sortable include AfterCommitQueue include CaseSensitivity - + extend Gitlab::ConfigHelper extend Enumerize @@ -336,7 +336,6 @@ class Project < ActiveRecord::Base end def add_import_job -<<<<<<< HEAD if repository_exists? if mirror? RepositoryUpdateMirrorWorker.perform_async(self.id) @@ -345,8 +344,6 @@ class Project < ActiveRecord::Base return end -======= ->>>>>>> ce/8-2-stable if forked? RepositoryForkWorker.perform_async(self.id, forked_from_project.path_with_namespace, self.namespace.path) else @@ -394,7 +391,6 @@ class Project < ActiveRecord::Base original_url end -<<<<<<< HEAD def mirror_updated? mirror? && self.mirror_last_update_at end @@ -443,8 +439,6 @@ class Project < ActiveRecord::Base repository.fetch_upstream(self.import_url) end -======= ->>>>>>> ce/8-2-stable def check_limit unless creator.can_create_project? or namespace.kind == 'group' errors[:limit_reached] << ("Your project limit is #{creator.projects_limit} projects! Please contact your administrator to increase it") From 463a3cfe0909447acd40a0dd33923ebb7b10b02a Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Thu, 19 Nov 2015 16:45:45 +0000 Subject: [PATCH 45/80] Merge branch 'dirceu/gitlab-ce-new-merge-request-from-file-edit' into 'master' Add option to create merge request when editing/creating a file Replaces !1611 Fixes #3059 See merge request !1820 --- CHANGELOG | 1 + .../blob/blob_file_dropzone.js.coffee | 17 +--- .../javascripts/new_commit_form.js.coffee | 21 +++++ .../creates_merge_request_for_commit.rb | 28 ++++++ app/controllers/projects/blob_controller.rb | 87 +++++++++++-------- app/controllers/projects/tree_controller.rb | 13 ++- app/helpers/merge_requests_helper.rb | 8 -- app/views/projects/blob/_actions.html.haml | 2 +- app/views/projects/blob/_new_dir.html.haml | 14 ++- app/views/projects/blob/_remove.html.haml | 16 ++-- app/views/projects/blob/_upload.html.haml | 18 ++-- app/views/projects/blob/edit.html.haml | 11 +-- app/views/projects/blob/new.html.haml | 16 ++-- app/views/projects/blob/show.html.haml | 4 +- .../projects/tree/_tree_content.html.haml | 2 +- .../_commit_message_container.html.haml | 8 +- app/views/shared/_new_commit_form.html.haml | 18 ++++ features/project/source/browse_files.feature | 14 +-- features/steps/project/source/browse_files.rb | 30 ++----- 19 files changed, 184 insertions(+), 144 deletions(-) create mode 100644 app/assets/javascripts/new_commit_form.js.coffee create mode 100644 app/controllers/concerns/creates_merge_request_for_commit.rb create mode 100644 app/views/shared/_new_commit_form.html.haml diff --git a/CHANGELOG b/CHANGELOG index 94f07a3168..190115503b 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -49,6 +49,7 @@ v 8.2.0 - Fix trailing whitespace issue in merge request/issue title - Fix bug when milestone/label filter was empty for dashboard issues page - Add ability to create milestone in group projects from single form + - Add option to create merge request when editing/creating a file (Dirceu Tiegs) - Prevent the last owner of a group from being able to delete themselves by 'adding' themselves as a master (James Lopez) v 8.1.4 diff --git a/app/assets/javascripts/blob/blob_file_dropzone.js.coffee b/app/assets/javascripts/blob/blob_file_dropzone.js.coffee index 5b604adbbb..195f8b11e5 100644 --- a/app/assets/javascripts/blob/blob_file_dropzone.js.coffee +++ b/app/assets/javascripts/blob/blob_file_dropzone.js.coffee @@ -23,18 +23,6 @@ class @BlobFileDropzone init: -> this.on 'addedfile', (file) -> $('.dropzone-alerts').html('').hide() - commit_message = form.find('#commit_message')[0] - - if /^Upload/.test(commit_message.placeholder) - commit_message.placeholder = 'Upload ' + file.name - - return - - this.on 'removedfile', (file) -> - commit_message = form.find('#commit_message')[0] - - if /^Upload/.test(commit_message.placeholder) - commit_message.placeholder = 'Upload new file' return @@ -47,8 +35,9 @@ class @BlobFileDropzone return this.on 'sending', (file, xhr, formData) -> - formData.append('new_branch', form.find('#new_branch').val()) - formData.append('commit_message', form.find('#commit_message').val()) + formData.append('new_branch', form.find('.js-new-branch').val()) + formData.append('create_merge_request', form.find('.js-create-merge-request').val()) + formData.append('commit_message', form.find('.js-commit-message').val()) return # Override behavior of adding error underneath preview diff --git a/app/assets/javascripts/new_commit_form.js.coffee b/app/assets/javascripts/new_commit_form.js.coffee new file mode 100644 index 0000000000..2e561dea3e --- /dev/null +++ b/app/assets/javascripts/new_commit_form.js.coffee @@ -0,0 +1,21 @@ +class @NewCommitForm + constructor: (form) -> + @newBranch = form.find('.js-new-branch') + @originalBranch = form.find('.js-original-branch') + @createMergeRequest = form.find('.js-create-merge-request') + @createMergeRequestFormGroup = form.find('.js-create-merge-request-form-group') + + @renderDestination() + @newBranch.keyup @renderDestination + + renderDestination: => + different = @newBranch.val() != @originalBranch.val() + + if different + @createMergeRequestFormGroup.show() + @createMergeRequest.prop('checked', true) unless @wasDifferent + else + @createMergeRequestFormGroup.hide() + @createMergeRequest.prop('checked', false) + + @wasDifferent = different diff --git a/app/controllers/concerns/creates_merge_request_for_commit.rb b/app/controllers/concerns/creates_merge_request_for_commit.rb new file mode 100644 index 0000000000..c752782215 --- /dev/null +++ b/app/controllers/concerns/creates_merge_request_for_commit.rb @@ -0,0 +1,28 @@ +module CreatesMergeRequestForCommit + extend ActiveSupport::Concern + + def new_merge_request_path + if @project.forked? + target_project = @project.forked_from_project || @project + target_branch = target_project.repository.root_ref + else + target_project = @project + target_branch = @ref + end + + new_namespace_project_merge_request_path( + @project.namespace, + @project, + merge_request: { + source_project_id: @project.id, + target_project_id: target_project.id, + source_branch: @new_branch, + target_branch: target_branch + } + ) + end + + def create_merge_request? + params[:create_merge_request] && @new_branch != @ref + end +end diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb index 93738aa1ee..31a33bfd23 100644 --- a/app/controllers/projects/blob_controller.rb +++ b/app/controllers/projects/blob_controller.rb @@ -1,6 +1,7 @@ # Controller for viewing a file's blame class Projects::BlobController < Projects::ApplicationController include ExtractsPath + include CreatesMergeRequestForCommit include ActionView::Helpers::SanitizeHelper # Raised when given an invalid file path @@ -22,21 +23,9 @@ class Projects::BlobController < Projects::ApplicationController end def create - result = Files::CreateService.new(@project, current_user, @commit_params).execute - - if result[:status] == :success - flash[:notice] = "The changes have been successfully committed" - respond_to do |format| - format.html { redirect_to namespace_project_blob_path(@project.namespace, @project, File.join(@target_branch, @file_path)) } - format.json { render json: { message: "success", filePath: namespace_project_blob_path(@project.namespace, @project, File.join(@target_branch, @file_path)) } } - end - else - flash[:alert] = result[:message] - respond_to do |format| - format.html { render :new } - format.json { render json: { message: "failed", filePath: namespace_project_blob_path(@project.namespace, @project, @id) } } - end - end + create_commit(Files::CreateService, success_path: after_create_path, + failure_view: :new, + failure_path: namespace_project_new_blob_path(@project.namespace, @project, @ref)) end def show @@ -47,21 +36,9 @@ class Projects::BlobController < Projects::ApplicationController end def update - result = Files::UpdateService.new(@project, current_user, @commit_params).execute - - if result[:status] == :success - flash[:notice] = "Your changes have been successfully committed" - respond_to do |format| - format.html { redirect_to after_edit_path } - format.json { render json: { message: "success", filePath: after_edit_path } } - end - else - flash[:alert] = result[:message] - respond_to do |format| - format.html { render :edit } - format.json { render json: { message: "failed", filePath: namespace_project_new_blob_path(@project.namespace, @project, @id) } } - end - end + create_commit(Files::UpdateService, success_path: after_edit_path, + failure_view: :edit, + failure_path: namespace_project_blob_path(@project.namespace, @project, @id)) end def preview @@ -77,7 +54,7 @@ class Projects::BlobController < Projects::ApplicationController if result[:status] == :success flash[:notice] = "Your changes have been successfully committed" - redirect_to namespace_project_tree_path(@project.namespace, @project, @target_branch) + redirect_to after_destroy_path else flash[:alert] = result[:message] render :show @@ -131,15 +108,51 @@ class Projects::BlobController < Projects::ApplicationController render_404 end + def create_commit(service, success_path:, failure_view:, failure_path:) + result = service.new(@project, current_user, @commit_params).execute + + if result[:status] == :success + flash[:notice] = "Your changes have been successfully committed" + respond_to do |format| + format.html { redirect_to success_path } + format.json { render json: { message: "success", filePath: success_path } } + end + else + flash[:alert] = result[:message] + respond_to do |format| + format.html { render failure_view } + format.json { render json: { message: "failed", filePath: failure_path } } + end + end + end + + def after_create_path + @after_create_path ||= + if create_merge_request? + new_merge_request_path + else + namespace_project_blob_path(@project.namespace, @project, File.join(@new_branch, @file_path)) + end + end + def after_edit_path @after_edit_path ||= - if from_merge_request + if create_merge_request? + new_merge_request_path + elsif from_merge_request && @new_branch == @ref diffs_namespace_project_merge_request_path(from_merge_request.target_project.namespace, from_merge_request.target_project, from_merge_request) + "#file-path-#{hexdigest(@path)}" - elsif @target_branch.present? - namespace_project_blob_path(@project.namespace, @project, File.join(@target_branch, @path)) else - namespace_project_blob_path(@project.namespace, @project, @id) + namespace_project_blob_path(@project.namespace, @project, File.join(@new_branch, @path)) + end + end + + def after_destroy_path + @after_destroy_path ||= + if create_merge_request? + new_merge_request_path + else + namespace_project_tree_path(@project.namespace, @project, @new_branch) end end @@ -154,7 +167,7 @@ class Projects::BlobController < Projects::ApplicationController def editor_variables @current_branch = @ref - @target_branch = params[:new_branch].present? ? sanitized_new_branch_name : @ref + @new_branch = params[:new_branch].present? ? sanitized_new_branch_name : @ref @file_path = if action_name.to_s == 'create' @@ -174,7 +187,7 @@ class Projects::BlobController < Projects::ApplicationController @commit_params = { file_path: @file_path, current_branch: @current_branch, - target_branch: @target_branch, + target_branch: @new_branch, commit_message: params[:commit_message], file_content: params[:content], file_content_encoding: params[:encoding] diff --git a/app/controllers/projects/tree_controller.rb b/app/controllers/projects/tree_controller.rb index bdcb1a3e29..8f272ad128 100644 --- a/app/controllers/projects/tree_controller.rb +++ b/app/controllers/projects/tree_controller.rb @@ -1,6 +1,7 @@ # Controller for viewing a repository's file structure class Projects::TreeController < Projects::ApplicationController include ExtractsPath + include CreatesMergeRequestForCommit include ActionView::Helpers::SanitizeHelper before_action :require_non_empty_project, except: [:new, :create] @@ -43,7 +44,7 @@ class Projects::TreeController < Projects::ApplicationController if result && result[:status] == :success flash[:notice] = "The directory has been successfully created" respond_to do |format| - format.html { redirect_to namespace_project_blob_path(@project.namespace, @project, File.join(@new_branch, @dir_name)) } + format.html { redirect_to after_create_dir_path } end else flash[:alert] = message @@ -53,6 +54,8 @@ class Projects::TreeController < Projects::ApplicationController end end + private + def assign_dir_vars @new_branch = params[:new_branch].present? ? sanitize(strip_tags(params[:new_branch])) : @ref @dir_name = File.join(@path, params[:dir_name]) @@ -63,4 +66,12 @@ class Projects::TreeController < Projects::ApplicationController commit_message: params[:commit_message], } end + + def after_create_dir_path + if create_merge_request? + new_merge_request_path + else + namespace_project_blob_path(@project.namespace, @project, File.join(@new_branch, @dir_name)) + end + end end diff --git a/app/helpers/merge_requests_helper.rb b/app/helpers/merge_requests_helper.rb index 728d877ace..b804d4f4e3 100644 --- a/app/helpers/merge_requests_helper.rb +++ b/app/helpers/merge_requests_helper.rb @@ -8,14 +8,6 @@ module MergeRequestsHelper ) end - def new_mr_path_for_fork_from_push_event(event) - new_namespace_project_merge_request_path( - event.project.namespace, - event.project, - new_mr_from_push_event(event, event.project.forked_from_project) - ) - end - def new_mr_from_push_event(event, target_project) { merge_request: { diff --git a/app/views/projects/blob/_actions.html.haml b/app/views/projects/blob/_actions.html.haml index 373b3a0c5b..ba3e0c3c59 100644 --- a/app/views/projects/blob/_actions.html.haml +++ b/app/views/projects/blob/_actions.html.haml @@ -19,4 +19,4 @@ - if allowed_tree_edit? .btn-group{ role: "group" } %button.btn.btn-default{ 'data-target' => '#modal-upload-blob', 'data-toggle' => 'modal' } Replace - %button.btn.btn-remove{ 'data-target' => '#modal-remove-blob', 'data-toggle' => 'modal' } Remove + %button.btn.btn-remove{ 'data-target' => '#modal-remove-blob', 'data-toggle' => 'modal' } Delete diff --git a/app/views/projects/blob/_new_dir.html.haml b/app/views/projects/blob/_new_dir.html.haml index a0fc8bbd75..13b5ffd17f 100644 --- a/app/views/projects/blob/_new_dir.html.haml +++ b/app/views/projects/blob/_new_dir.html.haml @@ -5,21 +5,19 @@ %a.close{href: "#", "data-dismiss" => "modal"} × %h3.page-title Create New Directory .modal-body - = form_tag namespace_project_create_dir_path(@project.namespace, @project, @id), method: :post, remote: false, id: 'dir-create-form', class: 'form-horizontal' do + = form_tag namespace_project_create_dir_path(@project.namespace, @project, @id), method: :post, remote: false, class: 'form-horizontal js-create-dir-form' do .form-group = label_tag :dir_name, 'Directory Name', class: 'control-label' .col-sm-10 = text_field_tag :dir_name, params[:dir_name], placeholder: "Directory name", required: true, class: 'form-control' - = render 'shared/commit_message_container', params: params, placeholder: '' - - unless @project.empty_repo? - .form-group - = label_tag :branch_name, 'Branch', class: 'control-label' - .col-sm-10 - = text_field_tag 'new_branch', @ref, class: "form-control" + + = render 'shared/new_commit_form', placeholder: "Add new directory" + .form-group .col-sm-offset-2.col-sm-10 = submit_tag "Create directory", class: 'btn btn-primary btn-create' = link_to "Cancel", '#', class: "btn btn-cancel", "data-dismiss" => "modal" :javascript - disableButtonIfAnyEmptyField($("#dir-create-form"), ".form-control", ".btn-create"); + disableButtonIfAnyEmptyField($(".js-create-dir-form"), ".form-control", ".btn-create"); + new NewCommitForm($('.js-create-dir-form')) diff --git a/app/views/projects/blob/_remove.html.haml b/app/views/projects/blob/_remove.html.haml index cae5ff0109..1cf19a7d3d 100644 --- a/app/views/projects/blob/_remove.html.haml +++ b/app/views/projects/blob/_remove.html.haml @@ -3,16 +3,16 @@ .modal-content .modal-header %a.close{href: "#", "data-dismiss" => "modal"} × - %h3.page-title Remove #{@blob.name} - %p.light - From branch - %strong= @ref + %h3.page-title Delete #{@blob.name} .modal-body - = form_tag namespace_project_blob_path(@project.namespace, @project, @id), method: :delete, class: 'form-horizontal js-requires-input' do - = render 'shared/commit_message_container', params: params, - placeholder: 'Removed this file because...' + = form_tag namespace_project_blob_path(@project.namespace, @project, @id), method: :delete, class: 'form-horizontal js-replace-blob-form js-requires-input' do + = render 'shared/new_commit_form', placeholder: "Delete #{@blob.name}" + .form-group .col-sm-offset-2.col-sm-10 - = button_tag 'Remove file', class: 'btn btn-remove btn-remove-file' + = button_tag 'Delete file', class: 'btn btn-remove btn-remove-file' = link_to "Cancel", '#', class: "btn btn-cancel", "data-dismiss" => "modal" + +:javascript + new NewCommitForm($('.js-replace-blob-form')) diff --git a/app/views/projects/blob/_upload.html.haml b/app/views/projects/blob/_upload.html.haml index a1c54e731f..3bb61f0c94 100644 --- a/app/views/projects/blob/_upload.html.haml +++ b/app/views/projects/blob/_upload.html.haml @@ -5,7 +5,7 @@ %a.close{href: "#", "data-dismiss" => "modal"} × %h3.page-title #{title} .modal-body - = form_tag form_path, method: method, class: 'blob-file-upload-form-js form-horizontal' do + = form_tag form_path, method: method, class: 'js-upload-blob-form form-horizontal' do .dropzone .dropzone-previews.blob-upload-dropzone-previews %p.dz-message.light @@ -13,19 +13,15 @@ = link_to 'click to upload', '#', class: "markdown-selector" %br .dropzone-alerts{class: "alert alert-danger data", style: "display:none"} - = render 'shared/commit_message_container', params: params, - placeholder: placeholder - - unless @project.empty_repo? - .form-group.branch - = label_tag 'branch', class: 'control-label' do - Branch - .col-sm-10 - = text_field_tag 'new_branch', @ref, class: "form-control" + + = render 'shared/new_commit_form', placeholder: placeholder + .form-group .col-sm-offset-2.col-sm-10 = button_tag button_title, class: 'btn btn-small btn-primary btn-upload-file', id: 'submit-all' = link_to "Cancel", '#', class: "btn btn-cancel", "data-dismiss" => "modal" :javascript - disableButtonIfEmptyField($('.blob-file-upload-form-js').find('#commit_message'), '.btn-upload-file'); - new BlobFileDropzone($('.blob-file-upload-form-js'), '#{method}'); + disableButtonIfEmptyField($('.js-upload-blob-form').find('.js-commit-message'), '.btn-upload-file'); + new BlobFileDropzone($('.js-upload-blob-form'), '#{method}'); + new NewCommitForm($('.js-upload-blob-form')) diff --git a/app/views/projects/blob/edit.html.haml b/app/views/projects/blob/edit.html.haml index a811adc509..5674516525 100644 --- a/app/views/projects/blob/edit.html.haml +++ b/app/views/projects/blob/edit.html.haml @@ -13,15 +13,9 @@ %i.fa.fa-eye = editing_preview_title(@blob.name) - = form_tag(namespace_project_update_blob_path(@project.namespace, @project, @id), method: :put, class: 'form-horizontal js-requires-input') do + = form_tag(namespace_project_update_blob_path(@project.namespace, @project, @id), method: :put, class: 'form-horizontal js-requires-input js-edit-blob-form') do = render 'projects/blob/editor', ref: @ref, path: @path, blob_data: @blob.data - = render 'shared/commit_message_container', params: params, placeholder: "Update #{@blob.name}" - - .form-group.branch - = label_tag 'branch', class: 'control-label' do - Branch - .col-sm-10 - = text_field_tag 'new_branch', @ref, class: "form-control" + = render 'shared/new_commit_form', placeholder: "Update #{@blob.name}" = hidden_field_tag 'last_commit', @last_commit = hidden_field_tag 'content', '', id: "file-content" @@ -30,3 +24,4 @@ :javascript blob = new EditBlob(gon.relative_url_root + "#{Gitlab::Application.config.assets.prefix}", "#{@blob.language.try(:ace_mode)}") + new NewCommitForm($('.js-edit-blob-form')) diff --git a/app/views/projects/blob/new.html.haml b/app/views/projects/blob/new.html.haml index 7975137c37..1ff6800545 100644 --- a/app/views/projects/blob/new.html.haml +++ b/app/views/projects/blob/new.html.haml @@ -2,20 +2,13 @@ = render "header_title" .gray-content-block.top-block - Create a new file + %h3.page-title + Create New File .file-editor - = form_tag(namespace_project_create_blob_path(@project.namespace, @project, @id), method: :post, class: 'form-horizontal form-new-file js-requires-input') do + = form_tag(namespace_project_create_blob_path(@project.namespace, @project, @id), method: :post, class: 'form-horizontal js-new-blob-form js-requires-input') do = render 'projects/blob/editor', ref: @ref - = render 'shared/commit_message_container', params: params, - placeholder: 'Add new file' - - - unless @project.empty_repo? - .form-group.branch - = label_tag 'branch', class: 'control-label' do - Branch - .col-sm-10 - = text_field_tag 'new_branch', @ref, class: "form-control js-quick-submit" + = render 'shared/new_commit_form', placeholder: "Add new file" = hidden_field_tag 'content', '', id: 'file-content' = render 'projects/commit_button', ref: @ref, @@ -23,3 +16,4 @@ :javascript blob = new NewBlob(gon.relative_url_root + "#{Gitlab::Application.config.assets.prefix}", null) + new NewCommitForm($('.js-new-blob-form')) diff --git a/app/views/projects/blob/show.html.haml b/app/views/projects/blob/show.html.haml index f52b89f692..b7276868ce 100644 --- a/app/views/projects/blob/show.html.haml +++ b/app/views/projects/blob/show.html.haml @@ -10,6 +10,4 @@ = render 'projects/blob/remove' - title = "Replace #{@blob.name}" - = render 'projects/blob/upload', title: title, placeholder: title, - button_title: 'Replace file', form_path: namespace_project_update_blob_path(@project.namespace, @project, @id), - method: :put + = render 'projects/blob/upload', title: title, placeholder: title, button_title: 'Replace file', form_path: namespace_project_update_blob_path(@project.namespace, @project, @id), method: :put diff --git a/app/views/projects/tree/_tree_content.html.haml b/app/views/projects/tree/_tree_content.html.haml index ee4c9d1693..c64e684df2 100644 --- a/app/views/projects/tree/_tree_content.html.haml +++ b/app/views/projects/tree/_tree_content.html.haml @@ -30,7 +30,7 @@ = render "projects/tree/readme", readme: tree.readme - if allowed_tree_edit? - = render 'projects/blob/upload', title: 'Upload', placeholder: 'Upload new file', button_title: 'Upload file', form_path: namespace_project_create_blob_path(@project.namespace, @project, @id), method: :post + = render 'projects/blob/upload', title: 'Upload New File', placeholder: 'Upload new file', button_title: 'Upload file', form_path: namespace_project_create_blob_path(@project.namespace, @project, @id), method: :post = render 'projects/blob/new_dir' :javascript diff --git a/app/views/shared/_commit_message_container.html.haml b/app/views/shared/_commit_message_container.html.haml index cc3f1268f8..7c57924277 100644 --- a/app/views/shared/_commit_message_container.html.haml +++ b/app/views/shared/_commit_message_container.html.haml @@ -1,13 +1,15 @@ .form-group.commit_message-group - = label_tag 'commit_message', class: 'control-label' do + - nonce = SecureRandom.hex + = label_tag "commit_message-#{nonce}", class: 'control-label' do Commit message .col-sm-10 .commit-message-container .max-width-marker = text_area_tag 'commit_message', (params[:commit_message] || local_assigns[:text]), - class: 'form-control js-quick-submit', placeholder: local_assigns[:placeholder], - required: true, rows: (local_assigns[:rows] || 3) + class: 'form-control js-commit-message js-quick-submit', placeholder: local_assigns[:placeholder], + required: true, rows: (local_assigns[:rows] || 3), + id: "commit_message-#{nonce}" - if local_assigns[:hint] %p.hint Try to keep the first line under 52 characters diff --git a/app/views/shared/_new_commit_form.html.haml b/app/views/shared/_new_commit_form.html.haml new file mode 100644 index 0000000000..8636341c60 --- /dev/null +++ b/app/views/shared/_new_commit_form.html.haml @@ -0,0 +1,18 @@ += render 'shared/commit_message_container', placeholder: placeholder + +- unless @project.empty_repo? + .form-group.branch + = label_tag 'branch', class: 'control-label' do + Branch + .col-sm-10 + = text_field_tag 'new_branch', @new_branch || @ref, class: "form-control js-new-branch" + + .form-group.js-create-merge-request-form-group + .col-sm-offset-2.col-sm-10 + .checkbox + - nonce = SecureRandom.hex + = label_tag "create_merge_request-#{nonce}" do + = check_box_tag 'create_merge_request', 1, true, class: 'js-create-merge-request', id: "create_merge_request-#{nonce}" + Start a new merge request with this commit + + = hidden_field_tag 'original_branch', @ref, class: 'js-original-branch' diff --git a/features/project/source/browse_files.feature b/features/project/source/browse_files.feature index 69aa79f2d2..e545ea63ca 100644 --- a/features/project/source/browse_files.feature +++ b/features/project/source/browse_files.feature @@ -42,7 +42,7 @@ Feature: Project Source Browse Files And I fill the new branch name And I click on "Upload file" Then I can see the new text file - And I am redirected to the uploaded file on new branch + And I am redirected to the new merge request page And I can see the new commit message @javascript @@ -64,7 +64,7 @@ Feature: Project Source Browse Files And I fill the commit message And I fill the new branch name And I click on "Commit Changes" - Then I am redirected to the new file on new branch + Then I am redirected to the new merge request page And I should see its new content @javascript @@ -134,7 +134,7 @@ Feature: Project Source Browse Files And I fill the commit message And I fill the new branch name And I click on "Commit Changes" - Then I am redirected to the ".gitignore" on new branch + Then I am redirected to the new merge request page And I should see its new content @javascript @wip @@ -154,7 +154,7 @@ Feature: Project Source Browse Files And I fill the commit message And I fill the new branch name And I click on "Create directory" - Then I am redirected to the new directory + Then I am redirected to the new merge request page @javascript Scenario: I attempt to create an existing directory @@ -174,12 +174,12 @@ Feature: Project Source Browse Files Then I see diff @javascript - Scenario: I can remove file and commit + Scenario: I can delete file and commit Given I click on ".gitignore" file in repo And I see the ".gitignore" - And I click on "Remove" + And I click on "Delete" And I fill the commit message - And I click on "Remove file" + And I click on "Delete file" Then I am redirected to the files URL And I don't see the ".gitignore" diff --git a/features/steps/project/source/browse_files.rb b/features/steps/project/source/browse_files.rb index 84725b9b58..f40e0f0d52 100644 --- a/features/steps/project/source/browse_files.rb +++ b/features/steps/project/source/browse_files.rb @@ -98,12 +98,12 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps click_button 'Create directory' end - step 'I click on "Remove"' do - click_button 'Remove' + step 'I click on "Delete"' do + click_button 'Delete' end - step 'I click on "Remove file"' do - click_button 'Remove file' + step 'I click on "Delete file"' do + click_button 'Delete file' end step 'I click on "Replace"' do @@ -142,7 +142,7 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps end step 'I can see new file page' do - expect(page).to have_content "new file" + expect(page).to have_content "Create New File" expect(page).to have_content "Commit message" end @@ -225,10 +225,6 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps expect(current_path).to eq(namespace_project_blob_path(@project.namespace, @project, 'master/.gitignore')) end - step 'I am redirected to the ".gitignore" on new branch' do - expect(current_path).to eq(namespace_project_blob_path(@project.namespace, @project, 'new_branch_name/.gitignore')) - end - step 'I am redirected to the permalink URL' do expect(current_path).to( eq(namespace_project_blob_path(@project.namespace, @project, @@ -247,20 +243,8 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps @project.namespace, @project, 'master/' + new_file_name_with_directory)) end - step 'I am redirected to the new file on new branch' do - expect(current_path).to eq(namespace_project_blob_path( - @project.namespace, @project, 'new_branch_name/' + new_file_name)) - end - - step 'I am redirected to the uploaded file on new branch' do - expect(current_path).to eq(namespace_project_blob_path( - @project.namespace, @project, - 'new_branch_name/' + File.basename(test_text_file))) - end - - step 'I am redirected to the new directory' do - expect(current_path).to eq(namespace_project_tree_path( - @project.namespace, @project, 'new_branch_name/' + new_dir_name)) + step 'I am redirected to the new merge request page' do + expect(current_path).to eq(new_namespace_project_merge_request_path(@project.namespace, @project)) end step 'I am redirected to the root directory' do From 64e3cba941100f5af21ce47323bfa424aef582c1 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Thu, 19 Nov 2015 17:22:20 +0000 Subject: [PATCH 46/80] Merge branch 'dbalexandre/gitlab-ce-fix-personal-snippet-access-workflow' into 'master' Improve personal snippet access workflow. Replaces !1709 Fixes #3258 See merge request !1817 --- CHANGELOG | 1 + app/controllers/snippets_controller.rb | 9 +- app/models/ability.rb | 82 +++++++++---- spec/controllers/snippets_controller_spec.rb | 118 +++++++++++++++++++ spec/factories.rb | 12 ++ 5 files changed, 199 insertions(+), 23 deletions(-) create mode 100644 spec/controllers/snippets_controller_spec.rb diff --git a/CHANGELOG b/CHANGELOG index 190115503b..c3fbe932d6 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -28,6 +28,7 @@ v 8.2.0 - Allow to define cache in `.gitlab-ci.yml` - Fix: 500 error returned if destroy request without HTTP referer (Kazuki Shimizu) - Remove deprecated CI events from project settings page + - Improve personal snippet access workflow (Douglas Alexandre) - [API] Add ability to fetch the commit ID of the last commit that actually touched a file - Fix omniauth documentation setting for omnibus configuration (Jon Cairns) - Add "New file" link to dropdown on project page diff --git a/app/controllers/snippets_controller.rb b/app/controllers/snippets_controller.rb index 9f9f9a92f1..08f2483af3 100644 --- a/app/controllers/snippets_controller.rb +++ b/app/controllers/snippets_controller.rb @@ -1,6 +1,9 @@ class SnippetsController < ApplicationController before_action :snippet, only: [:show, :edit, :destroy, :update, :raw] + # Allow read snippet + before_action :authorize_read_snippet!, only: [:show] + # Allow modify snippet before_action :authorize_update_snippet!, only: [:edit, :update] @@ -79,10 +82,14 @@ class SnippetsController < ApplicationController [Snippet::PUBLIC, Snippet::INTERNAL]). find(params[:id]) else - PersonalSnippet.are_public.find(params[:id]) + PersonalSnippet.find(params[:id]) end end + def authorize_read_snippet! + authenticate_user! unless can?(current_user, :read_personal_snippet, @snippet) + end + def authorize_update_snippet! return render_404 unless can?(current_user, :update_personal_snippet, @snippet) end diff --git a/app/models/ability.rb b/app/models/ability.rb index 500af08d20..07f3a56ec7 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -1,8 +1,8 @@ class Ability class << self def allowed(user, subject) - return not_auth_abilities(user, subject) if user.nil? - return [] unless user.kind_of?(User) + return anonymous_abilities(user, subject) if user.nil? + return [] unless user.is_a?(User) return [] if user.blocked? case subject.class.name @@ -20,15 +20,25 @@ class Ability end.concat(global_abilities(user)) end - # List of possible abilities - # for non-authenticated user - def not_auth_abilities(user, subject) - project = if subject.kind_of?(Project) + # List of possible abilities for anonymous user + def anonymous_abilities(user, subject) + case true + when subject.is_a?(PersonalSnippet) + anonymous_personal_snippet_abilities(subject) + when subject.is_a?(Project) || subject.respond_to?(:project) + anonymous_project_abilities(subject) + when subject.is_a?(Group) || subject.respond_to?(:group) + anonymous_group_abilities(subject) + else + [] + end + end + + def anonymous_project_abilities(subject) + project = if subject.is_a?(Project) subject - elsif subject.respond_to?(:project) - subject.project else - nil + subject.project end if project && project.public? @@ -48,19 +58,29 @@ class Ability rules - project_disabled_features_rules(project) else - group = if subject.kind_of?(Group) - subject - elsif subject.respond_to?(:group) - subject.group - else - nil - end + [] + end + end - if group && group.public_profile? - [:read_group] - else - [] - end + def anonymous_group_abilities(subject) + group = if subject.is_a?(Group) + subject + else + subject.group + end + + if group && group.public_profile? + [:read_group] + else + [] + end + end + + def anonymous_personal_snippet_abilities(snippet) + if snippet.public? + [:read_personal_snippet] + else + [] end end @@ -280,7 +300,7 @@ class Ability end end - [:note, :project_snippet, :personal_snippet].each do |name| + [:note, :project_snippet].each do |name| define_method "#{name}_abilities" do |user, subject| rules = [] @@ -300,6 +320,24 @@ class Ability end end + def personal_snippet_abilities(user, snippet) + rules = [] + + if snippet.author == user + rules += [ + :read_personal_snippet, + :update_personal_snippet, + :admin_personal_snippet + ] + end + + if snippet.public? || snippet.internal? + rules << :read_personal_snippet + end + + rules + end + def group_member_abilities(user, subject) rules = [] target_user = subject.user diff --git a/spec/controllers/snippets_controller_spec.rb b/spec/controllers/snippets_controller_spec.rb new file mode 100644 index 0000000000..e9b823c523 --- /dev/null +++ b/spec/controllers/snippets_controller_spec.rb @@ -0,0 +1,118 @@ +require 'spec_helper' + +describe SnippetsController do + describe 'GET #show' do + let(:user) { create(:user) } + + context 'when the personal snippet is private' do + let(:personal_snippet) { create(:personal_snippet, :private, author: user) } + + context 'when signed in' do + before do + sign_in(user) + end + + context 'when signed in user is not the author' do + let(:other_author) { create(:author) } + let(:other_personal_snippet) { create(:personal_snippet, :private, author: other_author) } + + it 'responds with status 404' do + get :show, id: other_personal_snippet.to_param + + expect(response.status).to eq(404) + end + end + + context 'when signed in user is the author' do + it 'renders the snippet' do + get :show, id: personal_snippet.to_param + + expect(assigns(:snippet)).to eq(personal_snippet) + expect(response.status).to eq(200) + end + end + end + + context 'when not signed in' do + it 'redirects to the sign in page' do + get :show, id: personal_snippet.to_param + + expect(response).to redirect_to(new_user_session_path) + end + end + end + + context 'when the personal snippet is internal' do + let(:personal_snippet) { create(:personal_snippet, :internal, author: user) } + + context 'when signed in' do + before do + sign_in(user) + end + + it 'renders the snippet' do + get :show, id: personal_snippet.to_param + + expect(assigns(:snippet)).to eq(personal_snippet) + expect(response.status).to eq(200) + end + end + + context 'when not signed in' do + it 'redirects to the sign in page' do + get :show, id: personal_snippet.to_param + + expect(response).to redirect_to(new_user_session_path) + end + end + end + + context 'when the personal snippet is public' do + let(:personal_snippet) { create(:personal_snippet, :public, author: user) } + + context 'when signed in' do + before do + sign_in(user) + end + + it 'renders the snippet' do + get :show, id: personal_snippet.to_param + + expect(assigns(:snippet)).to eq(personal_snippet) + expect(response.status).to eq(200) + end + end + + context 'when not signed in' do + it 'renders the snippet' do + get :show, id: personal_snippet.to_param + + expect(assigns(:snippet)).to eq(personal_snippet) + expect(response.status).to eq(200) + end + end + end + + context 'when the personal snippet does not exist' do + context 'when signed in' do + before do + sign_in(user) + end + + it 'responds with status 404' do + get :show, id: 'doesntexist' + + expect(response.status).to eq(404) + end + end + + context 'when not signed in' do + it 'responds with status 404' do + get :show, id: 'doesntexist' + + expect(response.status).to eq(404) + end + end + end + end +end diff --git a/spec/factories.rb b/spec/factories.rb index 200f18f660..4bf93adabe 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -165,6 +165,18 @@ FactoryGirl.define do title content file_name + + trait :public do + visibility_level Gitlab::VisibilityLevel::PUBLIC + end + + trait :internal do + visibility_level Gitlab::VisibilityLevel::INTERNAL + end + + trait :private do + visibility_level Gitlab::VisibilityLevel::PRIVATE + end end factory :snippet do From 34207d1dfbd687e38be518f569fe6a2095f65bfc Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Thu, 19 Nov 2015 23:23:31 +0000 Subject: [PATCH 47/80] Merge branch 'rs-safari-clipboard-fallback' into 'master' Add a fallback for Safari copy-to-clipboard Also, hide the tooltip in a less stupid way. Closes #3547 See merge request !1844 --- .../javascripts/copy_to_clipboard.js.coffee | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/app/assets/javascripts/copy_to_clipboard.js.coffee b/app/assets/javascripts/copy_to_clipboard.js.coffee index ec4b80cca6..9c68c5cc1b 100644 --- a/app/assets/javascripts/copy_to_clipboard.js.coffee +++ b/app/assets/javascripts/copy_to_clipboard.js.coffee @@ -9,13 +9,24 @@ $ -> clipboard.on 'success', (e) -> $(e.trigger). tooltip(trigger: 'manual', placement: 'auto bottom', title: 'Copied!'). - tooltip('show') + tooltip('show'). + one('mouseleave', -> $(this).tooltip('hide')) # Clear the selection and blur the trigger so it loses its border e.clearSelection() $(e.trigger).blur() - # Manually hide the tooltip after 1 second - setTimeout(-> - $(e.trigger).tooltip('hide') - , 1000) + # Safari doesn't support `execCommand`, so instead we inform the user to + # copy manually. + # + # See http://clipboardjs.com/#browser-support + clipboard.on 'error', (e) -> + if /Mac/i.test(navigator.userAgent) + title = "Press ⌘-C to copy" + else + title = "Press Ctrl-C to copy" + + $(e.trigger). + tooltip(trigger: 'manual', placement: 'auto bottom', html: true, title: title). + tooltip('show'). + one('mouseleave', -> $(this).tooltip('hide')) From 978f0bac8a4ea5cd695e43d35d88f767936f1399 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20Trzci=C5=84ski?= Date: Thu, 19 Nov 2015 22:57:06 +0000 Subject: [PATCH 48/80] Merge branch 'ci-yaml-validation' into 'master' Commits without .gitlab-ci.yml are marked as skipped - Commits without .gitlab-ci.yml are marked as skipped - Save detailed error when YAML syntax This also fixes: #3521 #3546 /cc @jacobvosmaer See merge request !1827 --- CHANGELOG | 4 ++++ app/controllers/ci/lints_controller.rb | 4 ++-- app/models/ci/commit.rb | 8 +++---- app/services/git_push_service.rb | 12 ---------- spec/lib/ci/gitlab_ci_yaml_processor_spec.rb | 6 ++++- .../services/ci/create_commit_service_spec.rb | 24 ++++++++++++++++--- 6 files changed, 36 insertions(+), 22 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index c3fbe932d6..1104980b28 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -11,6 +11,10 @@ v 8.2.0 - Upgrade gitlab_git to 7.2.20 and rugged to 0.23.3 (Stan Hu) - Improved performance of finding users by one of their Email addresses - Add allow_failure field to commit status API (Stan Hu) + - Commits without .gitlab-ci.yml are marked as skipped + - Save detailed error when YAML syntax is invalid + - Since GitLab CI is enabled by default, remove enabling it by pushing .gitlab-ci.yml + - Added build artifacts - Improved performance of replacing references in comments - Show last project commit to default branch on project home page - Highlight comment based on anchor in URL diff --git a/app/controllers/ci/lints_controller.rb b/app/controllers/ci/lints_controller.rb index 24dd1b5c93..a4f6aff49b 100644 --- a/app/controllers/ci/lints_controller.rb +++ b/app/controllers/ci/lints_controller.rb @@ -15,10 +15,10 @@ module Ci @builds = @config_processor.builds @status = true end - rescue Ci::GitlabCiYamlProcessor::ValidationError => e + rescue Ci::GitlabCiYamlProcessor::ValidationError, Psych::SyntaxError => e @error = e.message @status = false - rescue Exception + rescue @error = "Undefined error" @status = false end diff --git a/app/models/ci/commit.rb b/app/models/ci/commit.rb index 33b5717392..971e899de8 100644 --- a/app/models/ci/commit.rb +++ b/app/models/ci/commit.rb @@ -188,13 +188,13 @@ module Ci end def config_processor + return nil unless ci_yaml_file @config_processor ||= Ci::GitlabCiYamlProcessor.new(ci_yaml_file, gl_project.path_with_namespace) - rescue Ci::GitlabCiYamlProcessor::ValidationError => e + rescue Ci::GitlabCiYamlProcessor::ValidationError, Psych::SyntaxError => e save_yaml_error(e.message) nil - rescue Exception => e - logger.error e.message + "\n" + e.backtrace.join("\n") - save_yaml_error("Undefined yaml error") + rescue + save_yaml_error("Undefined error") nil end diff --git a/app/services/git_push_service.rb b/app/services/git_push_service.rb index ccb6b97858..f11690aa3f 100644 --- a/app/services/git_push_service.rb +++ b/app/services/git_push_service.rb @@ -58,12 +58,6 @@ class GitPushService @push_data = build_push_data(oldrev, newrev, ref) - # If CI was disabled but .gitlab-ci.yml file was pushed - # we enable CI automatically - if !project.builds_enabled? && gitlab_ci_yaml?(newrev) - project.enable_ci - end - EventCreateService.new.push(project, user, @push_data) project.execute_hooks(@push_data.dup, :push_hooks) project.execute_services(@push_data.dup, :push_hooks) @@ -134,10 +128,4 @@ class GitPushService def commit_user(commit) commit.author || user end - - def gitlab_ci_yaml?(sha) - @project.repository.blob_at(sha, '.gitlab-ci.yml') - rescue Rugged::ReferenceError - nil - end end diff --git a/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb b/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb index 7d90f9877c..6f287719ba 100644 --- a/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb +++ b/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb @@ -425,8 +425,12 @@ module Ci end describe "Error handling" do + it "fails to parse YAML" do + expect{GitlabCiYamlProcessor.new("invalid: yaml: test")}.to raise_error(Psych::SyntaxError) + end + it "indicates that object is invalid" do - expect{GitlabCiYamlProcessor.new("invalid_yaml\n!ccdvlf%612334@@@@")}.to raise_error(GitlabCiYamlProcessor::ValidationError) + expect{GitlabCiYamlProcessor.new("invalid_yaml")}.to raise_error(GitlabCiYamlProcessor::ValidationError) end it "returns errors if tags parameter is invalid" do diff --git a/spec/services/ci/create_commit_service_spec.rb b/spec/services/ci/create_commit_service_spec.rb index e3a8fe9681..e0ede1d58b 100644 --- a/spec/services/ci/create_commit_service_spec.rb +++ b/spec/services/ci/create_commit_service_spec.rb @@ -53,7 +53,7 @@ module Ci end end - it 'fails commits without .gitlab-ci.yml' do + it 'skips commits without .gitlab-ci.yml' do stub_ci_commit_yaml_file(nil) result = service.execute(project, user, ref: 'refs/heads/0_1', @@ -63,7 +63,24 @@ module Ci ) expect(result).to be_persisted expect(result.builds.any?).to be_falsey - expect(result.status).to eq('failed') + expect(result.status).to eq('skipped') + expect(result.yaml_errors).to be_nil + end + + it 'skips commits if yaml is invalid' do + message = 'message' + allow_any_instance_of(Ci::Commit).to receive(:git_commit_message) { message } + stub_ci_commit_yaml_file('invalid: file: file') + commits = [{ message: message }] + commit = service.execute(project, user, + ref: 'refs/tags/0_1', + before: '00000000', + after: '31das312', + commits: commits + ) + expect(commit.builds.any?).to be false + expect(commit.status).to eq('failed') + expect(commit.yaml_errors).to_not be_nil end describe :ci_skip? do @@ -100,7 +117,7 @@ module Ci end it "skips builds creation if there is [ci skip] tag in commit message and yaml is invalid" do - stub_ci_commit_yaml_file('invalid: file') + stub_ci_commit_yaml_file('invalid: file: fiile') commits = [{ message: message }] commit = service.execute(project, user, ref: 'refs/tags/0_1', @@ -110,6 +127,7 @@ module Ci ) expect(commit.builds.any?).to be false expect(commit.status).to eq("skipped") + expect(commit.yaml_errors).to be_nil end end From 48e86ec6105b879dffe30408f265b478ec21b706 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 19 Nov 2015 21:34:38 +0000 Subject: [PATCH 49/80] Merge branch 'emoji_votes' into 'master' Award Emoji This it first iteration of award emoji feature. We have plan to extend emoji picker by the next release. For now, you can add award by clicking to the emoji picker or posting a regular comment with emoji like ":+1:" and any other. You can post not only emoji that listed in the emoji picker. See merge request !1825 --- CHANGELOG | 1 + app/assets/javascripts/awards_handler.coffee | 91 +++++++++ app/assets/javascripts/notes.js.coffee | 9 +- app/assets/stylesheets/pages/issuable.scss | 68 +++++++ app/controllers/projects/issues_controller.rb | 2 +- .../projects/merge_requests_controller.rb | 2 +- app/controllers/projects/notes_controller.rb | 26 ++- app/finders/notes_finder.rb | 4 +- app/helpers/issues_helper.rb | 25 +++ app/models/concerns/issuable.rb | 49 ----- app/models/note.rb | 48 +---- app/services/notes/create_service.rb | 17 +- app/services/notification_service.rb | 1 + .../projects/issues/_discussion.html.haml | 2 +- app/views/projects/issues/_issue.html.haml | 2 - .../merge_requests/_merge_request.html.haml | 2 - app/views/projects/notes/_note.html.haml | 20 -- app/views/votes/_votes_block.html.haml | 42 +++- app/views/votes/_votes_inline.html.haml | 9 - config/routes.rb | 4 + .../20151106000015_add_is_award_to_notes.rb | 6 + db/schema.rb | 2 + doc/api/merge_requests.md | 12 -- doc/api/notes.md | 8 +- features/project/issues/award_emoji.feature | 14 ++ features/steps/project/issues/award_emoji.rb | 41 ++++ lib/api/entities.rb | 4 +- lib/award_emoji.rb | 12 ++ spec/helpers/issues_helper_spec.rb | 26 +++ spec/lib/votes_spec.rb | 188 ------------------ spec/models/note_spec.rb | 87 ++------ spec/models/project_spec.rb | 11 - spec/services/notes/create_service_spec.rb | 34 ++++ 33 files changed, 431 insertions(+), 438 deletions(-) create mode 100644 app/assets/javascripts/awards_handler.coffee delete mode 100644 app/views/votes/_votes_inline.html.haml create mode 100644 db/migrate/20151106000015_add_is_award_to_notes.rb create mode 100644 features/project/issues/award_emoji.feature create mode 100644 features/steps/project/issues/award_emoji.rb create mode 100644 lib/award_emoji.rb delete mode 100644 spec/lib/votes_spec.rb diff --git a/CHANGELOG b/CHANGELOG index 1104980b28..cc165e494a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -56,6 +56,7 @@ v 8.2.0 - Add ability to create milestone in group projects from single form - Add option to create merge request when editing/creating a file (Dirceu Tiegs) - Prevent the last owner of a group from being able to delete themselves by 'adding' themselves as a master (James Lopez) + - Add Award Emoji to issue and merge request pages v 8.1.4 - Fix bug where manually merged branches in a MR would end up with an empty diff (Stan Hu) diff --git a/app/assets/javascripts/awards_handler.coffee b/app/assets/javascripts/awards_handler.coffee new file mode 100644 index 0000000000..ae42e390c4 --- /dev/null +++ b/app/assets/javascripts/awards_handler.coffee @@ -0,0 +1,91 @@ +class @AwardsHandler + constructor: (@post_emoji_url, @noteable_type, @noteable_id) -> + + addAward: (emoji) -> + @postEmoji emoji, => + @addAwardToEmojiBar(emoji) + + addAwardToEmojiBar: (emoji, custom_path = '') -> + if @exist(emoji) + if @isActive(emoji) + @decrementCounter(emoji) + else + counter = @findEmojiIcon(emoji).siblings(".counter") + counter.text(parseInt(counter.text()) + 1) + counter.parent().addClass("active") + @addMeToAuthorList(emoji) + else + @createEmoji(emoji, custom_path) + + exist: (emoji) -> + @findEmojiIcon(emoji).length > 0 + + isActive: (emoji) -> + @findEmojiIcon(emoji).parent().hasClass("active") + + decrementCounter: (emoji) -> + counter = @findEmojiIcon(emoji).siblings(".counter") + + if parseInt(counter.text()) > 1 + counter.text(parseInt(counter.text()) - 1) + counter.parent().removeClass("active") + @removeMeFromAuthorList(emoji) + else + award = counter.parent() + award.tooltip("destroy") + award.remove() + + removeMeFromAuthorList: (emoji) -> + award_block = @findEmojiIcon(emoji).parent() + authors = award_block.attr("data-original-title").split(", ") + authors = _.without(authors, "me").join(", ") + award_block.attr("title", authors) + @resetTooltip(award_block) + + addMeToAuthorList: (emoji) -> + award_block = @findEmojiIcon(emoji).parent() + authors = award_block.attr("data-original-title").split(", ") + authors.push("me") + award_block.attr("title", authors.join(", ")) + @resetTooltip(award_block) + + resetTooltip: (award) -> + award.tooltip("destroy") + + # "destroy" call is asynchronous, this is why we need to set timeout. + setTimeout (-> + award.tooltip() + ), 200 + + + createEmoji: (emoji, custom_path) -> + nodes = [] + nodes.push("

") + + $(".awards-controls").before(nodes.join("\n")) + + $(".award").tooltip() + + getImage: (emoji, custom_path) -> + if custom_path + $(".awards-menu li").first().html().replace(/emoji\/.*\.png/, custom_path) + else + $("li[data-emoji='" + emoji + "']").html() + + + postEmoji: (emoji, callback) -> + $.post @post_emoji_url, { note: { + note: emoji + noteable_type: @noteable_type + noteable_id: @noteable_id + }},(data) -> + if data.ok + callback.call() + + findEmojiIcon: (emoji) -> + $(".icon[data-emoji='" + emoji + "']") \ No newline at end of file diff --git a/app/assets/javascripts/notes.js.coffee b/app/assets/javascripts/notes.js.coffee index ea75c656bc..7de7632201 100644 --- a/app/assets/javascripts/notes.js.coffee +++ b/app/assets/javascripts/notes.js.coffee @@ -113,13 +113,16 @@ class @Notes renderNote: (note) -> # render note if it not present in loaded list # or skip if rendered - if @isNewNote(note) + if @isNewNote(note) && !note.award @note_ids.push(note.id) $('ul.main-notes-list'). append(note.html). syntaxHighlight() @initTaskList() + if note.award + awards_handler.addAwardToEmojiBar(note.note, note.emoji_path) + ### Check if note does not exists on page ### @@ -255,7 +258,6 @@ class @Notes ### addNote: (xhr, note, status) => @renderNote(note) - @updateVotes() ### Called in response to the new note form being submitted @@ -473,9 +475,6 @@ class @Notes form = $(e.target).closest(".js-discussion-note-form") @removeDiscussionNoteForm(form) - updateVotes: -> - true - ### Called after an attachment file has been selected. diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss index abc27a19e3..3a08ee70bc 100644 --- a/app/assets/stylesheets/pages/issuable.scss +++ b/app/assets/stylesheets/pages/issuable.scss @@ -101,3 +101,71 @@ background-color: $background-color; } } + +.awards { + @include clearfix; + line-height: 34px; + margin: 2px 0; + + .award { + @include border-radius(5px); + + border: 1px solid; + padding: 0px 10px; + float: left; + margin: 0 5px; + border-color: $border-color; + cursor: pointer; + + &.active { + border-color: $border-gray-light; + background-color: $gray-light; + + .counter { + font-weight: bold; + } + } + + .icon { + float: left; + margin-right: 10px; + } + + .counter { + float: left; + } + } + + .awards-controls { + margin-left: 10px; + float: left; + + .add-award { + font-size: 24px; + color: $gl-gray; + position: relative; + top: 2px; + + &:hover, + &:link { + text-decoration: none; + } + } + + .awards-menu { + padding: $gl-padding; + min-width: 214px; + + > li { + margin: 5px; + } + } + } + + .awards-menu{ + li { + float: left; + margin: 3px; + } + } +} diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb index e74c2905e4..5250a0f5e6 100644 --- a/app/controllers/projects/issues_controller.rb +++ b/app/controllers/projects/issues_controller.rb @@ -60,7 +60,7 @@ class Projects::IssuesController < Projects::ApplicationController def show @participants = @issue.participants(current_user) @note = @project.notes.new(noteable: @issue) - @notes = @issue.notes.with_associations.fresh + @notes = @issue.notes.nonawards.with_associations.fresh @noteable = @issue respond_with(@issue) diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index 188f0cc4ce..6378a1f56b 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -254,7 +254,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController # Build a note object for comment form @note = @project.notes.new(noteable: @merge_request) - @notes = @merge_request.mr_and_commit_notes.inc_author.fresh + @notes = @merge_request.mr_and_commit_notes.nonawards.inc_author.fresh @discussions = Note.discussions_from_notes(@notes) @noteable = @merge_request diff --git a/app/controllers/projects/notes_controller.rb b/app/controllers/projects/notes_controller.rb index 41cd08c93c..263b8b8d94 100644 --- a/app/controllers/projects/notes_controller.rb +++ b/app/controllers/projects/notes_controller.rb @@ -3,7 +3,7 @@ class Projects::NotesController < Projects::ApplicationController before_action :authorize_read_note! before_action :authorize_create_note!, only: [:create] before_action :authorize_admin_note!, only: [:update, :destroy] - before_action :find_current_user_notes, except: [:destroy, :delete_attachment] + before_action :find_current_user_notes, except: [:destroy, :delete_attachment, :award_toggle] def index current_fetched_at = Time.now.to_i @@ -58,6 +58,27 @@ class Projects::NotesController < Projects::ApplicationController end end + def award_toggle + noteable = note_params[:noteable_type] == "issue" ? Issue : MergeRequest + noteable = noteable.find_by!(id: note_params[:noteable_id], project: project) + + data = { + author: current_user, + is_award: true, + note: note_params[:note] + } + + note = noteable.notes.find_by(data) + + if note + note.destroy + else + Notes::CreateService.new(project, current_user, note_params).execute + end + + render json: { ok: true } + end + private def note @@ -111,6 +132,9 @@ class Projects::NotesController < Projects::ApplicationController id: note.id, discussion_id: note.discussion_id, html: note_to_html(note), + award: note.is_award, + emoji_path: note.is_award ? ::AwardEmoji.path_to_emoji_image(note.note) : "", + note: note.note, discussion_html: note_to_discussion_html(note), discussion_with_diff_html: note_to_discussion_with_diff_html(note) } diff --git a/app/finders/notes_finder.rb b/app/finders/notes_finder.rb index ab252821b5..fa4c635f55 100644 --- a/app/finders/notes_finder.rb +++ b/app/finders/notes_finder.rb @@ -12,9 +12,9 @@ class NotesFinder when "commit" project.notes.for_commit_id(target_id).not_inline when "issue" - project.issues.find(target_id).notes.inc_author + project.issues.find(target_id).notes.nonawards.inc_author when "merge_request" - project.merge_requests.find(target_id).mr_and_commit_notes.inc_author + project.merge_requests.find(target_id).mr_and_commit_notes.nonawards.inc_author when "snippet", "project_snippet" project.snippets.find(target_id).notes else diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb index beb083d82d..2c791aa568 100644 --- a/app/helpers/issues_helper.rb +++ b/app/helpers/issues_helper.rb @@ -87,6 +87,31 @@ module IssuesHelper merge_requests.map(&:to_reference).to_sentence(last_word_connector: ', or ') end + def url_to_emoji(name) + emoji_path = ::AwardEmoji.path_to_emoji_image(name) + url_to_image(emoji_path) + end + + def emoji_author_list(notes, current_user) + list = notes.map do |note| + note.author == current_user ? "me" : note.author.username + end + + list.join(", ") + end + + def emoji_list + ::AwardEmoji::EMOJI_LIST + end + + def note_active_class(notes, current_user) + if current_user && notes.pluck(:author_id).include?(current_user.id) + "active" + else + "" + end + end + # Required for Gitlab::Markdown::IssueReferenceFilter module_function :url_for_issue end diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb index 492a026add..91da6797df 100644 --- a/app/models/concerns/issuable.rb +++ b/app/models/concerns/issuable.rb @@ -89,41 +89,6 @@ module Issuable opened? || reopened? end - # - # Votes - # - - # Return the number of -1 comments (downvotes) - def downvotes - filter_superceded_votes(notes.select(&:downvote?), notes).size - end - - def downvotes_in_percent - if votes_count.zero? - 0 - else - 100.0 - upvotes_in_percent - end - end - - # Return the number of +1 comments (upvotes) - def upvotes - filter_superceded_votes(notes.select(&:upvote?), notes).size - end - - def upvotes_in_percent - if votes_count.zero? - 0 - else - 100.0 / votes_count * upvotes - end - end - - # Return the total number of votes - def votes_count - upvotes + downvotes - end - def subscribed?(user) subscription = subscriptions.find_by_user_id(user.id) @@ -183,18 +148,4 @@ module Issuable def notes_with_associations notes.includes(:author, :project) end - - private - - def filter_superceded_votes(votes, notes) - filteredvotes = [] + votes - - votes.each do |vote| - if vote.superceded?(notes) - filteredvotes.delete(vote) - end - end - - filteredvotes - end end diff --git a/app/models/note.rb b/app/models/note.rb index 0b3aa30abd..e30be444eb 100644 --- a/app/models/note.rb +++ b/app/models/note.rb @@ -40,16 +40,20 @@ class Note < ActiveRecord::Base delegate :name, :email, to: :author, prefix: true validates :note, :project, presence: true + validates :note, uniqueness: { scope: [:author, :noteable_type, :noteable_id] }, if: ->(n) { n.is_award } validates :line_code, format: { with: /\A[a-z0-9]+_\d+_\d+\Z/ }, allow_blank: true # Attachments are deprecated and are handled by Markdown uploader validates :attachment, file_size: { maximum: :max_attachment_size } validates :noteable_id, presence: true, if: ->(n) { n.noteable_type.present? && n.noteable_type != 'Commit' } validates :commit_id, presence: true, if: ->(n) { n.noteable_type == 'Commit' } + validates :author, presence: true mount_uploader :attachment, AttachmentUploader # Scopes + scope :awards, ->{ where(is_award: true) } + scope :nonawards, ->{ where(is_award: false) } scope :for_commit_id, ->(commit_id) { where(noteable_type: "Commit", commit_id: commit_id) } scope :inline, ->{ where("line_code IS NOT NULL") } scope :not_inline, ->{ where(line_code: [nil, '']) } @@ -97,6 +101,12 @@ class Note < ActiveRecord::Base def search(query) where("LOWER(note) like :query", query: "%#{query.downcase}%") end + + def grouped_awards + awards.select(:note).distinct.map do |note| + [ note.note, where(note: note.note) ] + end + end end def cross_reference? @@ -288,44 +298,6 @@ class Note < ActiveRecord::Base nil end - DOWNVOTES = %w(-1 :-1: :thumbsdown: :thumbs_down_sign:) - - # Check if the note is a downvote - def downvote? - votable? && note.start_with?(*DOWNVOTES) - end - - UPVOTES = %w(+1 :+1: :thumbsup: :thumbs_up_sign:) - - # Check if the note is an upvote - def upvote? - votable? && note.start_with?(*UPVOTES) - end - - def superceded?(notes) - return false unless vote? - - notes.each do |note| - next if note == self - - if note.vote? && - self[:author_id] == note[:author_id] && - self[:created_at] <= note[:created_at] - return true - end - end - - false - end - - def vote? - upvote? || downvote? - end - - def votable? - for_issue? || (for_merge_request? && !for_diff_line?) - end - # Mentionable override. def gfm_reference(from_project = nil) noteable.gfm_reference(from_project) diff --git a/app/services/notes/create_service.rb b/app/services/notes/create_service.rb index 2001dc89c3..25a985df4d 100644 --- a/app/services/notes/create_service.rb +++ b/app/services/notes/create_service.rb @@ -5,11 +5,16 @@ module Notes note.author = current_user note.system = false + if contains_emoji_only?(params[:note]) + note.is_award = true + note.note = emoji_name(params[:note]) + end + if note.save notification_service.new_note(note) - # Skip system notes, like status changes and cross-references. - unless note.system + # Skip system notes, like status changes and cross-references and awards + unless note.system || note.is_award event_service.leave_note(note, note.author) note.create_cross_references! execute_hooks(note) @@ -28,5 +33,13 @@ module Notes note.project.execute_hooks(note_data, :note_hooks) note.project.execute_services(note_data, :note_hooks) end + + def contains_emoji_only?(note) + note =~ /\A:?[-_+[:alnum:]]*:?\s?\z/ + end + + def emoji_name(note) + note.match(/\A:?([-_+[:alnum:]]*):?\s?/)[1] + end end end diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index 6ed6ebca58..dc78f85105 100644 --- a/app/services/notification_service.rb +++ b/app/services/notification_service.rb @@ -102,6 +102,7 @@ class NotificationService # ignore gitlab service messages return true if note.note.start_with?('Status changed to closed') return true if note.cross_reference? && note.system == true + return true if note.is_award target = note.noteable diff --git a/app/views/projects/issues/_discussion.html.haml b/app/views/projects/issues/_discussion.html.haml index c5fd863ae9..020952dd00 100644 --- a/app/views/projects/issues/_discussion.html.haml +++ b/app/views/projects/issues/_discussion.html.haml @@ -7,7 +7,7 @@ = render 'shared/show_aside' -.gray-content-block.second-block +.gray-content-block.second-block.oneline-block .row .col-md-9 .votes-holder.pull-right diff --git a/app/views/projects/issues/_issue.html.haml b/app/views/projects/issues/_issue.html.haml index 55ce912829..d7657ee7e4 100644 --- a/app/views/projects/issues/_issue.html.haml +++ b/app/views/projects/issues/_issue.html.haml @@ -29,8 +29,6 @@ .issue-info = "#{issue.to_reference} opened #{time_ago_with_tooltip(issue.created_at, placement: 'bottom')} by #{link_to_member(@project, issue.author, avatar: false)}".html_safe - - if issue.votes_count > 0 - = render 'votes/votes_inline', votable: issue - if issue.milestone   %span diff --git a/app/views/projects/merge_requests/_merge_request.html.haml b/app/views/projects/merge_requests/_merge_request.html.haml index c5234c0618..83e8ad1198 100644 --- a/app/views/projects/merge_requests/_merge_request.html.haml +++ b/app/views/projects/merge_requests/_merge_request.html.haml @@ -34,8 +34,6 @@ .merge-request-info = "##{merge_request.iid} opened #{time_ago_with_tooltip(merge_request.created_at, placement: 'bottom')} by #{link_to_member(@project, merge_request.author, avatar: false)}".html_safe - - if merge_request.votes_count > 0 - = render 'votes/votes_inline', votable: merge_request - if merge_request.milestone_id?   %span diff --git a/app/views/projects/notes/_note.html.haml b/app/views/projects/notes/_note.html.haml index efa7dd01cc..dd0abc8c74 100644 --- a/app/views/projects/notes/_note.html.haml +++ b/app/views/projects/notes/_note.html.haml @@ -35,26 +35,6 @@ - if note.updated_by && note.updated_by != note.author by #{link_to_member(note.project, note.updated_by, avatar: false, author_class: nil)} - - if note.superceded?(@notes) - - if note.upvote? - %span.vote.upvote.label.label-gray.strikethrough - = icon('thumbs-up') - \+1 - - if note.downvote? - %span.vote.downvote.label.label-gray.strikethrough - = icon('thumbs-down') - \-1 - - else - - if note.upvote? - %span.vote.upvote.label.label-success - = icon('thumbs-up') - \+1 - - if note.downvote? - %span.vote.downvote.label.label-danger - = icon('thumbs-down') - \-1 - - .note-body{class: note_editable?(note) ? 'js-task-list-container' : ''} .note-text = preserve do diff --git a/app/views/votes/_votes_block.html.haml b/app/views/votes/_votes_block.html.haml index 36ea674206..7eb27c12d3 100644 --- a/app/views/votes/_votes_block.html.haml +++ b/app/views/votes/_votes_block.html.haml @@ -1,10 +1,32 @@ -.votes.votes-block - .btn-group - - unless votable.upvotes.zero? - .btn.btn-sm.disabled.cgreen - %i.fa.fa-thumbs-up - = votable.upvotes - - unless votable.downvotes.zero? - .btn.btn-sm.disabled.cred - %i.fa.fa-thumbs-down - = votable.downvotes +.awards.votes-block + - votable.notes.awards.grouped_awards.each do |emoji, notes| + .award{class: (note_active_class(notes, current_user)), title: emoji_author_list(notes, current_user)} + .icon{"data-emoji" => "#{emoji}"} + = image_tag url_to_emoji(emoji), height: "20px", width: "20px" + .counter + = notes.count + + - if current_user + .dropdown.awards-controls + %a.add-award{"data-toggle" => "dropdown", "data-target" => "#", "href" => "#"} + = icon('smile-o') + %ul.dropdown-menu.awards-menu + - emoji_list.each do |emoji| + %li{"data-emoji" => "#{emoji}"}= image_tag url_to_emoji(emoji), height: "20px", width: "20px" + +- if current_user + :coffeescript + post_emoji_url = "#{award_toggle_namespace_project_notes_path(@project.namespace, @project)}" + noteable_type = "#{votable.class.name.underscore}" + noteable_id = "#{votable.id}" + window.awards_handler = new AwardsHandler(post_emoji_url, noteable_type, noteable_id) + + $(".awards-menu li").click (e)-> + emoji = $(this).data("emoji") + awards_handler.addAward(emoji) + + $(".awards").on "click", ".award", (e)-> + emoji = $(this).find(".icon").data("emoji") + awards_handler.addAward(emoji) + + $(".award").tooltip() diff --git a/app/views/votes/_votes_inline.html.haml b/app/views/votes/_votes_inline.html.haml deleted file mode 100644 index 2cb3ae04e1..0000000000 --- a/app/views/votes/_votes_inline.html.haml +++ /dev/null @@ -1,9 +0,0 @@ -.votes.votes-inline - - unless votable.upvotes.zero? - %span.upvotes.cgreen - + #{votable.upvotes} - - unless votable.downvotes.zero? - \/ - - unless votable.downvotes.zero? - %span.downvotes.cred - \- #{votable.downvotes} diff --git a/config/routes.rb b/config/routes.rb index 0bc2c17345..ac81a2aac7 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -664,6 +664,10 @@ Gitlab::Application.routes.draw do member do delete :delete_attachment end + + collection do + post :award_toggle + end end resources :uploads, only: [:create] do diff --git a/db/migrate/20151106000015_add_is_award_to_notes.rb b/db/migrate/20151106000015_add_is_award_to_notes.rb new file mode 100644 index 0000000000..02b271637e --- /dev/null +++ b/db/migrate/20151106000015_add_is_award_to_notes.rb @@ -0,0 +1,6 @@ +class AddIsAwardToNotes < ActiveRecord::Migration + def change + add_column :notes, :is_award, :boolean, default: false, null: false + add_index :notes, :is_award + end +end diff --git a/db/schema.rb b/db/schema.rb index 440a33e200..f77f6dfc66 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -554,12 +554,14 @@ ActiveRecord::Schema.define(version: 20151116144118) do t.boolean "system", default: false, null: false t.text "st_diff" t.integer "updated_by_id" + t.boolean "is_award", default: false, null: false end add_index "notes", ["author_id"], name: "index_notes_on_author_id", using: :btree add_index "notes", ["commit_id"], name: "index_notes_on_commit_id", using: :btree add_index "notes", ["created_at", "id"], name: "index_notes_on_created_at_and_id", using: :btree add_index "notes", ["created_at"], name: "index_notes_on_created_at", using: :btree + add_index "notes", ["is_award"], name: "index_notes_on_is_award", using: :btree add_index "notes", ["line_code"], name: "index_notes_on_line_code", using: :btree add_index "notes", ["noteable_id", "noteable_type"], name: "index_notes_on_noteable_id_and_noteable_type", using: :btree add_index "notes", ["noteable_type"], name: "index_notes_on_noteable_type", using: :btree diff --git a/doc/api/merge_requests.md b/doc/api/merge_requests.md index ffa7f2cdf1..2f17d4ae06 100644 --- a/doc/api/merge_requests.md +++ b/doc/api/merge_requests.md @@ -31,8 +31,6 @@ Parameters: "project_id": 3, "title": "test1", "state": "opened", - "upvotes": 0, - "downvotes": 0, "author": { "id": 1, "username": "admin", @@ -77,8 +75,6 @@ Parameters: "project_id": 3, "title": "test1", "state": "merged", - "upvotes": 0, - "downvotes": 0, "author": { "id": 1, "username": "admin", @@ -126,8 +122,6 @@ Parameters: "updated_at": "2015-02-02T20:08:49.959Z", "target_branch": "secret_token", "source_branch": "version-1-9", - "upvotes": 0, - "downvotes": 0, "author": { "name": "Chad Hamill", "username": "jarrett", @@ -198,8 +192,6 @@ Parameters: "project_id": 3, "title": "test1", "state": "opened", - "upvotes": 0, - "downvotes": 0, "author": { "id": 1, "username": "admin", @@ -250,8 +242,6 @@ Parameters: "title": "test1", "description": "description1", "state": "opened", - "upvotes": 0, - "downvotes": 0, "author": { "id": 1, "username": "admin", @@ -304,8 +294,6 @@ Parameters: "project_id": 3, "title": "test1", "state": "merged", - "upvotes": 0, - "downvotes": 0, "author": { "id": 1, "username": "admin", diff --git a/doc/api/notes.md b/doc/api/notes.md index c683cb883d..bcba1f6215 100644 --- a/doc/api/notes.md +++ b/doc/api/notes.md @@ -32,9 +32,7 @@ Parameters: "created_at": "2013-09-30T13:46:01Z" }, "created_at": "2013-10-02T09:22:45Z", - "system": true, - "upvote": false, - "downvote": false + "system": true }, { "id": 305, @@ -49,9 +47,7 @@ Parameters: "created_at": "2013-09-30T13:46:01Z" }, "created_at": "2013-10-02T09:56:03Z", - "system": false, - "upvote": false, - "downvote": false + "system": false } ] ``` diff --git a/features/project/issues/award_emoji.feature b/features/project/issues/award_emoji.feature new file mode 100644 index 0000000000..a9bc8ffb9b --- /dev/null +++ b/features/project/issues/award_emoji.feature @@ -0,0 +1,14 @@ +Feature: Award Emoji + Background: + Given I sign in as a user + And I own project "Shop" + And project "Shop" has issue "Bugfix" + And I visit "Bugfix" issue page + + @javascript + Scenario: I add and remove award in the issue + Given I click to emoji-picker + And I click to emoji in the picker + Then I have award added + And I can remove it by clicking to icon + \ No newline at end of file diff --git a/features/steps/project/issues/award_emoji.rb b/features/steps/project/issues/award_emoji.rb new file mode 100644 index 0000000000..8f7a45dec0 --- /dev/null +++ b/features/steps/project/issues/award_emoji.rb @@ -0,0 +1,41 @@ +class Spinach::Features::AwardEmoji < Spinach::FeatureSteps + include SharedAuthentication + include SharedProject + include SharedPaths + include Select2Helper + + step 'I visit "Bugfix" issue page' do + visit namespace_project_issue_path(@project.namespace, @project, @issue) + end + + step 'I click to emoji-picker' do + page.within ".awards-controls" do + page.find(".add-award").click + end + end + + step 'I click to emoji in the picker' do + page.within ".awards-menu" do + page.first("img").click + end + end + + step 'I can remove it by clicking to icon' do + page.within ".awards" do + page.first(".award").click + expect(page).to_not have_selector ".award" + end + end + + step 'I have award added' do + page.within ".awards" do + expect(page).to have_selector ".award" + expect(page.find(".award .counter")).to have_content "1" + end + end + + step 'project "Shop" has issue "Bugfix"' do + @project = Project.find_by(name: "Shop") + @issue = create(:issue, title: "Bugfix", project: project) + end +end diff --git a/lib/api/entities.rb b/lib/api/entities.rb index d6aec03d7f..3da6bc415d 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -162,7 +162,7 @@ module API end class MergeRequest < ProjectEntity - expose :target_branch, :source_branch, :upvotes, :downvotes + expose :target_branch, :source_branch expose :author, :assignee, using: Entities::UserBasic expose :source_project_id, :target_project_id expose :label_names, as: :labels @@ -192,8 +192,6 @@ module API expose :author, using: Entities::UserBasic expose :created_at expose :system?, as: :system - expose :upvote?, as: :upvote - expose :downvote?, as: :downvote end class MRNote < Grape::Entity diff --git a/lib/award_emoji.rb b/lib/award_emoji.rb new file mode 100644 index 0000000000..d58a196c4e --- /dev/null +++ b/lib/award_emoji.rb @@ -0,0 +1,12 @@ +class AwardEmoji + EMOJI_LIST = [ + "+1", "-1", "100", "blush", "heart", "smile", "rage", + "beers", "disappointed", "ok_hand", + "helicopter", "shit", "airplane", "alarm_clock", + "ambulance", "anguished", "two_hearts", "wink" + ] + + def self.path_to_emoji_image(name) + "emoji/#{Emoji.emoji_filename(name)}.png" + end +end diff --git a/spec/helpers/issues_helper_spec.rb b/spec/helpers/issues_helper_spec.rb index 78a6b631eb..1f2c4ee77b 100644 --- a/spec/helpers/issues_helper_spec.rb +++ b/spec/helpers/issues_helper_spec.rb @@ -127,4 +127,30 @@ describe IssuesHelper do it { is_expected.to eq("!1, !2, or !3") } end + describe "#url_to_emoji" do + it "returns url" do + expect(url_to_emoji("smile")).to include("emoji/1F604.png") + end + end + + describe "#emoji_list" do + it "returns url" do + expect(emoji_list).to be_kind_of(Array) + end + end + + describe "#note_active_class" do + before do + @note = create :note + @note1 = create :note + end + + it "returns empty string for unauthenticated user" do + expect(note_active_class(Note.all, nil)).to eq("") + end + + it "returns active string for author" do + expect(note_active_class(Note.all, @note.author)).to eq("active") + end + end end diff --git a/spec/lib/votes_spec.rb b/spec/lib/votes_spec.rb deleted file mode 100644 index 39e5d054e6..0000000000 --- a/spec/lib/votes_spec.rb +++ /dev/null @@ -1,188 +0,0 @@ -require 'spec_helper' - -describe Issue, 'Votes' do - let(:issue) { create(:issue) } - - describe "#upvotes" do - it "with no notes has a 0/0 score" do - expect(issue.upvotes).to eq(0) - end - - it "should recognize non-+1 notes" do - add_note "No +1 here" - expect(issue.notes.size).to eq(1) - expect(issue.notes.first.upvote?).to be_falsey - expect(issue.upvotes).to eq(0) - end - - it "should recognize a single +1 note" do - add_note "+1 This is awesome" - expect(issue.upvotes).to eq(1) - end - - it 'should recognize multiple +1 notes' do - add_note '+1 This is awesome', create(:user) - add_note '+1 I want this', create(:user) - expect(issue.upvotes).to eq(2) - end - - it 'should not count 2 +1 votes from the same user' do - add_note '+1 This is awesome' - add_note '+1 I want this' - expect(issue.upvotes).to eq(1) - end - end - - describe "#downvotes" do - it "with no notes has a 0/0 score" do - expect(issue.downvotes).to eq(0) - end - - it "should recognize non--1 notes" do - add_note "Almost got a -1" - expect(issue.notes.size).to eq(1) - expect(issue.notes.first.downvote?).to be_falsey - expect(issue.downvotes).to eq(0) - end - - it "should recognize a single -1 note" do - add_note "-1 This is bad" - expect(issue.downvotes).to eq(1) - end - - it "should recognize multiple -1 notes" do - add_note('-1 This is bad', create(:user)) - add_note('-1 Away with this', create(:user)) - expect(issue.downvotes).to eq(2) - end - end - - describe "#votes_count" do - it "with no notes has a 0/0 score" do - expect(issue.votes_count).to eq(0) - end - - it "should recognize non notes" do - add_note "No +1 here" - expect(issue.notes.size).to eq(1) - expect(issue.votes_count).to eq(0) - end - - it "should recognize a single +1 note" do - add_note "+1 This is awesome" - expect(issue.votes_count).to eq(1) - end - - it "should recognize a single -1 note" do - add_note "-1 This is bad" - expect(issue.votes_count).to eq(1) - end - - it "should recognize multiple notes" do - add_note('+1 This is awesome', create(:user)) - add_note('-1 This is bad', create(:user)) - add_note('+1 I want this', create(:user)) - expect(issue.votes_count).to eq(3) - end - - it 'should not count 2 -1 votes from the same user' do - add_note '-1 This is suspicious' - add_note '-1 This is bad' - expect(issue.votes_count).to eq(1) - end - end - - describe "#upvotes_in_percent" do - it "with no notes has a 0% score" do - expect(issue.upvotes_in_percent).to eq(0) - end - - it "should count a single 1 note as 100%" do - add_note "+1 This is awesome" - expect(issue.upvotes_in_percent).to eq(100) - end - - it 'should count multiple +1 notes as 100%' do - add_note('+1 This is awesome', create(:user)) - add_note('+1 I want this', create(:user)) - expect(issue.upvotes_in_percent).to eq(100) - end - - it 'should count fractions for multiple +1 and -1 notes correctly' do - add_note('+1 This is awesome', create(:user)) - add_note('+1 I want this', create(:user)) - add_note('-1 This is bad', create(:user)) - add_note('+1 me too', create(:user)) - expect(issue.upvotes_in_percent).to eq(75) - end - end - - describe "#downvotes_in_percent" do - it "with no notes has a 0% score" do - expect(issue.downvotes_in_percent).to eq(0) - end - - it "should count a single -1 note as 100%" do - add_note "-1 This is bad" - expect(issue.downvotes_in_percent).to eq(100) - end - - it 'should count multiple -1 notes as 100%' do - add_note('-1 This is bad', create(:user)) - add_note('-1 Away with this', create(:user)) - expect(issue.downvotes_in_percent).to eq(100) - end - - it 'should count fractions for multiple +1 and -1 notes correctly' do - add_note('+1 This is awesome', create(:user)) - add_note('+1 I want this', create(:user)) - add_note('-1 This is bad', create(:user)) - add_note('+1 me too', create(:user)) - expect(issue.downvotes_in_percent).to eq(25) - end - end - - describe '#filter_superceded_votes' do - - it 'should count a users vote only once amongst multiple votes' do - add_note('-1 This needs work before I will accept it') - add_note('+1 I want this', create(:user)) - add_note('+1 This is is awesome', create(:user)) - add_note('+1 this looks good now') - add_note('+1 This is awesome', create(:user)) - add_note('+1 me too', create(:user)) - expect(issue.downvotes).to eq(0) - expect(issue.upvotes).to eq(5) - end - - it 'should count each users vote only once' do - add_note '-1 This needs work before it will be accepted' - add_note '+1 I like this' - add_note '+1 I still like this' - add_note '+1 I really like this' - add_note '+1 Give me this now!!!!' - expect(issue.downvotes).to eq(0) - expect(issue.upvotes).to eq(1) - end - - it 'should count a users vote only once without caring about comments' do - add_note '-1 This needs work before it will be accepted' - add_note 'Comment 1' - add_note 'Another comment' - add_note '+1 vote' - add_note 'final comment' - expect(issue.downvotes).to eq(0) - expect(issue.upvotes).to eq(1) - end - - end - - def add_note(text, author = issue.author) - created_at = Time.now - 1.hour + Note.count.seconds - issue.notes << create(:note, - note: text, - project: issue.project, - author_id: author.id, - created_at: created_at) - end -end diff --git a/spec/models/note_spec.rb b/spec/models/note_spec.rb index 75564839dc..f347f53755 100644 --- a/spec/models/note_spec.rb +++ b/spec/models/note_spec.rb @@ -32,77 +32,6 @@ describe Note do it { is_expected.to validate_presence_of(:project) } end - describe '#votable?' do - it 'is true for issue notes' do - note = build(:note_on_issue) - expect(note).to be_votable - end - - it 'is true for merge request notes' do - note = build(:note_on_merge_request) - expect(note).to be_votable - end - - it 'is false for merge request diff notes' do - note = build(:note_on_merge_request_diff) - expect(note).not_to be_votable - end - - it 'is false for commit notes' do - note = build(:note_on_commit) - expect(note).not_to be_votable - end - - it 'is false for commit diff notes' do - note = build(:note_on_commit_diff) - expect(note).not_to be_votable - end - end - - describe 'voting score' do - it 'recognizes a neutral note' do - note = build(:votable_note, note: 'This is not a +1 note') - expect(note).not_to be_upvote - expect(note).not_to be_downvote - end - - it 'recognizes a neutral emoji note' do - note = build(:votable_note, note: "I would :+1: this, but I don't want to") - expect(note).not_to be_upvote - expect(note).not_to be_downvote - end - - it 'recognizes a +1 note' do - note = build(:votable_note, note: '+1 for this') - expect(note).to be_upvote - end - - it 'recognizes a +1 emoji as a vote' do - note = build(:votable_note, note: ':+1: for this') - expect(note).to be_upvote - end - - it 'recognizes a thumbsup emoji as a vote' do - note = build(:votable_note, note: ':thumbsup: for this') - expect(note).to be_upvote - end - - it 'recognizes a -1 note' do - note = build(:votable_note, note: '-1 for this') - expect(note).to be_downvote - end - - it 'recognizes a -1 emoji as a vote' do - note = build(:votable_note, note: ':-1: for this') - expect(note).to be_downvote - end - - it 'recognizes a thumbsdown emoji as a vote' do - note = build(:votable_note, note: ':thumbsdown: for this') - expect(note).to be_downvote - end - end - describe "Commit notes" do let!(:note) { create(:note_on_commit, note: "+1 from me") } let!(:commit) { note.noteable } @@ -139,10 +68,6 @@ describe Note do it "should be recognized by #for_commit_diff_line?" do expect(note).to be_for_commit_diff_line end - - it "should not be votable" do - expect(note).not_to be_votable - end end describe 'authorization' do @@ -204,4 +129,16 @@ describe Note do it { expect(Note.search('wow')).to include(note) } end + + describe :grouped_awards do + before do + create :note, note: "smile", is_award: true + create :note, note: "smile", is_award: true + end + + it "returns grouped array of notes" do + expect(Note.grouped_awards.first.first).to eq("smile") + expect(Note.grouped_awards.first.last).to match_array(Note.all) + end + end end diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 8d7e6e7676..3c53722010 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -345,17 +345,6 @@ describe Project do expect(project1.star_count).to eq(0) expect(project2.star_count).to eq(0) end - - it 'is decremented when an upvoter account is deleted' do - user = create :user - project = create :project, :public - user.toggle_star(project) - project.reload - expect(project.star_count).to eq(1) - user.destroy - project.reload - expect(project.star_count).to eq(0) - end end describe :avatar_type do diff --git a/spec/services/notes/create_service_spec.rb b/spec/services/notes/create_service_spec.rb index f2ea0805b2..cc38d25779 100644 --- a/spec/services/notes/create_service_spec.rb +++ b/spec/services/notes/create_service_spec.rb @@ -24,4 +24,38 @@ describe Notes::CreateService do it { expect(@note.note).to eq('Awesome comment') } end end + + describe "award emoji" do + before do + project.team << [user, :master] + end + + it "creates emoji note" do + opts = { + note: ':smile: ', + noteable_type: 'Issue', + noteable_id: issue.id + } + + @note = Notes::CreateService.new(project, user, opts).execute + + expect(@note).to be_valid + expect(@note.note).to eq('smile') + expect(@note.is_award).to be_truthy + end + + it "creates regular note if emoji name is invalid" do + opts = { + note: ':smile: moretext: ', + noteable_type: 'Issue', + noteable_id: issue.id + } + + @note = Notes::CreateService.new(project, user, opts).execute + + expect(@note).to be_valid + expect(@note.note).to eq(opts[:note]) + expect(@note.is_award).to be_falsy + end + end end From 094bb6f8ef5cde03a5b741975a877c070259b481 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Fri, 20 Nov 2015 01:08:07 +0000 Subject: [PATCH 50/80] Merge branch 'rs-mr-reference-copy' into 'master' Add clipboard button to merge request cross-project reference See merge request !1847 --- app/views/projects/merge_requests/_discussion.html.haml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/views/projects/merge_requests/_discussion.html.haml b/app/views/projects/merge_requests/_discussion.html.haml index 7e60782ff5..cb75bd8c5b 100644 --- a/app/views/projects/merge_requests/_discussion.html.haml +++ b/app/views/projects/merge_requests/_discussion.html.haml @@ -14,8 +14,10 @@ #votes= render 'votes/votes_block', votable: @merge_request = render "projects/merge_requests/show/participants" .col-md-3 - %span.slead.has_tooltip{:"data-original-title" => 'Cross-project reference'} - = cross_project_reference(@project, @merge_request) + .input-group.cross-project-reference + %span.slead.has_tooltip{title: 'Cross-project reference'} + = cross_project_reference(@project, @merge_request) + = clipboard_button .row %section.col-md-9 From c279bd812e7e24099640862fa986e4d1954817d5 Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Fri, 20 Nov 2015 11:13:43 +0200 Subject: [PATCH 51/80] Fix for Emoji --- app/assets/javascripts/awards_handler.coffee | 2 +- app/controllers/projects/notes_controller.rb | 2 +- app/helpers/issues_helper.rb | 2 ++ app/services/notes/create_service.rb | 4 ++-- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/app/assets/javascripts/awards_handler.coffee b/app/assets/javascripts/awards_handler.coffee index ae42e390c4..635c9b4f8d 100644 --- a/app/assets/javascripts/awards_handler.coffee +++ b/app/assets/javascripts/awards_handler.coffee @@ -80,7 +80,7 @@ class @AwardsHandler postEmoji: (emoji, callback) -> $.post @post_emoji_url, { note: { - note: emoji + note: ":" + emoji + ":" noteable_type: @noteable_type noteable_id: @noteable_id }},(data) -> diff --git a/app/controllers/projects/notes_controller.rb b/app/controllers/projects/notes_controller.rb index 263b8b8d94..1e3f1d8fd2 100644 --- a/app/controllers/projects/notes_controller.rb +++ b/app/controllers/projects/notes_controller.rb @@ -65,7 +65,7 @@ class Projects::NotesController < Projects::ApplicationController data = { author: current_user, is_award: true, - note: note_params[:note] + note: note_params[:note].gsub(":", '') } note = noteable.notes.find_by(data) diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb index 2c791aa568..493f370d9a 100644 --- a/app/helpers/issues_helper.rb +++ b/app/helpers/issues_helper.rb @@ -90,6 +90,8 @@ module IssuesHelper def url_to_emoji(name) emoji_path = ::AwardEmoji.path_to_emoji_image(name) url_to_image(emoji_path) + rescue StandardError + "" end def emoji_author_list(notes, current_user) diff --git a/app/services/notes/create_service.rb b/app/services/notes/create_service.rb index 25a985df4d..dbff58dfb9 100644 --- a/app/services/notes/create_service.rb +++ b/app/services/notes/create_service.rb @@ -35,11 +35,11 @@ module Notes end def contains_emoji_only?(note) - note =~ /\A:?[-_+[:alnum:]]*:?\s?\z/ + note =~ /\A:[-_+[:alnum:]]*:\s?\z/ end def emoji_name(note) - note.match(/\A:?([-_+[:alnum:]]*):?\s?/)[1] + note.match(/\A:([-_+[:alnum:]]*):\s?/)[1] end end end From 1cdee35f604c29af286dbdcb8a26c070c665b1f6 Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Thu, 19 Nov 2015 10:05:53 +0000 Subject: [PATCH 52/80] Merge branch 'atom-feed-latest-update' into 'master' Improve performance of user profiles, finding groups, and finding projects This MR improves the following: * Rendering of profile pages and Atom feeds * Finding groups (using GroupsFinder & friends) * Finding projects (using ProjectsFinder & friends) Initially this MR was intended to only improve rendering of Atom feeds, but over time other fixes were introduced as well as the same code was the cause of all these problems. See merge request !1790 --- CHANGELOG | 2 + app/controllers/users_controller.rb | 29 ++--- app/finders/contributed_projects_finder.rb | 37 ++++++ app/finders/groups_finder.rb | 67 +++++----- app/finders/joined_groups_finder.rb | 49 +++++++ app/finders/personal_projects_finder.rb | 41 ++++++ app/finders/projects_finder.rb | 121 ++++++++---------- app/models/concerns/sortable.rb | 3 +- app/models/event.rb | 10 ++ app/models/group.rb | 8 ++ app/models/project.rb | 4 + app/models/user.rb | 81 +++++++----- .../dashboard/projects/index.atom.builder | 2 +- app/views/groups/show.atom.builder | 2 +- app/views/projects/show.atom.builder | 2 +- app/views/users/show.atom.builder | 2 +- ...0151118162244_add_projects_public_index.rb | 5 + db/schema.rb | 3 +- lib/gitlab/sql/union.rb | 34 +++++ spec/controllers/users_controller_spec.rb | 23 +++- .../contributed_projects_finder_spec.rb | 35 +++++ spec/finders/group_finder_spec.rb | 15 --- spec/finders/groups_finder_spec.rb | 48 +++++++ spec/finders/joined_groups_finder_spec.rb | 49 +++++++ spec/finders/personal_projects_finder_spec.rb | 34 +++++ spec/finders/projects_finder_spec.rb | 75 ++++++----- spec/lib/gitlab/sql/union_spec.rb | 16 +++ spec/models/event_spec.rb | 38 ++++++ spec/models/group_spec.rb | 27 ++++ spec/models/project_spec.rb | 19 +++ spec/models/user_spec.rb | 34 ++++- 31 files changed, 700 insertions(+), 215 deletions(-) create mode 100644 app/finders/contributed_projects_finder.rb create mode 100644 app/finders/joined_groups_finder.rb create mode 100644 app/finders/personal_projects_finder.rb create mode 100644 db/migrate/20151118162244_add_projects_public_index.rb create mode 100644 lib/gitlab/sql/union.rb create mode 100644 spec/finders/contributed_projects_finder_spec.rb delete mode 100644 spec/finders/group_finder_spec.rb create mode 100644 spec/finders/groups_finder_spec.rb create mode 100644 spec/finders/joined_groups_finder_spec.rb create mode 100644 spec/finders/personal_projects_finder_spec.rb create mode 100644 spec/lib/gitlab/sql/union_spec.rb diff --git a/CHANGELOG b/CHANGELOG index cc165e494a..0a9ef0a943 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -3,6 +3,8 @@ Please view this file on the master branch, on stable branches it's out of date. v 8.3.0 (unreleased) v 8.2.0 + - Improved performance of finding projects and groups in various places + - Improved performance of rendering user profile pages and Atom feeds - Fix grouping of contributors by email in graph. - Remove CSS property preventing hard tabs from rendering in Chromium 45 (Stan Hu) - Fix Drone CI service template not saving properly (Stan Hu) diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 1484356a7f..30cb869eb2 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -3,14 +3,11 @@ class UsersController < ApplicationController before_action :set_user def show - @contributed_projects = contributed_projects.joined(@user). - reject(&:forked?) + @contributed_projects = contributed_projects.joined(@user).reject(&:forked?) - @projects = @user.personal_projects. - where(id: authorized_projects_ids).includes(:namespace) + @projects = PersonalProjectsFinder.new(@user).execute(current_user) - # Collect only groups common for both users - @groups = @user.groups & GroupsFinder.new.execute(current_user) + @groups = JoinedGroupsFinder.new(@user).execute(current_user) respond_to do |format| format.html @@ -53,16 +50,8 @@ class UsersController < ApplicationController @user = User.find_by_username!(params[:username]) end - def authorized_projects_ids - # Projects user can view - @authorized_projects_ids ||= - ProjectsFinder.new.execute(current_user).pluck(:id) - end - def contributed_projects - @contributed_projects = Project. - where(id: authorized_projects_ids & @user.contributed_projects_ids). - includes(:namespace) + ContributedProjectsFinder.new(@user).execute(current_user) end def contributions_calendar @@ -73,9 +62,13 @@ class UsersController < ApplicationController def load_events # Get user activity feed for projects common for both users @events = @user.recent_events. - where(project_id: authorized_projects_ids). - with_associations + merge(projects_for_current_user). + references(:project). + with_associations. + limit_recent(20, params[:offset]) + end - @events = @events.limit(20).offset(params[:offset] || 0) + def projects_for_current_user + ProjectsFinder.new.execute(current_user) end end diff --git a/app/finders/contributed_projects_finder.rb b/app/finders/contributed_projects_finder.rb new file mode 100644 index 0000000000..0209649b01 --- /dev/null +++ b/app/finders/contributed_projects_finder.rb @@ -0,0 +1,37 @@ +class ContributedProjectsFinder + def initialize(user) + @user = user + end + + # Finds the projects "@user" contributed to, limited to either public projects + # or projects visible to the given user. + # + # current_user - When given the list of the projects is limited to those only + # visible by this user. + # + # Returns an ActiveRecord::Relation. + def execute(current_user = nil) + if current_user + relation = projects_visible_to_user(current_user) + else + relation = public_projects + end + + relation.includes(:namespace).order_id_desc + end + + private + + def projects_visible_to_user(current_user) + authorized = @user.contributed_projects.visible_to_user(current_user) + + union = Gitlab::SQL::Union. + new([authorized.select(:id), public_projects.select(:id)]) + + Project.where("projects.id IN (#{union.to_sql})") + end + + def public_projects + @user.contributed_projects.public_only + end +end diff --git a/app/finders/groups_finder.rb b/app/finders/groups_finder.rb index b5f3176461..91cb0f228f 100644 --- a/app/finders/groups_finder.rb +++ b/app/finders/groups_finder.rb @@ -1,39 +1,44 @@ class GroupsFinder - def execute(current_user, options = {}) - all_groups(current_user) + # Finds the groups available to the given user. + # + # current_user - The user to find the groups for. + # + # Returns an ActiveRecord::Relation. + def execute(current_user = nil) + if current_user + relation = groups_visible_to_user(current_user) + else + relation = public_groups + end + + relation.order_id_desc end private - def all_groups(current_user) - group_ids = if current_user - if current_user.authorized_groups.any? - # User has access to groups - # - # Return only: - # groups with public projects - # groups with internal projects - # groups with joined projects - # - Project.public_and_internal_only.pluck(:namespace_id) + - current_user.authorized_groups.pluck(:id) - else - # User has no group membership - # - # Return only: - # groups with public projects - # groups with internal projects - # - Project.public_and_internal_only.pluck(:namespace_id) - end - else - # Not authenticated - # - # Return only: - # groups with public projects - Project.public_only.pluck(:namespace_id) - end + # This method returns the groups "current_user" can see. + def groups_visible_to_user(current_user) + base = groups_for_projects(public_and_internal_projects) - Group.where("public IS TRUE OR id IN(?)", group_ids) + union = Gitlab::SQL::Union. + new([base.select(:id), current_user.authorized_groups.select(:id)]) + + Group.where("namespaces.id IN (#{union.to_sql})") + end + + def public_groups + groups_for_projects(public_projects) + end + + def groups_for_projects(projects) + Group.public_and_given_groups(projects.select(:namespace_id)) + end + + def public_projects + Project.unscoped.public_only + end + + def public_and_internal_projects + Project.unscoped.public_and_internal_only end end diff --git a/app/finders/joined_groups_finder.rb b/app/finders/joined_groups_finder.rb new file mode 100644 index 0000000000..e7523136fe --- /dev/null +++ b/app/finders/joined_groups_finder.rb @@ -0,0 +1,49 @@ +# Class for finding the groups a user is a member of. +class JoinedGroupsFinder + def initialize(user = nil) + @user = user + end + + # Finds the groups of the source user, optionally limited to those visible to + # the current user. + # + # current_user - If given the groups of "@user" will only include the groups + # "current_user" can also see. + # + # Returns an ActiveRecord::Relation. + def execute(current_user = nil) + if current_user + relation = groups_visible_to_user(current_user) + else + relation = public_groups + end + + relation.order_id_desc + end + + private + + # Returns the groups the user in "current_user" can see. + # + # This list includes all public/internal projects as well as the projects of + # "@user" that "current_user" also has access to. + def groups_visible_to_user(current_user) + base = @user.authorized_groups.visible_to_user(current_user) + extra = public_and_internal_groups + union = Gitlab::SQL::Union.new([base.select(:id), extra.select(:id)]) + + Group.where("namespaces.id IN (#{union.to_sql})") + end + + def public_groups + groups_for_projects(@user.authorized_projects.public_only) + end + + def public_and_internal_groups + groups_for_projects(@user.authorized_projects.public_and_internal_only) + end + + def groups_for_projects(projects) + @user.groups.public_and_given_groups(projects.select(:namespace_id)) + end +end diff --git a/app/finders/personal_projects_finder.rb b/app/finders/personal_projects_finder.rb new file mode 100644 index 0000000000..a61ffa2299 --- /dev/null +++ b/app/finders/personal_projects_finder.rb @@ -0,0 +1,41 @@ +class PersonalProjectsFinder + def initialize(user) + @user = user + end + + # Finds the projects belonging to the user in "@user", limited to either + # public projects or projects visible to the given user. + # + # current_user - When given the list of projects is limited to those only + # visible by this user. + # + # Returns an ActiveRecord::Relation. + def execute(current_user = nil) + if current_user + relation = projects_visible_to_user(current_user) + else + relation = public_projects + end + + relation.includes(:namespace).order_id_desc + end + + private + + def projects_visible_to_user(current_user) + authorized = @user.personal_projects.visible_to_user(current_user) + + union = Gitlab::SQL::Union. + new([authorized.select(:id), public_and_internal_projects.select(:id)]) + + Project.where("projects.id IN (#{union.to_sql})") + end + + def public_projects + @user.personal_projects.public_only + end + + def public_and_internal_projects + @user.personal_projects.public_and_internal_only + end +end diff --git a/app/finders/projects_finder.rb b/app/finders/projects_finder.rb index c81bb51583..dd35c215c5 100644 --- a/app/finders/projects_finder.rb +++ b/app/finders/projects_finder.rb @@ -1,11 +1,39 @@ class ProjectsFinder - def execute(current_user, options = {}) + # Returns all projects, optionally including group projects a user has access + # to. + # + # ## Examples + # + # Retrieving all public projects: + # + # ProjectsFinder.new.execute + # + # Retrieving all public/internal projects and those the given user has access + # to: + # + # ProjectsFinder.new.execute(some_user) + # + # Retrieving all public/internal projects as well as the group's projects the + # user has access to: + # + # ProjectsFinder.new.execute(some_user, group: some_group) + # + # Returns an ActiveRecord::Relation. + def execute(current_user = nil, options = {}) group = options[:group] if group - group_projects(current_user, group) + base, extra = group_projects(current_user, group) else - all_projects(current_user) + base, extra = all_projects(current_user) + end + + if base and extra + union = Gitlab::SQL::Union.new([base.select(:id), extra.select(:id)]) + + Project.where("projects.id IN (#{union.to_sql})") + else + base end end @@ -13,77 +41,36 @@ class ProjectsFinder def group_projects(current_user, group) if current_user - if group.users.include?(current_user) - # User is group member - # - # Return ALL group projects - group.projects - else - projects_members = ProjectMember.in_projects(group.projects). - with_user(current_user) - - if projects_members.any? - # User is a project member - # - # Return only: - # public projects - # internal projects - # joined projects - # - group.projects.where( - "projects.id IN (?) OR projects.visibility_level IN (?)", - projects_members.pluck(:source_id), - Project.public_and_internal_levels - ) - else - # User has no access to group or group projects - # - # Return only: - # public projects - # internal projects - # - group.projects.public_and_internal_only - end - end + [ + group_projects_for_user(current_user, group), + group.projects.public_and_internal_only + ] else - # Not authenticated - # - # Return only: - # public projects - group.projects.public_only + [group.projects.public_only] end end def all_projects(current_user) if current_user - if current_user.authorized_projects.any? - # User has access to private projects - # - # Return only: - # public projects - # internal projects - # joined projects - # - Project.where( - "projects.id IN (?) OR projects.visibility_level IN (?)", - current_user.authorized_projects.pluck(:id), - Project.public_and_internal_levels - ) - else - # User has no access to private projects - # - # Return only: - # public projects - # internal projects - # - Project.public_and_internal_only - end + [current_user.authorized_projects, public_and_internal_projects] else - # Not authenticated - # - # Return only: - # public projects - Project.public_only + [Project.public_only] end end + + def group_projects_for_user(current_user, group) + if group.users.include?(current_user) + group.projects + else + group.projects.visible_to_user(current_user) + end + end + + def public_projects + Project.unscoped.public_only + end + + def public_and_internal_projects + Project.unscoped.public_and_internal_only + end end diff --git a/app/models/concerns/sortable.rb b/app/models/concerns/sortable.rb index 913c747a1c..7391a77383 100644 --- a/app/models/concerns/sortable.rb +++ b/app/models/concerns/sortable.rb @@ -8,8 +8,9 @@ module Sortable included do # By default all models should be ordered # by created_at field starting from newest - default_scope { order(id: :desc) } + default_scope { order_id_desc } + scope :order_id_desc, -> { reorder(id: :desc) } scope :order_created_desc, -> { reorder(created_at: :desc) } scope :order_created_asc, -> { reorder(created_at: :asc) } scope :order_updated_desc, -> { reorder(updated_at: :desc) } diff --git a/app/models/event.rb b/app/models/event.rb index bf64ac29d3..9afd223bce 100644 --- a/app/models/event.rb +++ b/app/models/event.rb @@ -63,6 +63,16 @@ class Event < ActiveRecord::Base Event::PUSHED, ["MergeRequest", "Issue"], [Event::CREATED, Event::CLOSED, Event::MERGED]) end + + def latest_update_time + row = select(:updated_at, :project_id).reorder(id: :desc).take + + row ? row.updated_at : nil + end + + def limit_recent(limit = 20, offset = nil) + recent.limit(limit).offset(offset) + end end def proper? diff --git a/app/models/group.rb b/app/models/group.rb index 2c9e75496b..1b5b875a19 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -49,6 +49,14 @@ class Group < Namespace def reference_pattern User.reference_pattern end + + def public_and_given_groups(ids) + where('public IS TRUE OR namespaces.id IN (?)', ids) + end + + def visible_to_user(user) + where(id: user.authorized_groups.select(:id).reorder(nil)) + end end def to_reference(_from_project = nil) diff --git a/app/models/project.rb b/app/models/project.rb index 70a648e68a..f0a4b6aae7 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -286,6 +286,10 @@ class Project < ActiveRecord::Base joins(join_body).reorder('join_note_counts.amount DESC') end + + def visible_to_user(user) + where(id: user.authorized_projects.select(:id).reorder(nil)) + end end def team diff --git a/app/models/user.rb b/app/models/user.rb index 61abea1f6e..9374f01f99 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -389,42 +389,23 @@ class User < ActiveRecord::Base end end - # Groups user has access to + # Returns the groups a user has access to def authorized_groups - @authorized_groups ||= begin - group_ids = (groups.pluck(:id) + authorized_projects.pluck(:namespace_id)) - Group.where(id: group_ids) - end + union = Gitlab::SQL::Union. + new([groups.select(:id), authorized_projects.select(:namespace_id)]) + + Group.where("namespaces.id IN (#{union.to_sql})") end - def authorized_projects_id - @authorized_projects_id ||= begin - project_ids = personal_projects.pluck(:id) - project_ids.push(*groups_projects.pluck(:id)) - project_ids.push(*projects.pluck(:id).uniq) - end - end - - def master_or_owner_projects_id - @master_or_owner_projects_id ||= begin - scope = { access_level: [ Gitlab::Access::MASTER, Gitlab::Access::OWNER ] } - project_ids = personal_projects.pluck(:id) - project_ids.push(*groups_projects.where(members: scope).pluck(:id)) - project_ids.push(*projects.where(members: scope).pluck(:id).uniq) - end - end - - # Projects user has access to + # Returns the groups a user is authorized to access. def authorized_projects - @authorized_projects ||= Project.where(id: authorized_projects_id) + Project.where("projects.id IN (#{projects_union.to_sql})") end def owned_projects @owned_projects ||= - begin - namespace_ids = owned_groups.pluck(:id).push(namespace.id) - Project.in_namespace(namespace_ids).joins(:namespace) - end + Project.where('namespace_id IN (?) OR namespace_id = ?', + owned_groups.select(:id), namespace.id).joins(:namespace) end # Team membership in authorized projects @@ -739,12 +720,25 @@ class User < ActiveRecord::Base Doorkeeper::AccessToken.where(resource_owner_id: self.id, revoked_at: nil) end - def contributed_projects_ids - Event.contributions.where(author_id: self). + # Returns the projects a user contributed to in the last year. + # + # This method relies on a subquery as this performs significantly better + # compared to a JOIN when coupled with, for example, + # `Project.visible_to_user`. That is, consider the following code: + # + # some_user.contributed_projects.visible_to_user(other_user) + # + # If this method were to use a JOIN the resulting query would take roughly 200 + # ms on a database with a similar size to GitLab.com's database. On the other + # hand, using a subquery means we can get the exact same data in about 40 ms. + def contributed_projects + events = Event.select(:project_id). + contributions.where(author_id: self). where("created_at > ?", Time.now - 1.year). - reorder(project_id: :desc). - select(:project_id). - uniq.map(&:project_id) + uniq. + reorder(nil) + + Project.where(id: events) end def restricted_signup_domains @@ -777,8 +771,27 @@ class User < ActiveRecord::Base def ci_authorized_runners @ci_authorized_runners ||= begin runner_ids = Ci::RunnerProject.joins(:project). - where(ci_projects: { gitlab_id: master_or_owner_projects_id }).select(:runner_id) + where("ci_projects.gitlab_id IN (#{ci_projects_union.to_sql})"). + select(:runner_id) + Ci::Runner.specific.where(id: runner_ids) end end + + private + + def projects_union + Gitlab::SQL::Union.new([personal_projects.select(:id), + groups_projects.select(:id), + projects.select(:id)]) + end + + def ci_projects_union + scope = { access_level: [Gitlab::Access::MASTER, Gitlab::Access::OWNER] } + groups = groups_projects.where(members: scope) + other = projects.where(members: scope) + + Gitlab::SQL::Union.new([personal_projects.select(:id), groups.select(:id), + other.select(:id)]) + end end diff --git a/app/views/dashboard/projects/index.atom.builder b/app/views/dashboard/projects/index.atom.builder index d2c5148684..c8c219f4cc 100644 --- a/app/views/dashboard/projects/index.atom.builder +++ b/app/views/dashboard/projects/index.atom.builder @@ -4,7 +4,7 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear xml.link href: dashboard_projects_url(format: :atom, private_token: current_user.try(:private_token)), rel: "self", type: "application/atom+xml" xml.link href: dashboard_projects_url, rel: "alternate", type: "text/html" xml.id dashboard_projects_url - xml.updated @events.maximum(:updated_at).strftime("%Y-%m-%dT%H:%M:%SZ") if @events.any? + xml.updated @events.latest_update_time.strftime("%Y-%m-%dT%H:%M:%SZ") if @events.any? @events.each do |event| event_to_atom(xml, event) diff --git a/app/views/groups/show.atom.builder b/app/views/groups/show.atom.builder index a91d1a6e94..7ea574434c 100644 --- a/app/views/groups/show.atom.builder +++ b/app/views/groups/show.atom.builder @@ -4,7 +4,7 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear xml.link href: group_url(@group, format: :atom, private_token: current_user.try(:private_token)), rel: "self", type: "application/atom+xml" xml.link href: group_url(@group), rel: "alternate", type: "text/html" xml.id group_url(@group) - xml.updated @events.maximum(:updated_at).strftime("%Y-%m-%dT%H:%M:%SZ") if @events.any? + xml.updated @events.latest_update_time.strftime("%Y-%m-%dT%H:%M:%SZ") if @events.any? @events.each do |event| event_to_atom(xml, event) diff --git a/app/views/projects/show.atom.builder b/app/views/projects/show.atom.builder index 242684e5c7..15c4976755 100644 --- a/app/views/projects/show.atom.builder +++ b/app/views/projects/show.atom.builder @@ -4,7 +4,7 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear xml.link href: namespace_project_url(@project.namespace, @project, format: :atom, private_token: current_user.try(:private_token)), rel: "self", type: "application/atom+xml" xml.link href: namespace_project_url(@project.namespace, @project), rel: "alternate", type: "text/html" xml.id namespace_project_url(@project.namespace, @project) - xml.updated @events.maximum(:updated_at).strftime("%Y-%m-%dT%H:%M:%SZ") if @events.any? + xml.updated @events.latest_update_time.strftime("%Y-%m-%dT%H:%M:%SZ") if @events.any? @events.each do |event| event_to_atom(xml, event) diff --git a/app/views/users/show.atom.builder b/app/views/users/show.atom.builder index 50232dc718..2fe5b7fac8 100644 --- a/app/views/users/show.atom.builder +++ b/app/views/users/show.atom.builder @@ -4,7 +4,7 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear xml.link href: user_url(@user, :atom), rel: "self", type: "application/atom+xml" xml.link href: user_url(@user), rel: "alternate", type: "text/html" xml.id user_url(@user) - xml.updated @events.maximum(:updated_at).strftime("%Y-%m-%dT%H:%M:%SZ") if @events.any? + xml.updated @events.latest_update_time.strftime("%Y-%m-%dT%H:%M:%SZ") if @events.any? @events.each do |event| event_to_atom(xml, event) diff --git a/db/migrate/20151118162244_add_projects_public_index.rb b/db/migrate/20151118162244_add_projects_public_index.rb new file mode 100644 index 0000000000..fded70e3c0 --- /dev/null +++ b/db/migrate/20151118162244_add_projects_public_index.rb @@ -0,0 +1,5 @@ +class AddProjectsPublicIndex < ActiveRecord::Migration + def change + add_index :namespaces, :public + end +end diff --git a/db/schema.rb b/db/schema.rb index f77f6dfc66..80e9405f6f 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20151116144118) do +ActiveRecord::Schema.define(version: 20151118162244) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -538,6 +538,7 @@ ActiveRecord::Schema.define(version: 20151116144118) do add_index "namespaces", ["name"], name: "index_namespaces_on_name", unique: true, using: :btree add_index "namespaces", ["owner_id"], name: "index_namespaces_on_owner_id", using: :btree add_index "namespaces", ["path"], name: "index_namespaces_on_path", unique: true, using: :btree + add_index "namespaces", ["public"], name: "index_namespaces_on_public", using: :btree add_index "namespaces", ["type"], name: "index_namespaces_on_type", using: :btree create_table "notes", force: true do |t| diff --git a/lib/gitlab/sql/union.rb b/lib/gitlab/sql/union.rb new file mode 100644 index 0000000000..1cd89b3a9c --- /dev/null +++ b/lib/gitlab/sql/union.rb @@ -0,0 +1,34 @@ +module Gitlab + module SQL + # Class for building SQL UNION statements. + # + # ORDER BYs are dropped from the relations as the final sort order is not + # guaranteed any way. + # + # Example usage: + # + # union = Gitlab::SQL::Union.new(user.personal_projects, user.projects) + # sql = union.to_sql + # + # Project.where("id IN (#{sql})") + class Union + def initialize(relations) + @relations = relations + end + + def to_sql + # Some relations may include placeholders for prepared statements, these + # aren't incremented properly when joining relations together this way. + # By using "unprepared_statements" we remove the usage of placeholders + # (thus fixing this problem), at a slight performance cost. + fragments = ActiveRecord::Base.connection.unprepared_statement do + @relations.map do |rel| + rel.reorder(nil).to_sql + end + end + + fragments.join("\nUNION\n") + end + end + end +end diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb index 9f89101d7f..104a5f5014 100644 --- a/spec/controllers/users_controller_spec.rb +++ b/spec/controllers/users_controller_spec.rb @@ -16,13 +16,26 @@ describe UsersController do context 'with rendered views' do render_views - it 'renders the show template' do - sign_in(user) + describe 'when logged in' do + before do + sign_in(user) + end - get :show, username: user.username + it 'renders the show template' do + get :show, username: user.username - expect(response).to be_success - expect(response).to render_template('show') + expect(response).to be_success + expect(response).to render_template('show') + end + end + + describe 'when logged out' do + it 'renders the show template' do + get :show, username: user.username + + expect(response).to be_success + expect(response).to render_template('show') + end end end end diff --git a/spec/finders/contributed_projects_finder_spec.rb b/spec/finders/contributed_projects_finder_spec.rb new file mode 100644 index 0000000000..65d7f14c72 --- /dev/null +++ b/spec/finders/contributed_projects_finder_spec.rb @@ -0,0 +1,35 @@ +require 'spec_helper' + +describe ContributedProjectsFinder do + let(:source_user) { create(:user) } + let(:current_user) { create(:user) } + + let(:finder) { described_class.new(source_user) } + + let!(:public_project) { create(:project, :public) } + let!(:private_project) { create(:project, :private) } + + before do + private_project.team << [source_user, Gitlab::Access::MASTER] + private_project.team << [current_user, Gitlab::Access::DEVELOPER] + public_project.team << [source_user, Gitlab::Access::MASTER] + + create(:event, action: Event::PUSHED, project: public_project, + target: public_project, author: source_user) + + create(:event, action: Event::PUSHED, project: private_project, + target: private_project, author: source_user) + end + + describe 'without a current user' do + subject { finder.execute } + + it { is_expected.to eq([public_project]) } + end + + describe 'with a current user' do + subject { finder.execute(current_user) } + + it { is_expected.to eq([private_project, public_project]) } + end +end diff --git a/spec/finders/group_finder_spec.rb b/spec/finders/group_finder_spec.rb deleted file mode 100644 index 78dc027837..0000000000 --- a/spec/finders/group_finder_spec.rb +++ /dev/null @@ -1,15 +0,0 @@ -require 'spec_helper' - -describe GroupsFinder do - let(:user) { create :user } - let!(:group) { create :group } - let!(:public_group) { create :group, public: true } - - describe :execute do - it 'finds public group' do - groups = GroupsFinder.new.execute(user) - expect(groups.size).to eq(1) - expect(groups.first).to eq(public_group) - end - end -end diff --git a/spec/finders/groups_finder_spec.rb b/spec/finders/groups_finder_spec.rb new file mode 100644 index 0000000000..4f6a000822 --- /dev/null +++ b/spec/finders/groups_finder_spec.rb @@ -0,0 +1,48 @@ +require 'spec_helper' + +describe GroupsFinder do + describe '#execute' do + let(:user) { create(:user) } + + let(:group1) { create(:group) } + let(:group2) { create(:group) } + let(:group3) { create(:group) } + let(:group4) { create(:group, public: true) } + + let!(:public_project) { create(:project, :public, group: group1) } + let!(:internal_project) { create(:project, :internal, group: group2) } + let!(:private_project) { create(:project, :private, group: group3) } + + let(:finder) { described_class.new } + + describe 'with a user' do + subject { finder.execute(user) } + + describe 'when the user is not a member of any groups' do + it { is_expected.to eq([group4, group2, group1]) } + end + + describe 'when the user is a member of a group' do + before do + group3.add_user(user, Gitlab::Access::DEVELOPER) + end + + it { is_expected.to eq([group4, group3, group2, group1]) } + end + + describe 'when the user is a member of a private project' do + before do + private_project.team.add_user(user, Gitlab::Access::DEVELOPER) + end + + it { is_expected.to eq([group4, group3, group2, group1]) } + end + end + + describe 'without a user' do + subject { finder.execute } + + it { is_expected.to eq([group4, group1]) } + end + end +end diff --git a/spec/finders/joined_groups_finder_spec.rb b/spec/finders/joined_groups_finder_spec.rb new file mode 100644 index 0000000000..2d9068cc72 --- /dev/null +++ b/spec/finders/joined_groups_finder_spec.rb @@ -0,0 +1,49 @@ +require 'spec_helper' + +describe JoinedGroupsFinder do + describe '#execute' do + let(:source_user) { create(:user) } + let(:current_user) { create(:user) } + + let(:group1) { create(:group) } + let(:group2) { create(:group) } + let(:group3) { create(:group) } + let(:group4) { create(:group, public: true) } + + let!(:public_project) { create(:project, :public, group: group1) } + let!(:internal_project) { create(:project, :internal, group: group2) } + let!(:private_project) { create(:project, :private, group: group3) } + + let(:finder) { described_class.new(source_user) } + + before do + [group1, group2, group3, group4].each do |group| + group.add_user(source_user, Gitlab::Access::MASTER) + end + end + + describe 'with a current user' do + describe 'when the current user has access to the projects of the source user' do + before do + private_project.team.add_user(current_user, Gitlab::Access::DEVELOPER) + end + + subject { finder.execute(current_user) } + + it { is_expected.to eq([group4, group3, group2, group1]) } + end + + describe 'when the current user does not have access to the projects of the source user' do + subject { finder.execute(current_user) } + + it { is_expected.to eq([group4, group2, group1]) } + end + end + + describe 'without a current user' do + subject { finder.execute } + + it { is_expected.to eq([group4, group1]) } + end + end +end diff --git a/spec/finders/personal_projects_finder_spec.rb b/spec/finders/personal_projects_finder_spec.rb new file mode 100644 index 0000000000..38817add45 --- /dev/null +++ b/spec/finders/personal_projects_finder_spec.rb @@ -0,0 +1,34 @@ +require 'spec_helper' + +describe PersonalProjectsFinder do + let(:source_user) { create(:user) } + let(:current_user) { create(:user) } + + let(:finder) { described_class.new(source_user) } + + let!(:public_project) do + create(:project, :public, namespace: source_user.namespace, name: 'A', + path: 'A') + end + + let!(:private_project) do + create(:project, :private, namespace: source_user.namespace, name: 'B', + path: 'B') + end + + before do + private_project.team << [current_user, Gitlab::Access::DEVELOPER] + end + + describe 'without a current user' do + subject { finder.execute } + + it { is_expected.to eq([public_project]) } + end + + describe 'with a current user' do + subject { finder.execute(current_user) } + + it { is_expected.to eq([private_project, public_project]) } + end +end diff --git a/spec/finders/projects_finder_spec.rb b/spec/finders/projects_finder_spec.rb index de9d4cd612..d1dede78f7 100644 --- a/spec/finders/projects_finder_spec.rb +++ b/spec/finders/projects_finder_spec.rb @@ -1,51 +1,56 @@ require 'spec_helper' describe ProjectsFinder do - let(:user) { create :user } - let(:group) { create :group } + describe '#execute' do + let(:user) { create(:user) } - let(:project1) { create(:empty_project, :public, group: group) } - let(:project2) { create(:empty_project, :internal, group: group) } - let(:project3) { create(:empty_project, :private, group: group) } - let(:project4) { create(:empty_project, :private, group: group) } + let!(:private_project) { create(:project, :private) } + let!(:internal_project) { create(:project, :internal) } + let!(:public_project) { create(:project, :public) } - context 'non authenticated' do - subject { ProjectsFinder.new.execute(nil, group: group) } + let(:finder) { described_class.new } - it { is_expected.to include(project1) } - it { is_expected.not_to include(project2) } - it { is_expected.not_to include(project3) } - it { is_expected.not_to include(project4) } - end + describe 'without a group' do + describe 'without a user' do + subject { finder.execute } - context 'authenticated' do - subject { ProjectsFinder.new.execute(user, group: group) } + it { is_expected.to eq([public_project]) } + end - it { is_expected.to include(project1) } - it { is_expected.to include(project2) } - it { is_expected.not_to include(project3) } - it { is_expected.not_to include(project4) } - end + describe 'with a user' do + subject { finder.execute(user) } - context 'authenticated, project member' do - before { project3.team << [user, :developer] } + describe 'without private projects' do + it { is_expected.to eq([public_project, internal_project]) } + end - subject { ProjectsFinder.new.execute(user, group: group) } + describe 'with private projects' do + before do + private_project.team.add_user(user, Gitlab::Access::MASTER) + end - it { is_expected.to include(project1) } - it { is_expected.to include(project2) } - it { is_expected.to include(project3) } - it { is_expected.not_to include(project4) } - end + it do + is_expected.to eq([public_project, internal_project, + private_project]) + end + end + end + end - context 'authenticated, group member' do - before { group.add_developer(user) } + describe 'with a group' do + let(:group) { public_project.group } - subject { ProjectsFinder.new.execute(user, group: group) } + describe 'without a user' do + subject { finder.execute(nil, group: group) } - it { is_expected.to include(project1) } - it { is_expected.to include(project2) } - it { is_expected.to include(project3) } - it { is_expected.to include(project4) } + it { is_expected.to eq([public_project]) } + end + + describe 'with a user' do + subject { finder.execute(user, group: group) } + + it { is_expected.to eq([public_project, internal_project]) } + end + end end end diff --git a/spec/lib/gitlab/sql/union_spec.rb b/spec/lib/gitlab/sql/union_spec.rb new file mode 100644 index 0000000000..9e1cd4419e --- /dev/null +++ b/spec/lib/gitlab/sql/union_spec.rb @@ -0,0 +1,16 @@ +require 'spec_helper' + +describe Gitlab::SQL::Union do + describe '#to_sql' do + it 'returns a String joining relations together using a UNION' do + rel1 = User.where(email: 'alice@example.com') + rel2 = User.where(email: 'bob@example.com') + union = described_class.new([rel1, rel2]) + + sql1 = rel1.reorder(nil).to_sql + sql2 = rel2.reorder(nil).to_sql + + expect(union.to_sql).to eq("#{sql1}\nUNION\n#{sql2}") + end + end +end diff --git a/spec/models/event_spec.rb b/spec/models/event_spec.rb index 0f32f162a1..ae53f7a536 100644 --- a/spec/models/event_spec.rb +++ b/spec/models/event_spec.rb @@ -64,4 +64,42 @@ describe Event do it { expect(@event.branch_name).to eq("master") } it { expect(@event.author).to eq(@user) } end + + describe '.latest_update_time' do + describe 'when events are present' do + let(:time) { Time.utc(2015, 1, 1) } + + before do + create(:closed_issue_event, updated_at: time) + create(:closed_issue_event, updated_at: time + 5) + end + + it 'returns the latest update time' do + expect(Event.latest_update_time).to eq(time + 5) + end + end + + describe 'when no events exist' do + it 'returns nil' do + expect(Event.latest_update_time).to be_nil + end + end + end + + describe '.limit_recent' do + let!(:event1) { create(:closed_issue_event) } + let!(:event2) { create(:closed_issue_event) } + + describe 'without an explicit limit' do + subject { Event.limit_recent } + + it { is_expected.to eq([event2, event1]) } + end + + describe 'with an explicit limit' do + subject { Event.limit_recent(1) } + + it { is_expected.to eq([event2]) } + end + end end diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb index bbfc5535ee..6f166b5ab7 100644 --- a/spec/models/group_spec.rb +++ b/spec/models/group_spec.rb @@ -38,6 +38,33 @@ describe Group do it { is_expected.not_to validate_presence_of :owner } end + describe '.public_and_given_groups' do + let!(:public_group) { create(:group, public: true) } + + subject { described_class.public_and_given_groups([group.id]) } + + it { is_expected.to eq([public_group, group]) } + end + + describe '.visible_to_user' do + let!(:group) { create(:group) } + let!(:user) { create(:user) } + + subject { described_class.visible_to_user(user) } + + describe 'when the user has access to a group' do + before do + group.add_user(user, Gitlab::Access::MASTER) + end + + it { is_expected.to eq([group]) } + end + + describe 'when the user does not have access to any groups' do + it { is_expected.to eq([]) } + end + end + describe '#to_reference' do it 'returns a String reference to the object' do expect(group.to_reference).to eq "@#{group.name}" diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 3c53722010..f80fada45e 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -453,4 +453,23 @@ describe Project do end end end + + describe '.visible_to_user' do + let!(:project) { create(:project, :private) } + let!(:user) { create(:user) } + + subject { described_class.visible_to_user(user) } + + describe 'when a user has access to a project' do + before do + project.team.add_user(user, Gitlab::Access::MASTER) + end + + it { is_expected.to eq([project]) } + end + + describe 'when a user does not have access to any projects' do + it { is_expected.to eq([]) } + end + end end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 7d716c2312..4631b12faf 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -686,7 +686,7 @@ describe User do end end - describe "#contributed_projects_ids" do + describe "#contributed_projects" do subject { create(:user) } let!(:project1) { create(:project) } let!(:project2) { create(:project, forked_from_project: project3) } @@ -701,15 +701,15 @@ describe User do end it "includes IDs for projects the user has pushed to" do - expect(subject.contributed_projects_ids).to include(project1.id) + expect(subject.contributed_projects).to include(project1) end it "includes IDs for projects the user has had merge requests merged into" do - expect(subject.contributed_projects_ids).to include(project3.id) + expect(subject.contributed_projects).to include(project3) end it "doesn't include IDs for unrelated projects" do - expect(subject.contributed_projects_ids).not_to include(project2.id) + expect(subject.contributed_projects).not_to include(project2) end end @@ -758,4 +758,30 @@ describe User do expect(subject.recent_push).to eq(nil) end end + + describe '#authorized_groups' do + let!(:user) { create(:user) } + let!(:private_group) { create(:group) } + + before do + private_group.add_user(user, Gitlab::Access::MASTER) + end + + subject { user.authorized_groups } + + it { is_expected.to eq([private_group]) } + end + + describe '#authorized_projects' do + let!(:user) { create(:user) } + let!(:private_project) { create(:project, :private) } + + before do + private_project.team << [user, Gitlab::Access::MASTER] + end + + subject { user.authorized_projects } + + it { is_expected.to eq([private_project]) } + end end From 4fddde0135dc88f4a5848fa1416b6bfcee350f8d Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 20 Nov 2015 11:03:03 +0100 Subject: [PATCH 53/80] Fix changing group member permissions Signed-off-by: Dmitriy Zaporozhets --- app/views/groups/group_members/update.js.haml | 2 +- features/steps/groups.rb | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/app/views/groups/group_members/update.js.haml b/app/views/groups/group_members/update.js.haml index 5bad48abaf..df726e2b2b 100644 --- a/app/views/groups/group_members/update.js.haml +++ b/app/views/groups/group_members/update.js.haml @@ -1,2 +1,2 @@ :plain - $("##{dom_id(@member)}").replaceWith('#{escape_javascript(render(@member, member: @member, show_controls: true))}'); + $("##{dom_id(@group_member)}").replaceWith('#{escape_javascript(render(@group_member, member: @group_member, show_controls: true))}'); diff --git a/features/steps/groups.rb b/features/steps/groups.rb index e3b2805425..3aaa05b592 100644 --- a/features/steps/groups.rb +++ b/features/steps/groups.rb @@ -153,6 +153,10 @@ class Spinach::Features::Groups < Spinach::FeatureSteps click_on 'Save' end end + + page.within "#group_member_#{member.id}" do + expect(page).to have_content "Developer" + end end step 'I go to "Audit Events"' do From 5918ba9bcca40907c284a836d0434ea1f6ceb29e Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 20 Nov 2015 11:18:10 +0100 Subject: [PATCH 54/80] Prevent crash on project members page if it shared with other group Signed-off-by: Dmitriy Zaporozhets --- app/helpers/groups_helper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/helpers/groups_helper.rb b/app/helpers/groups_helper.rb index 1d36969cd6..5827a94844 100644 --- a/app/helpers/groups_helper.rb +++ b/app/helpers/groups_helper.rb @@ -12,7 +12,7 @@ module GroupsHelper end def should_user_see_group_roles?(user, group) - if user + if user && group user.is_admin? || group.members.exists?(user_id: user.id) else false From dc030ac1b4e6fc0329d5a464b14c2c24acc4f36f Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 18 Nov 2015 15:15:47 +0100 Subject: [PATCH 55/80] Fix huge line height for diff files list Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/pages/commit.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/app/assets/stylesheets/pages/commit.scss b/app/assets/stylesheets/pages/commit.scss index fbd7c363de..a0e5f7554e 100644 --- a/app/assets/stylesheets/pages/commit.scss +++ b/app/assets/stylesheets/pages/commit.scss @@ -56,6 +56,7 @@ li { padding: 3px 0px; + line-height: 20px; } } .new-file { From 5ac2c3f0aa8730e0b874706965ce734a2318fa93 Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Thu, 19 Nov 2015 17:05:30 +0100 Subject: [PATCH 56/80] Update LFS docs for cloning [ci skip] --- doc/workflow/git_lfs.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/doc/workflow/git_lfs.md b/doc/workflow/git_lfs.md index e1064051fe..616a71522a 100644 --- a/doc/workflow/git_lfs.md +++ b/doc/workflow/git_lfs.md @@ -55,7 +55,7 @@ In `config/gitlab.yml`: * When SSH is set as a remote, Git LFS objects still go through HTTPS * Any Git LFS request will ask for HTTPS credentials to be provided so good Git credentials store is recommended * Currently, storing GitLab Git LFS objects on a non-local storage (like S3 buckets) is not supported -* Git LFS always assumes HTTPS so if you have GitLab server on HTTP you will have to add the url to Git config manually (see #troubleshooting-tips) +* Git LFS always assumes HTTPS so if you have GitLab server on HTTP you will have to add the URL to Git config manually (see #troubleshooting-tips) ## Using Git LFS @@ -77,11 +77,10 @@ git commit -am "Added Debian iso" # commit the file meta data git push origin master # sync the git repo and large file to the GitLab server ``` -Downloading a single large file is also very simple: +Cloning the repository works the same as before. Git automatically detects the LFS-tracked files and clones them via HTTP. If you performed the git clone command with a SSH URL, you have to enter your GitLab credentials for HTTP authentication. ```bash git clone git@gitlab.example.com:group/project.git -git lfs fetch debian.iso # download the large file ``` From 03442eb346ece62d0561118bc43464bafddff5df Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Wed, 18 Nov 2015 11:06:12 +0100 Subject: [PATCH 57/80] Lfs on by default. --- config/gitlab.yml.example | 2 +- config/initializers/1_settings.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example index 8fdb2603ce..1788d4c2c7 100644 --- a/config/gitlab.yml.example +++ b/config/gitlab.yml.example @@ -126,7 +126,7 @@ production: &base ## Git LFS lfs: - enabled: false + enabled: true # The location where LFS objects are stored (default: shared/lfs-objects). # storage_path: shared/lfs-objects diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb index 6b7990c0ab..b498fb1e1d 100644 --- a/config/initializers/1_settings.rb +++ b/config/initializers/1_settings.rb @@ -203,7 +203,7 @@ Settings.incoming_email['mailbox'] = "inbox" if Settings.incoming_email['mail # Git LFS # Settings['lfs'] ||= Settingslogic.new({}) -Settings.lfs['enabled'] = false if Settings.lfs['enabled'].nil? +Settings.lfs['enabled'] = true if Settings.lfs['enabled'].nil? Settings.lfs['storage_path'] = File.expand_path(Settings.lfs['storage_path'] || File.join(Settings.shared['path'], "lfs-objects"), Rails.root) # From a2001eecc7fc4e3515d75c6949ae633e06a286e7 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Wed, 18 Nov 2015 11:39:26 +0100 Subject: [PATCH 58/80] Backup LFS objects same as any upload. --- doc/raketasks/backup_restore.md | 2 +- lib/backup/lfs.rb | 13 +++++++++++++ lib/backup/manager.rb | 2 +- lib/tasks/gitlab/backup.rake | 21 +++++++++++++++++++++ 4 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 lib/backup/lfs.rb diff --git a/doc/raketasks/backup_restore.md b/doc/raketasks/backup_restore.md index 1a5442cdac..4e645b21a8 100644 --- a/doc/raketasks/backup_restore.md +++ b/doc/raketasks/backup_restore.md @@ -29,7 +29,7 @@ sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production ``` Also you can choose what should be backed up by adding environment variable SKIP. Available options: db, -uploads (attachments), repositories, builds(CI build output logs), artifacts (CI build artifacts). +uploads (attachments), repositories, builds(CI build output logs), artifacts (CI build artifacts), lfs (LFS objects). Use a comma to specify several options at the same time. ``` diff --git a/lib/backup/lfs.rb b/lib/backup/lfs.rb new file mode 100644 index 0000000000..4153467fbe --- /dev/null +++ b/lib/backup/lfs.rb @@ -0,0 +1,13 @@ +require 'backup/files' + +module Backup + class Lfs < Files + def initialize + super('lfs', Settings.lfs.storage_path) + end + + def create_files_dir + Dir.mkdir(app_files_dir, 0700) + end + end +end diff --git a/lib/backup/manager.rb b/lib/backup/manager.rb index e7eda7c6f4..099062eeb8 100644 --- a/lib/backup/manager.rb +++ b/lib/backup/manager.rb @@ -154,7 +154,7 @@ module Backup end def archives_to_backup - %w{uploads builds artifacts}.map{ |name| (name + ".tar.gz") unless skipped?(name) }.compact + %w{uploads builds artifacts lfs}.map{ |name| (name + ".tar.gz") unless skipped?(name) }.compact end def folders_to_backup diff --git a/lib/tasks/gitlab/backup.rake b/lib/tasks/gitlab/backup.rake index 3c46bcea40..cb4abe1379 100644 --- a/lib/tasks/gitlab/backup.rake +++ b/lib/tasks/gitlab/backup.rake @@ -13,6 +13,7 @@ namespace :gitlab do Rake::Task["gitlab:backup:uploads:create"].invoke Rake::Task["gitlab:backup:builds:create"].invoke Rake::Task["gitlab:backup:artifacts:create"].invoke + Rake::Task["gitlab:backup:lfs:create"].invoke backup = Backup::Manager.new backup.pack @@ -34,6 +35,7 @@ namespace :gitlab do Rake::Task["gitlab:backup:uploads:restore"].invoke unless backup.skipped?("uploads") Rake::Task["gitlab:backup:builds:restore"].invoke unless backup.skipped?("builds") Rake::Task["gitlab:backup:artifacts:restore"].invoke unless backup.skipped?("artifacts") + Rake::Task["gitlab:backup:lfs:restore"].invoke unless backup.skipped?("lfs") Rake::Task["gitlab:shell:setup"].invoke backup.cleanup @@ -134,6 +136,25 @@ namespace :gitlab do end end + namespace :lfs do + task create: :environment do + $progress.puts "Dumping lfs objects ... ".blue + + if ENV["SKIP"] && ENV["SKIP"].include?("lfs") + $progress.puts "[SKIPPED]".cyan + else + Backup::Lfs.new.dump + $progress.puts "done".green + end + end + + task restore: :environment do + $progress.puts "Restoring lfs objects ... ".blue + Backup::Lfs.new.restore + $progress.puts "done".green + end + end + def configure_cron_mode if ENV['CRON'] # We need an object we can say 'puts' and 'print' to; let's use a From 6fe8c226c5e5f5ee1d2f27741faa251cc2b85579 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Wed, 18 Nov 2015 13:21:57 +0100 Subject: [PATCH 59/80] Add lfs to backup specs. --- spec/tasks/gitlab/backup_rake_spec.rb | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/spec/tasks/gitlab/backup_rake_spec.rb b/spec/tasks/gitlab/backup_rake_spec.rb index fb5e74af64..63bed2414d 100644 --- a/spec/tasks/gitlab/backup_rake_spec.rb +++ b/spec/tasks/gitlab/backup_rake_spec.rb @@ -16,7 +16,7 @@ describe 'gitlab:app namespace rake task' do end def reenable_backup_sub_tasks - %w{db repo uploads builds artifacts}.each do |subtask| + %w{db repo uploads builds artifacts lfs}.each do |subtask| Rake::Task["gitlab:backup:#{subtask}:create"].reenable end end @@ -49,7 +49,7 @@ describe 'gitlab:app namespace rake task' do to raise_error(SystemExit) end - it 'should invoke restoration on mach' do + it 'should invoke restoration on match' do allow(YAML).to receive(:load_file). and_return({ gitlab_version: gitlab_version }) expect(Rake::Task["gitlab:backup:db:restore"]).to receive(:invoke) @@ -57,6 +57,7 @@ describe 'gitlab:app namespace rake task' do expect(Rake::Task["gitlab:backup:builds:restore"]).to receive(:invoke) expect(Rake::Task["gitlab:backup:uploads:restore"]).to receive(:invoke) expect(Rake::Task["gitlab:backup:artifacts:restore"]).to receive(:invoke) + expect(Rake::Task["gitlab:backup:lfs:restore"]).to receive(:invoke) expect(Rake::Task["gitlab:shell:setup"]).to receive(:invoke) expect { run_rake_task('gitlab:backup:restore') }.not_to raise_error end @@ -114,7 +115,7 @@ describe 'gitlab:app namespace rake task' do it 'should set correct permissions on the tar contents' do tar_contents, exit_status = Gitlab::Popen.popen( - %W{tar -tvf #{@backup_tar} db uploads.tar.gz repositories builds.tar.gz artifacts.tar.gz} + %W{tar -tvf #{@backup_tar} db uploads.tar.gz repositories builds.tar.gz artifacts.tar.gz lfs.tar.gz} ) expect(exit_status).to eq(0) expect(tar_contents).to match('db/') @@ -122,12 +123,13 @@ describe 'gitlab:app namespace rake task' do expect(tar_contents).to match('repositories/') expect(tar_contents).to match('builds.tar.gz') expect(tar_contents).to match('artifacts.tar.gz') + expect(tar_contents).to match('lfs.tar.gz') expect(tar_contents).not_to match(/^.{4,9}[rwx].* (database.sql.gz|uploads.tar.gz|repositories|builds.tar.gz|artifacts.tar.gz)\/$/) end it 'should delete temp directories' do temp_dirs = Dir.glob( - File.join(Gitlab.config.backup.path, '{db,repositories,uploads,builds,artifacts}') + File.join(Gitlab.config.backup.path, '{db,repositories,uploads,builds,artifacts,lfs}') ) expect(temp_dirs).to be_empty @@ -163,13 +165,14 @@ describe 'gitlab:app namespace rake task' do it "does not contain skipped item" do tar_contents, _exit_status = Gitlab::Popen.popen( - %W{tar -tvf #{@backup_tar} db uploads.tar.gz repositories builds.tar.gz artifacts.tar.gz} + %W{tar -tvf #{@backup_tar} db uploads.tar.gz repositories builds.tar.gz artifacts.tar.gz lfs.tar.gz} ) expect(tar_contents).to match('db/') expect(tar_contents).to match('uploads.tar.gz') expect(tar_contents).to match('builds.tar.gz') expect(tar_contents).to match('artifacts.tar.gz') + expect(tar_contents).to match('lfs.tar.gz') expect(tar_contents).not_to match('repositories/') end @@ -183,6 +186,7 @@ describe 'gitlab:app namespace rake task' do expect(Rake::Task["gitlab:backup:uploads:restore"]).not_to receive :invoke expect(Rake::Task["gitlab:backup:builds:restore"]).to receive :invoke expect(Rake::Task["gitlab:backup:artifacts:restore"]).to receive :invoke + expect(Rake::Task["gitlab:backup:lfs:restore"]).to receive :invoke expect(Rake::Task["gitlab:shell:setup"]).to receive :invoke expect { run_rake_task('gitlab:backup:restore') }.not_to raise_error end From 2811347884f40ab776c14611de94292c24da65c8 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Thu, 19 Nov 2015 19:22:46 +0100 Subject: [PATCH 60/80] Add support for batch download operation --- lib/gitlab/lfs/response.rb | 105 ++++++++++++++++++------- lib/gitlab/lfs/router.rb | 2 +- spec/lib/gitlab/lfs/lfs_router_spec.rb | 25 ++++-- 3 files changed, 96 insertions(+), 36 deletions(-) diff --git a/lib/gitlab/lfs/response.rb b/lib/gitlab/lfs/response.rb index 4202c78646..ddadc07ebb 100644 --- a/lib/gitlab/lfs/response.rb +++ b/lib/gitlab/lfs/response.rb @@ -26,7 +26,7 @@ module Gitlab def render_download_object_response(oid) render_response_to_download do - if check_download_sendfile_header? && check_download_accept_header? + if check_download_sendfile_header? render_lfs_sendfile(oid) else render_not_found @@ -34,20 +34,15 @@ module Gitlab end end - def render_lfs_api_auth - render_response_to_push do - request_body = JSON.parse(@request.body.read) - return render_not_found if request_body.empty? || request_body['objects'].empty? - - response = build_response(request_body['objects']) - [ - 200, - { - "Content-Type" => "application/json; charset=utf-8", - "Cache-Control" => "private", - }, - [JSON.dump(response)] - ] + def render_batch_operation_response + request_body = JSON.parse(@request.body.read) + case request_body["operation"] + when "download" + render_batch_download(request_body) + when "upload" + render_batch_upload(request_body) + else + render_forbidden end end @@ -142,6 +137,38 @@ module Gitlab end end + def render_batch_upload(body) + return render_not_found if body.empty? || body['objects'].nil? + + render_response_to_push do + response = build_upload_batch_response(body['objects']) + [ + 200, + { + "Content-Type" => "application/json; charset=utf-8", + "Cache-Control" => "private", + }, + [JSON.dump(response)] + ] + end + end + + def render_batch_download(body) + return render_not_found if body.empty? || body['objects'].nil? + + render_response_to_download do + response = build_download_batch_response(body['objects']) + [ + 200, + { + "Content-Type" => "application/json; charset=utf-8", + "Cache-Control" => "private", + }, + [JSON.dump(response)] + ] + end + end + def render_lfs_download_hypermedia(oid) return render_not_found unless oid.present? @@ -266,10 +293,16 @@ module Gitlab @project.lfs_objects.where(oid: objects_oids).pluck(:oid).to_set end - def build_response(objects) + def build_upload_batch_response(objects) selected_objects = select_existing_objects(objects) - upload_hypermedia(objects, selected_objects) + upload_hypermedia_links(objects, selected_objects) + end + + def build_download_batch_response(objects) + selected_objects = select_existing_objects(objects) + + download_hypermedia_links(objects, selected_objects) end def download_hypermedia(oid) @@ -279,7 +312,6 @@ module Gitlab { 'href' => "#{@origin_project.http_url_to_repo}/gitlab-lfs/objects/#{oid}", 'header' => { - 'Accept' => "application/vnd.git-lfs+json; charset=utf-8", 'Authorization' => @env['HTTP_AUTHORIZATION'] }.compact } @@ -287,21 +319,40 @@ module Gitlab } end - def upload_hypermedia(all_objects, existing_objects) + def download_hypermedia_links(all_objects, existing_objects) all_objects.each do |object| - object['_links'] = hypermedia_links(object) unless existing_objects.include?(object['oid']) + # generate links only for existing objects + next unless existing_objects.include?(object['oid']) + + object['_links'] = { + 'download' => { + 'href' => "#{@origin_project.http_url_to_repo}/gitlab-lfs/objects/#{object['oid']}", + 'header' => { + 'Authorization' => @env['HTTP_AUTHORIZATION'] + }.compact + } + } end { 'objects' => all_objects } end - def hypermedia_links(object) - { - "upload" => { - 'href' => "#{@origin_project.http_url_to_repo}/gitlab-lfs/objects/#{object['oid']}/#{object['size']}", - 'header' => { 'Authorization' => @env['HTTP_AUTHORIZATION'] } - }.compact - } + def upload_hypermedia_links(all_objects, existing_objects) + all_objects.each do |object| + # generate links only for non-existing objects + next if existing_objects.include?(object['oid']) + + object['_links'] = { + 'upload' => { + 'href' => "#{@origin_project.http_url_to_repo}/gitlab-lfs/objects/#{object['oid']}/#{object['size']}", + 'header' => { + 'Authorization' => @env['HTTP_AUTHORIZATION'] + }.compact + } + } + end + + { 'objects' => all_objects } end end end diff --git a/lib/gitlab/lfs/router.rb b/lib/gitlab/lfs/router.rb index 4809e83498..2b3f2e8e95 100644 --- a/lib/gitlab/lfs/router.rb +++ b/lib/gitlab/lfs/router.rb @@ -48,7 +48,7 @@ module Gitlab # Check for Batch API if post_path[0].ends_with?("/info/lfs/objects/batch") - lfs.render_lfs_api_auth + lfs.render_batch_operation_response else nil end diff --git a/spec/lib/gitlab/lfs/lfs_router_spec.rb b/spec/lib/gitlab/lfs/lfs_router_spec.rb index cebcb5bc88..5eafaad79c 100644 --- a/spec/lib/gitlab/lfs/lfs_router_spec.rb +++ b/spec/lib/gitlab/lfs/lfs_router_spec.rb @@ -66,7 +66,7 @@ describe Gitlab::Lfs::Router do json_response = ActiveSupport::JSON.decode(lfs_router_auth.try_call.last.first) expect(json_response['_links']['download']['href']).to eq("#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}.git/gitlab-lfs/objects/#{sample_oid}") - expect(json_response['_links']['download']['header']).to eq("Authorization" => @auth, "Accept" => "application/vnd.git-lfs+json; charset=utf-8") + expect(json_response['_links']['download']['header']).to eq("Authorization" => @auth) end end @@ -107,7 +107,7 @@ describe Gitlab::Lfs::Router do json_response = ActiveSupport::JSON.decode(lfs_router_public_auth.try_call.last.first) expect(json_response['_links']['download']['href']).to eq("#{Gitlab.config.gitlab.url}/#{public_project.path_with_namespace}.git/gitlab-lfs/objects/#{sample_oid}") - expect(json_response['_links']['download']['header']).to eq("Accept" => "application/vnd.git-lfs+json; charset=utf-8") + expect(json_response['_links']['download']['header']).to eq({}) end end @@ -117,7 +117,7 @@ describe Gitlab::Lfs::Router do json_response = ActiveSupport::JSON.decode(lfs_router_public_noauth.try_call.last.first) expect(json_response['_links']['download']['href']).to eq("#{Gitlab.config.gitlab.url}/#{public_project.path_with_namespace}.git/gitlab-lfs/objects/#{sample_oid}") - expect(json_response['_links']['download']['header']).to eq("Accept" => "application/vnd.git-lfs+json; charset=utf-8") + expect(json_response['_links']['download']['header']).to eq({}) end end end @@ -191,7 +191,7 @@ describe Gitlab::Lfs::Router do json_response = ActiveSupport::JSON.decode(lfs_router_forked_auth.try_call.last.first) expect(json_response['_links']['download']['href']).to eq("#{Gitlab.config.gitlab.url}/#{forked_project.path_with_namespace}.git/gitlab-lfs/objects/#{sample_oid}") - expect(json_response['_links']['download']['header']).to eq("Accept" => "application/vnd.git-lfs+json; charset=utf-8") + expect(json_response['_links']['download']['header']).to eq({}) end end @@ -219,7 +219,7 @@ describe Gitlab::Lfs::Router do json_response = ActiveSupport::JSON.decode(lfs_router_forked_auth.try_call.last.first) expect(json_response['_links']['download']['href']).to eq("#{Gitlab.config.gitlab.url}/#{forked_project.path_with_namespace}.git/gitlab-lfs/objects/91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897") - expect(json_response['_links']['download']['header']).to eq("Accept" => "application/vnd.git-lfs+json; charset=utf-8", "Authorization" => @auth) + expect(json_response['_links']['download']['header']).to eq("Authorization" => @auth) end end @@ -250,7 +250,8 @@ describe Gitlab::Lfs::Router do body = { 'objects' => [{ 'oid' => sample_oid, 'size' => sample_size - }] + }], + 'operation' => 'upload' }.to_json env['rack.input'] = StringIO.new(body) end @@ -286,7 +287,8 @@ describe Gitlab::Lfs::Router do 'objects' => [{ 'oid' => '91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897', 'size' => 1575078 - }] + }], + 'operation' => 'upload' }.to_json env['rack.input'] = StringIO.new(body) end @@ -315,7 +317,8 @@ describe Gitlab::Lfs::Router do { 'oid' => sample_oid, 'size' => sample_size } - ] + ], + 'operation' => 'upload' }.to_json env['rack.input'] = StringIO.new(body) public_project.lfs_objects << lfs_object @@ -351,6 +354,12 @@ describe Gitlab::Lfs::Router do end context 'when user is not authenticated' do + before do + env['rack.input'] = StringIO.new( + { 'objects' => [], 'operation' => 'upload' }.to_json + ) + end + context 'when user has push access' do before do project.team << [user, :master] From 7ea48bfb25ad44ece1a23b23bd7a29b0928ec2ba Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Fri, 20 Nov 2015 11:59:32 +0100 Subject: [PATCH 61/80] Part of tests done [ci skip] --- lib/gitlab/lfs/response.rb | 27 +- spec/lib/gitlab/lfs/lfs_router_spec.rb | 481 ++++++++++++++++++------- 2 files changed, 371 insertions(+), 137 deletions(-) diff --git a/lib/gitlab/lfs/response.rb b/lib/gitlab/lfs/response.rb index ddadc07ebb..0371e1a710 100644 --- a/lib/gitlab/lfs/response.rb +++ b/lib/gitlab/lfs/response.rb @@ -42,7 +42,7 @@ module Gitlab when "upload" render_batch_upload(request_body) else - render_forbidden + render_not_found end end @@ -322,16 +322,21 @@ module Gitlab def download_hypermedia_links(all_objects, existing_objects) all_objects.each do |object| # generate links only for existing objects - next unless existing_objects.include?(object['oid']) - - object['_links'] = { - 'download' => { - 'href' => "#{@origin_project.http_url_to_repo}/gitlab-lfs/objects/#{object['oid']}", - 'header' => { - 'Authorization' => @env['HTTP_AUTHORIZATION'] - }.compact + if existing_objects.include?(object['oid']) + object['actions'] = { + 'download' => { + 'href' => "#{@origin_project.http_url_to_repo}/gitlab-lfs/objects/#{object['oid']}", + 'header' => { + 'Authorization' => @env['HTTP_AUTHORIZATION'] + }.compact + } } - } + else + object['error'] = { + 'code' => 404, + 'message' => "Object does not exist on the server or you don't have permissions to access it", + } + end end { 'objects' => all_objects } @@ -342,7 +347,7 @@ module Gitlab # generate links only for non-existing objects next if existing_objects.include?(object['oid']) - object['_links'] = { + object['actions'] = { 'upload' => { 'href' => "#{@origin_project.http_url_to_repo}/gitlab-lfs/objects/#{object['oid']}/#{object['size']}", 'header' => { diff --git a/spec/lib/gitlab/lfs/lfs_router_spec.rb b/spec/lib/gitlab/lfs/lfs_router_spec.rb index 5eafaad79c..b0cf38e225 100644 --- a/spec/lib/gitlab/lfs/lfs_router_spec.rb +++ b/spec/lib/gitlab/lfs/lfs_router_spec.rb @@ -238,142 +238,371 @@ describe Gitlab::Lfs::Router do end end - describe 'when initiating pushing of the lfs object' do + describe 'when handling lfs batch request' do before do enable_lfs env['REQUEST_METHOD'] = 'POST' - env["PATH_INFO"] = "#{project.repository.path_with_namespace}.git/info/lfs/objects/batch" + env['PATH_INFO'] = "#{project.repository.path_with_namespace}.git/info/lfs/objects/batch" end - describe 'when user is authenticated' do + describe 'download' do + describe 'when user is authenticated' do + before do + body = { 'objects' => [{ + 'oid' => sample_oid, + 'size' => sample_size + }], + 'operation' => 'download' + }.to_json + env['rack.input'] = StringIO.new(body) + end + + describe 'when user has download access' do + before do + @auth = authorize(user) + env["HTTP_AUTHORIZATION"] = @auth + project.team << [user, :reporter] + end + + context 'when downloading an lfs object that is assigned to our project' do + before do + project.lfs_objects << lfs_object + end + + it 'responds with status 200 and href to download' do + response = lfs_router_auth.try_call + expect(response.first).to eq(200) + response_body = ActiveSupport::JSON.decode(response.last.first) + + expect(response_body).to eq( + 'objects' => [{ + 'oid' => sample_oid, + 'size' => sample_size, + 'actions' => { + 'download' => { + 'href' => "#{project.http_url_to_repo}/gitlab-lfs/objects/#{sample_oid}", + 'header' => {'Authorization' => @auth} + } + } + }]) + end + end + + context 'when downloading an lfs object that is assigned to other project' do + before do + public_project.lfs_objects << lfs_object + end + + it 'responds with status 200 and error message' do + response = lfs_router_auth.try_call + expect(response.first).to eq(200) + response_body = ActiveSupport::JSON.decode(response.last.first) + + expect(response_body).to eq( + 'objects' => [{ + 'oid' => sample_oid, + 'size' => sample_size, + 'error' => { + 'code' => 404, + 'message' => "Object does not exist on the server or you don't have permissions to access it", + } + }]) + end + end + + context 'when downloading a lfs object that does not exist' do + before do + body = { + 'objects' => [{ + 'oid' => '91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897', + 'size' => 1575078 + }], + 'operation' => 'download' + }.to_json + env['rack.input'] = StringIO.new(body) + end + + it "responds with status 200 and error message" do + response = lfs_router_auth.try_call + expect(response.first).to eq(200) + response_body = ActiveSupport::JSON.decode(response.last.first) + + expect(response_body).to eq( + 'objects' => [{ + 'oid' => '91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897', + 'size' => 1575078, + 'error' => { + 'code' => 404, + 'message' => "Object does not exist on the server or you don't have permissions to access it", + } + }]) + end + end + + context 'when downloading one new and one existing lfs object' do + before do + body = { + 'objects' => [ + { 'oid' => '91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897', + 'size' => 1575078 + }, + { 'oid' => sample_oid, + 'size' => sample_size + } + ], + 'operation' => 'download' + }.to_json + env['rack.input'] = StringIO.new(body) + project.lfs_objects << lfs_object + end + + it "responds with status 200 with upload hypermedia link for the new object" do + response = lfs_router_auth.try_call + expect(response.first).to eq(200) + response_body = ActiveSupport::JSON.decode(response.last.first) + + expect(response_body).to eq( + 'objects' => [{ + 'oid' => '91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897', + 'size' => 1575078, + 'error' => { + 'code' => 404, + 'message' => "Object does not exist on the server or you don't have permissions to access it", + } + }, + { + 'oid' => sample_oid, + 'size' => sample_size, + 'actions' => { + 'download' => { + 'href' => "#{project.http_url_to_repo}/gitlab-lfs/objects/#{sample_oid}", + 'header' => {'Authorization' => @auth} + } + } + }]) + end + end + end + + context 'when user does is not member of the project' do + before do + @auth = authorize(user) + env["HTTP_AUTHORIZATION"] = @auth + project.team << [user, :guest] + end + + it 'responds with 403' do + expect(lfs_router_auth.try_call.first).to eq(403) + end + end + + context 'when user does not have download access' do + before do + @auth = authorize(user) + env["HTTP_AUTHORIZATION"] = @auth + project.team << [user, :guest] + end + + it 'responds with 403' do + expect(lfs_router_auth.try_call.first).to eq(403) + end + end + end + + context 'when user is not authenticated' do + before do + body = { 'objects' => [{ + 'oid' => sample_oid, + 'size' => sample_size + }], + 'operation' => 'download' + }.to_json + env['rack.input'] = StringIO.new(body) + end + + describe 'is accessing public project' do + before do + public_project.lfs_objects << lfs_object + end + + it 'responds with status 200 and href to download' do + response = lfs_router_public_noauth.try_call + expect(response.first).to eq(200) + response_body = ActiveSupport::JSON.decode(response.last.first) + + expect(response_body).to eq( + 'objects' => [{ + 'oid' => sample_oid, + 'size' => sample_size, + 'actions' => { + 'download' => { + 'href' => "#{public_project.http_url_to_repo}/gitlab-lfs/objects/#{sample_oid}", + 'header' => {} + } + } + }]) + end + end + + describe 'is accessing non-public project' do + before do + project.lfs_objects << lfs_object + end + + it 'responds with authorization required' do + expect(lfs_router_noauth.try_call.first).to eq(401) + end + end + end + end + + describe 'upload' do + describe 'when user is authenticated' do + before do + body = { 'objects' => [{ + 'oid' => sample_oid, + 'size' => sample_size + }], + 'operation' => 'upload' + }.to_json + env['rack.input'] = StringIO.new(body) + end + + describe 'when user has project push access' do + before do + @auth = authorize(user) + env["HTTP_AUTHORIZATION"] = @auth + project.team << [user, :master] + end + + context 'when pushing an lfs object that already exists' do + before do + public_project.lfs_objects << lfs_object + end + + it "responds with status 200 and links the object to the project" do + response_body = lfs_router_auth.try_call.last + response = ActiveSupport::JSON.decode(response_body.first) + + expect(response['objects']).to be_kind_of(Array) + expect(response['objects'].first['oid']).to eq(sample_oid) + expect(response['objects'].first['size']).to eq(sample_size) + expect(lfs_object.projects.pluck(:id)).to_not include(project.id) + expect(lfs_object.projects.pluck(:id)).to include(public_project.id) + expect(response['objects'].first).to have_key('_links') + end + end + + context 'when pushing a lfs object that does not exist' do + before do + body = { + 'objects' => [{ + 'oid' => '91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897', + 'size' => 1575078 + }], + 'operation' => 'upload' + }.to_json + env['rack.input'] = StringIO.new(body) + end + + it "responds with status 200 and upload hypermedia link" do + response = lfs_router_auth.try_call + expect(response.first).to eq(200) + + response_body = ActiveSupport::JSON.decode(response.last.first) + expect(response_body['objects']).to be_kind_of(Array) + expect(response_body['objects'].first['oid']).to eq("91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897") + expect(response_body['objects'].first['size']).to eq(1575078) + expect(lfs_object.projects.pluck(:id)).not_to include(project.id) + expect(response_body['objects'].first['_links']['upload']['href']).to eq("#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}.git/gitlab-lfs/objects/91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897/1575078") + expect(response_body['objects'].first['_links']['upload']['header']).to eq("Authorization" => @auth) + end + end + + context 'when pushing one new and one existing lfs object' do + before do + body = { + 'objects' => [ + { 'oid' => '91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897', + 'size' => 1575078 + }, + { 'oid' => sample_oid, + 'size' => sample_size + } + ], + 'operation' => 'upload' + }.to_json + env['rack.input'] = StringIO.new(body) + public_project.lfs_objects << lfs_object + end + + it "responds with status 200 with upload hypermedia link for the new object" do + response = lfs_router_auth.try_call + expect(response.first).to eq(200) + + response_body = ActiveSupport::JSON.decode(response.last.first) + expect(response_body['objects']).to be_kind_of(Array) + + + expect(response_body['objects'].first['oid']).to eq("91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897") + expect(response_body['objects'].first['size']).to eq(1575078) + expect(response_body['objects'].first['_links']['upload']['href']).to eq("#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}.git/gitlab-lfs/objects/91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897/1575078") + expect(response_body['objects'].first['_links']['upload']['header']).to eq("Authorization" => @auth) + + expect(response_body['objects'].last['oid']).to eq(sample_oid) + expect(response_body['objects'].last['size']).to eq(sample_size) + expect(lfs_object.projects.pluck(:id)).to_not include(project.id) + expect(lfs_object.projects.pluck(:id)).to include(public_project.id) + expect(response_body['objects'].last).to have_key('_links') + end + end + end + + context 'when user does not have push access' do + it 'responds with 403' do + expect(lfs_router_auth.try_call.first).to eq(403) + end + end + end + + context 'when user is not authenticated' do + before do + env['rack.input'] = StringIO.new( + { 'objects' => [], 'operation' => 'upload' }.to_json + ) + end + + context 'when user has push access' do + before do + project.team << [user, :master] + end + + it "responds with status 401" do + expect(lfs_router_public_noauth.try_call.first).to eq(401) + end + end + + context 'when user does not have push access' do + it "responds with status 401" do + expect(lfs_router_public_noauth.try_call.first).to eq(401) + end + end + end + end + + describe 'unsupported' do before do body = { 'objects' => [{ - 'oid' => sample_oid, - 'size' => sample_size - }], - 'operation' => 'upload' - }.to_json + 'oid' => sample_oid, + 'size' => sample_size + }], + 'operation' => 'other' + }.to_json env['rack.input'] = StringIO.new(body) end - describe 'when user has project push access' do - before do - @auth = authorize(user) - env["HTTP_AUTHORIZATION"] = @auth - project.team << [user, :master] - end - - context 'when pushing an lfs object that already exists' do - before do - public_project.lfs_objects << lfs_object - end - - it "responds with status 200 and links the object to the project" do - response_body = lfs_router_auth.try_call.last - response = ActiveSupport::JSON.decode(response_body.first) - - expect(response['objects']).to be_kind_of(Array) - expect(response['objects'].first['oid']).to eq(sample_oid) - expect(response['objects'].first['size']).to eq(sample_size) - expect(lfs_object.projects.pluck(:id)).to_not include(project.id) - expect(lfs_object.projects.pluck(:id)).to include(public_project.id) - expect(response['objects'].first).to have_key('_links') - end - end - - context 'when pushing a lfs object that does not exist' do - before do - body = { - 'objects' => [{ - 'oid' => '91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897', - 'size' => 1575078 - }], - 'operation' => 'upload' - }.to_json - env['rack.input'] = StringIO.new(body) - end - - it "responds with status 200 and upload hypermedia link" do - response = lfs_router_auth.try_call - expect(response.first).to eq(200) - - response_body = ActiveSupport::JSON.decode(response.last.first) - expect(response_body['objects']).to be_kind_of(Array) - expect(response_body['objects'].first['oid']).to eq("91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897") - expect(response_body['objects'].first['size']).to eq(1575078) - expect(lfs_object.projects.pluck(:id)).not_to include(project.id) - expect(response_body['objects'].first['_links']['upload']['href']).to eq("#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}.git/gitlab-lfs/objects/91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897/1575078") - expect(response_body['objects'].first['_links']['upload']['header']).to eq("Authorization" => @auth) - end - end - - context 'when pushing one new and one existing lfs object' do - before do - body = { - 'objects' => [ - { 'oid' => '91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897', - 'size' => 1575078 - }, - { 'oid' => sample_oid, - 'size' => sample_size - } - ], - 'operation' => 'upload' - }.to_json - env['rack.input'] = StringIO.new(body) - public_project.lfs_objects << lfs_object - end - - it "responds with status 200 with upload hypermedia link for the new object" do - response = lfs_router_auth.try_call - expect(response.first).to eq(200) - - response_body = ActiveSupport::JSON.decode(response.last.first) - expect(response_body['objects']).to be_kind_of(Array) - - - expect(response_body['objects'].first['oid']).to eq("91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897") - expect(response_body['objects'].first['size']).to eq(1575078) - expect(response_body['objects'].first['_links']['upload']['href']).to eq("#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}.git/gitlab-lfs/objects/91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897/1575078") - expect(response_body['objects'].first['_links']['upload']['header']).to eq("Authorization" => @auth) - - expect(response_body['objects'].last['oid']).to eq(sample_oid) - expect(response_body['objects'].last['size']).to eq(sample_size) - expect(lfs_object.projects.pluck(:id)).to_not include(project.id) - expect(lfs_object.projects.pluck(:id)).to include(public_project.id) - expect(response_body['objects'].last).to have_key('_links') - end - end - end - - context 'when user does not have push access' do - it 'responds with 403' do - expect(lfs_router_auth.try_call.first).to eq(403) - end - end - end - - context 'when user is not authenticated' do - before do - env['rack.input'] = StringIO.new( - { 'objects' => [], 'operation' => 'upload' }.to_json - ) - end - - context 'when user has push access' do - before do - project.team << [user, :master] - end - - it "responds with status 401" do - expect(lfs_router_public_noauth.try_call.first).to eq(401) - end - end - - context 'when user does not have push access' do - it "responds with status 401" do - expect(lfs_router_public_noauth.try_call.first).to eq(401) - end + it 'responds with status 404' do + expect(lfs_router_public_noauth.try_call.first).to eq(404) end end end From 760dc3e42c74f7ee9cac4525c47ae12df548069c Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Fri, 20 Nov 2015 12:21:41 +0100 Subject: [PATCH 62/80] Fix upload tests, reformat code and make rubocop happy --- lib/gitlab/lfs/response.rb | 3 +- spec/lib/gitlab/lfs/lfs_router_spec.rb | 229 ++++++++++++------------- 2 files changed, 110 insertions(+), 122 deletions(-) diff --git a/lib/gitlab/lfs/response.rb b/lib/gitlab/lfs/response.rb index 0371e1a710..ada518f9e0 100644 --- a/lib/gitlab/lfs/response.rb +++ b/lib/gitlab/lfs/response.rb @@ -321,7 +321,6 @@ module Gitlab def download_hypermedia_links(all_objects, existing_objects) all_objects.each do |object| - # generate links only for existing objects if existing_objects.include?(object['oid']) object['actions'] = { 'download' => { @@ -344,7 +343,7 @@ module Gitlab def upload_hypermedia_links(all_objects, existing_objects) all_objects.each do |object| - # generate links only for non-existing objects + # generate actions only for non-existing objects next if existing_objects.include?(object['oid']) object['actions'] = { diff --git a/spec/lib/gitlab/lfs/lfs_router_spec.rb b/spec/lib/gitlab/lfs/lfs_router_spec.rb index b0cf38e225..f898b76eb5 100644 --- a/spec/lib/gitlab/lfs/lfs_router_spec.rb +++ b/spec/lib/gitlab/lfs/lfs_router_spec.rb @@ -248,11 +248,11 @@ describe Gitlab::Lfs::Router do describe 'download' do describe 'when user is authenticated' do before do - body = { 'objects' => [{ - 'oid' => sample_oid, - 'size' => sample_size - }], - 'operation' => 'download' + body = { 'operation' => 'download', + 'objects' => [ + { 'oid' => sample_oid, + 'size' => sample_size + }] }.to_json env['rack.input'] = StringIO.new(body) end @@ -274,17 +274,16 @@ describe Gitlab::Lfs::Router do expect(response.first).to eq(200) response_body = ActiveSupport::JSON.decode(response.last.first) - expect(response_body).to eq( - 'objects' => [{ - 'oid' => sample_oid, + expect(response_body).to eq('objects' => [ + { 'oid' => sample_oid, 'size' => sample_size, 'actions' => { 'download' => { - 'href' => "#{project.http_url_to_repo}/gitlab-lfs/objects/#{sample_oid}", - 'header' => {'Authorization' => @auth} + 'href' => "#{project.http_url_to_repo}/gitlab-lfs/objects/#{sample_oid}", + 'header' => { 'Authorization' => @auth } + } } - } - }]) + }]) end end @@ -298,26 +297,24 @@ describe Gitlab::Lfs::Router do expect(response.first).to eq(200) response_body = ActiveSupport::JSON.decode(response.last.first) - expect(response_body).to eq( - 'objects' => [{ - 'oid' => sample_oid, - 'size' => sample_size, - 'error' => { - 'code' => 404, - 'message' => "Object does not exist on the server or you don't have permissions to access it", - } - }]) + expect(response_body).to eq('objects' => [ + { 'oid' => sample_oid, + 'size' => sample_size, + 'error' => { + 'code' => 404, + 'message' => "Object does not exist on the server or you don't have permissions to access it", + } + }]) end end context 'when downloading a lfs object that does not exist' do before do - body = { - 'objects' => [{ - 'oid' => '91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897', - 'size' => 1575078 - }], - 'operation' => 'download' + body = { 'operation' => 'download', + 'objects' => [ + { 'oid' => '91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897', + 'size' => 1575078 + }] }.to_json env['rack.input'] = StringIO.new(body) end @@ -327,30 +324,28 @@ describe Gitlab::Lfs::Router do expect(response.first).to eq(200) response_body = ActiveSupport::JSON.decode(response.last.first) - expect(response_body).to eq( - 'objects' => [{ - 'oid' => '91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897', - 'size' => 1575078, - 'error' => { - 'code' => 404, - 'message' => "Object does not exist on the server or you don't have permissions to access it", - } - }]) + expect(response_body).to eq('objects' => [ + { 'oid' => '91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897', + 'size' => 1575078, + 'error' => { + 'code' => 404, + 'message' => "Object does not exist on the server or you don't have permissions to access it", + } + }]) end end context 'when downloading one new and one existing lfs object' do before do - body = { - 'objects' => [ - { 'oid' => '91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897', - 'size' => 1575078 - }, - { 'oid' => sample_oid, - 'size' => sample_size - } - ], - 'operation' => 'download' + body = { 'operation' => 'download', + 'objects' => [ + { 'oid' => '91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897', + 'size' => 1575078 + }, + { 'oid' => sample_oid, + 'size' => sample_size + } + ] }.to_json env['rack.input'] = StringIO.new(body) project.lfs_objects << lfs_object @@ -361,25 +356,23 @@ describe Gitlab::Lfs::Router do expect(response.first).to eq(200) response_body = ActiveSupport::JSON.decode(response.last.first) - expect(response_body).to eq( - 'objects' => [{ - 'oid' => '91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897', - 'size' => 1575078, - 'error' => { - 'code' => 404, - 'message' => "Object does not exist on the server or you don't have permissions to access it", - } - }, - { - 'oid' => sample_oid, - 'size' => sample_size, - 'actions' => { - 'download' => { - 'href' => "#{project.http_url_to_repo}/gitlab-lfs/objects/#{sample_oid}", - 'header' => {'Authorization' => @auth} - } - } - }]) + expect(response_body).to eq('objects' => [ + { 'oid' => '91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897', + 'size' => 1575078, + 'error' => { + 'code' => 404, + 'message' => "Object does not exist on the server or you don't have permissions to access it", + } + }, + { 'oid' => sample_oid, + 'size' => sample_size, + 'actions' => { + 'download' => { + 'href' => "#{project.http_url_to_repo}/gitlab-lfs/objects/#{sample_oid}", + 'header' => { 'Authorization' => @auth } + } + } + }]) end end end @@ -411,11 +404,12 @@ describe Gitlab::Lfs::Router do context 'when user is not authenticated' do before do - body = { 'objects' => [{ - 'oid' => sample_oid, - 'size' => sample_size - }], - 'operation' => 'download' + body = { 'operation' => 'download', + 'objects' => [ + { 'oid' => sample_oid, + 'size' => sample_size + }], + }.to_json env['rack.input'] = StringIO.new(body) end @@ -430,17 +424,16 @@ describe Gitlab::Lfs::Router do expect(response.first).to eq(200) response_body = ActiveSupport::JSON.decode(response.last.first) - expect(response_body).to eq( - 'objects' => [{ - 'oid' => sample_oid, - 'size' => sample_size, - 'actions' => { - 'download' => { - 'href' => "#{public_project.http_url_to_repo}/gitlab-lfs/objects/#{sample_oid}", - 'header' => {} - } - } - }]) + expect(response_body).to eq('objects' => [ + { 'oid' => sample_oid, + 'size' => sample_size, + 'actions' => { + 'download' => { + 'href' => "#{public_project.http_url_to_repo}/gitlab-lfs/objects/#{sample_oid}", + 'header' => {} + } + } + }]) end end @@ -459,12 +452,12 @@ describe Gitlab::Lfs::Router do describe 'upload' do describe 'when user is authenticated' do before do - body = { 'objects' => [{ - 'oid' => sample_oid, - 'size' => sample_size - }], - 'operation' => 'upload' - }.to_json + body = { 'operation' => 'upload', + 'objects' => [ + { 'oid' => sample_oid, + 'size' => sample_size + }] + }.to_json env['rack.input'] = StringIO.new(body) end @@ -472,7 +465,7 @@ describe Gitlab::Lfs::Router do before do @auth = authorize(user) env["HTTP_AUTHORIZATION"] = @auth - project.team << [user, :master] + project.team << [user, :developer] end context 'when pushing an lfs object that already exists' do @@ -489,19 +482,19 @@ describe Gitlab::Lfs::Router do expect(response['objects'].first['size']).to eq(sample_size) expect(lfs_object.projects.pluck(:id)).to_not include(project.id) expect(lfs_object.projects.pluck(:id)).to include(public_project.id) - expect(response['objects'].first).to have_key('_links') + expect(response['objects'].first['actions']['upload']['href']).to eq("#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}.git/gitlab-lfs/objects/#{sample_oid}/#{sample_size}") + expect(response['objects'].first['actions']['upload']['header']).to eq('Authorization' => @auth) end end context 'when pushing a lfs object that does not exist' do before do - body = { - 'objects' => [{ - 'oid' => '91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897', - 'size' => 1575078 - }], - 'operation' => 'upload' - }.to_json + body = { 'operation' => 'upload', + 'objects' => [ + { 'oid' => '91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897', + 'size' => 1575078 + }] + }.to_json env['rack.input'] = StringIO.new(body) end @@ -514,26 +507,25 @@ describe Gitlab::Lfs::Router do expect(response_body['objects'].first['oid']).to eq("91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897") expect(response_body['objects'].first['size']).to eq(1575078) expect(lfs_object.projects.pluck(:id)).not_to include(project.id) - expect(response_body['objects'].first['_links']['upload']['href']).to eq("#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}.git/gitlab-lfs/objects/91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897/1575078") - expect(response_body['objects'].first['_links']['upload']['header']).to eq("Authorization" => @auth) + expect(response_body['objects'].first['actions']['upload']['href']).to eq("#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}.git/gitlab-lfs/objects/91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897/1575078") + expect(response_body['objects'].first['actions']['upload']['header']).to eq('Authorization' => @auth) end end context 'when pushing one new and one existing lfs object' do before do - body = { - 'objects' => [ - { 'oid' => '91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897', - 'size' => 1575078 - }, - { 'oid' => sample_oid, - 'size' => sample_size - } - ], - 'operation' => 'upload' + body = { 'operation' => 'upload', + 'objects' => [ + { 'oid' => '91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897', + 'size' => 1575078 + }, + { 'oid' => sample_oid, + 'size' => sample_size + } + ] }.to_json env['rack.input'] = StringIO.new(body) - public_project.lfs_objects << lfs_object + project.lfs_objects << lfs_object end it "responds with status 200 with upload hypermedia link for the new object" do @@ -543,17 +535,14 @@ describe Gitlab::Lfs::Router do response_body = ActiveSupport::JSON.decode(response.last.first) expect(response_body['objects']).to be_kind_of(Array) - expect(response_body['objects'].first['oid']).to eq("91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897") expect(response_body['objects'].first['size']).to eq(1575078) - expect(response_body['objects'].first['_links']['upload']['href']).to eq("#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}.git/gitlab-lfs/objects/91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897/1575078") - expect(response_body['objects'].first['_links']['upload']['header']).to eq("Authorization" => @auth) + expect(response_body['objects'].first['actions']['upload']['href']).to eq("#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}.git/gitlab-lfs/objects/91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897/1575078") + expect(response_body['objects'].first['actions']['upload']['header']).to eq("Authorization" => @auth) expect(response_body['objects'].last['oid']).to eq(sample_oid) expect(response_body['objects'].last['size']).to eq(sample_size) - expect(lfs_object.projects.pluck(:id)).to_not include(project.id) - expect(lfs_object.projects.pluck(:id)).to include(public_project.id) - expect(response_body['objects'].last).to have_key('_links') + expect(response_body['objects'].last).to_not have_key('actions') end end end @@ -592,11 +581,11 @@ describe Gitlab::Lfs::Router do describe 'unsupported' do before do - body = { 'objects' => [{ - 'oid' => sample_oid, - 'size' => sample_size - }], - 'operation' => 'other' + body = { 'operation' => 'other', + 'objects' => [ + { 'oid' => sample_oid, + 'size' => sample_size + }] }.to_json env['rack.input'] = StringIO.new(body) end From 89dec03c737f8e93dcbd04e22ce1c29fa2fc45ea Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Fri, 20 Nov 2015 12:45:30 +0100 Subject: [PATCH 63/80] Error 501 when client is using deprecated API. --- lib/gitlab/lfs/response.rb | 60 ++------ lib/gitlab/lfs/router.rb | 4 +- spec/lib/gitlab/lfs/lfs_router_spec.rb | 186 +++++-------------------- 3 files changed, 52 insertions(+), 198 deletions(-) diff --git a/lib/gitlab/lfs/response.rb b/lib/gitlab/lfs/response.rb index ada518f9e0..aceef53ba6 100644 --- a/lib/gitlab/lfs/response.rb +++ b/lib/gitlab/lfs/response.rb @@ -10,20 +10,6 @@ module Gitlab @request = request end - # Return a response for a download request - # Can be a response to: - # Request from a user to get the file - # Request from gitlab-workhorse which file to serve to the user - def render_download_hypermedia_response(oid) - render_response_to_download do - if check_download_accept_header? - render_lfs_download_hypermedia(oid) - else - render_not_found - end - end - end - def render_download_object_response(oid) render_response_to_download do if check_download_sendfile_header? @@ -66,13 +52,24 @@ module Gitlab end end + def render_unsupported_deprecated_api + [ + 501, + { "Content-Type" => "application/json; charset=utf-8" }, + [JSON.dump({ + 'message' => 'Server supports batch API only, please update your Git LFS client to version 0.6.0 and up.', + 'documentation_url' => "#{Gitlab.config.gitlab.url}/help", + })] + ] + end + private def render_not_enabled [ 501, { - "Content-Type" => "application/vnd.git-lfs+json", + "Content-Type" => "application/json; charset=utf-8", }, [JSON.dump({ 'message' => 'Git LFS is not enabled on this GitLab server, contact your admin.', @@ -169,21 +166,6 @@ module Gitlab end end - def render_lfs_download_hypermedia(oid) - return render_not_found unless oid.present? - - lfs_object = object_for_download(oid) - if lfs_object - [ - 200, - { "Content-Type" => "application/vnd.git-lfs+json" }, - [JSON.dump(download_hypermedia(oid))] - ] - else - render_not_found - end - end - def render_lfs_upload_ok(oid, size, tmp_file) if store_file(oid, size, tmp_file) [ @@ -226,10 +208,6 @@ module Gitlab @env['HTTP_X_SENDFILE_TYPE'].to_s == "X-Sendfile" end - def check_download_accept_header? - @env['HTTP_ACCEPT'].to_s == "application/vnd.git-lfs+json; charset=utf-8" - end - def user_can_fetch? # Check user access against the project they used to initiate the pull @user.can?(:download_code, @origin_project) @@ -305,20 +283,6 @@ module Gitlab download_hypermedia_links(objects, selected_objects) end - def download_hypermedia(oid) - { - '_links' => { - 'download' => - { - 'href' => "#{@origin_project.http_url_to_repo}/gitlab-lfs/objects/#{oid}", - 'header' => { - 'Authorization' => @env['HTTP_AUTHORIZATION'] - }.compact - } - } - } - end - def download_hypermedia_links(all_objects, existing_objects) all_objects.each do |object| if existing_objects.include?(object['oid']) diff --git a/lib/gitlab/lfs/router.rb b/lib/gitlab/lfs/router.rb index 2b3f2e8e95..78d0289110 100644 --- a/lib/gitlab/lfs/router.rb +++ b/lib/gitlab/lfs/router.rb @@ -34,7 +34,7 @@ module Gitlab case path_match[1] when "info/lfs" - lfs.render_download_hypermedia_response(oid) + lfs.render_unsupported_deprecated_api when "gitlab-lfs" lfs.render_download_object_response(oid) else @@ -49,6 +49,8 @@ module Gitlab # Check for Batch API if post_path[0].ends_with?("/info/lfs/objects/batch") lfs.render_batch_operation_response + elsif post_path[0].ends_with?("/info/lfs/objects") + lfs.render_unsupported_deprecated_api else nil end diff --git a/spec/lib/gitlab/lfs/lfs_router_spec.rb b/spec/lib/gitlab/lfs/lfs_router_spec.rb index f898b76eb5..92598559ae 100644 --- a/spec/lib/gitlab/lfs/lfs_router_spec.rb +++ b/spec/lib/gitlab/lfs/lfs_router_spec.rb @@ -26,19 +26,41 @@ describe Gitlab::Lfs::Router do let(:sample_oid) { "b68143e6463773b1b6c6fd009a76c32aeec041faff32ba2ed42fd7f708a17f80" } let(:sample_size) { 499013 } + let(:respond_with_deprecated) {[ 501, { "Content-Type"=>"application/json; charset=utf-8" }, ["{\"message\":\"Server supports batch API only, please update your Git LFS client to version 0.6.0 and up.\",\"documentation_url\":\"#{Gitlab.config.gitlab.url}/help\"}"]]} + let(:respond_with_disabled) {[ 501, { "Content-Type"=>"application/json; charset=utf-8" }, ["{\"message\":\"Git LFS is not enabled on this GitLab server, contact your admin.\",\"documentation_url\":\"#{Gitlab.config.gitlab.url}/help\"}"]]} describe 'when lfs is disabled' do before do allow(Gitlab.config.lfs).to receive(:enabled).and_return(false) + env['REQUEST_METHOD'] = 'POST' + body = { + 'objects' => [ + { 'oid' => '91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897', + 'size' => 1575078 + }, + { 'oid' => sample_oid, + 'size' => sample_size + } + ], + 'operation' => 'upload' + }.to_json + env['rack.input'] = StringIO.new(body) + env["PATH_INFO"] = "#{project.repository.path_with_namespace}.git/info/lfs/objects/batch" + end + + it 'responds with 501' do + expect(lfs_router_auth.try_call).to match_array(respond_with_disabled) + end + end + + describe 'when fetching lfs object using deprecated API' do + before do + enable_lfs env["PATH_INFO"] = "#{project.repository.path_with_namespace}.git/info/lfs/objects/#{sample_oid}" end it 'responds with 501' do - respond_with_disabled = [ 501, - { "Content-Type"=>"application/vnd.git-lfs+json" }, - ["{\"message\":\"Git LFS is not enabled on this GitLab server, contact your admin.\",\"documentation_url\":\"#{Gitlab.config.gitlab.url}/help\"}"] - ] - expect(lfs_router_auth.try_call).to match_array(respond_with_disabled) + expect(lfs_router_auth.try_call).to match_array(respond_with_deprecated) end end @@ -46,93 +68,10 @@ describe Gitlab::Lfs::Router do before do enable_lfs env['HTTP_ACCEPT'] = "application/vnd.git-lfs+json; charset=utf-8" - env["PATH_INFO"] = "#{project.repository.path_with_namespace}.git/info/lfs/objects/#{sample_oid}" - end - - describe 'when user is authenticated' do - context 'and user has project download access' do - before do - @auth = authorize(user) - env["HTTP_AUTHORIZATION"] = @auth - project.lfs_objects << lfs_object - project.team << [user, :master] - end - - it "responds with status 200" do - expect(lfs_router_auth.try_call.first).to eq(200) - end - - it "responds with download hypermedia" do - json_response = ActiveSupport::JSON.decode(lfs_router_auth.try_call.last.first) - - expect(json_response['_links']['download']['href']).to eq("#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}.git/gitlab-lfs/objects/#{sample_oid}") - expect(json_response['_links']['download']['header']).to eq("Authorization" => @auth) - end - end - - context 'and user does not have project access' do - it "responds with status 403" do - expect(lfs_router_auth.try_call.first).to eq(403) - end - end - end - - describe 'when user is unauthenticated' do - context 'and user does not have download access' do - it "responds with status 401" do - expect(lfs_router_noauth.try_call.first).to eq(401) - end - end - - context 'and user has download access' do - before do - project.team << [user, :master] - end - - it "responds with status 401" do - expect(lfs_router_noauth.try_call.first).to eq(401) - end - end - end - - describe 'and project is public' do - context 'and project has access to the lfs object' do - before do - public_project.lfs_objects << lfs_object - end - - context 'and user is authenticated' do - it "responds with status 200 and sends download hypermedia" do - expect(lfs_router_public_auth.try_call.first).to eq(200) - json_response = ActiveSupport::JSON.decode(lfs_router_public_auth.try_call.last.first) - - expect(json_response['_links']['download']['href']).to eq("#{Gitlab.config.gitlab.url}/#{public_project.path_with_namespace}.git/gitlab-lfs/objects/#{sample_oid}") - expect(json_response['_links']['download']['header']).to eq({}) - end - end - - context 'and user is unauthenticated' do - it "responds with status 200 and sends download hypermedia" do - expect(lfs_router_public_noauth.try_call.first).to eq(200) - json_response = ActiveSupport::JSON.decode(lfs_router_public_noauth.try_call.last.first) - - expect(json_response['_links']['download']['href']).to eq("#{Gitlab.config.gitlab.url}/#{public_project.path_with_namespace}.git/gitlab-lfs/objects/#{sample_oid}") - expect(json_response['_links']['download']['header']).to eq({}) - end - end - end - - context 'and project does not have access to the lfs object' do - it "responds with status 404" do - expect(lfs_router_public_auth.try_call.first).to eq(404) - end - end + env["PATH_INFO"] = "#{project.repository.path_with_namespace}.git/gitlab-lfs/objects/#{sample_oid}" end describe 'and request comes from gitlab-workhorse' do - before do - env["PATH_INFO"] = "#{project.repository.path_with_namespace}.git/gitlab-lfs/objects/#{sample_oid}" - end context 'without user being authorized' do it "responds with status 401" do expect(lfs_router_noauth.try_call.first).to eq(401) @@ -173,68 +112,17 @@ describe Gitlab::Lfs::Router do end end end + end - describe 'from a forked public project' do - before do - env['HTTP_ACCEPT'] = "application/vnd.git-lfs+json; charset=utf-8" - env["PATH_INFO"] = "#{forked_project.repository.path_with_namespace}.git/info/lfs/objects/#{sample_oid}" - end + describe 'when handling lfs request using deprecated API' do + before do + enable_lfs + env['REQUEST_METHOD'] = 'POST' + env["PATH_INFO"] = "#{project.repository.path_with_namespace}.git/info/lfs/objects" + end - context "when fetching a lfs object" do - context "and user has project download access" do - before do - public_project.lfs_objects << lfs_object - end - - it "can download the lfs object" do - expect(lfs_router_forked_auth.try_call.first).to eq(200) - json_response = ActiveSupport::JSON.decode(lfs_router_forked_auth.try_call.last.first) - - expect(json_response['_links']['download']['href']).to eq("#{Gitlab.config.gitlab.url}/#{forked_project.path_with_namespace}.git/gitlab-lfs/objects/#{sample_oid}") - expect(json_response['_links']['download']['header']).to eq({}) - end - end - - context "and user is not authenticated but project is public" do - before do - public_project.lfs_objects << lfs_object - end - - it "can download the lfs object" do - expect(lfs_router_forked_auth.try_call.first).to eq(200) - end - end - - context "and user has project download access" do - before do - env["PATH_INFO"] = "#{forked_project.repository.path_with_namespace}.git/info/lfs/objects/91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897" - @auth = ActionController::HttpAuthentication::Basic.encode_credentials(user.username, user.password) - env["HTTP_AUTHORIZATION"] = @auth - lfs_object_two = create(:lfs_object, :with_file, oid: "91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897", size: 1575078) - public_project.lfs_objects << lfs_object_two - end - - it "can get a lfs object that is not in the forked project" do - expect(lfs_router_forked_auth.try_call.first).to eq(200) - - json_response = ActiveSupport::JSON.decode(lfs_router_forked_auth.try_call.last.first) - expect(json_response['_links']['download']['href']).to eq("#{Gitlab.config.gitlab.url}/#{forked_project.path_with_namespace}.git/gitlab-lfs/objects/91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897") - expect(json_response['_links']['download']['header']).to eq("Authorization" => @auth) - end - end - - context "and user has project download access" do - before do - env["PATH_INFO"] = "#{forked_project.repository.path_with_namespace}.git/info/lfs/objects/267c8b1d876743971e3a9978405818ff5ca731c4c870b06507619cd9b1847b6b" - lfs_object_three = create(:lfs_object, :with_file, oid: "267c8b1d876743971e3a9978405818ff5ca731c4c870b06507619cd9b1847b6b", size: 127192524) - project.lfs_objects << lfs_object_three - end - - it "cannot get a lfs object that is not in the project" do - expect(lfs_router_forked_auth.try_call.first).to eq(404) - end - end - end + it 'responds with 501' do + expect(lfs_router_auth.try_call).to match_array(respond_with_deprecated) end end From a07be7bcf57b24271b656971b26b03e9aef9db11 Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Fri, 20 Nov 2015 15:40:17 +0100 Subject: [PATCH 64/80] Removed merge conflicts in the User model --- app/models/user.rb | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/app/models/user.rb b/app/models/user.rb index 758fa33765..d654567a88 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -422,26 +422,7 @@ class User < ActiveRecord::Base union = Gitlab::SQL::Union. new([groups.select(:id), authorized_projects.select(:namespace_id)]) -<<<<<<< HEAD - def authorized_projects_id - @authorized_projects_id ||= begin - project_ids = personal_projects.pluck(:id) - project_ids.push(*groups_projects.pluck(:id)) - project_ids.push(*projects.pluck(:id).uniq) - project_ids.push(*groups.joins(:shared_projects).pluck(:project_id)) - end - end - - def master_or_owner_projects_id - @master_or_owner_projects_id ||= begin - scope = { access_level: [ Gitlab::Access::MASTER, Gitlab::Access::OWNER ] } - project_ids = personal_projects.pluck(:id) - project_ids.push(*groups_projects.where(members: scope).pluck(:id)) - project_ids.push(*projects.where(members: scope).pluck(:id).uniq) - end -======= Group.where("namespaces.id IN (#{union.to_sql})") ->>>>>>> b6f0eddce552d7423869e9072a7a0706e309dbdf end # Returns the groups a user is authorized to access. @@ -834,7 +815,8 @@ class User < ActiveRecord::Base def projects_union Gitlab::SQL::Union.new([personal_projects.select(:id), groups_projects.select(:id), - projects.select(:id)]) + projects.select(:id), + groups.joins(:shared_projects).select(:project_id)]) end def ci_projects_union From d39de0ea91b26b8840195e5674b92c353cc16661 Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Fri, 20 Nov 2015 15:40:24 +0100 Subject: [PATCH 65/80] Resolved merge conflicts in ProjectsFinder This also required some changes to the specs (as they weren't entirely working correctly) and the ProjectsFinder itself to make it possible to UNION more than 2 queries together. --- app/finders/projects_finder.rb | 60 +++------------------ spec/finders/projects_finder_spec.rb | 80 ++++++++++++++++------------ 2 files changed, 52 insertions(+), 88 deletions(-) diff --git a/app/finders/projects_finder.rb b/app/finders/projects_finder.rb index f5c1d79931..93fc7c4b01 100644 --- a/app/finders/projects_finder.rb +++ b/app/finders/projects_finder.rb @@ -23,17 +23,17 @@ class ProjectsFinder group = options[:group] if group - base, extra = group_projects(current_user, group) + segments = group_projects(current_user, group) else - base, extra = all_projects(current_user) + segments = all_projects(current_user) end - if base and extra - union = Gitlab::SQL::Union.new([base.select(:id), extra.select(:id)]) + if segments.length > 1 + union = Gitlab::SQL::Union.new(segments.map { |s| s.select(:id) }) Project.where("projects.id IN (#{union.to_sql})") else - base + segments.first end end @@ -41,57 +41,11 @@ class ProjectsFinder def group_projects(current_user, group) if current_user -<<<<<<< HEAD - if group.users.include?(current_user) - # User is group member - # - # Return ALL group projects - group.projects - else - projects_members = ProjectMember.in_projects(group.projects). - with_user(current_user) - - if projects_members.any? - # User is a project member - # - # Return only: - # public projects - # internal projects - # joined projects - # - group.projects.where( - "projects.id IN (?) OR projects.visibility_level IN (?)", - projects_members.pluck(:source_id), - Project.public_and_internal_levels - ) - else - # User has no access to group or group projects - # or has access through shared project - # - # Return only: - # public projects - # internal projects - # shared projects - projects_ids = [] - ProjectGroupLink.where(project_id: group.projects).each do |shared_project| - if shared_project.group.users.include?(current_user) || shared_project.project.users.include?(current_user) - projects_ids << shared_project.project.id - end - end - - group.projects.where( - "projects.id IN (?) OR projects.visibility_level IN (?)", - projects_ids, - Project.public_and_internal_levels - ) - end - end -======= [ group_projects_for_user(current_user, group), - group.projects.public_and_internal_only + group.projects.public_and_internal_only, + group.shared_projects.visible_to_user(current_user) ] ->>>>>>> b6f0eddce552d7423869e9072a7a0706e309dbdf else [group.projects.public_only] end diff --git a/spec/finders/projects_finder_spec.rb b/spec/finders/projects_finder_spec.rb index 3ff0fe87d6..fae0da9d89 100644 --- a/spec/finders/projects_finder_spec.rb +++ b/spec/finders/projects_finder_spec.rb @@ -1,27 +1,25 @@ require 'spec_helper' describe ProjectsFinder do -<<<<<<< HEAD - let(:user) { create :user } - let(:group) { create :group } - let(:group2) { create :group } - - let(:project1) { create(:empty_project, :public, group: group) } - let(:project2) { create(:empty_project, :internal, group: group) } - let(:project3) { create(:empty_project, :private, group: group) } - let(:project4) { create(:empty_project, :private, group: group) } - let(:project5) { create(:empty_project, :private, group: group2) } - let(:project6) { create(:empty_project, :internal, group: group2) } - let(:project7) { create(:empty_project, :public, group: group2) } - let(:project8) { create(:empty_project, :private, group: group2) } -======= describe '#execute' do let(:user) { create(:user) } + let(:group) { create(:group) } - let!(:private_project) { create(:project, :private) } - let!(:internal_project) { create(:project, :internal) } - let!(:public_project) { create(:project, :public) } ->>>>>>> b6f0eddce552d7423869e9072a7a0706e309dbdf + let!(:private_project) do + create(:project, :private, name: 'A', path: 'A') + end + + let!(:internal_project) do + create(:project, :internal, group: group, name: 'B', path: 'B') + end + + let!(:public_project) do + create(:project, :public, group: group, name: 'C', path: 'C') + end + + let!(:shared_project) do + create(:project, :private, name: 'D', path: 'D') + end let(:finder) { described_class.new } @@ -53,8 +51,6 @@ describe ProjectsFinder do end describe 'with a group' do - let(:group) { public_project.group } - describe 'without a user' do subject { finder.execute(nil, group: group) } @@ -64,22 +60,36 @@ describe ProjectsFinder do describe 'with a user' do subject { finder.execute(user, group: group) } - it { is_expected.to eq([public_project, internal_project]) } + describe 'without shared projects' do + it { is_expected.to eq([public_project, internal_project]) } + end + + describe 'with shared projects and group membership' do + before do + group.add_user(user, Gitlab::Access::DEVELOPER) + + shared_project.project_group_links. + create(group_access: Gitlab::Access::MASTER, group: group) + end + + it do + is_expected.to eq([shared_project, public_project, internal_project]) + end + end + + describe 'with shared projects and project membership' do + before do + shared_project.team.add_user(user, Gitlab::Access::DEVELOPER) + + shared_project.project_group_links. + create(group_access: Gitlab::Access::MASTER, group: group) + end + + it do + is_expected.to eq([shared_project, public_project, internal_project]) + end + end end end end - - context 'authenticated, group member with project shared with group' do - before do - group.add_user(user, Gitlab::Access::DEVELOPER) - project5.project_group_links.create group_access: Gitlab::Access::MASTER, group: group - end - - subject { ProjectsFinder.new.execute(user, group: group2) } - - it { should include(project5) } - it { should include(project6) } - it { should include(project7) } - it { should_not include(project8) } - end end From b6ec1714a92970dcc29b68006ea3302ceb22f4f1 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Fri, 20 Nov 2015 12:41:26 +0000 Subject: [PATCH 66/80] Merge branch 'workhorse-version' into 'master' Bump GitLab Workhorse version to 0.4.2 See merge request !1830 --- GITLAB_WORKHORSE | 1 - GITLAB_WORKHORSE_VERSION | 2 +- doc/install/installation.md | 4 ++-- doc/update/8.1-to-8.2.md | 2 +- 4 files changed, 4 insertions(+), 5 deletions(-) delete mode 100644 GITLAB_WORKHORSE diff --git a/GITLAB_WORKHORSE b/GITLAB_WORKHORSE deleted file mode 100644 index 267577d47e..0000000000 --- a/GITLAB_WORKHORSE +++ /dev/null @@ -1 +0,0 @@ -0.4.1 diff --git a/GITLAB_WORKHORSE_VERSION b/GITLAB_WORKHORSE_VERSION index 9e11b32fca..2b7c5ae018 100644 --- a/GITLAB_WORKHORSE_VERSION +++ b/GITLAB_WORKHORSE_VERSION @@ -1 +1 @@ -0.3.1 +0.4.2 diff --git a/doc/install/installation.md b/doc/install/installation.md index 52ae30af80..a88ba8eeb5 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -327,12 +327,12 @@ GitLab Shell is an SSH access and repository management software developed speci cd /home/git sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-workhorse.git cd gitlab-workhorse - sudo -u git -H git checkout 0.4.1 + sudo -u git -H git checkout 0.4.2 sudo -u git -H make ### Initialize Database and Activate Advanced Features - # Go to Gitlab installation folder + # Go to GitLab installation folder cd /home/git/gitlab diff --git a/doc/update/8.1-to-8.2.md b/doc/update/8.1-to-8.2.md index 261031442a..b57e999cfb 100644 --- a/doc/update/8.1-to-8.2.md +++ b/doc/update/8.1-to-8.2.md @@ -81,7 +81,7 @@ from GitLab 8.1. cd /home/git sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-workhorse.git cd gitlab-workhorse -sudo -u git -H git checkout 0.4.1 +sudo -u git -H git checkout 0.4.2 sudo -u git -H make ``` From 3e48a136ac80be549c0fb3112b23f1207eebe67d Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Fri, 20 Nov 2015 11:18:48 -0500 Subject: [PATCH 67/80] Version 8.2.0.rc2 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 88b48676b1..37344c64d8 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.2.0.rc1 \ No newline at end of file +8.2.0.rc2 \ No newline at end of file From a9a303a26fe20de38bf42a01c497b5de9931fa89 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Fri, 20 Nov 2015 11:23:49 -0500 Subject: [PATCH 68/80] Version 8.2.0.rc2-ee --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index e40da89725..198c7c3564 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.2.0.rc1-ee +8.2.0.rc2-ee \ No newline at end of file From 81134fd03aeba0689b98092bfcc33b564674794b Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Sat, 21 Nov 2015 15:50:31 +0000 Subject: [PATCH 69/80] Merge branch 'api-tags-doc' into 'master' Add tags page to readme The tags page was separated for the release feature but not to the index readme. [ci skip] See merge request !1861 --- doc/api/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/api/README.md b/doc/api/README.md index 6b8528de50..25a31b235c 100644 --- a/doc/api/README.md +++ b/doc/api/README.md @@ -10,6 +10,7 @@ - [Repositories](repositories.md) - [Repository Files](repository_files.md) - [Commits](commits.md) +- [Tags](tags.md) - [Branches](branches.md) - [Merge Requests](merge_requests.md) - [Issues](issues.md) From ae36d23497cf1f51e573524c1ef9477375c0f528 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Sat, 21 Nov 2015 16:08:12 +0000 Subject: [PATCH 70/80] Merge branch 'award-emoji-doc' into 'master' Use award emoticons in GitLab workflow Remove the old voting slides and use the emoji bar. [ci skip] See merge request !1863 --- doc/workflow/gitlab_flow.md | 9 ++++----- doc/workflow/voting_slider.png | Bin 5329 -> 0 bytes 2 files changed, 4 insertions(+), 5 deletions(-) delete mode 100644 doc/workflow/voting_slider.png diff --git a/doc/workflow/gitlab_flow.md b/doc/workflow/gitlab_flow.md index 31495bce76..8965e5b365 100644 --- a/doc/workflow/gitlab_flow.md +++ b/doc/workflow/gitlab_flow.md @@ -244,13 +244,12 @@ Developing software happen in small messy steps and it is OK to have your histor You can use tools to view the network graphs of commits and understand the messy history that created your code. If you rebase code the history is incorrect, and there is no way for tools to remedy this because they can't deal with changing commit identifiers. -## Voting on merge requests +## Award emojis on issues and merge requests -![Voting slider in GitLab](voting_slider.png) +![Emoji bar in GitLab](award_emoji.png) -It is common to voice approval or disapproval by using +1 or -1 emoticons. -In GitLab the +1 and -1 are aggregated and shown at the top of the merge request. -As a rule of thumb anything that doesn't have two times more +1's than -1's is suspect and should not be merged yet. +It is common to voice approval or disapproval by using +1 or -1. In GitLab you +can use emojis to give a virtual high five on issues and merge requests. ## Pushing and removing branches diff --git a/doc/workflow/voting_slider.png b/doc/workflow/voting_slider.png deleted file mode 100644 index 4c660ef95937c66924a2f01373cc4efed4eae831..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5329 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 From 0df5340036c3510bc7bad77c4db4704f40f2621e Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Fri, 20 Nov 2015 20:05:56 +0000 Subject: [PATCH 71/80] Merge branch 'fix-drone-service-hook' into 'master' Fix Drone web hook URL not being updated Fixes regression of !1774: fixes Drone Web hook for both service templates and project services. See merge request !1856 --- app/models/project_services/drone_ci_service.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/models/project_services/drone_ci_service.rb b/app/models/project_services/drone_ci_service.rb index c240213200..127684bd27 100644 --- a/app/models/project_services/drone_ci_service.rb +++ b/app/models/project_services/drone_ci_service.rb @@ -32,6 +32,8 @@ class DroneCiService < CiService def compose_service_hook hook = service_hook || build_service_hook + # If using a service template, project may not be available + hook.url = [drone_url, "/api/hook", "?owner=#{project.namespace.path}", "&name=#{project.path}", "&access_token=#{token}"].join if project hook.enable_ssl_verification = enable_ssl_verification hook.save end From 098aec21f7317e2bd3e40abe267d49909ebacbc6 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Sat, 21 Nov 2015 17:20:12 +0000 Subject: [PATCH 72/80] Merge branch 'issue_3598' into 'master' Remove accidentally added line. Reference: #3598 See merge request !1858 --- app/workers/repository_import_worker.rb | 3 --- 1 file changed, 3 deletions(-) diff --git a/app/workers/repository_import_worker.rb b/app/workers/repository_import_worker.rb index 1de4916199..d18c0706b3 100644 --- a/app/workers/repository_import_worker.rb +++ b/app/workers/repository_import_worker.rb @@ -51,8 +51,5 @@ class RepositoryImportWorker end project.import_finish - - # Explicitly update mirror so that upstream remote is created and fetched - project.update_mirror end end From 4412cb25365575c939e172094469125fe161cea7 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Sat, 21 Nov 2015 12:23:59 -0500 Subject: [PATCH 73/80] Revert "Merge remote-tracking branch 'ce/8-2-stable' into 8-2-stable-ee" This reverts commit 240fcb40c891a40f5929503ec72d761fc8ac1a55, reversing changes made to 115bbd8a00b2e1b6cf283f2c582534c0ab0fc164. These two lines were removed from CE but need to stay in EE. This revert ensures that we're up-to-date with the CE upstream but leaves the required lines intact. --- app/workers/repository_import_worker.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/workers/repository_import_worker.rb b/app/workers/repository_import_worker.rb index d18c0706b3..1de4916199 100644 --- a/app/workers/repository_import_worker.rb +++ b/app/workers/repository_import_worker.rb @@ -51,5 +51,8 @@ class RepositoryImportWorker end project.import_finish + + # Explicitly update mirror so that upstream remote is created and fetched + project.update_mirror end end From d241253fff1bbcc75a13425908104b8c1cf8b675 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Sat, 21 Nov 2015 13:15:51 -0500 Subject: [PATCH 74/80] Add award_emoji.png doc image [ci skip] --- doc/workflow/award_emoji.png | Bin 0 -> 6620 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 doc/workflow/award_emoji.png diff --git a/doc/workflow/award_emoji.png b/doc/workflow/award_emoji.png new file mode 100644 index 0000000000000000000000000000000000000000..fb26ee043930b2a06f4b93dd3918c041e2f32033 GIT binary patch literal 6620 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 literal 0 HcmV?d00001 From 53c0b6213ff5f06d3ace23a747148d42c917d559 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Sat, 21 Nov 2015 18:58:47 +0000 Subject: [PATCH 75/80] Merge branch 'award_fix' into 'master' Award Emoji: fix for merge requests Closes #3597 See merge request !1865 --- app/controllers/projects/notes_controller.rb | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app/controllers/projects/notes_controller.rb b/app/controllers/projects/notes_controller.rb index 1e3f1d8fd2..ead940aea6 100644 --- a/app/controllers/projects/notes_controller.rb +++ b/app/controllers/projects/notes_controller.rb @@ -59,8 +59,11 @@ class Projects::NotesController < Projects::ApplicationController end def award_toggle - noteable = note_params[:noteable_type] == "issue" ? Issue : MergeRequest - noteable = noteable.find_by!(id: note_params[:noteable_id], project: project) + noteable = if note_params[:noteable_type] == "issue" + project.issues.find(note_params[:noteable_id]) + else + project.merge_requests.find(note_params[:noteable_id]) + end data = { author: current_user, From 27821ce01fde7e5b3dfce243e22894b44aa2a81d Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Sat, 21 Nov 2015 22:27:48 +0000 Subject: [PATCH 76/80] Merge branch 'consistent-tags-api' into 'master' Make tag API for release feature consistent Make tags API consistent with other tags methods. This changes the endpoint from `PUT /projects/:id/repository/:tag/release` to `PUT /projects/:id/repository/tags/:tag_name/release`. On thing the API is still missing, is an error if the tag does not exist. Right now it returns 200 even the tag does not exist. I'll fix that such it returns 404. @stanhu Can you review? @rspeicher This MR should go into 8.2 See merge request !1864 --- app/services/create_release_service.rb | 31 +++++++++++ app/services/create_tag_service.rb | 10 ++-- app/services/update_release_service.rb | 29 +++++++++++ doc/api/tags.md | 39 +++++++++++--- lib/api/entities.rb | 3 +- lib/api/tags.rb | 37 +++++++++++--- spec/requests/api/tags_spec.rb | 71 ++++++++++++++++++++++++-- 7 files changed, 196 insertions(+), 24 deletions(-) create mode 100644 app/services/create_release_service.rb create mode 100644 app/services/update_release_service.rb diff --git a/app/services/create_release_service.rb b/app/services/create_release_service.rb new file mode 100644 index 0000000000..e06a6f2f47 --- /dev/null +++ b/app/services/create_release_service.rb @@ -0,0 +1,31 @@ +require_relative 'base_service' + +class CreateReleaseService < BaseService + def execute(tag_name, release_description) + + repository = project.repository + existing_tag = repository.find_tag(tag_name) + + # Only create a release if the tag exists + if existing_tag + release = project.releases.find_by(tag: tag_name) + + if release + error('Release already exists', 409) + else + release = project.releases.new({ tag: tag_name, description: release_description }) + release.save + + success(release) + end + else + error('Tag does not exist', 404) + end + end + + def success(release) + out = super() + out[:release] = release + out + end +end diff --git a/app/services/create_tag_service.rb b/app/services/create_tag_service.rb index 9917119fce..2452999382 100644 --- a/app/services/create_tag_service.rb +++ b/app/services/create_tag_service.rb @@ -19,16 +19,16 @@ class CreateTagService < BaseService new_tag = repository.find_tag(tag_name) if new_tag - if release_description - release = project.releases.find_or_initialize_by(tag: tag_name) - release.update_attributes(description: release_description) - end - push_data = create_push_data(project, current_user, new_tag) EventCreateService.new.push(project, current_user, push_data) project.execute_hooks(push_data.dup, :tag_push_hooks) project.execute_services(push_data.dup, :tag_push_hooks) + if release_description + CreateReleaseService.new(@project, @current_user). + execute(tag_name, release_description) + end + success(new_tag) else error('Invalid reference name') diff --git a/app/services/update_release_service.rb b/app/services/update_release_service.rb new file mode 100644 index 0000000000..25eb13ef09 --- /dev/null +++ b/app/services/update_release_service.rb @@ -0,0 +1,29 @@ +require_relative 'base_service' + +class UpdateReleaseService < BaseService + def execute(tag_name, release_description) + + repository = project.repository + existing_tag = repository.find_tag(tag_name) + + if existing_tag + release = project.releases.find_by(tag: tag_name) + + if release + release.update_attributes(description: release_description) + + success(release) + else + error('Release does not exist', 404) + end + else + error('Tag does not exist', 404) + end + end + + def success(release) + out = super() + out[:release] = release + out + end +end diff --git a/doc/api/tags.md b/doc/api/tags.md index b5b90cf6b8..085d387e82 100644 --- a/doc/api/tags.md +++ b/doc/api/tags.md @@ -29,7 +29,7 @@ Parameters: ] }, "release": { - "tag": "1.0.0", + "tag_name": "1.0.0", "description": "Amazing release. Wow" }, "name": "v1.0.0", @@ -70,7 +70,7 @@ Parameters: ] }, "release": { - "tag": "1.0.0", + "tag_name": "1.0.0", "description": "Amazing release. Wow" }, "name": "v1.0.0", @@ -84,23 +84,48 @@ It returns 200 if the operation succeed. In case of an error, 405 with an explaining error message is returned. -## New release +## Create a new release -Add release notes to the existing git tag +Add release notes to the existing git tag. It returns 201 if the release is +created successfully. If the tag does not exist, 404 is returned. If there +already exists a release for the given tag, 409 is returned. ``` -PUT /projects/:id/repository/:tag/release +POST /projects/:id/repository/tags/:tag_name/release ``` Parameters: - `id` (required) - The ID of a project -- `tag` (required) - The name of a tag +- `tag_name` (required) - The name of a tag - `description` (required) - Release notes with markdown support ```json { - "tag": "1.0.0", + "tag_name": "1.0.0", "description": "Amazing release. Wow" } ``` + +## Update a release + +Updates the release notes of a given release. It returns 200 if the release is +successfully updated. If the tag or the release does not exist, it returns 404 +with a proper error message. + +``` +PUT /projects/:id/repository/tags/:tag_name/release +``` + +Parameters: + +- `id` (required) - The ID of a project +- `tag_name` (required) - The name of a tag +- `description` (required) - Release notes with markdown support + +```json +{ + "tag_name": "1.0.0", + "description": "Amazing release. Wow" +} +``` \ No newline at end of file diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 3da6bc415d..5dea74db29 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -322,7 +322,8 @@ module API end class Release < Grape::Entity - expose :tag, :description + expose :tag, as: :tag_name + expose :description end class RepoTag < Grape::Entity diff --git a/lib/api/tags.rb b/lib/api/tags.rb index 673342dd44..47621f443e 100644 --- a/lib/api/tags.rb +++ b/lib/api/tags.rb @@ -44,17 +44,42 @@ module API # # Parameters: # id (required) - The ID of a project - # tag (required) - The name of the tag + # tag_name (required) - The name of the tag # description (required) - Release notes with markdown support # Example Request: - # PUT /projects/:id/repository/tags - put ':id/repository/:tag/release', requirements: { tag: /.*/ } do + # POST /projects/:id/repository/tags/:tag_name/release + post ':id/repository/tags/:tag_name/release', requirements: { tag_name: /.*/ } do authorize_push_project required_attributes! [:description] - release = user_project.releases.find_or_initialize_by(tag: params[:tag]) - release.update_attributes(description: params[:description]) + result = CreateReleaseService.new(user_project, current_user). + execute(params[:tag_name], params[:description]) - present release, with: Entities::Release + if result[:status] == :success + present result[:release], with: Entities::Release + else + render_api_error!(result[:message], result[:http_status]) + end + end + + # Updates a release notes of a tag + # + # Parameters: + # id (required) - The ID of a project + # tag_name (required) - The name of the tag + # description (required) - Release notes with markdown support + # Example Request: + # PUT /projects/:id/repository/tags/:tag_name/release + put ':id/repository/tags/:tag_name/release', requirements: { tag_name: /.*/ } do + authorize_push_project + required_attributes! [:description] + result = UpdateReleaseService.new(user_project, current_user). + execute(params[:tag_name], params[:description]) + + if result[:status] == :success + present result[:release], with: Entities::Release + else + render_api_error!(result[:message], result[:http_status]) + end end end end diff --git a/spec/requests/api/tags_spec.rb b/spec/requests/api/tags_spec.rb index cc9a5f4758..17f2643fd4 100644 --- a/spec/requests/api/tags_spec.rb +++ b/spec/requests/api/tags_spec.rb @@ -28,10 +28,10 @@ describe API::API, api: true do before do release = project.releases.find_or_initialize_by(tag: tag_name) release.update_attributes(description: description) - get api("/projects/#{project.id}/repository/tags", user) end it "should return an array of project tags with release info" do + get api("/projects/#{project.id}/repository/tags", user) expect(response.status).to eq(200) expect(json_response).to be_an Array expect(json_response.first['name']).to eq(tag_name) @@ -119,17 +119,78 @@ describe API::API, api: true do end end - describe 'PUT /projects/:id/repository/:tag/release' do + describe 'POST /projects/:id/repository/tags/:tag_name/release' do let(:tag_name) { project.repository.tag_names.first } let(:description) { 'Awesome release!' } it 'should create description for existing git tag' do - put api("/projects/#{project.id}/repository/#{tag_name}/release", user), + post api("/projects/#{project.id}/repository/tags/#{tag_name}/release", user), description: description - expect(response.status).to eq(200) - expect(json_response['tag']).to eq(tag_name) + expect(response.status).to eq(201) + expect(json_response['tag_name']).to eq(tag_name) expect(json_response['description']).to eq(description) end + + it 'should return 404 if the tag does not exist' do + post api("/projects/#{project.id}/repository/tags/foobar/release", user), + description: description + + expect(response.status).to eq(404) + expect(json_response['message']).to eq('Tag does not exist') + end + + context 'on tag with existing release' do + before do + release = project.releases.find_or_initialize_by(tag: tag_name) + release.update_attributes(description: description) + end + + it 'should return 409 if there is already a release' do + post api("/projects/#{project.id}/repository/tags/#{tag_name}/release", user), + description: description + + expect(response.status).to eq(409) + expect(json_response['message']).to eq('Release already exists') + end + end + end + + describe 'PUT id/repository/tags/:tag_name/release' do + let(:tag_name) { project.repository.tag_names.first } + let(:description) { 'Awesome release!' } + let(:new_description) { 'The best release!' } + + context 'on tag with existing release' do + before do + release = project.releases.find_or_initialize_by(tag: tag_name) + release.update_attributes(description: description) + end + + it 'should update the release description' do + put api("/projects/#{project.id}/repository/tags/#{tag_name}/release", user), + description: new_description + + expect(response.status).to eq(200) + expect(json_response['tag_name']).to eq(tag_name) + expect(json_response['description']).to eq(new_description) + end + end + + it 'should return 404 if the tag does not exist' do + put api("/projects/#{project.id}/repository/tags/foobar/release", user), + description: new_description + + expect(response.status).to eq(404) + expect(json_response['message']).to eq('Tag does not exist') + end + + it 'should return 404 if the release does not exist' do + put api("/projects/#{project.id}/repository/tags/#{tag_name}/release", user), + description: new_description + + expect(response.status).to eq(404) + expect(json_response['message']).to eq('Release does not exist') + end end end From 94b33caf8488d98f49ff3c1b468d3e0327135bc4 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Sun, 22 Nov 2015 03:45:15 +0000 Subject: [PATCH 77/80] Merge branch 'fix-award-emoji-api' into 'master' Add upvote/downvote fields to merge request and note API to preserve compatibility As discussed in !1825 we should not break the API compatibility. * This MR adds the fields `upvotes`/`downvotes` to the merge request API again, which always return `0`. * Add the fields `upvote`/`downvote` to the notes API, which always return `false` This behavior is documented in the API docs. See merge request !1867 --- app/models/concerns/issuable.rb | 10 ++++++++++ app/models/note.rb | 10 ++++++++++ doc/api/merge_requests.md | 32 +++++++++++++++++++++++++------- doc/api/notes.md | 11 ++++++++--- lib/api/entities.rb | 5 +++++ 5 files changed, 58 insertions(+), 10 deletions(-) diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb index 91da6797df..b54145ba1b 100644 --- a/app/models/concerns/issuable.rb +++ b/app/models/concerns/issuable.rb @@ -89,6 +89,16 @@ module Issuable opened? || reopened? end + # Deprecated. Still exists to preserve API compatibility. + def downvotes + 0 + end + + # Deprecated. Still exists to preserve API compatibility. + def upvotes + 0 + end + def subscribed?(user) subscription = subscriptions.find_by_user_id(user.id) diff --git a/app/models/note.rb b/app/models/note.rb index e30be444eb..1c6345e735 100644 --- a/app/models/note.rb +++ b/app/models/note.rb @@ -335,6 +335,16 @@ class Note < ActiveRecord::Base read_attribute(:system) end + # Deprecated. Still exists to preserve API compatibility. + def downvote? + false + end + + # Deprecated. Still exists to preserve API compatibility. + def upvote? + false + end + def editable? !system? end diff --git a/doc/api/merge_requests.md b/doc/api/merge_requests.md index 2f17d4ae06..0cef09d5b2 100644 --- a/doc/api/merge_requests.md +++ b/doc/api/merge_requests.md @@ -3,8 +3,9 @@ ## List merge requests Get all merge requests for this project. -The `state` parameter can be used to get only merge requests with a given state (`opened`, `closed`, or `merged`) or all of them (`all`). -The pagination parameters `page` and `per_page` can be used to restrict the list of merge requests. +The `state` parameter can be used to get only merge requests with a given state (`opened`, `closed`, or `merged`) or all of them (`all`). +The pagination parameters `page` and `per_page` can be used to restrict the list of merge requests. With GitLab 8.2 the return fields `upvotes` and +`downvotes` are deprecated and always return `0`. ``` GET /projects/:id/merge_requests @@ -31,6 +32,8 @@ Parameters: "project_id": 3, "title": "test1", "state": "opened", + "upvotes": 0, + "downvotes": 0, "author": { "id": 1, "username": "admin", @@ -55,7 +58,7 @@ Parameters: ## Get single MR -Shows information about a single merge request. +Shows information about a single merge request. With GitLab 8.2 the return fields `upvotes` and `downvotes` are deprecated and always return `0`. ``` GET /projects/:id/merge_request/:merge_request_id @@ -75,6 +78,8 @@ Parameters: "project_id": 3, "title": "test1", "state": "merged", + "upvotes": 0, + "downvotes": 0, "author": { "id": 1, "username": "admin", @@ -98,7 +103,9 @@ Parameters: ## Get single MR changes -Shows information about the merge request including its files and changes +Shows information about the merge request including its files and changes. +With GitLab 8.2 the return fields `upvotes` and `downvotes` are deprecated and +always return `0`. ``` GET /projects/:id/merge_request/:merge_request_id/changes @@ -122,6 +129,8 @@ Parameters: "updated_at": "2015-02-02T20:08:49.959Z", "target_branch": "secret_token", "source_branch": "version-1-9", + "upvotes": 0, + "downvotes": 0, "author": { "name": "Chad Hamill", "username": "jarrett", @@ -167,7 +176,8 @@ Parameters: ## Create MR -Creates a new merge request. +Creates a new merge request. With GitLab 8.2 the return fields `upvotes` and ` +downvotes` are deprecated and always return `0`. ``` POST /projects/:id/merge_requests @@ -192,6 +202,8 @@ Parameters: "project_id": 3, "title": "test1", "state": "opened", + "upvotes": 0, + "downvotes": 0, "author": { "id": 1, "username": "admin", @@ -217,7 +229,8 @@ If an error occurs, an error number and a message explaining the reason is retur ## Update MR -Updates an existing merge request. You can change the target branch, title, or even close the MR. +Updates an existing merge request. You can change the target branch, title, or even close the MR. With GitLab 8.2 the return fields `upvotes` and `downvotes` +are deprecated and always return `0`. ``` PUT /projects/:id/merge_request/:merge_request_id @@ -242,6 +255,8 @@ Parameters: "title": "test1", "description": "description1", "state": "opened", + "upvotes": 0, + "downvotes": 0, "author": { "id": 1, "username": "admin", @@ -266,7 +281,8 @@ If an error occurs, an error number and a message explaining the reason is retur ## Accept MR -Merge changes submitted with MR using this API. +Merge changes submitted with MR using this API. With GitLab 8.2 the return +fields `upvotes` and `downvotes` are deprecated and always return `0`. If merge success you get `200 OK`. @@ -294,6 +310,8 @@ Parameters: "project_id": 3, "title": "test1", "state": "merged", + "upvotes": 0, + "downvotes": 0, "author": { "id": 1, "username": "admin", diff --git a/doc/api/notes.md b/doc/api/notes.md index bcba1f6215..e7f299c099 100644 --- a/doc/api/notes.md +++ b/doc/api/notes.md @@ -6,7 +6,8 @@ Notes are comments on snippets, issues or merge requests. ### List project issue notes -Gets a list of all notes for a single issue. +Gets a list of all notes for a single issue. With GitLab 8.2 the return fields +`upvote` and `downvote` are deprecated and always return `false`. ``` GET /projects/:id/issues/:issue_id/notes @@ -32,7 +33,9 @@ Parameters: "created_at": "2013-09-30T13:46:01Z" }, "created_at": "2013-10-02T09:22:45Z", - "system": true + "system": true, + "upvote": false, + "downvote": false }, { "id": 305, @@ -47,7 +50,9 @@ Parameters: "created_at": "2013-09-30T13:46:01Z" }, "created_at": "2013-10-02T09:56:03Z", - "system": false + "system": true, + "upvote": false, + "downvote": false } ] ``` diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 5dea74db29..9f337bc3cc 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -163,6 +163,8 @@ module API class MergeRequest < ProjectEntity expose :target_branch, :source_branch + # deprecated, always returns 0 + expose :upvotes, :downvotes expose :author, :assignee, using: Entities::UserBasic expose :source_project_id, :target_project_id expose :label_names, as: :labels @@ -192,6 +194,9 @@ module API expose :author, using: Entities::UserBasic expose :created_at expose :system?, as: :system + # upvote? and downvote? are deprecated, always return false + expose :upvote?, as: :upvote + expose :downvote?, as: :downvote end class MRNote < Grape::Entity From aeaa5b5037a30b4a49b520bd92ed6a40f55e7fb7 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sat, 21 Nov 2015 09:40:03 +0000 Subject: [PATCH 78/80] Merge branch 'fix-merge-requests-without-source-projects' into 'master' Handle removed source projects in MR CI commits Fixes #3599 @dzaporozhets assigning this to you since you wrote the original code. Perhaps checking for the source project isn't the right way, but I'm not sure if there's a better way (e.g. somewhere earlier in the process) that we can detect this. See merge request !1859 --- app/models/merge_request.rb | 2 +- spec/models/merge_request_spec.rb | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 2eb03b8ba5..942a052876 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -473,7 +473,7 @@ class MergeRequest < ActiveRecord::Base end def ci_commit - if last_commit + if last_commit and source_project source_project.ci_commit(last_commit.id) end end diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index 90af75ff0e..567c911425 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -193,4 +193,29 @@ describe MergeRequest do it_behaves_like 'a Taskable' do subject { create :merge_request, :simple } end + + describe '#ci_commit' do + describe 'when the source project exists' do + it 'returns the latest commit' do + commit = double(:commit, id: '123abc') + ci_commit = double(:ci_commit) + + allow(subject).to receive(:last_commit).and_return(commit) + + expect(subject.source_project).to receive(:ci_commit). + with('123abc'). + and_return(ci_commit) + + expect(subject.ci_commit).to eq(ci_commit) + end + end + + describe 'when the source project does not exist' do + it 'returns nil' do + allow(subject).to receive(:source_project).and_return(nil) + + expect(subject.ci_commit).to be_nil + end + end + end end From dbcd646296bfce1f734a05663ef160a3cf96cdd1 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Sun, 22 Nov 2015 04:10:25 +0000 Subject: [PATCH 79/80] Merge branch 'award_fix' into 'master' Emoji bug: Invalid url to image Closes #3591 See merge request !1868 --- app/assets/javascripts/awards_handler.coffee | 2 +- app/controllers/projects/notes_controller.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/awards_handler.coffee b/app/assets/javascripts/awards_handler.coffee index 635c9b4f8d..09b48fe557 100644 --- a/app/assets/javascripts/awards_handler.coffee +++ b/app/assets/javascripts/awards_handler.coffee @@ -73,7 +73,7 @@ class @AwardsHandler getImage: (emoji, custom_path) -> if custom_path - $(".awards-menu li").first().html().replace(/emoji\/.*\.png/, custom_path) + $("").attr({src: custom_path, width: 20, height: 20}).wrap("
").parent().html() else $("li[data-emoji='" + emoji + "']").html() diff --git a/app/controllers/projects/notes_controller.rb b/app/controllers/projects/notes_controller.rb index ead940aea6..5ac18446aa 100644 --- a/app/controllers/projects/notes_controller.rb +++ b/app/controllers/projects/notes_controller.rb @@ -136,7 +136,7 @@ class Projects::NotesController < Projects::ApplicationController discussion_id: note.discussion_id, html: note_to_html(note), award: note.is_award, - emoji_path: note.is_award ? ::AwardEmoji.path_to_emoji_image(note.note) : "", + emoji_path: note.is_award ? view_context.image_url(::AwardEmoji.path_to_emoji_image(note.note)) : "", note: note.note, discussion_html: note_to_discussion_html(note), discussion_with_diff_html: note_to_discussion_with_diff_html(note) From 07140614ca47a39ac24c725298dd8ab9e9b6033f Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Sat, 21 Nov 2015 23:38:05 -0500 Subject: [PATCH 80/80] Version 8.2.0-ee --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 86bb9d5a15..3e62582739 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.2.0.rc2-ee +8.2.0-ee \ No newline at end of file