From 9769c2d7fd0728caf951858162ec7df6f93a8a83 Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Tue, 19 Aug 2014 00:23:02 +0200 Subject: [PATCH 01/97] Fix #6417: users with group permission should be able to create groups via API --- doc/api/groups.md | 2 +- lib/api/groups.rb | 4 ++-- spec/factories.rb | 1 + spec/requests/api/groups_spec.rb | 19 ++++++++++--------- 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/doc/api/groups.md b/doc/api/groups.md index b5a4b05cca..c903a850fd 100644 --- a/doc/api/groups.md +++ b/doc/api/groups.md @@ -35,7 +35,7 @@ Parameters: ## New group -Creates a new project group. Available only for admin. +Creates a new project group. Available only for users who can create groups. ``` POST /groups diff --git a/lib/api/groups.rb b/lib/api/groups.rb index a92abd4b69..218cec4088 100644 --- a/lib/api/groups.rb +++ b/lib/api/groups.rb @@ -20,7 +20,7 @@ module API present @groups, with: Entities::Group end - # Create group. Available only for admin + # Create group. Available only for users who can create groups. # # Parameters: # name (required) - The name of the group @@ -28,7 +28,7 @@ module API # Example Request: # POST /groups post do - authenticated_as_admin! + authorize! :create_group, current_user required_attributes! [:name, :path] attrs = attributes_for_keys [:name, :path, :description] diff --git a/spec/factories.rb b/spec/factories.rb index fc103e5b13..d2b0eeea08 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -22,6 +22,7 @@ FactoryGirl.define do password "12345678" confirmed_at { Time.now } confirmation_token { nil } + can_create_group true trait :admin do admin true diff --git a/spec/requests/api/groups_spec.rb b/spec/requests/api/groups_spec.rb index d963dbac9f..62b42d63fc 100644 --- a/spec/requests/api/groups_spec.rb +++ b/spec/requests/api/groups_spec.rb @@ -3,8 +3,9 @@ require 'spec_helper' describe API::API, api: true do include ApiHelpers - let(:user1) { create(:user) } + let(:user1) { create(:user, can_create_group: false) } let(:user2) { create(:user) } + let(:user3) { create(:user) } let(:admin) { create(:admin) } let!(:group1) { create(:group) } let!(:group2) { create(:group) } @@ -94,32 +95,32 @@ describe API::API, api: true do end describe "POST /groups" do - context "when authenticated as user" do + context "when authenticated as user without group permissions" do it "should not create group" do post api("/groups", user1), attributes_for(:group) expect(response.status).to eq(403) end end - context "when authenticated as admin" do + context "when authenticated as user with group permissions" do it "should create group" do - post api("/groups", admin), attributes_for(:group) + post api("/groups", user3), attributes_for(:group) expect(response.status).to eq(201) end it "should not create group, duplicate" do - post api("/groups", admin), {name: "Duplicate Test", path: group2.path} + post api("/groups", user3), {name: 'Duplicate Test', path: group2.path} expect(response.status).to eq(400) expect(response.message).to eq("Bad Request") end it "should return 400 bad request error if name not given" do - post api("/groups", admin), {path: group2.path} + post api("/groups", user3), {path: group2.path} expect(response.status).to eq(400) end it "should return 400 bad request error if path not given" do - post api("/groups", admin), { name: 'test' } + post api("/groups", user3), {name: 'test'} expect(response.status).to eq(400) end end @@ -133,8 +134,8 @@ describe API::API, api: true do end it "should not remove a group if not an owner" do - user3 = create(:user) - group1.add_user(user3, Gitlab::Access::MASTER) + user4 = create(:user) + group1.add_user(user4, Gitlab::Access::MASTER) delete api("/groups/#{group1.id}", user3) expect(response.status).to eq(403) end From ac509359b82e0a58b6a05b418abcb89e016aff24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robin=20Gau=C3=9F?= Date: Fri, 17 Apr 2015 14:57:31 +0200 Subject: [PATCH 02/97] Fix link to gitlab.yml.example in paragraph 5 --- doc/update/7.6-to-7.7.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/update/7.6-to-7.7.md b/doc/update/7.6-to-7.7.md index 5924371315..910c7dcdd3 100644 --- a/doc/update/7.6-to-7.7.md +++ b/doc/update/7.6-to-7.7.md @@ -67,7 +67,7 @@ sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab #### New configuration options for `gitlab.yml` -There are new configuration options available for [`gitlab.yml`](config/gitlab.yml.example). View them with the command below and apply them to your current `gitlab.yml`. +There are new configuration options available for [`gitlab.yml`](/config/gitlab.yml.example). View them with the command below and apply them to your current `gitlab.yml`. ``` git diff origin/7-6-stable:config/gitlab.yml.example origin/7-7-stable:config/gitlab.yml.example From 644a8437d0891a167cc369383ac7356a5b7672ab Mon Sep 17 00:00:00 2001 From: Kevin Lyda Date: Mon, 20 Apr 2015 10:31:18 +0100 Subject: [PATCH 03/97] Add link to services api doc. --- doc/api/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/api/README.md b/doc/api/README.md index dec530d0b8..f6757b0a6a 100644 --- a/doc/api/README.md +++ b/doc/api/README.md @@ -6,6 +6,7 @@ - [Session](session.md) - [Projects](projects.md) - [Project Snippets](project_snippets.md) +- [Services](services.md) - [Repositories](repositories.md) - [Repository Files](repository_files.md) - [Commits](commits.md) From fab876b9f9804ecbc950f676e3cf06e65db8acc1 Mon Sep 17 00:00:00 2001 From: Aurelio Jargas Date: Wed, 22 Apr 2015 18:41:05 -0300 Subject: [PATCH 04/97] Remove duplicate CHANGELOG line for v7.10.0 The other one is 3 lines below the removed. --- CHANGELOG | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 5bb6842f50..b537f4212d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -95,7 +95,6 @@ v 7.10.0 (unreleased) - Fixed link paths for HTTP and SSH on the admin project view (Jeremy Maziarz) - Fix and improve help rendering (Sullivan Sénéchal) - Fix final line in EmailsOnPush email diff being rendered as error. - - Authometic setup GitLab CI project for forks if origin project has GitLab CI enabled - Prevent duplicate Buildkite service creation. - Fix git over ssh errors 'fatal: protocol error: bad line length character' - Automatically setup GitLab CI project for forks if origin project has GitLab CI enabled From 9a2e3d3d8196afefe32b099162b17f7441de8fb1 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Thu, 23 Apr 2015 07:42:28 -0700 Subject: [PATCH 05/97] Fix broken file browsing with relative submodule in personal projects Closes https://github.com/gitlabhq/gitlabhq/issues/7554 --- CHANGELOG | 2 +- app/helpers/submodule_helper.rb | 2 +- spec/helpers/submodule_helper_spec.rb | 15 +++++++++++---- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 5bb6842f50..89dc7444a4 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -4,7 +4,7 @@ v 7.11.0 (unreleased) - Fix clone URL field and X11 Primary selection (Dmitry Medvinsky) - Ignore invalid lines in .gitmodules - Fix "Cannot move project" error message from popping up after a successful transfer (Stan Hu) - - + - Fix broken file browsing with relative submodule in personal projects (Stan Hu) - Add "Reply quoting selected text" shortcut key (`r`) - - diff --git a/app/helpers/submodule_helper.rb b/app/helpers/submodule_helper.rb index 9954617c76..e13d4eaf10 100644 --- a/app/helpers/submodule_helper.rb +++ b/app/helpers/submodule_helper.rb @@ -63,7 +63,7 @@ module SubmoduleHelper namespace = components.pop.gsub(/^\.\.$/, '') if namespace.empty? - namespace = @project.group.path + namespace = @project.namespace.name end [ diff --git a/spec/helpers/submodule_helper_spec.rb b/spec/helpers/submodule_helper_spec.rb index e99c3f5bc1..e98b75afab 100644 --- a/spec/helpers/submodule_helper_spec.rb +++ b/spec/helpers/submodule_helper_spec.rb @@ -117,34 +117,41 @@ describe SubmoduleHelper do context 'submodules with relative links' do let(:group) { create(:group) } let(:project) { create(:project, group: group) } + let(:commit_id) { sample_commit[:id] } before do self.instance_variable_set(:@project, project) end it 'one level down' do - commit_id = sample_commit[:id] result = relative_self_links('../test.git', commit_id) expect(result).to eq(["/#{group.path}/test", "/#{group.path}/test/tree/#{commit_id}"]) end it 'two levels down' do - commit_id = sample_commit[:id] result = relative_self_links('../../test.git', commit_id) expect(result).to eq(["/#{group.path}/test", "/#{group.path}/test/tree/#{commit_id}"]) end it 'one level down with namespace and repo' do - commit_id = sample_commit[:id] result = relative_self_links('../foobar/test.git', commit_id) expect(result).to eq(["/foobar/test", "/foobar/test/tree/#{commit_id}"]) end it 'two levels down with namespace and repo' do - commit_id = sample_commit[:id] result = relative_self_links('../foobar/baz/test.git', commit_id) expect(result).to eq(["/baz/test", "/baz/test/tree/#{commit_id}"]) end + + context 'personal project' do + let(:user) { create(:user) } + let(:project) { create(:project, namespace: user.namespace) } + + it 'one level down with personal project' do + result = relative_self_links('../test.git', commit_id) + expect(result).to eq(["/#{user.username}/test", "/#{user.username}/test/tree/#{commit_id}"]) + end + end end end From a62060b1de558dc61b7f1df63bbe8d7ffeeec632 Mon Sep 17 00:00:00 2001 From: Karen Carias Date: Fri, 24 Apr 2015 02:19:21 +0000 Subject: [PATCH 06/97] Added " How to maintain tight control over the number of active users on your GitLab installation" to documentation --- doc/raketasks/user_management.md | 35 ++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/doc/raketasks/user_management.md b/doc/raketasks/user_management.md index 80b01ca404..04a8126c16 100644 --- a/doc/raketasks/user_management.md +++ b/doc/raketasks/user_management.md @@ -47,3 +47,38 @@ sudo gitlab-rake gitlab:import:all_users_to_all_groups # installation from source bundle exec rake gitlab:import:all_users_to_all_groups RAILS_ENV=production ``` + +## Maintain tight control over the number of active users on your GitLab installation + +- Enable this setting to keep new users blocked until they have been cleared by the admin + +```bash +(default: false). +block_auto_created_users: false + +Base where we can search for users + +Ex. ou=People,dc=gitlab,dc=example + +base: '' + +Filter LDAP users + +Format: RFC 4515 http://tools.ietf.org/search/rfc4515 +Ex. (employeeType=developer) + +Note: GitLab does not support omniauth-ldap's custom filter syntax. + +user_filter: '' +``` + +- GitLab EE only: add more LDAP servers + +```bash +Choose an ID made of a-z and 0-9 . This ID will be stored in the database +so that GitLab can remember which LDAP server a user belongs to. +uswest2: +label: +host: +.... +``` \ No newline at end of file From 5f2e8b6147eecc8f9a946b4e964bbb99b676ec58 Mon Sep 17 00:00:00 2001 From: Guillaume Delbergue Date: Fri, 24 Apr 2015 10:00:31 +0200 Subject: [PATCH 07/97] Add footnotes support to Markdown Signed-off-by: Guillaume Delbergue --- CHANGELOG | 1 + app/helpers/gitlab_markdown_helper.rb | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 2e91c72a25..fd6ea54fbf 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -17,6 +17,7 @@ v 7.11.0 (unreleased) - Improve UI for sidebar. Increase separation between navigation and content - Improve new project command options (Ben Bodenmiller) - Prevent sending empty messages to HipChat (Chulki Lee) + - Add footnotes support to Markdown (Guillaume Delbergue) v 7.10.0 (unreleased) - Ignore submodules that are defined in .gitmodules but are checked in as directories. diff --git a/app/helpers/gitlab_markdown_helper.rb b/app/helpers/gitlab_markdown_helper.rb index aff7011edd..bc23450000 100644 --- a/app/helpers/gitlab_markdown_helper.rb +++ b/app/helpers/gitlab_markdown_helper.rb @@ -49,7 +49,8 @@ module GitlabMarkdownHelper strikethrough: true, lax_spacing: true, space_after_headers: true, - superscript: true + superscript: true, + footnotes: true ) end From aa9435cddbe57841b4572e05fb4e7756f8b47405 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Sat, 25 Apr 2015 19:18:09 -0400 Subject: [PATCH 08/97] Remove duplicate settings for default_url_options Closes internal https://dev.gitlab.org/gitlab/gitlabhq/issues/2269 --- app/controllers/application_controller.rb | 12 ------------ app/mailers/notify.rb | 7 +------ .../project_services/gitlab_issue_tracker_service.rb | 5 ----- 3 files changed, 1 insertion(+), 23 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index cfe2c76265..69fd790183 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -182,18 +182,6 @@ class ApplicationController < ActionController::Base response.headers["Expires"] = "Fri, 01 Jan 1990 00:00:00 GMT" end - def default_url_options - if !Rails.env.test? - port = Gitlab.config.gitlab.port unless Gitlab.config.gitlab_on_standard_port? - { host: Gitlab.config.gitlab.host, - protocol: Gitlab.config.gitlab.protocol, - port: port, - script_name: Gitlab.config.gitlab.relative_url_root } - else - super - end - end - def default_headers headers['X-Frame-Options'] = 'DENY' headers['X-XSS-Protection'] = '1; mode=block' diff --git a/app/mailers/notify.rb b/app/mailers/notify.rb index 2c0d451511..79fb48b00d 100644 --- a/app/mailers/notify.rb +++ b/app/mailers/notify.rb @@ -16,11 +16,6 @@ class Notify < ActionMailer::Base attr_accessor :current_user helper_method :current_user, :can? - default_url_options[:host] = Gitlab.config.gitlab.host - default_url_options[:protocol] = Gitlab.config.gitlab.protocol - default_url_options[:port] = Gitlab.config.gitlab.port unless Gitlab.config.gitlab_on_standard_port? - default_url_options[:script_name] = Gitlab.config.gitlab.relative_url_root - default from: Proc.new { default_sender_address.format } default reply_to: Gitlab.config.gitlab.email_reply_to @@ -69,7 +64,7 @@ class Notify < ActionMailer::Base # Only the displayed name changes; the actual email address is always the same. def sender(sender_id, send_from_user_email = false) return unless sender = User.find(sender_id) - + address = default_sender_address address.display_name = sender.name diff --git a/app/models/project_services/gitlab_issue_tracker_service.rb b/app/models/project_services/gitlab_issue_tracker_service.rb index 5f0553f3b0..0ebc0a3ba1 100644 --- a/app/models/project_services/gitlab_issue_tracker_service.rb +++ b/app/models/project_services/gitlab_issue_tracker_service.rb @@ -21,11 +21,6 @@ class GitlabIssueTrackerService < IssueTrackerService include Rails.application.routes.url_helpers - default_url_options[:host] = Gitlab.config.gitlab.host - default_url_options[:protocol] = Gitlab.config.gitlab.protocol - default_url_options[:port] = Gitlab.config.gitlab.port unless Gitlab.config.gitlab_on_standard_port? - default_url_options[:script_name] = Gitlab.config.gitlab.relative_url_root - prop_accessor :title, :description, :project_url, :issues_url, :new_issue_url def default? From 2c90579749459f0d4d5d534785aa3006bec1a444 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Sat, 25 Apr 2015 19:41:46 -0400 Subject: [PATCH 09/97] Set default_url_options in test environments too --- config/initializers/8_default_url_options.rb | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/config/initializers/8_default_url_options.rb b/config/initializers/8_default_url_options.rb index 8c1b56846d..8fd27b1d88 100644 --- a/config/initializers/8_default_url_options.rb +++ b/config/initializers/8_default_url_options.rb @@ -1,13 +1,11 @@ -unless Rails.env.test? - default_url_options = { - host: Gitlab.config.gitlab.host, - protocol: Gitlab.config.gitlab.protocol, - script_name: Gitlab.config.gitlab.relative_url_root - } +default_url_options = { + host: Gitlab.config.gitlab.host, + protocol: Gitlab.config.gitlab.protocol, + script_name: Gitlab.config.gitlab.relative_url_root +} - unless Gitlab.config.gitlab_on_standard_port? - default_url_options[:port] = Gitlab.config.gitlab.port - end - - Rails.application.routes.default_url_options = default_url_options +unless Gitlab.config.gitlab_on_standard_port? + default_url_options[:port] = Gitlab.config.gitlab.port end + +Rails.application.routes.default_url_options = default_url_options From 4ca2b99f4715288678ddd7e4ff509d4a7c481a62 Mon Sep 17 00:00:00 2001 From: Sullivan SENECHAL Date: Sun, 26 Apr 2015 22:49:12 +0200 Subject: [PATCH 10/97] Fix "`` is missing X-UA-Compatible `` tag that disables old IE compatibility modes" --- app/views/layouts/_head.html.haml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/views/layouts/_head.html.haml b/app/views/layouts/_head.html.haml index 0ff1665455..f72882d883 100644 --- a/app/views/layouts/_head.html.haml +++ b/app/views/layouts/_head.html.haml @@ -1,5 +1,6 @@ %head %meta{charset: "utf-8"} + %meta{'http-equiv' => 'X-UA-Compatible', content: 'IE=edge'} %meta{content: "GitLab Community Edition", name: "description"} %title From 570594a469fe481060d312d9d90980c5f9289e2f Mon Sep 17 00:00:00 2001 From: Sullivan SENECHAL Date: Sun, 26 Apr 2015 23:32:35 +0200 Subject: [PATCH 11/97] Fix '.container or .container-fluid should be the first child inside of a .navbar' issue --- app/views/layouts/_head_panel.html.haml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/layouts/_head_panel.html.haml b/app/views/layouts/_head_panel.html.haml index 281ce31fe9..8d33175ce4 100644 --- a/app/views/layouts/_head_panel.html.haml +++ b/app/views/layouts/_head_panel.html.haml @@ -1,6 +1,6 @@ %header.navbar.navbar-fixed-top.navbar-gitlab{ class: nav_header_class } - .navbar-inner - .container + .container + .navbar-inner %div.app_logo = link_to root_path, class: "home has_bottom_tooltip", title: "Dashboard" do = brand_header_logo From 76e720dfa94f8dc8daf1544f571be60990b79da8 Mon Sep 17 00:00:00 2001 From: Sullivan SENECHAL Date: Mon, 27 Apr 2015 00:00:17 +0200 Subject: [PATCH 12/97] Bootstrap 3.3.4 --- Gemfile.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index f0f8601a76..b0a52f477a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -47,7 +47,7 @@ GEM astrolabe (1.3.0) parser (>= 2.2.0.pre.3, < 3.0) attr_required (1.0.0) - autoprefixer-rails (5.1.6) + autoprefixer-rails (5.1.11) execjs json awesome_print (1.2.0) @@ -60,7 +60,7 @@ GEM erubis (>= 2.6.6) binding_of_caller (0.7.2) debug_inspector (>= 0.0.1) - bootstrap-sass (3.3.3) + bootstrap-sass (3.3.4.1) autoprefixer-rails (>= 5.0.0.1) sass (>= 3.2.19) brakeman (3.0.1) @@ -151,7 +151,7 @@ GEM escape_utils (0.2.4) eventmachine (1.0.4) excon (0.32.1) - execjs (2.0.2) + execjs (2.5.2) expression_parser (0.9.0) factory_girl (4.3.0) activesupport (>= 3.0.0) From f28f5e49f62f8ae780d991cf266cff95e1a5c057 Mon Sep 17 00:00:00 2001 From: Sullivan SENECHAL Date: Mon, 27 Apr 2015 00:43:02 +0200 Subject: [PATCH 13/97] Fix wrong placement of show-aside link --- app/views/admin/projects/index.html.haml | 4 ++-- app/views/admin/users/index.html.haml | 4 ++-- app/views/dashboard/projects/starred.html.haml | 5 ++--- app/views/dashboard/show.html.haml | 4 ++-- app/views/groups/show.html.haml | 5 +++-- app/views/projects/issues/_discussion.html.haml | 5 +++-- app/views/projects/merge_requests/_discussion.html.haml | 4 ++-- app/views/projects/show.html.haml | 4 ++-- app/views/shared/_show_aside.html.haml | 2 ++ app/views/users/show.html.haml | 4 ++-- 10 files changed, 22 insertions(+), 19 deletions(-) create mode 100644 app/views/shared/_show_aside.html.haml diff --git a/app/views/admin/projects/index.html.haml b/app/views/admin/projects/index.html.haml index 3bbe10bc27..0a13791029 100644 --- a/app/views/admin/projects/index.html.haml +++ b/app/views/admin/projects/index.html.haml @@ -1,6 +1,6 @@ += render 'shared/show_aside' + .row - = link_to '#aside', class: 'show-aside' do - %i.fa.fa-angle-left %aside.col-md-3 .admin-filter = form_tag admin_namespaces_projects_path, method: :get, class: '' do diff --git a/app/views/admin/users/index.html.haml b/app/views/admin/users/index.html.haml index 25c1730ef7..23a9d76963 100644 --- a/app/views/admin/users/index.html.haml +++ b/app/views/admin/users/index.html.haml @@ -1,6 +1,6 @@ += render 'shared/show_aside' + .row - = link_to '#aside', class: 'show-aside' do - %i.fa.fa-angle-left %aside.col-md-3 .admin-filter %ul.nav.nav-pills.nav-stacked diff --git a/app/views/dashboard/projects/starred.html.haml b/app/views/dashboard/projects/starred.html.haml index f4ad2b294b..67943f2267 100644 --- a/app/views/dashboard/projects/starred.html.haml +++ b/app/views/dashboard/projects/starred.html.haml @@ -1,4 +1,6 @@ - if @projects.any? + = render 'shared/show_aside' + .dashboard.row %section.activities.col-md-8 = render 'dashboard/activities' @@ -15,9 +17,6 @@ = render 'shared/projects_list', projects: @projects, projects_limit: 20, stars: true, avatar: false - = link_to '#aside', class: 'show-aside' do - %i.fa.fa-angle-left - - else %h3 You don't have starred projects yet %p.slead Visit project page and press on star icon and it will appear on this page. diff --git a/app/views/dashboard/show.html.haml b/app/views/dashboard/show.html.haml index 2754a4894d..5001c2101e 100644 --- a/app/views/dashboard/show.html.haml +++ b/app/views/dashboard/show.html.haml @@ -3,13 +3,13 @@ = auto_discovery_link_tag(:atom, dashboard_url(format: :atom, private_token: current_user.private_token), title: "All activity") - if @projects.any? + = render 'shared/show_aside' + .dashboard.row %section.activities.col-md-8 = render 'activities' %aside.col-md-4 = render 'sidebar' - = link_to '#aside', class: 'show-aside' do - %i.fa.fa-angle-left - else = render "zero_authorized_projects" diff --git a/app/views/groups/show.html.haml b/app/views/groups/show.html.haml index 3db0dfa59b..1678311141 100644 --- a/app/views/groups/show.html.haml +++ b/app/views/groups/show.html.haml @@ -13,6 +13,9 @@ .description = escaped_autolink(@group.description) %hr + + = render 'shared/show_aside' + .row %section.activities.col-md-8 .hidden-xs @@ -33,5 +36,3 @@ = spinner %aside.side.col-md-4 = render "projects", projects: @projects - = link_to '#aside', class: 'show-aside' do - %i.fa.fa-angle-left diff --git a/app/views/projects/issues/_discussion.html.haml b/app/views/projects/issues/_discussion.html.haml index 288b48f458..ceca265301 100644 --- a/app/views/projects/issues/_discussion.html.haml +++ b/app/views/projects/issues/_discussion.html.haml @@ -4,6 +4,9 @@ = link_to 'Reopen Issue', issue_path(@issue, issue: {state_event: :reopen }, status_only: true), method: :put, class: "btn btn-grouped btn-reopen js-note-target-reopen", title: 'Reopen Issue' - else = link_to 'Close Issue', issue_path(@issue, issue: {state_event: :close }, status_only: true), method: :put, class: "btn btn-grouped btn-close js-note-target-close", title: "Close Issue" + += render 'shared/show_aside' + .row %section.col-md-9 .votes-holder.pull-right @@ -29,5 +32,3 @@ - @issue.labels.each do |label| = link_to namespace_project_issues_path(@project.namespace, @project, label_name: label.name) do = render_colored_label(label) - = link_to '#aside', class: 'show-aside' do - %i.fa.fa-angle-left diff --git a/app/views/projects/merge_requests/_discussion.html.haml b/app/views/projects/merge_requests/_discussion.html.haml index eb72eaabd8..9a2aa9c3de 100644 --- a/app/views/projects/merge_requests/_discussion.html.haml +++ b/app/views/projects/merge_requests/_discussion.html.haml @@ -5,6 +5,8 @@ - if @merge_request.closed? = link_to 'Reopen', merge_request_path(@merge_request, merge_request: {state_event: :reopen }), method: :put, class: "btn btn-grouped btn-reopen reopen-mr-link js-note-target-reopen", title: "Reopen merge request" += render 'shared/show_aside' + .row %section.col-md-9 .votes-holder.pull-right @@ -27,5 +29,3 @@ - @merge_request.labels.each do |label| = link_to namespace_project_merge_requests_path(@project.namespace, @project, label_name: label.name) do = render_colored_label(label) - = link_to '#aside', class: 'show-aside' do - %i.fa.fa-angle-left diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml index 1787caa243..cd18ae0c8d 100644 --- a/app/views/projects/show.html.haml +++ b/app/views/projects/show.html.haml @@ -37,9 +37,9 @@ .tab-content .tab-pane.active#tab-activity + = render 'shared/show_aside' + .row - = link_to '#aside', class: 'show-aside' do - %i.fa.fa-angle-left %section.col-md-9 .hidden-xs = render "events/event_last_push", event: @last_push diff --git a/app/views/shared/_show_aside.html.haml b/app/views/shared/_show_aside.html.haml new file mode 100644 index 0000000000..3ac9b11b4f --- /dev/null +++ b/app/views/shared/_show_aside.html.haml @@ -0,0 +1,2 @@ += link_to '#aside', class: 'show-aside' do + %i.fa.fa-angle-left diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml index 15a3f741e6..0576c6a11b 100644 --- a/app/views/users/show.html.haml +++ b/app/views/users/show.html.haml @@ -1,9 +1,9 @@ = content_for :meta_tags do = auto_discovery_link_tag(:atom, user_url(@user, format: :atom), title: "#{@user.name} activity") += render 'shared/show_aside' + .row - = link_to '#aside', class: 'show-aside' do - %i.fa.fa-angle-left %section.col-md-8 .header-with-avatar = image_tag avatar_icon(@user.email, 90), class: "avatar avatar-tile s90", alt: '' From ef0055b52d85bb9f38c36303d2291ab2a29d0780 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Sun, 26 Apr 2015 21:46:27 -0700 Subject: [PATCH 14/97] Fix bug where commit data would not appear in some subdirectories The upgrade from Rails v4.1.2 to v4.1.9 (76aad9b76ed) caused slashes in a tree to be escaped automatically. Using wildcard globs prevents this behavior. Closes #1478, #1459 --- CHANGELOG | 2 +- config/routes.rb | 2 +- spec/lib/extracts_path_spec.rb | 16 ++++++++++++++++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 92ae6767ea..e0c4033c3b 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -16,7 +16,7 @@ v 7.11.0 (unreleased) - Don't crash when an MR from a fork has a cross-reference comment from the target project on of its commits. - Include commit comments in MR from a forked project. - - - + - Fix bug where commit data would not appear in some subdirectories (Stan Hu) - Fix bug where Slack service channel was not saved in admin template settings. (Stan Hu) - Move snippets UI to fluid layout - Improve UI for sidebar. Increase separation between navigation and content diff --git a/config/routes.rb b/config/routes.rb index e059f5830f..4b38dede7b 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -435,7 +435,7 @@ Gitlab::Application.routes.draw do member do # tree viewer logs get 'logs_tree', constraints: { id: Gitlab::Regex.git_reference_regex } - get 'logs_tree/:path' => 'refs#logs_tree', as: :logs_file, constraints: { + get 'logs_tree/*path' => 'refs#logs_tree', as: :logs_file, constraints: { id: Gitlab::Regex.git_reference_regex, path: /.*/ } diff --git a/spec/lib/extracts_path_spec.rb b/spec/lib/extracts_path_spec.rb index ac602eac15..05bcebaa3a 100644 --- a/spec/lib/extracts_path_spec.rb +++ b/spec/lib/extracts_path_spec.rb @@ -2,6 +2,8 @@ require 'spec_helper' describe ExtractsPath do include ExtractsPath + include RepoHelpers + include Rails.application.routes.url_helpers let(:project) { double('project') } @@ -11,6 +13,20 @@ describe ExtractsPath do project.stub(path_with_namespace: 'gitlab/gitlab-ci') end + describe '#assign_ref' do + let(:ref) { sample_commit[:id] } + let(:params) { {path: sample_commit[:line_code_path], ref: ref} } + + before do + @project = create(:project) + end + + it "log tree path should have no escape sequences" do + assign_ref_vars + expect(@logs_path).to eq("/#{@project.path_with_namespace}/refs/#{ref}/logs_tree/files/ruby/popen.rb") + end + end + describe '#extract_ref' do it "returns an empty pair when no @project is set" do @project = nil From 57c724558db9c17b7d4c27fcbadf93451b801ad7 Mon Sep 17 00:00:00 2001 From: Chulki Lee Date: Fri, 23 Jan 2015 16:29:02 -0800 Subject: [PATCH 15/97] Add api version property on hipchat service --- app/controllers/projects/services_controller.rb | 2 +- app/models/project_services/hipchat_service.rb | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/app/controllers/projects/services_controller.rb b/app/controllers/projects/services_controller.rb index 2080ee9a00..dc18bbd8d5 100644 --- a/app/controllers/projects/services_controller.rb +++ b/app/controllers/projects/services_controller.rb @@ -1,5 +1,5 @@ class Projects::ServicesController < Projects::ApplicationController - ALLOWED_PARAMS = [:title, :token, :type, :active, :api_key, :subdomain, + ALLOWED_PARAMS = [:title, :token, :type, :active, :api_key, :api_version, :subdomain, :room, :recipients, :project_url, :webhook, :user_key, :device, :priority, :sound, :bamboo_url, :username, :password, :build_key, :server, :teamcity_url, :build_type, diff --git a/app/models/project_services/hipchat_service.rb b/app/models/project_services/hipchat_service.rb index 2fa5f0ce71..3a15b2207e 100644 --- a/app/models/project_services/hipchat_service.rb +++ b/app/models/project_services/hipchat_service.rb @@ -20,7 +20,7 @@ class HipchatService < Service MAX_COMMITS = 3 - prop_accessor :token, :room, :server, :notify, :color + prop_accessor :token, :room, :server, :notify, :color, :api_version validates :token, presence: true, if: :activated? def title @@ -41,6 +41,8 @@ class HipchatService < Service { type: 'text', name: 'room', placeholder: 'Room name or ID' }, { type: 'checkbox', name: 'notify' }, { type: 'select', name: 'color', choices: ['yellow', 'red', 'green', 'purple', 'gray', 'random'] }, + { type: 'text', name: 'api_version', + placeholder: 'Leave blank for default (v2)' }, { type: 'text', name: 'server', placeholder: 'Leave blank for default. https://hipchat.example.com' } ] @@ -60,7 +62,7 @@ class HipchatService < Service private def gate - options = { api_version: 'v2' } + options = { api_version: api_version || 'v2' } options[:server_url] = server unless server.blank? @gate ||= HipChat::Client.new(token, options) end From 44afcd2019d3c1c77c91f24a08e657331568c39f Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Mon, 27 Apr 2015 06:09:20 -0700 Subject: [PATCH 16/97] Fix DB error when trying to tag a repository Upon tagging a repository, an error due to a missing migration occurred: ``` PG::Error: ERROR: column "taggings_count" does not exist LINE 1: UPDATE "tags" SET "taggings_count" = COALESCE("taggings_coun... ``` Ran `rake acts_as_taggable_on_engine:install:migrations`, removed the first migration that created the `tags` and `taggings` table, and added the rest. Closes #1512 Closes https://github.com/gitlabhq/gitlabhq/issues/6867 Closes https://github.com/gitlabhq/gitlabhq/issues/9194 --- CHANGELOG | 2 +- ...ique_indices.acts_as_taggable_on_engine.rb | 20 +++++++++++++++++++ ...ache_to_tags.acts_as_taggable_on_engine.rb | 15 ++++++++++++++ ...ggable_index.acts_as_taggable_on_engine.rb | 10 ++++++++++ ...or_tag_names.acts_as_taggable_on_engine.rb | 10 ++++++++++ db/schema.rb | 7 +++++-- features/project/project.feature | 7 +++++++ features/steps/project/project.rb | 8 ++++++++ 8 files changed, 76 insertions(+), 3 deletions(-) create mode 100644 db/migrate/20150425164648_add_missing_unique_indices.acts_as_taggable_on_engine.rb create mode 100644 db/migrate/20150425164649_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb create mode 100644 db/migrate/20150425164650_add_missing_taggable_index.acts_as_taggable_on_engine.rb create mode 100644 db/migrate/20150425164651_change_collation_for_tag_names.acts_as_taggable_on_engine.rb diff --git a/CHANGELOG b/CHANGELOG index 38dcb7dd22..840ef787be 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -7,7 +7,7 @@ v 7.11.0 (unreleased) - Fix "Cannot move project" error message from popping up after a successful transfer (Stan Hu) - Redirect to sign in page after signing out. - Fix "Hello @username." references not working by no longer allowing usernames to end in period. - - + - Fix DB error when trying to tag a repository (Stan Hu) - Add "Reply quoting selected text" shortcut key (`r`) - Fix bug causing `@whatever` inside an issue's first code block to be picked up as a user mention. - Fix bug causing `@whatever` inside an inline code snippet (backtick-style) to be picked up as a user mention. diff --git a/db/migrate/20150425164648_add_missing_unique_indices.acts_as_taggable_on_engine.rb b/db/migrate/20150425164648_add_missing_unique_indices.acts_as_taggable_on_engine.rb new file mode 100644 index 0000000000..4ca676f6c7 --- /dev/null +++ b/db/migrate/20150425164648_add_missing_unique_indices.acts_as_taggable_on_engine.rb @@ -0,0 +1,20 @@ +# This migration comes from acts_as_taggable_on_engine (originally 2) +class AddMissingUniqueIndices < ActiveRecord::Migration + def self.up + add_index :tags, :name, unique: true + + remove_index :taggings, :tag_id + remove_index :taggings, [:taggable_id, :taggable_type, :context] + add_index :taggings, + [:tag_id, :taggable_id, :taggable_type, :context, :tagger_id, :tagger_type], + unique: true, name: 'taggings_idx' + end + + def self.down + remove_index :tags, :name + + remove_index :taggings, name: 'taggings_idx' + add_index :taggings, :tag_id + add_index :taggings, [:taggable_id, :taggable_type, :context] + end +end diff --git a/db/migrate/20150425164649_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb b/db/migrate/20150425164649_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb new file mode 100644 index 0000000000..8edb508078 --- /dev/null +++ b/db/migrate/20150425164649_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb @@ -0,0 +1,15 @@ +# This migration comes from acts_as_taggable_on_engine (originally 3) +class AddTaggingsCounterCacheToTags < ActiveRecord::Migration + def self.up + add_column :tags, :taggings_count, :integer, default: 0 + + ActsAsTaggableOn::Tag.reset_column_information + ActsAsTaggableOn::Tag.find_each do |tag| + ActsAsTaggableOn::Tag.reset_counters(tag.id, :taggings) + end + end + + def self.down + remove_column :tags, :taggings_count + end +end diff --git a/db/migrate/20150425164650_add_missing_taggable_index.acts_as_taggable_on_engine.rb b/db/migrate/20150425164650_add_missing_taggable_index.acts_as_taggable_on_engine.rb new file mode 100644 index 0000000000..71f2d7f433 --- /dev/null +++ b/db/migrate/20150425164650_add_missing_taggable_index.acts_as_taggable_on_engine.rb @@ -0,0 +1,10 @@ +# This migration comes from acts_as_taggable_on_engine (originally 4) +class AddMissingTaggableIndex < ActiveRecord::Migration + def self.up + add_index :taggings, [:taggable_id, :taggable_type, :context] + end + + def self.down + remove_index :taggings, [:taggable_id, :taggable_type, :context] + end +end diff --git a/db/migrate/20150425164651_change_collation_for_tag_names.acts_as_taggable_on_engine.rb b/db/migrate/20150425164651_change_collation_for_tag_names.acts_as_taggable_on_engine.rb new file mode 100644 index 0000000000..bfb06bc7cd --- /dev/null +++ b/db/migrate/20150425164651_change_collation_for_tag_names.acts_as_taggable_on_engine.rb @@ -0,0 +1,10 @@ +# This migration comes from acts_as_taggable_on_engine (originally 5) +# This migration is added to circumvent issue #623 and have special characters +# work properly +class ChangeCollationForTagNames < ActiveRecord::Migration + def up + if ActsAsTaggableOn::Utils.using_mysql? + execute("ALTER TABLE tags MODIFY name varchar(255) CHARACTER SET utf8 COLLATE utf8_bin;") + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 8683c0446f..adfc241dea 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -433,13 +433,16 @@ ActiveRecord::Schema.define(version: 20150425173433) do t.datetime "created_at" end - add_index "taggings", ["tag_id"], name: "index_taggings_on_tag_id", using: :btree + add_index "taggings", ["tag_id", "taggable_id", "taggable_type", "context", "tagger_id", "tagger_type"], name: "taggings_idx", unique: true, using: :btree add_index "taggings", ["taggable_id", "taggable_type", "context"], name: "index_taggings_on_taggable_id_and_taggable_type_and_context", using: :btree create_table "tags", force: true do |t| - t.string "name" + t.string "name" + t.integer "taggings_count", default: 0 end + add_index "tags", ["name"], name: "index_tags_on_name", unique: true, using: :btree + create_table "users", force: true do |t| t.string "email", default: "", null: false t.string "encrypted_password", default: "", null: false diff --git a/features/project/project.feature b/features/project/project.feature index 3e1fd54bee..ae28312a69 100644 --- a/features/project/project.feature +++ b/features/project/project.feature @@ -55,3 +55,10 @@ Feature: Project Then I should see project "Forum" README And I visit project "Shop" page Then I should see project "Shop" README + + Scenario: I tag a project + When I visit edit project "Shop" page + Then I should see project settings + And I add project tags + And I save project + Then I should see project tags diff --git a/features/steps/project/project.rb b/features/steps/project/project.rb index d39c8e7d2d..f14396bcff 100644 --- a/features/steps/project/project.rb +++ b/features/steps/project/project.rb @@ -94,4 +94,12 @@ class Spinach::Features::Project < Spinach::FeatureSteps page.should have_link 'README.md' page.should have_content 'testme' end + + step 'I add project tags' do + fill_in 'Tags', with: 'tag1, tag2' + end + + step 'I should see project tags' do + expect(find_field('Tags').value).to eq 'tag1, tag2' + end end From f50103ad7e16f05b7c14e5976ffcedd59994d844 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Thu, 23 Apr 2015 21:32:51 +0000 Subject: [PATCH 17/97] Upgrade Docker build to v7.10.0 --- docker/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index bb25bb677c..69e34955b7 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -11,7 +11,7 @@ RUN apt-get update -q \ # If the Omnibus package version below is outdated please contribute a merge request to update it. # If you run GitLab Enterprise Edition point it to a location where you have downloaded it. RUN TMP_FILE=$(mktemp); \ - wget -q -O $TMP_FILE https://downloads-packages.s3.amazonaws.com/ubuntu-14.04/gitlab_7.9.2-omnibus-1_amd64.deb \ + wget -q -O $TMP_FILE https://downloads-packages.s3.amazonaws.com/ubuntu-14.04/gitlab-ce_7.10.0~omnibus.2-1_amd64.deb \ && dpkg -i $TMP_FILE \ && rm -f $TMP_FILE From bc9ba5237cafd4b24405596f0c9e8af099635c29 Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Mon, 27 Apr 2015 16:29:31 +0300 Subject: [PATCH 18/97] Revert "Added X-GitLab-Event header for web hooks" This reverts commit 548f182814acd0f7a110e6c165c186e345901b00. --- CHANGELOG | 1 - app/controllers/admin/hooks_controller.rb | 2 +- app/models/hooks/web_hook.rb | 16 +++++----------- app/models/project.rb | 2 +- app/services/system_hooks_service.rb | 6 +++--- app/services/test_hook_service.rb | 2 +- app/workers/project_web_hook_worker.rb | 4 ++-- app/workers/system_hook_worker.rb | 4 ++-- lib/api/system_hooks.rb | 2 +- spec/models/hooks/web_hook_spec.rb | 14 +++++--------- 10 files changed, 21 insertions(+), 32 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 38dcb7dd22..97b8c182c4 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -11,7 +11,6 @@ v 7.11.0 (unreleased) - Add "Reply quoting selected text" shortcut key (`r`) - Fix bug causing `@whatever` inside an issue's first code block to be picked up as a user mention. - Fix bug causing `@whatever` inside an inline code snippet (backtick-style) to be picked up as a user mention. - - Added GitLab Event header for project hooks - - Show Atom feed buttons everywhere where applicable. - Add project activity atom feed. diff --git a/app/controllers/admin/hooks_controller.rb b/app/controllers/admin/hooks_controller.rb index 690096bdbc..0a463239d7 100644 --- a/app/controllers/admin/hooks_controller.rb +++ b/app/controllers/admin/hooks_controller.rb @@ -33,7 +33,7 @@ class Admin::HooksController < Admin::ApplicationController owner_name: "Someone", owner_email: "example@gitlabhq.com" } - @hook.execute(data, 'system_hooks') + @hook.execute(data) redirect_to :back end diff --git a/app/models/hooks/web_hook.rb b/app/models/hooks/web_hook.rb index e9fd441352..315d96af1b 100644 --- a/app/models/hooks/web_hook.rb +++ b/app/models/hooks/web_hook.rb @@ -30,15 +30,12 @@ class WebHook < ActiveRecord::Base validates :url, presence: true, format: { with: /\A#{URI.regexp(%w(http https))}\z/, message: "should be a valid url" } - def execute(data, hook_name) + def execute(data) parsed_url = URI.parse(url) if parsed_url.userinfo.blank? WebHook.post(url, body: data.to_json, - headers: { - "Content-Type" => "application/json", - "X-Gitlab-Event" => hook_name.singularize.titleize - }, + headers: { "Content-Type" => "application/json" }, verify: false) else post_url = url.gsub("#{parsed_url.userinfo}@", "") @@ -48,10 +45,7 @@ class WebHook < ActiveRecord::Base } WebHook.post(post_url, body: data.to_json, - headers: { - "Content-Type" => "application/json", - "X-Gitlab-Event" => hook_name.singularize.titleize - }, + headers: { "Content-Type" => "application/json" }, verify: false, basic_auth: auth) end @@ -60,7 +54,7 @@ class WebHook < ActiveRecord::Base false end - def async_execute(data, hook_name) - Sidekiq::Client.enqueue(ProjectWebHookWorker, id, data, hook_name) + def async_execute(data) + Sidekiq::Client.enqueue(ProjectWebHookWorker, id, data) end end diff --git a/app/models/project.rb b/app/models/project.rb index 391c9ed6e9..397232e98d 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -483,7 +483,7 @@ class Project < ActiveRecord::Base def execute_hooks(data, hooks_scope = :push_hooks) hooks.send(hooks_scope).each do |hook| - hook.async_execute(data, hooks_scope.to_s) + hook.async_execute(data) end end diff --git a/app/services/system_hooks_service.rb b/app/services/system_hooks_service.rb index 60235b6be2..c5d0b08845 100644 --- a/app/services/system_hooks_service.rb +++ b/app/services/system_hooks_service.rb @@ -7,12 +7,12 @@ class SystemHooksService def execute_hooks(data) SystemHook.all.each do |sh| - async_execute_hook(sh, data, 'system_hooks') + async_execute_hook sh, data end end - def async_execute_hook(hook, data, hook_name) - Sidekiq::Client.enqueue(SystemHookWorker, hook.id, data, hook_name) + def async_execute_hook(hook, data) + Sidekiq::Client.enqueue(SystemHookWorker, hook.id, data) end def build_event_data(model, event) diff --git a/app/services/test_hook_service.rb b/app/services/test_hook_service.rb index e85e58751e..21ec2c01cb 100644 --- a/app/services/test_hook_service.rb +++ b/app/services/test_hook_service.rb @@ -1,6 +1,6 @@ class TestHookService def execute(hook, current_user) data = Gitlab::PushDataBuilder.build_sample(hook.project, current_user) - hook.execute(data, 'push_hooks') + hook.execute(data) end end diff --git a/app/workers/project_web_hook_worker.rb b/app/workers/project_web_hook_worker.rb index fb87896528..73085c046b 100644 --- a/app/workers/project_web_hook_worker.rb +++ b/app/workers/project_web_hook_worker.rb @@ -3,8 +3,8 @@ class ProjectWebHookWorker sidekiq_options queue: :project_web_hook - def perform(hook_id, data, hook_name) + def perform(hook_id, data) data = data.with_indifferent_access - WebHook.find(hook_id).execute(data, hook_name) + WebHook.find(hook_id).execute(data) end end diff --git a/app/workers/system_hook_worker.rb b/app/workers/system_hook_worker.rb index a122c27476..3ebc62b7e7 100644 --- a/app/workers/system_hook_worker.rb +++ b/app/workers/system_hook_worker.rb @@ -3,7 +3,7 @@ class SystemHookWorker sidekiq_options queue: :system_hook - def perform(hook_id, data, hook_name) - SystemHook.find(hook_id).execute(data, hook_name) + def perform(hook_id, data) + SystemHook.find(hook_id).execute data end end diff --git a/lib/api/system_hooks.rb b/lib/api/system_hooks.rb index 22b8f90dc5..518964db50 100644 --- a/lib/api/system_hooks.rb +++ b/lib/api/system_hooks.rb @@ -47,7 +47,7 @@ module API owner_name: "Someone", owner_email: "example@gitlabhq.com" } - @hook.execute(data, 'system_hooks') + @hook.execute(data) data end diff --git a/spec/models/hooks/web_hook_spec.rb b/spec/models/hooks/web_hook_spec.rb index 14f873e6b5..67ec9193ad 100644 --- a/spec/models/hooks/web_hook_spec.rb +++ b/spec/models/hooks/web_hook_spec.rb @@ -52,26 +52,22 @@ describe ProjectHook do end it "POSTs to the web hook URL" do - @project_hook.execute(@data, 'push_hooks') - expect(WebMock).to have_requested(:post, @project_hook.url). - with(headers: {'Content-Type'=>'application/json', 'X-Gitlab-Event'=>'Push Hook'}). - once + @project_hook.execute(@data) + expect(WebMock).to have_requested(:post, @project_hook.url).once end it "POSTs the data as JSON" do json = @data.to_json - @project_hook.execute(@data, 'push_hooks') - expect(WebMock).to have_requested(:post, @project_hook.url). - with(headers: {'Content-Type'=>'application/json', 'X-Gitlab-Event'=>'Push Hook'}). - once + @project_hook.execute(@data) + expect(WebMock).to have_requested(:post, @project_hook.url).with(body: json).once end it "catches exceptions" do expect(WebHook).to receive(:post).and_raise("Some HTTP Post error") expect { - @project_hook.execute(@data, 'push_hooks') + @project_hook.execute(@data) }.to raise_error end end From a1c01bc19bb48e921566304305ef3cfba02e671b Mon Sep 17 00:00:00 2001 From: Jakub Jirutka Date: Mon, 9 Feb 2015 00:01:31 +0100 Subject: [PATCH 19/97] Fix (project_)name_regex to accept non-ASCII letters and dash --- CHANGELOG | 1 + lib/gitlab/regex.rb | 8 ++++---- spec/lib/gitlab/regex_spec.rb | 3 +++ 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 38dcb7dd22..c18650e17b 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -26,6 +26,7 @@ v 7.11.0 (unreleased) - Prevent sending empty messages to HipChat (Chulki Lee) - Improve UI for mobile phones on dashboard and project pages - Add room notification and message color option for HipChat + - Allow to use non-ASCII letters and dashes in project and namespace name. (Jakub Jirutka) v 7.10.0 - Ignore submodules that are defined in .gitmodules but are checked in as directories. diff --git a/lib/gitlab/regex.rb b/lib/gitlab/regex.rb index 0571574aa4..9f1adc860d 100644 --- a/lib/gitlab/regex.rb +++ b/lib/gitlab/regex.rb @@ -15,20 +15,20 @@ module Gitlab def namespace_name_regex - @namespace_name_regex ||= /\A[a-zA-Z0-9_\-\. ]*\z/.freeze + @namespace_name_regex ||= /\A[\p{Alnum}\p{Pd}_\. ]*\z/.freeze end def namespace_name_regex_message - "can contain only letters, digits, '_', '-', '.' and space." + "can contain only letters, digits, '_', '.', dash and space." end def project_name_regex - @project_name_regex ||= /\A[a-zA-Z0-9_.][a-zA-Z0-9_\-\. ]*\z/.freeze + @project_name_regex ||= /\A[\p{Alnum}_][\p{Alnum}\p{Pd}_\. ]*\z/.freeze end def project_name_regex_message - "can contain only letters, digits, '_', '-', '.' and space. " \ + "can contain only letters, digits, '_', '.', dash and space. " \ "It must start with letter, digit or '_'." end diff --git a/spec/lib/gitlab/regex_spec.rb b/spec/lib/gitlab/regex_spec.rb index 727884c41c..7fdc8fa600 100644 --- a/spec/lib/gitlab/regex_spec.rb +++ b/spec/lib/gitlab/regex_spec.rb @@ -1,3 +1,4 @@ +# coding: utf-8 require 'spec_helper' describe Gitlab::Regex do @@ -16,6 +17,8 @@ describe Gitlab::Regex do it { expect('GitLab CE').to match(Gitlab::Regex.project_name_regex) } it { expect('100 lines').to match(Gitlab::Regex.project_name_regex) } it { expect('gitlab.git').to match(Gitlab::Regex.project_name_regex) } + it { expect('Český název').to match(Gitlab::Regex.project_name_regex) } + it { expect('Dash – is this').to match(Gitlab::Regex.project_name_regex) } it { expect('?gitlab').not_to match(Gitlab::Regex.project_name_regex) } end end From f21e26966805a24f777352fe441f51db1ba6e96a Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 27 Apr 2015 18:05:51 +0300 Subject: [PATCH 20/97] Fix adding new group members from admin area Signed-off-by: Dmitriy Zaporozhets --- CHANGELOG | 2 +- app/views/admin/groups/show.html.haml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 38dcb7dd22..8b8df0444e 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -17,7 +17,7 @@ v 7.11.0 (unreleased) - Add project activity atom feed. - Don't crash when an MR from a fork has a cross-reference comment from the target project on of its commits. - Include commit comments in MR from a forked project. - - + - Fix adding new group members from admin area - Add default project and snippet visibility settings to the admin web UI. - Fix bug where Slack service channel was not saved in admin template settings. (Stan Hu) - Move snippets UI to fluid layout diff --git a/app/views/admin/groups/show.html.haml b/app/views/admin/groups/show.html.haml index 14996dcd6a..427f38018b 100644 --- a/app/views/admin/groups/show.html.haml +++ b/app/views/admin/groups/show.html.haml @@ -60,7 +60,7 @@ = form_tag members_update_admin_group_path(@group), id: "new_project_member", class: "bulk_import", method: :put do %div - = users_select_tag(:user_ids, multiple: true, email_user: true) + = users_select_tag(:user_ids, multiple: true, email_user: true, scope: :all) %div.prepend-top-10 = select_tag :access_level, options_for_select(GroupMember.access_level_roles), class: "project-access-select select2" %hr From 79d0b69345477fca94818a1c9d18b6a936e82189 Mon Sep 17 00:00:00 2001 From: jubianchi Date: Thu, 29 Jan 2015 08:22:07 +0100 Subject: [PATCH 21/97] Send 500 errors as JSON in the API --- lib/api/api.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/api/api.rb b/lib/api/api.rb index 60858a3940..d2a35c78fc 100644 --- a/lib/api/api.rb +++ b/lib/api/api.rb @@ -19,7 +19,7 @@ module API message << " " << trace.join("\n ") API.logger.add Logger::FATAL, message - rack_response({ 'message' => '500 Internal Server Error' }, 500) + rack_response({ 'message' => '500 Internal Server Error' }.to_json, 500) end format :json From 3070b2cfc7bc09dac42f4af3724c27ecc1ed7a97 Mon Sep 17 00:00:00 2001 From: jubianchi Date: Thu, 29 Jan 2015 12:37:17 +0100 Subject: [PATCH 22/97] Add a rake task to automatically restart foreman when changes occur --- Gemfile | 1 + Gemfile.lock | 13 ++++++++----- lib/tasks/dev.rake | 5 +++++ 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/Gemfile b/Gemfile index 3e1fa01675..ea62396d8a 100644 --- a/Gemfile +++ b/Gemfile @@ -208,6 +208,7 @@ group :development do gem "letter_opener" gem 'quiet_assets', '~> 1.0.1' gem 'rack-mini-profiler', require: false + gem 'rerun', '~> 0.10.0' # Better errors handler gem 'better_errors' diff --git a/Gemfile.lock b/Gemfile.lock index 0f965d7b54..676a519790 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -167,7 +167,7 @@ GEM faraday (>= 0.7.4, < 0.9) fastercsv (1.5.5) ffaker (1.22.1) - ffi (1.9.3) + ffi (1.9.8) fog (1.21.0) fog-brightbox fog-core (~> 1.21, >= 1.21.1) @@ -323,8 +323,8 @@ GEM addressable (~> 2.3) letter_opener (1.1.2) launchy (~> 2.2) - listen (2.3.1) - celluloid (>= 0.15.2) + listen (2.10.0) + celluloid (~> 0.16.0) rb-fsevent (>= 0.9.3) rb-inotify (>= 0.9) lumberjack (1.0.4) @@ -456,8 +456,8 @@ GEM raindrops (0.13.0) rake (10.4.2) raphael-rails (2.1.2) - rb-fsevent (0.9.3) - rb-inotify (0.9.2) + rb-fsevent (0.9.4) + rb-inotify (0.9.5) ffi (>= 0.5.0) rdoc (3.12.2) json (~> 1.4) @@ -482,6 +482,8 @@ GEM redis-store (1.1.4) redis (>= 2.2) request_store (1.0.5) + rerun (0.10.0) + listen (~> 2.7, >= 2.7.3) rest-client (1.6.7) mime-types (>= 1.16) rinku (1.7.3) @@ -763,6 +765,7 @@ DEPENDENCIES redcarpet (~> 3.2.3) redis-rails request_store + rerun (~> 0.10.0) rspec-rails (= 2.99) rubocop (= 0.28.0) rugments diff --git a/lib/tasks/dev.rake b/lib/tasks/dev.rake index 058c741704..b22c631c8b 100644 --- a/lib/tasks/dev.rake +++ b/lib/tasks/dev.rake @@ -7,4 +7,9 @@ namespace :dev do Rake::Task["gitlab:setup"].invoke Rake::Task["gitlab:shell:setup"].invoke end + + desc 'GITLAB | Start/restart foreman and watch for changes' + task :foreman => :environment do + sh 'rerun --dir app,config,lib -- foreman start' + end end From e3d2304d6971c42436e711ccf70b8e4d5114f887 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Mon, 27 Apr 2015 15:43:50 -0400 Subject: [PATCH 23/97] Specs don't need to set default_url_options anymore --- spec/features/users_spec.rb | 7 ------- spec/support/reference_filter_spec_helper.rb | 11 ----------- 2 files changed, 18 deletions(-) diff --git a/spec/features/users_spec.rb b/spec/features/users_spec.rb index 4cfaab03ca..93d2b18b5f 100644 --- a/spec/features/users_spec.rb +++ b/spec/features/users_spec.rb @@ -1,13 +1,6 @@ require 'spec_helper' feature 'Users' do - around do |ex| - old_url_options = Rails.application.routes.default_url_options - Rails.application.routes.default_url_options = { host: 'example.foo' } - ex.run - Rails.application.routes.default_url_options = old_url_options - end - scenario 'GET /users/sign_in creates a new user account' do visit new_user_session_path fill_in 'user_name', with: 'Name Surname' diff --git a/spec/support/reference_filter_spec_helper.rb b/spec/support/reference_filter_spec_helper.rb index bcee5715ca..0e035f0e59 100644 --- a/spec/support/reference_filter_spec_helper.rb +++ b/spec/support/reference_filter_spec_helper.rb @@ -4,17 +4,6 @@ module ReferenceFilterSpecHelper extend ActiveSupport::Concern - included do - before { set_default_url_options } - end - - # Allow *_url helpers to work - def set_default_url_options - Rails.application.routes.default_url_options = { - host: 'example.foo' - } - end - # Shortcut to Rails' auto-generated routes helpers, to avoid including the # module def urls From 27eeffa4370988136b41d1bcdceecc0e3747fe4c Mon Sep 17 00:00:00 2001 From: Marcos SF Filho Date: Mon, 27 Apr 2015 20:51:26 +0000 Subject: [PATCH 24/97] Fix file paths for installations from the source --- doc/logs/logs.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/doc/logs/logs.md b/doc/logs/logs.md index ec0109a426..83c32b0925 100644 --- a/doc/logs/logs.md +++ b/doc/logs/logs.md @@ -5,7 +5,7 @@ In addition to system log files, GitLab Enterprise Edition comes with Audit Even System log files are typically plain text in a standard log file format. This guide talks about how to read and use these system log files. #### production.log -This file lives in `/var/log/gitlab/gitlab-rails/production.log` for omnibus package or in `/home/git/gitlab/logs/production.log` for installations from the source. +This file lives in `/var/log/gitlab/gitlab-rails/production.log` for omnibus package or in `/home/git/gitlab/log/production.log` for installations from the source. This file contains information about all performed requests. You can see url and type of request, IP address and what exactly parts of code were involved to service this particular request. Also you can see all SQL request that have been performed and how much time it took. This task is more useful for GitLab contributors and developers. Use part of this log file when you are going to report bug. @@ -30,7 +30,7 @@ Completed 200 OK in 166ms (Views: 117.4ms | ActiveRecord: 27.2ms) In this example we can see that server processed HTTP request with url `/gitlabhq/yaml_db/tree/master` from IP 168.111.56.1 at 2015-02-12 19:34:53 +0200. Also we can see that request was processed by Projects::TreeController. #### application.log -This file lives in `/var/log/gitlab/gitlab-rails/application.log` for omnibus package or in `/home/git/gitlab/logs/application.log` for installations from the source. +This file lives in `/var/log/gitlab/gitlab-rails/application.log` for omnibus package or in `/home/git/gitlab/log/application.log` for installations from the source. This log file helps you discover events happening in your instance such as user creation, project removing and so on. @@ -42,7 +42,7 @@ October 07, 2014 11:25: User "Claudie Hodkiewicz" (nasir_stehr@olson.co.uk) was October 07, 2014 11:25: Project "project133" was removed ``` #### githost.log -This file lives in `/var/log/gitlab/gitlab-rails/githost.log` for omnibus package or in `/home/git/gitlab/logs/githost.log` for installations from the source. +This file lives in `/var/log/gitlab/gitlab-rails/githost.log` for omnibus package or in `/home/git/gitlab/log/githost.log` for installations from the source. The GitLab has to interact with git repositories but in some rare cases something can go wrong and in this case you will know what exactly happened. This log file contains all failed requests from GitLab to git repository. In majority of cases this file will be useful for developers only. ``` @@ -52,7 +52,7 @@ error: failed to push some refs to '/Users/vsizov/gitlab-development-kit/reposit ``` #### satellites.log -This file lives in `/var/log/gitlab/gitlab-rails/satellites.log` for omnibus package or in `/home/git/gitlab/logs/satellites.log` for installations from the source. +This file lives in `/var/log/gitlab/gitlab-rails/satellites.log` for omnibus package or in `/home/git/gitlab/log/satellites.log` for installations from the source. In some cases GitLab should perform write actions to git repository, for example when it is needed to merge the merge request or edit a file with online editor. If something went wrong you can look into this file to find out what exactly happened. ``` @@ -62,7 +62,7 @@ October 07, 2014 11:36: PID: 1872: -> fatal: repository '/Users/vsizov/gitlab-de ``` #### sidekiq.log -This file lives in `/var/log/gitlab/gitlab-rails/sidekiq.log` for omnibus package or in `/home/git/gitlab/logs/sidekiq.log` for installations from the source. +This file lives in `/var/log/gitlab/gitlab-rails/sidekiq.log` for omnibus package or in `/home/git/gitlab/log/sidekiq.log` for installations from the source. GitLab uses background jobs for processing tasks which can take a long time. All information about processing these jobs are writing down to this file. ``` @@ -71,7 +71,7 @@ GitLab uses background jobs for processing tasks which can take a long time. All ``` #### gitlab-shell.log -This file lives in `/var/log/gitlab/gitlab-shell/gitlab-shell.log` for omnibus package or in `/home/git/gitlab-shell/logs/sidekiq.log` for installations from the source. +This file lives in `/var/log/gitlab/gitlab-shell/gitlab-shell.log` for omnibus package or in `/home/git/gitlab-shell/gitlab-shell.log` for installations from the source. gitlab-shell is using by Gitlab for executing git commands and provide ssh access to git repositories. @@ -81,7 +81,7 @@ I, [2015-02-13T06:17:00.679433 #9291] INFO -- : Moving existing hooks directory ``` #### unicorn_stderr.log -This file lives in `/var/log/gitlab/unicorn/unicorn_stderr.log` for omnibus package or in `/home/git/gitlab/logs/unicorn_stderr.log` for installations from the source. +This file lives in `/var/log/gitlab/unicorn/unicorn_stderr.log` for omnibus package or in `/home/git/gitlab/log/unicorn_stderr.log` for installations from the source. Unicorn is a high-performance forking Web server which is used for serving GitLab application. You can look at this log, for example, if your application does not respond. This log cantains all information about state of unicorn processes at any given time. @@ -99,4 +99,4 @@ W, [2015-02-13T07:16:01.313000 #9094] WARN -- : Unicorn::WorkerKiller send SIGQ I, [2015-02-13T07:16:01.530733 #9047] INFO -- : reaped # worker=1 I, [2015-02-13T07:16:01.534501 #13379] INFO -- : worker=1 spawned pid=13379 I, [2015-02-13T07:16:01.534848 #13379] INFO -- : worker=1 ready -``` +``` \ No newline at end of file From 72a7febeada2c58c98caee8bb7ce18886a7c0868 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Sun, 12 Apr 2015 22:27:45 -0700 Subject: [PATCH 25/97] Fix "Revspec not found" errors when viewing diffs in a forked project with submodules Closes #1413 --- CHANGELOG | 1 + app/helpers/diff_helper.rb | 4 +- app/helpers/submodule_helper.rb | 4 +- app/views/projects/diffs/_file.html.haml | 2 +- .../merge_requests_controller_spec.rb | 20 +++++++ spec/factories/projects.rb | 8 +++ spec/support/test_env.rb | 53 ++++++++++++++++--- 7 files changed, 80 insertions(+), 12 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 97a469513c..a6bfedf283 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -7,6 +7,7 @@ v 7.11.0 (unreleased) - Fix "Cannot move project" error message from popping up after a successful transfer (Stan Hu) - Redirect to sign in page after signing out. - Fix "Hello @username." references not working by no longer allowing usernames to end in period. + - Fix "Revspec not found" errors when viewing diffs in a forked project with submodules (Stan Hu) - - Fix broken file browsing with relative submodule in personal projects (Stan Hu) - Add "Reply quoting selected text" shortcut key (`r`) diff --git a/app/helpers/diff_helper.rb b/app/helpers/diff_helper.rb index 4f42972a4d..162778ade5 100644 --- a/app/helpers/diff_helper.rb +++ b/app/helpers/diff_helper.rb @@ -140,8 +140,8 @@ module DiffHelper end end - def submodule_link(blob, ref) - tree, commit = submodule_links(blob, ref) + def submodule_link(blob, ref, repository = @repository) + tree, commit = submodule_links(blob, ref, repository) commit_id = if commit.nil? blob.id[0..10] else diff --git a/app/helpers/submodule_helper.rb b/app/helpers/submodule_helper.rb index e13d4eaf10..6def7793dc 100644 --- a/app/helpers/submodule_helper.rb +++ b/app/helpers/submodule_helper.rb @@ -2,8 +2,8 @@ module SubmoduleHelper include Gitlab::ShellAdapter # links to files listing for submodule if submodule is a project on this server - def submodule_links(submodule_item, ref = nil) - url = @repository.submodule_url_for(ref, submodule_item.path) + def submodule_links(submodule_item, ref = nil, repository = @repository) + url = repository.submodule_url_for(ref, submodule_item.path) return url, nil unless url =~ /([^\/:]+)\/([^\/]+\.git)\Z/ diff --git a/app/views/projects/diffs/_file.html.haml b/app/views/projects/diffs/_file.html.haml index 672a663532..d4b019780f 100644 --- a/app/views/projects/diffs/_file.html.haml +++ b/app/views/projects/diffs/_file.html.haml @@ -11,7 +11,7 @@ = view_file_btn(@commit.parent_id, diff_file, project) - elsif diff_file.diff.submodule? - submodule_item = project.repository.blob_at(@commit.id, diff_file.file_path) - = submodule_link(submodule_item, @commit.id) + = submodule_link(submodule_item, @commit.id, project.repository) - else %span - if diff_file.renamed_file diff --git a/spec/controllers/merge_requests_controller_spec.rb b/spec/controllers/merge_requests_controller_spec.rb index d6f56ed33d..c94ef1629a 100644 --- a/spec/controllers/merge_requests_controller_spec.rb +++ b/spec/controllers/merge_requests_controller_spec.rb @@ -78,4 +78,24 @@ describe Projects::MergeRequestsController do end end end + + context '#diffs with forked projects with submodules' do + render_views + let(:project) { create(:project) } + let(:fork_project) { create(:forked_project_with_submodules) } + let(:merge_request) { create(:merge_request_with_diffs, source_project: fork_project, source_branch: 'add-submodule-version-bump', target_branch: 'master', target_project: project) } + + before do + fork_project.build_forked_project_link(forked_to_project_id: fork_project.id, forked_from_project_id: project.id) + fork_project.save + merge_request.reload + end + + it '#diffs' do + get(:diffs, namespace_id: project.namespace.to_param, + project_id: project.to_param, id: merge_request.iid, format: 'json') + expect(response).to be_success + expect(response.body).to have_content('Subproject commit') + end + end end diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb index 0899a7603f..57fa079d75 100644 --- a/spec/factories/projects.rb +++ b/spec/factories/projects.rb @@ -76,6 +76,14 @@ FactoryGirl.define do end end + factory :forked_project_with_submodules, parent: :empty_project do + path { 'forked-gitlabhq' } + + after :create do |project| + TestEnv.copy_forked_repo_with_submodules(project) + end + end + factory :redmine_project, parent: :project do after :create do |project| project.create_redmine_service( diff --git a/spec/support/test_env.rb b/spec/support/test_env.rb index 44d70e741b..d1844bd2b8 100644 --- a/spec/support/test_env.rb +++ b/spec/support/test_env.rb @@ -14,6 +14,10 @@ module TestEnv 'master' => '5937ac0' } + FORKED_BRANCH_SHA = BRANCH_SHA.merge({ + 'add-submodule-version-bump' => '3f547c08' + }) + # Test environment # # See gitlab.yml.example test section for paths @@ -31,6 +35,8 @@ module TestEnv # Create repository for FactoryGirl.create(:project) setup_factory_repo + # Create repository for FactoryGirl.create(:forked_project_with_submodules) + setup_forked_repo end def disable_mailer @@ -61,14 +67,26 @@ module TestEnv end def setup_factory_repo - clone_url = "https://gitlab.com/gitlab-org/#{factory_repo_name}.git" + setup_repo(factory_repo_path, factory_repo_path_bare, factory_repo_name, + BRANCH_SHA) + end - unless File.directory?(factory_repo_path) - system(*%W(git clone -q #{clone_url} #{factory_repo_path})) + # This repo has a submodule commit that is not present in the main test + # repository. + def setup_forked_repo + setup_repo(forked_repo_path, forked_repo_path_bare, forked_repo_name, + FORKED_BRANCH_SHA) + end + + def setup_repo(repo_path, repo_path_bare, repo_name, branch_sha) + clone_url = "https://gitlab.com/gitlab-org/#{repo_name}.git" + + unless File.directory?(repo_path) + system(*%W(git clone -q #{clone_url} #{repo_path})) end - Dir.chdir(factory_repo_path) do - BRANCH_SHA.each do |branch, sha| + Dir.chdir(repo_path) do + branch_sha.each do |branch, sha| # Try to reset without fetching to avoid using the network. reset = %W(git update-ref refs/heads/#{branch} #{sha}) unless system(*reset) @@ -85,7 +103,7 @@ module TestEnv end # We must copy bare repositories because we will push to them. - system(git_env, *%W(git clone -q --bare #{factory_repo_path} #{factory_repo_path_bare})) + system(git_env, *%W(git clone -q --bare #{repo_path} #{repo_path_bare})) end def copy_repo(project) @@ -100,6 +118,14 @@ module TestEnv Gitlab.config.gitlab_shell.repos_path end + def copy_forked_repo_with_submodules(project) + base_repo_path = File.expand_path(forked_repo_path_bare) + target_repo_path = File.expand_path(repos_path + "/#{project.namespace.path}/#{project.path}.git") + FileUtils.mkdir_p(target_repo_path) + FileUtils.cp_r("#{base_repo_path}/.", target_repo_path) + FileUtils.chmod_R 0755, target_repo_path + end + private def factory_repo_path @@ -114,9 +140,22 @@ module TestEnv 'gitlab-test' end + def forked_repo_path + @forked_repo_path ||= Rails.root.join('tmp', 'tests', forked_repo_name) + end + + def forked_repo_path_bare + "#{forked_repo_path}_bare" + end + + def forked_repo_name + 'gitlab-test-fork' + end + + # Prevent developer git configurations from being persisted to test # repositories def git_env - {'GIT_TEMPLATE_DIR' => ''} + { 'GIT_TEMPLATE_DIR' => '' } end end From f476888e77b8ccdc7fe69d3e0aba68d6aa407ad2 Mon Sep 17 00:00:00 2001 From: Sytse Sijbrandij Date: Mon, 27 Apr 2015 23:09:03 -0700 Subject: [PATCH 26/97] Add more instuctions on how to publish docker images yourself. --- docker/README.md | 44 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/docker/README.md b/docker/README.md index b7e8b0db7e..a54739ae3d 100644 --- a/docker/README.md +++ b/docker/README.md @@ -3,16 +3,19 @@ What is GitLab? GitLab offers git repository management, code reviews, issue tracking, activity feeds, wikis. It has LDAP/AD integration, handles 25,000 users on a single server but can also run on a highly available active/active cluster. A subscription gives you access to our support team and to GitLab Enterprise Edition that contains extra features aimed at larger organizations. - - -![GitLab Logo](https://gitlab.com/uploads/appearance/logo/1/brand_logo-c37eb221b456bb4b472cc1084480991f.png) +Learn more on [https://about.gitlab.com](https://about.gitlab.com) -How to use these images +How to build and use images yourself ====================== -At this moment GitLab doesn't have official Docker images. For convinience we will use suffix _xy where xy is current version of GitLab. -Build your own based on the Omnibus packages with the following commands (it assumes you're in the GitLab repo root directory): +At this moment GitLab doesn't have official Docker images. +There are unofficial images at the bottom of this document. +But in this section we'll build our own. +For convinience we will use suffix _xy where xy is current version of GitLab. +Build your own based on the Omnibus packages with the following commands. +Run these from the GitLab repo root directory. +People using boot2docker should run it without sudo. ```bash sudo docker build --tag gitlab_data_image docker/data/ @@ -42,11 +45,11 @@ sudo docker run --detach --name gitlab_app_xy --publish 8080:80 --publish 2222:2 It might take a while before the docker container is responding to queries. You can follow the configuration process with `sudo docker logs -f gitlab_app_xy`. -You can then go to `http://localhost:8080/` (or `http://192.168.59.103:8080/` if you use boot2docker). +You can then go to [http://localhost:8080/](http://localhost:8080/) or [http://192.168.59.103:8080/](http://192.168.59.103:8080/) if you use boot2docker. + You can login with username `root` and password `5iveL!fe`. Next time, you can just use `sudo docker start gitlab_app` and `sudo docker stop gitlab_app`. - How to configure GitLab ======================== @@ -55,7 +58,7 @@ This container uses the official Omnibus GitLab distribution, so all configurati To access GitLab configuration, you can start an interactive command line in a new container using the shared data volume container, you will be able to browse the 3 directories and use your favorite text editor: ```bash -sudo docker run -ti -e TERM=linux --rm --volumes-from gitlab_data ubuntu +sudo docker run -ti -e TERM=linux --rm --volumes-from gitlab_data ubuntu vi /etc/gitlab/gitlab.rb ``` @@ -86,3 +89,26 @@ sudo docker rmi gitlab_app_image_78 Troubleshooting ========================= Please see the [troubleshooting](troubleshooting.md) file in this directory. + + +Publish the images to Dockerhub +========================= +Login to Dockerhub with `sudo docker login` and run the following (replace '7.9.2' with the version you're using and 'Sytse Sijbrandij' with your name): + +```bash +sudo docker commit -m "Initial commit" -a "Sytse Sijbrandij" gitlab_app_xy sytse/gitlab-ce:7.9.2 +sudo docker push sytse/gitlab-ce:7.9.2 +sudo docker commit -m "Initial commit" -a "Sytse Sijbrandij" gitlab_data sytse/gitlab_data +sudo docker push sytse/gitlab_data +``` + +Use images published to Dockerhub +================================ +This examples uses the unofficial images made by GitLab CEO Sytse. + +```bash +sudo docker pull sytse/gitlab_data +sudo docker pull sytse/gitlab-ce:7.9.2 +sudo docker run --name gitlab_data_volume sytse/gitlab_data /bin/true +sudo docker run --detach --name gitlab_app_7_9_2 --publish 8080:80 --publish 2222:22 --volumes-from gitlab_data_volume sytse/gitlab-ce:7.9.2 +``` From d5fe1e57d5107c5ddc57feee5c3d1f7ed03941ab Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 28 Apr 2015 12:48:42 +0300 Subject: [PATCH 27/97] Draft improvements to search layout Signed-off-by: Dmitriy Zaporozhets --- app/controllers/search_controller.rb | 9 +++-- app/views/layouts/_search.html.haml | 2 +- app/views/layouts/nav/_search.html.haml | 30 ++++++++++++++++ .../layouts/nav/search/_project.html.haml | 35 ++++++++++++++++++ .../layouts/nav/search/_snippet.html.haml | 14 ++++++++ app/views/layouts/search.html.haml | 6 +--- app/views/search/_global_filter.html.haml | 16 --------- app/views/search/_project_filter.html.haml | 32 ----------------- app/views/search/_results.html.haml | 31 ++++------------ app/views/search/_snippet_filter.html.haml | 13 ------- app/views/search/show.html.haml | 36 +++++++++---------- 11 files changed, 109 insertions(+), 115 deletions(-) create mode 100644 app/views/layouts/nav/_search.html.haml create mode 100644 app/views/layouts/nav/search/_project.html.haml create mode 100644 app/views/layouts/nav/search/_snippet.html.haml delete mode 100644 app/views/search/_global_filter.html.haml delete mode 100644 app/views/search/_project_filter.html.haml delete mode 100644 app/views/search/_snippet_filter.html.haml diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb index c5828d0b2d..ad9e9e8487 100644 --- a/app/controllers/search_controller.rb +++ b/app/controllers/search_controller.rb @@ -4,20 +4,22 @@ class SearchController < ApplicationController def show return if params[:search].nil? || params[:search].blank? + @search_term = params[:search] + if params[:project_id].present? @project = Project.find_by(id: params[:project_id]) @project = nil unless can?(current_user, :download_code, @project) end if params[:group_id].present? - @group = Group.find_by(id: params[:group_id]) + @group = Group.find_by(id: params[:group_id]) @group = nil unless can?(current_user, :read_group, @group) end - + @scope = params[:scope] @show_snippets = params[:snippets].eql? 'true' - @search_results = + @search_results = if @project unless %w(blobs notes issues merge_requests wiki_blobs). include?(@scope) @@ -37,6 +39,7 @@ class SearchController < ApplicationController end Search::GlobalService.new(current_user, params).execute end + @objects = @search_results.objects(@scope, params[:page]) end diff --git a/app/views/layouts/_search.html.haml b/app/views/layouts/_search.html.haml index 04f7984685..58e6bd3158 100644 --- a/app/views/layouts/_search.html.haml +++ b/app/views/layouts/_search.html.haml @@ -1,6 +1,6 @@ .search = form_tag search_path, method: :get, class: 'navbar-form pull-left' do |f| - = search_field_tag "search", nil, placeholder: search_placeholder, class: "search-input" + = search_field_tag "search", @search_term, placeholder: search_placeholder, class: "search-input" = hidden_field_tag :group_id, @group.try(:id) - if @project && @project.persisted? = hidden_field_tag :project_id, @project.id diff --git a/app/views/layouts/nav/_search.html.haml b/app/views/layouts/nav/_search.html.haml new file mode 100644 index 0000000000..35806c2d0f --- /dev/null +++ b/app/views/layouts/nav/_search.html.haml @@ -0,0 +1,30 @@ +%ul.nav.nav-sidebar.search-filter + - if @project + = render 'layouts/nav/search/project' + + - elsif @show_snippets + = render 'layouts/nav/search/snippet' + + - else + %li{class: ("active" if @scope == 'projects')} + = link_to search_filter_path(scope: 'projects') do + = icon('bookmark fw') + %span + Projects + %span.count + = @search_results.projects_count + %li{class: ("active" if @scope == 'issues')} + = link_to search_filter_path(scope: 'issues') do + = icon('exclamation-circle fw') + %span + Issues + %span.count + = @search_results.issues_count + %li{class: ("active" if @scope == 'merge_requests')} + = link_to search_filter_path(scope: 'merge_requests') do + = icon('tasks fw') + %span + Merge requests + %span.count + = @search_results.merge_requests_count + diff --git a/app/views/layouts/nav/search/_project.html.haml b/app/views/layouts/nav/search/_project.html.haml new file mode 100644 index 0000000000..344cb4b480 --- /dev/null +++ b/app/views/layouts/nav/search/_project.html.haml @@ -0,0 +1,35 @@ +%li{class: ("active" if @scope == 'blobs')} + = link_to search_filter_path(scope: 'blobs') do + = icon('code fw') + %span + Code + %span.count + = @search_results.blobs_count +%li{class: ("active" if @scope == 'issues')} + = link_to search_filter_path(scope: 'issues') do + = icon('exclamation-circle fw') + %span + Issues + %span.count + = @search_results.issues_count +%li{class: ("active" if @scope == 'merge_requests')} + = link_to search_filter_path(scope: 'merge_requests') do + = icon('tasks fw') + %span + Merge requests + %span.count + = @search_results.merge_requests_count +%li{class: ("active" if @scope == 'notes')} + = link_to search_filter_path(scope: 'notes') do + = icon('comments fw') + %span + Comments + %span.count + = @search_results.notes_count +%li{class: ("active" if @scope == 'wiki_blobs')} + = link_to search_filter_path(scope: 'wiki_blobs') do + = icon('book fw') + %span + Wiki + %span.count + = @search_results.wiki_blobs_count diff --git a/app/views/layouts/nav/search/_snippet.html.haml b/app/views/layouts/nav/search/_snippet.html.haml new file mode 100644 index 0000000000..e63a221fb8 --- /dev/null +++ b/app/views/layouts/nav/search/_snippet.html.haml @@ -0,0 +1,14 @@ +%li{class: ("active" if @scope == 'snippet_blobs')} + = link_to search_filter_path(scope: 'snippet_blobs', snippets: true, group_id: nil, project_id: nil) do + = icon('code fw') + %span + Snippet Contents + %span.count + = @search_results.snippet_blobs_count +%li{class: ("active" if @scope == 'snippet_titles')} + = link_to search_filter_path(scope: 'snippet_titles', snippets: true, group_id: nil, project_id: nil) do + = icon('book fw') + %span + Titles and Filenames + %span.count + = @search_results.snippet_titles_count diff --git a/app/views/layouts/search.html.haml b/app/views/layouts/search.html.haml index f9d8db06e1..c9b76e8fca 100644 --- a/app/views/layouts/search.html.haml +++ b/app/views/layouts/search.html.haml @@ -2,9 +2,5 @@ %html{ lang: "en"} = render "layouts/head", title: "Search" %body{class: "#{app_theme} application", :'data-page' => body_data_page} - = render "layouts/broadcast" = render "layouts/head_panel", title: link_to("Search", search_path) - .container.navless-container - .content - = render "layouts/flash" - = yield + = render 'layouts/page', sidebar: 'layouts/nav/search' diff --git a/app/views/search/_global_filter.html.haml b/app/views/search/_global_filter.html.haml deleted file mode 100644 index 442bd84f93..0000000000 --- a/app/views/search/_global_filter.html.haml +++ /dev/null @@ -1,16 +0,0 @@ -%ul.nav.nav-pills.nav-stacked.search-filter - %li{class: ("active" if @scope == 'projects')} - = link_to search_filter_path(scope: 'projects') do - Projects - .pull-right - = @search_results.projects_count - %li{class: ("active" if @scope == 'issues')} - = link_to search_filter_path(scope: 'issues') do - Issues - .pull-right - = @search_results.issues_count - %li{class: ("active" if @scope == 'merge_requests')} - = link_to search_filter_path(scope: 'merge_requests') do - Merge requests - .pull-right - = @search_results.merge_requests_count diff --git a/app/views/search/_project_filter.html.haml b/app/views/search/_project_filter.html.haml deleted file mode 100644 index ad933502a2..0000000000 --- a/app/views/search/_project_filter.html.haml +++ /dev/null @@ -1,32 +0,0 @@ -%ul.nav.nav-pills.nav-stacked.search-filter - %li{class: ("active" if @scope == 'blobs')} - = link_to search_filter_path(scope: 'blobs') do - %i.fa.fa-code - Code - .pull-right - = @search_results.blobs_count - %li{class: ("active" if @scope == 'issues')} - = link_to search_filter_path(scope: 'issues') do - %i.fa.fa-exclamation-circle - Issues - .pull-right - = @search_results.issues_count - %li{class: ("active" if @scope == 'merge_requests')} - = link_to search_filter_path(scope: 'merge_requests') do - %i.fa.fa-code-fork - Merge requests - .pull-right - = @search_results.merge_requests_count - %li{class: ("active" if @scope == 'notes')} - = link_to search_filter_path(scope: 'notes') do - %i.fa.fa-comments - Comments - .pull-right - = @search_results.notes_count - %li{class: ("active" if @scope == 'wiki_blobs')} - = link_to search_filter_path(scope: 'wiki_blobs') do - %i.fa.fa-book - Wiki - .pull-right - = @search_results.wiki_blobs_count - diff --git a/app/views/search/_results.html.haml b/app/views/search/_results.html.haml index 796dd752a4..f741a64cba 100644 --- a/app/views/search/_results.html.haml +++ b/app/views/search/_results.html.haml @@ -1,28 +1,9 @@ -%h4 - #{@search_results.total_count} results found - - unless @show_snippets - - if @project - for #{link_to @project.name_with_namespace, [@project.namespace.becomes(Namespace), @project]} - - elsif @group - for #{link_to @group.name, @group} - -%hr - -.row - .col-sm-3 - - if @project - = render "project_filter" - - elsif @show_snippets - = render 'snippet_filter' - - else - = render "global_filter" - .col-sm-9 - .search-results - - if @search_results.empty? - = render partial: "search/results/empty", locals: { message: "We couldn't find any matching results" } - - else - = render partial: "search/results/#{@scope.singularize}", collection: @objects - = paginate @objects, theme: 'gitlab' +.search-results + - if @search_results.empty? + = render partial: "search/results/empty", locals: { message: "We couldn't find any matching results" } + - else + = render partial: "search/results/#{@scope.singularize}", collection: @objects + = paginate @objects, theme: 'gitlab' :javascript $(".search-results .term").highlight("#{escape_javascript(params[:search])}"); diff --git a/app/views/search/_snippet_filter.html.haml b/app/views/search/_snippet_filter.html.haml deleted file mode 100644 index 95d23fa9f4..0000000000 --- a/app/views/search/_snippet_filter.html.haml +++ /dev/null @@ -1,13 +0,0 @@ -%ul.nav.nav-pills.nav-stacked.search-filter - %li{class: ("active" if @scope == 'snippet_blobs')} - = link_to search_filter_path(scope: 'snippet_blobs', snippets: true, group_id: nil, project_id: nil) do - %i.fa.fa-code - Snippet Contents - .pull-right - = @search_results.snippet_blobs_count - %li{class: ("active" if @scope == 'snippet_titles')} - = link_to search_filter_path(scope: 'snippet_titles', snippets: true, group_id: nil, project_id: nil) do - %i.fa.fa-book - Titles and Filenames - .pull-right - = @search_results.snippet_titles_count diff --git a/app/views/search/show.html.haml b/app/views/search/show.html.haml index 5b4816e4c4..fcdd63a764 100644 --- a/app/views/search/show.html.haml +++ b/app/views/search/show.html.haml @@ -1,22 +1,18 @@ -= form_tag search_path, method: :get, class: 'form-horizontal' do |f| - .search-holder.clearfix - .form-group - = label_tag :search, class: 'control-label' do - %span Looking for - .col-sm-6 - = search_field_tag :search, params[:search], placeholder: "issue 143", class: "form-control search-text-input", id: "dashboard_search" - .col-sm-4 - = button_tag 'Search', class: "btn btn-create" - .form-group - .col-sm-2 - - unless params[:snippets].eql? 'true' - .col-sm-10 - = render 'filter', f: f - = hidden_field_tag :project_id, params[:project_id] - = hidden_field_tag :group_id, params[:group_id] - = hidden_field_tag :snippets, params[:snippets] - = hidden_field_tag :scope, params[:scope] +- if @search_term + .lead + Search for + %code + = @search_term + - unless @show_snippets + - if @project + in project #{link_to @project.name_with_namespace, [@project.namespace.becomes(Namespace), @project]} + - elsif @group + in group #{link_to @group.name, @group} + .pull-right + = render 'filter' + %hr .results.prepend-top-10 - - if params[:search].present? - = render 'search/results' + = render 'search/results' +- else + wow From 1ff01d26e1943a16f77e2ab08e89c92d72fcbf62 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 28 Apr 2015 22:04:19 +0300 Subject: [PATCH 28/97] Continue refactoring and restyle of search layout Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/generic/common.scss | 11 +---- app/views/layouts/_head_panel.html.haml | 5 +- app/views/layouts/_search.html.haml | 2 +- app/views/layouts/nav/_search.html.haml | 56 +++++++++++----------- app/views/search/_filter.html.haml | 4 +- app/views/search/_form.html.haml | 12 +++++ app/views/search/_results.html.haml | 24 +++++++--- app/views/search/results/_empty.html.haml | 6 ++- app/views/search/show.html.haml | 20 ++------ db/schema.rb | 28 ++++++++++- 10 files changed, 98 insertions(+), 70 deletions(-) create mode 100644 app/views/search/_form.html.haml diff --git a/app/assets/stylesheets/generic/common.scss b/app/assets/stylesheets/generic/common.scss index 7c3021989a..1e569978cc 100644 --- a/app/assets/stylesheets/generic/common.scss +++ b/app/assets/stylesheets/generic/common.scss @@ -333,17 +333,8 @@ table { } .search_box { - position: relative; - padding: 30px; + @extend .well; text-align: center; - background-color: #F9F9F9; - border: 1px solid #DDDDDD; - border-radius: 0px; -} - -.search_glyph { - color: #555; - font-size: 42px; } .task-status { diff --git a/app/views/layouts/_head_panel.html.haml b/app/views/layouts/_head_panel.html.haml index fc4656be07..a7ec19cb69 100644 --- a/app/views/layouts/_head_panel.html.haml +++ b/app/views/layouts/_head_panel.html.haml @@ -13,8 +13,9 @@ .navbar-collapse.collapse %ul.nav.navbar-nav - %li.hidden-sm.hidden-xs - = render 'layouts/search' + - unless current_controller?(:search) + %li.hidden-sm.hidden-xs + = render 'layouts/search' %li.visible-sm.visible-xs = link_to search_path, title: 'Search', data: {toggle: 'tooltip', placement: 'bottom'} do = icon('search') diff --git a/app/views/layouts/_search.html.haml b/app/views/layouts/_search.html.haml index 58e6bd3158..04f7984685 100644 --- a/app/views/layouts/_search.html.haml +++ b/app/views/layouts/_search.html.haml @@ -1,6 +1,6 @@ .search = form_tag search_path, method: :get, class: 'navbar-form pull-left' do |f| - = search_field_tag "search", @search_term, placeholder: search_placeholder, class: "search-input" + = search_field_tag "search", nil, placeholder: search_placeholder, class: "search-input" = hidden_field_tag :group_id, @group.try(:id) - if @project && @project.persisted? = hidden_field_tag :project_id, @project.id diff --git a/app/views/layouts/nav/_search.html.haml b/app/views/layouts/nav/_search.html.haml index 35806c2d0f..f95f6acb28 100644 --- a/app/views/layouts/nav/_search.html.haml +++ b/app/views/layouts/nav/_search.html.haml @@ -1,30 +1,30 @@ -%ul.nav.nav-sidebar.search-filter - - if @project - = render 'layouts/nav/search/project' +- if @search_term + %ul.nav.nav-sidebar.search-filter + - if @project + = render 'layouts/nav/search/project' - - elsif @show_snippets - = render 'layouts/nav/search/snippet' - - - else - %li{class: ("active" if @scope == 'projects')} - = link_to search_filter_path(scope: 'projects') do - = icon('bookmark fw') - %span - Projects - %span.count - = @search_results.projects_count - %li{class: ("active" if @scope == 'issues')} - = link_to search_filter_path(scope: 'issues') do - = icon('exclamation-circle fw') - %span - Issues - %span.count - = @search_results.issues_count - %li{class: ("active" if @scope == 'merge_requests')} - = link_to search_filter_path(scope: 'merge_requests') do - = icon('tasks fw') - %span - Merge requests - %span.count - = @search_results.merge_requests_count + - elsif @show_snippets + = render 'layouts/nav/search/snippet' + - else + %li{class: ("active" if @scope == 'projects')} + = link_to search_filter_path(scope: 'projects') do + = icon('bookmark fw') + %span + Projects + %span.count + = @search_results.projects_count + %li{class: ("active" if @scope == 'issues')} + = link_to search_filter_path(scope: 'issues') do + = icon('exclamation-circle fw') + %span + Issues + %span.count + = @search_results.issues_count + %li{class: ("active" if @scope == 'merge_requests')} + = link_to search_filter_path(scope: 'merge_requests') do + = icon('tasks fw') + %span + Merge requests + %span.count + = @search_results.merge_requests_count diff --git a/app/views/search/_filter.html.haml b/app/views/search/_filter.html.haml index ffc145497a..e2d0cab9e7 100644 --- a/app/views/search/_filter.html.haml +++ b/app/views/search/_filter.html.haml @@ -1,5 +1,5 @@ .dropdown.inline - %button.dropdown-toggle.btn.btn-sm{type: 'button', 'data-toggle' => 'dropdown'} + %button.dropdown-toggle.btn.btn{type: 'button', 'data-toggle' => 'dropdown'} %i.fa.fa-tags %span.light Group: - if @group.present? @@ -17,7 +17,7 @@ = group.name .dropdown.inline.prepend-left-10.project-filter - %button.dropdown-toggle.btn.btn-sm{type: 'button', 'data-toggle' => 'dropdown'} + %button.dropdown-toggle.btn.btn{type: 'button', 'data-toggle' => 'dropdown'} %i.fa.fa-tags %span.light Project: - if @project.present? diff --git a/app/views/search/_form.html.haml b/app/views/search/_form.html.haml new file mode 100644 index 0000000000..a9ec7df296 --- /dev/null +++ b/app/views/search/_form.html.haml @@ -0,0 +1,12 @@ += form_tag search_path, method: :get, class: 'form-inline' do |f| + = hidden_field_tag :project_id, params[:project_id] + = hidden_field_tag :group_id, params[:group_id] + = hidden_field_tag :snippets, params[:snippets] + = hidden_field_tag :scope, params[:scope] + .search-holder.clearfix + .form-group + = search_field_tag :search, params[:search], placeholder: "Search for projects, issues etc", class: "form-control search-text-input input-mn-300", id: "dashboard_search", autofocus: true + = button_tag 'Search', class: "btn btn-info" + - unless params[:snippets].eql? 'true' + .pull-right + = render 'filter' diff --git a/app/views/search/_results.html.haml b/app/views/search/_results.html.haml index f741a64cba..741c780ad9 100644 --- a/app/views/search/_results.html.haml +++ b/app/views/search/_results.html.haml @@ -1,9 +1,21 @@ -.search-results - - if @search_results.empty? - = render partial: "search/results/empty", locals: { message: "We couldn't find any matching results" } - - else - = render partial: "search/results/#{@scope.singularize}", collection: @objects - = paginate @objects, theme: 'gitlab' +- if @search_results.empty? + = render partial: "search/results/empty" +- else + .light + Search results for + %code + = @search_term + - unless @show_snippets + - if @project + in project #{link_to @project.name_with_namespace, [@project.namespace.becomes(Namespace), @project]} + - elsif @group + in group #{link_to @group.name, @group} + + %br + .results.prepend-top-10 + .search-results + = render partial: "search/results/#{@scope.singularize}", collection: @objects + = paginate @objects, theme: 'gitlab' :javascript $(".search-results .term").highlight("#{escape_javascript(params[:search])}"); diff --git a/app/views/search/results/_empty.html.haml b/app/views/search/results/_empty.html.haml index 01fb8cd9b8..05a63016c0 100644 --- a/app/views/search/results/_empty.html.haml +++ b/app/views/search/results/_empty.html.haml @@ -1,4 +1,6 @@ .search_box .search_glyph - %span.fa.fa-search - %h4 #{message} + %h4 + = icon('search') + We couldn't find any results matching + %code #{@search_term} diff --git a/app/views/search/show.html.haml b/app/views/search/show.html.haml index fcdd63a764..8e11154279 100644 --- a/app/views/search/show.html.haml +++ b/app/views/search/show.html.haml @@ -1,18 +1,4 @@ += render 'search/form' +%hr - if @search_term - .lead - Search for - %code - = @search_term - - unless @show_snippets - - if @project - in project #{link_to @project.name_with_namespace, [@project.namespace.becomes(Namespace), @project]} - - elsif @group - in group #{link_to @group.name, @group} - - .pull-right - = render 'filter' - %hr - .results.prepend-top-10 - = render 'search/results' -- else - wow + = render 'search/results' diff --git a/db/schema.rb b/db/schema.rb index 8683c0446f..43faaf3168 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -349,10 +349,10 @@ ActiveRecord::Schema.define(version: 20150425173433) do t.string "import_url" 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.integer "star_count", default: 0, null: false + t.string "avatar" t.string "import_type" t.string "import_source" end @@ -472,7 +472,6 @@ ActiveRecord::Schema.define(version: 20150425173433) do t.integer "notification_level", default: 1, null: false t.datetime "password_expires_at" t.integer "created_by_id" - t.datetime "last_credential_check_at" t.string "avatar" t.string "confirmation_token" t.datetime "confirmed_at" @@ -480,6 +479,7 @@ ActiveRecord::Schema.define(version: 20150425173433) do t.string "unconfirmed_email" t.boolean "hide_no_ssh_key", default: false t.string "website_url", default: "", null: false + t.datetime "last_credential_check_at" t.string "github_access_token" t.string "gitlab_access_token" t.string "notification_email" @@ -501,6 +501,30 @@ ActiveRecord::Schema.define(version: 20150425173433) do add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree add_index "users", ["username"], name: "index_users_on_username", using: :btree + create_table "users_groups", force: true do |t| + t.integer "group_access", null: false + t.integer "group_id", null: false + t.integer "user_id", null: false + t.datetime "created_at" + t.datetime "updated_at" + t.integer "notification_level", default: 3, null: false + end + + add_index "users_groups", ["user_id"], name: "index_users_groups_on_user_id", using: :btree + + create_table "users_projects", force: true do |t| + t.integer "user_id", null: false + t.integer "project_id", null: false + t.datetime "created_at" + t.datetime "updated_at" + t.integer "project_access", default: 0, null: false + t.integer "notification_level", default: 3, null: false + end + + add_index "users_projects", ["project_access"], name: "index_users_projects_on_project_access", using: :btree + add_index "users_projects", ["project_id"], name: "index_users_projects_on_project_id", using: :btree + add_index "users_projects", ["user_id"], name: "index_users_projects_on_user_id", using: :btree + create_table "users_star_projects", force: true do |t| t.integer "project_id", null: false t.integer "user_id", null: false From 981c3c303ffe27999a7399c9b5bf8fef83a1ca5d Mon Sep 17 00:00:00 2001 From: Kyle Date: Wed, 29 Apr 2015 00:06:48 +0200 Subject: [PATCH 29/97] Fix #9219 Affix menu size change --- app/assets/stylesheets/pages/issuable.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss index a640a4e205..586e7b5f8d 100644 --- a/app/assets/stylesheets/pages/issuable.scss +++ b/app/assets/stylesheets/pages/issuable.scss @@ -19,7 +19,7 @@ &.affix { position: fixed; top: 70px; - width: 220px; + margin-right: 35px; } } } From a8956e8850b9bc691a1f6875b821159e4722c2b9 Mon Sep 17 00:00:00 2001 From: Karen Carias Date: Tue, 28 Apr 2015 23:45:44 +0000 Subject: [PATCH 30/97] Added phrase "Here's how to close multiple issues in one commit message" so that doc is easier to find by users --- doc/customization/issue_closing.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/customization/issue_closing.md b/doc/customization/issue_closing.md index aa65a082a5..64f128f5a6 100644 --- a/doc/customization/issue_closing.md +++ b/doc/customization/issue_closing.md @@ -1,5 +1,7 @@ # Issue closing pattern +Here's how to close multiple issues in one commit message: + If a commit message matches the regular expression below, all issues referenced from the matched text will be closed. This happens when the commit is pushed or merged into the default branch of a project. @@ -33,4 +35,4 @@ issue_closing_pattern: '((?:[Cc]los(?:e[sd]|ing)|[Ff]ix(?:e[sd]|ing)?) +(?:(?:is For manual installs you can customize the pattern in [gitlab.yml][0]. [0]: https://gitlab.com/gitlab-org/gitlab-ce/blob/40c3675372320febf5264061c9bcd63db2dfd13c/config/gitlab.yml.example#L65 -[1]: http://rubular.com/r/Xmbexed1OJ +[1]: http://rubular.com/r/Xmbexed1OJ \ No newline at end of file From 24037e7e6323ff0f91d21d111bd2092f948c8255 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 29 Apr 2015 12:19:54 +0300 Subject: [PATCH 31/97] Move search categories (projects, issues etc) below search field. Instead use sidebar for dashbaord nav Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/base/gl_bootstrap.scss | 6 ++ app/views/layouts/nav/_search.html.haml | 30 -------- .../layouts/nav/search/_project.html.haml | 35 --------- .../layouts/nav/search/_snippet.html.haml | 14 ---- app/views/layouts/search.html.haml | 2 +- app/views/search/_category.html.haml | 77 +++++++++++++++++++ app/views/search/_form.html.haml | 2 +- app/views/search/show.html.haml | 2 + 8 files changed, 87 insertions(+), 81 deletions(-) delete mode 100644 app/views/layouts/nav/_search.html.haml delete mode 100644 app/views/layouts/nav/search/_project.html.haml delete mode 100644 app/views/layouts/nav/search/_snippet.html.haml create mode 100644 app/views/search/_category.html.haml diff --git a/app/assets/stylesheets/base/gl_bootstrap.scss b/app/assets/stylesheets/base/gl_bootstrap.scss index 427f333423..21acbfa5e5 100644 --- a/app/assets/stylesheets/base/gl_bootstrap.scss +++ b/app/assets/stylesheets/base/gl_bootstrap.scss @@ -137,6 +137,12 @@ color: #666; } +.nav-pills > .active > a > span > .badge { + background-color: #fff; + color: $gl-primary; +} + + /** * fix to keep tooltips position in top navigation bar * diff --git a/app/views/layouts/nav/_search.html.haml b/app/views/layouts/nav/_search.html.haml deleted file mode 100644 index f95f6acb28..0000000000 --- a/app/views/layouts/nav/_search.html.haml +++ /dev/null @@ -1,30 +0,0 @@ -- if @search_term - %ul.nav.nav-sidebar.search-filter - - if @project - = render 'layouts/nav/search/project' - - - elsif @show_snippets - = render 'layouts/nav/search/snippet' - - - else - %li{class: ("active" if @scope == 'projects')} - = link_to search_filter_path(scope: 'projects') do - = icon('bookmark fw') - %span - Projects - %span.count - = @search_results.projects_count - %li{class: ("active" if @scope == 'issues')} - = link_to search_filter_path(scope: 'issues') do - = icon('exclamation-circle fw') - %span - Issues - %span.count - = @search_results.issues_count - %li{class: ("active" if @scope == 'merge_requests')} - = link_to search_filter_path(scope: 'merge_requests') do - = icon('tasks fw') - %span - Merge requests - %span.count - = @search_results.merge_requests_count diff --git a/app/views/layouts/nav/search/_project.html.haml b/app/views/layouts/nav/search/_project.html.haml deleted file mode 100644 index 344cb4b480..0000000000 --- a/app/views/layouts/nav/search/_project.html.haml +++ /dev/null @@ -1,35 +0,0 @@ -%li{class: ("active" if @scope == 'blobs')} - = link_to search_filter_path(scope: 'blobs') do - = icon('code fw') - %span - Code - %span.count - = @search_results.blobs_count -%li{class: ("active" if @scope == 'issues')} - = link_to search_filter_path(scope: 'issues') do - = icon('exclamation-circle fw') - %span - Issues - %span.count - = @search_results.issues_count -%li{class: ("active" if @scope == 'merge_requests')} - = link_to search_filter_path(scope: 'merge_requests') do - = icon('tasks fw') - %span - Merge requests - %span.count - = @search_results.merge_requests_count -%li{class: ("active" if @scope == 'notes')} - = link_to search_filter_path(scope: 'notes') do - = icon('comments fw') - %span - Comments - %span.count - = @search_results.notes_count -%li{class: ("active" if @scope == 'wiki_blobs')} - = link_to search_filter_path(scope: 'wiki_blobs') do - = icon('book fw') - %span - Wiki - %span.count - = @search_results.wiki_blobs_count diff --git a/app/views/layouts/nav/search/_snippet.html.haml b/app/views/layouts/nav/search/_snippet.html.haml deleted file mode 100644 index e63a221fb8..0000000000 --- a/app/views/layouts/nav/search/_snippet.html.haml +++ /dev/null @@ -1,14 +0,0 @@ -%li{class: ("active" if @scope == 'snippet_blobs')} - = link_to search_filter_path(scope: 'snippet_blobs', snippets: true, group_id: nil, project_id: nil) do - = icon('code fw') - %span - Snippet Contents - %span.count - = @search_results.snippet_blobs_count -%li{class: ("active" if @scope == 'snippet_titles')} - = link_to search_filter_path(scope: 'snippet_titles', snippets: true, group_id: nil, project_id: nil) do - = icon('book fw') - %span - Titles and Filenames - %span.count - = @search_results.snippet_titles_count diff --git a/app/views/layouts/search.html.haml b/app/views/layouts/search.html.haml index c9b76e8fca..4b526686be 100644 --- a/app/views/layouts/search.html.haml +++ b/app/views/layouts/search.html.haml @@ -3,4 +3,4 @@ = render "layouts/head", title: "Search" %body{class: "#{app_theme} application", :'data-page' => body_data_page} = render "layouts/head_panel", title: link_to("Search", search_path) - = render 'layouts/page', sidebar: 'layouts/nav/search' + = render 'layouts/page' diff --git a/app/views/search/_category.html.haml b/app/views/search/_category.html.haml new file mode 100644 index 0000000000..154332cb9a --- /dev/null +++ b/app/views/search/_category.html.haml @@ -0,0 +1,77 @@ +%ul.nav.nav-pills.search-filter + - if @project + %li{class: ("active" if @scope == 'blobs')} + = link_to search_filter_path(scope: 'blobs') do + = icon('code fw') + %span + Code + %span.badge + = @search_results.blobs_count + %li{class: ("active" if @scope == 'issues')} + = link_to search_filter_path(scope: 'issues') do + = icon('exclamation-circle fw') + %span + Issues + %span.badge + = @search_results.issues_count + %li{class: ("active" if @scope == 'merge_requests')} + = link_to search_filter_path(scope: 'merge_requests') do + = icon('tasks fw') + %span + Merge requests + %span.badge + = @search_results.merge_requests_count + %li{class: ("active" if @scope == 'notes')} + = link_to search_filter_path(scope: 'notes') do + = icon('comments fw') + %span + Comments + %span.badge + = @search_results.notes_count + %li{class: ("active" if @scope == 'wiki_blobs')} + = link_to search_filter_path(scope: 'wiki_blobs') do + = icon('book fw') + %span + Wiki + %span.badge + = @search_results.wiki_blobs_count + + - elsif @show_snippets + %li{class: ("active" if @scope == 'snippet_blobs')} + = link_to search_filter_path(scope: 'snippet_blobs', snippets: true, group_id: nil, project_id: nil) do + = icon('code fw') + %span + Snippet Contents + %span.badge + = @search_results.snippet_blobs_count + %li{class: ("active" if @scope == 'snippet_titles')} + = link_to search_filter_path(scope: 'snippet_titles', snippets: true, group_id: nil, project_id: nil) do + = icon('book fw') + %span + Titles and Filenames + %span.badge + = @search_results.snippet_titles_count + + - else + %li{class: ("active" if @scope == 'projects')} + = link_to search_filter_path(scope: 'projects') do + = icon('bookmark fw') + %span + Projects + %span.badge + = @search_results.projects_count + %li{class: ("active" if @scope == 'issues')} + = link_to search_filter_path(scope: 'issues') do + = icon('exclamation-circle fw') + %span + Issues + %span.badge + = @search_results.issues_count + %li{class: ("active" if @scope == 'merge_requests')} + = link_to search_filter_path(scope: 'merge_requests') do + = icon('tasks fw') + %span + Merge requests + %span.badge + = @search_results.merge_requests_count + diff --git a/app/views/search/_form.html.haml b/app/views/search/_form.html.haml index a9ec7df296..47016daf1f 100644 --- a/app/views/search/_form.html.haml +++ b/app/views/search/_form.html.haml @@ -6,7 +6,7 @@ .search-holder.clearfix .form-group = search_field_tag :search, params[:search], placeholder: "Search for projects, issues etc", class: "form-control search-text-input input-mn-300", id: "dashboard_search", autofocus: true - = button_tag 'Search', class: "btn btn-info" + = button_tag 'Search', class: "btn btn-primary" - unless params[:snippets].eql? 'true' .pull-right = render 'filter' diff --git a/app/views/search/show.html.haml b/app/views/search/show.html.haml index 8e11154279..e9f2711be2 100644 --- a/app/views/search/show.html.haml +++ b/app/views/search/show.html.haml @@ -1,4 +1,6 @@ = render 'search/form' %hr - if @search_term + = render 'search/category' + %hr = render 'search/results' From acad85459fcd9ed7136ecf7327e90bc961544fdf Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 29 Apr 2015 12:24:54 +0300 Subject: [PATCH 32/97] Revert "Fix '.container or .container-fluid should be the first child inside of a .navbar' issue" This reverts commit 570594a469fe481060d312d9d90980c5f9289e2f. --- app/views/layouts/_head_panel.html.haml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/layouts/_head_panel.html.haml b/app/views/layouts/_head_panel.html.haml index fc4656be07..8d4c7b39b1 100644 --- a/app/views/layouts/_head_panel.html.haml +++ b/app/views/layouts/_head_panel.html.haml @@ -1,6 +1,6 @@ %header.navbar.navbar-fixed-top.navbar-gitlab{ class: nav_header_class } - .container - .navbar-inner + .navbar-inner + .container %div.app_logo = link_to root_path, class: 'home', title: 'Dashboard', id: 'js-shortcuts-home', data: {toggle: 'tooltip', placement: 'bottom'} do = brand_header_logo From 2b0a1ca013590f3c885d34b98d109f66d5313cce Mon Sep 17 00:00:00 2001 From: Sullivan SENECHAL Date: Wed, 29 Apr 2015 12:36:12 +0200 Subject: [PATCH 33/97] Fix .container position on navbar (reloaded) --- app/assets/stylesheets/generic/header.scss | 10 +-- app/assets/stylesheets/generic/mobile.scss | 2 +- .../stylesheets/themes/gitlab-theme.scss | 20 +++-- app/views/layouts/_empty_head_panel.html.haml | 7 +- app/views/layouts/_head_panel.html.haml | 81 +++++++++---------- .../layouts/_public_head_panel.html.haml | 33 ++++---- 6 files changed, 73 insertions(+), 80 deletions(-) diff --git a/app/assets/stylesheets/generic/header.scss b/app/assets/stylesheets/generic/header.scss index b861646191..df1553d859 100644 --- a/app/assets/stylesheets/generic/header.scss +++ b/app/assets/stylesheets/generic/header.scss @@ -10,7 +10,10 @@ header { border: none; width: 100%; - .navbar-inner { + .container { + width: 100% !important; + padding: 0; + background: #FFF; border-bottom: 1px solid #DDD; filter: none; @@ -123,11 +126,6 @@ header { } } - .container { - width: 100% !important; - padding: 0px; - } - /** * * Logo holder diff --git a/app/assets/stylesheets/generic/mobile.scss b/app/assets/stylesheets/generic/mobile.scss index c9bbacd734..b7f6fac522 100644 --- a/app/assets/stylesheets/generic/mobile.scss +++ b/app/assets/stylesheets/generic/mobile.scss @@ -56,7 +56,7 @@ } } - .navbar-inner .title { + .container .title { margin-left: 6px !important; max-width: 70% !important; } diff --git a/app/assets/stylesheets/themes/gitlab-theme.scss b/app/assets/stylesheets/themes/gitlab-theme.scss index ee75fe6188..139b3cc1ac 100644 --- a/app/assets/stylesheets/themes/gitlab-theme.scss +++ b/app/assets/stylesheets/themes/gitlab-theme.scss @@ -1,19 +1,17 @@ @mixin gitlab-theme($color-light, $color, $color-darker, $color-dark) { header { &.navbar-gitlab { - .navbar-inner { - .app_logo { - background-color: $color-darker; + .app_logo { + background-color: $color-darker; + a { + color: $color-light; + } + + &:hover { + background-color: $color-dark; a { - color: $color-light; - } - - &:hover { - background-color: $color-dark; - a { - color: #FFF; - } + color: #FFF; } } } diff --git a/app/views/layouts/_empty_head_panel.html.haml b/app/views/layouts/_empty_head_panel.html.haml index b81c2d0364..358caa3868 100644 --- a/app/views/layouts/_empty_head_panel.html.haml +++ b/app/views/layouts/_empty_head_panel.html.haml @@ -1,5 +1,4 @@ %header.navbar.navbar-fixed-top.navbar-gitlab - .navbar-inner - .container - %h4.center - = image_tag 'logo-white.png', width: 32, height: 32 + .container + %h4.center + = image_tag 'logo-white.png', width: 32, height: 32 diff --git a/app/views/layouts/_head_panel.html.haml b/app/views/layouts/_head_panel.html.haml index 8d4c7b39b1..3329a71243 100644 --- a/app/views/layouts/_head_panel.html.haml +++ b/app/views/layouts/_head_panel.html.haml @@ -1,48 +1,47 @@ %header.navbar.navbar-fixed-top.navbar-gitlab{ class: nav_header_class } - .navbar-inner - .container - %div.app_logo - = link_to root_path, class: 'home', title: 'Dashboard', id: 'js-shortcuts-home', data: {toggle: 'tooltip', placement: 'bottom'} do - = brand_header_logo - %h3 GitLab - %h1.title= title + .container + %div.app_logo + = link_to root_path, class: 'home', title: 'Dashboard', id: 'js-shortcuts-home', data: {toggle: 'tooltip', placement: 'bottom'} do + = brand_header_logo + %h3 GitLab + %h1.title= title - %button.navbar-toggle{type: 'button', data: {target: '.navbar-collapse', toggle: 'collapse'}} - %span.sr-only Toggle navigation - = icon('bars') + %button.navbar-toggle{type: 'button', data: {target: '.navbar-collapse', toggle: 'collapse'}} + %span.sr-only Toggle navigation + = icon('bars') - .navbar-collapse.collapse - %ul.nav.navbar-nav - %li.hidden-sm.hidden-xs - = render 'layouts/search' - %li.visible-sm.visible-xs - = link_to search_path, title: 'Search', data: {toggle: 'tooltip', placement: 'bottom'} do - = icon('search') + .navbar-collapse.collapse + %ul.nav.navbar-nav + %li.hidden-sm.hidden-xs + = render 'layouts/search' + %li.visible-sm.visible-xs + = link_to search_path, title: 'Search', data: {toggle: 'tooltip', placement: 'bottom'} do + = icon('search') + %li + = link_to help_path, title: 'Help', data: {toggle: 'tooltip', placement: 'bottom'} do + = icon('question-circle') + %li + = link_to explore_root_path, title: 'Explore', data: {toggle: 'tooltip', placement: 'bottom'} do + = icon('globe') + %li + = link_to user_snippets_path(current_user), title: 'Your snippets', data: {toggle: 'tooltip', placement: 'bottom'} do + = icon('clipboard') + - if current_user.is_admin? %li - = link_to help_path, title: 'Help', data: {toggle: 'tooltip', placement: 'bottom'} do - = icon('question-circle') + = link_to admin_root_path, title: 'Admin area', data: {toggle: 'tooltip', placement: 'bottom'} do + = icon('cogs') + - if current_user.can_create_project? %li - = link_to explore_root_path, title: 'Explore', data: {toggle: 'tooltip', placement: 'bottom'} do - = icon('globe') - %li - = link_to user_snippets_path(current_user), title: 'Your snippets', data: {toggle: 'tooltip', placement: 'bottom'} do - = icon('clipboard') - - if current_user.is_admin? - %li - = link_to admin_root_path, title: 'Admin area', data: {toggle: 'tooltip', placement: 'bottom'} do - = icon('cogs') - - if current_user.can_create_project? - %li - = link_to new_project_path, title: 'New project', data: {toggle: 'tooltip', placement: 'bottom'} do - = icon('plus') - %li - = link_to profile_path, title: 'Profile settings', data: {toggle: 'tooltip', placement: 'bottom'} do - = icon('user') - %li - = link_to destroy_user_session_path, class: 'logout', method: :delete, title: 'Sign out', data: {toggle: 'tooltip', placement: 'bottom'} do - = icon('sign-out') - %li.hidden-xs - = link_to current_user, class: 'profile-pic', id: 'profile-pic', data: {toggle: 'tooltip', placement: 'bottom'} do - = image_tag avatar_icon(current_user.email, 60), alt: 'User activity' + = link_to new_project_path, title: 'New project', data: {toggle: 'tooltip', placement: 'bottom'} do + = icon('plus') + %li + = link_to profile_path, title: 'Profile settings', data: {toggle: 'tooltip', placement: 'bottom'} do + = icon('user') + %li + = link_to destroy_user_session_path, class: 'logout', method: :delete, title: 'Sign out', data: {toggle: 'tooltip', placement: 'bottom'} do + = icon('sign-out') + %li.hidden-xs + = link_to current_user, class: 'profile-pic', id: 'profile-pic', data: {toggle: 'tooltip', placement: 'bottom'} do + = image_tag avatar_icon(current_user.email, 60), alt: 'User activity' = render 'shared/outdated_browser' diff --git a/app/views/layouts/_public_head_panel.html.haml b/app/views/layouts/_public_head_panel.html.haml index 98a87a39bd..8a297566d6 100644 --- a/app/views/layouts/_public_head_panel.html.haml +++ b/app/views/layouts/_public_head_panel.html.haml @@ -1,23 +1,22 @@ %header.navbar.navbar-fixed-top.navbar-gitlab{ class: nav_header_class } - .navbar-inner - .container - %div.app_logo - = link_to explore_root_path, class: "home" do - = brand_header_logo - %h3 GitLab - %h1.title= title + .container + %div.app_logo + = link_to explore_root_path, class: "home" do + = brand_header_logo + %h3 GitLab + %h1.title= title - %button.navbar-toggle{"data-target" => ".navbar-collapse", "data-toggle" => "collapse", type: "button"} - %span.sr-only Toggle navigation - %i.fa.fa-bars + %button.navbar-toggle{"data-target" => ".navbar-collapse", "data-toggle" => "collapse", type: "button"} + %span.sr-only Toggle navigation + %i.fa.fa-bars - - unless current_controller?('sessions') - .pull-right.hidden-xs - = link_to "Sign in", new_session_path(:user, redirect_to_referer: 'yes'), class: 'btn btn-sign-in btn-new append-right-10' + - unless current_controller?('sessions') + .pull-right.hidden-xs + = link_to "Sign in", new_session_path(:user, redirect_to_referer: 'yes'), class: 'btn btn-sign-in btn-new append-right-10' - .navbar-collapse.collapse - %ul.nav.navbar-nav - %li.visible-xs - = link_to "Sign in", new_session_path(:user, redirect_to_referer: 'yes') + .navbar-collapse.collapse + %ul.nav.navbar-nav + %li.visible-xs + = link_to "Sign in", new_session_path(:user, redirect_to_referer: 'yes') = render 'shared/outdated_browser' From 4d3a93af2db702197911d2e3ef58d3365f4cc7ed Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Wed, 29 Apr 2015 13:46:57 +0300 Subject: [PATCH 34/97] Remove abandoned GroupMembers --- ...20150429002313_remove_abandoned_group_members_records.rb | 6 ++++++ db/schema.rb | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 db/migrate/20150429002313_remove_abandoned_group_members_records.rb diff --git a/db/migrate/20150429002313_remove_abandoned_group_members_records.rb b/db/migrate/20150429002313_remove_abandoned_group_members_records.rb new file mode 100644 index 0000000000..6013605bb3 --- /dev/null +++ b/db/migrate/20150429002313_remove_abandoned_group_members_records.rb @@ -0,0 +1,6 @@ +class RemoveAbandonedGroupMembersRecords < ActiveRecord::Migration + def change + execute("DELETE FROM members WHERE type = 'GroupMember' AND source_id NOT IN(\ + SELECT id FROM namespaces WHERE type='Group')") + end +end diff --git a/db/schema.rb b/db/schema.rb index 8683c0446f..2530eb6fa9 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: 20150425173433) do +ActiveRecord::Schema.define(version: 20150429002313) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" From 808b05e9747d46821ff1cc6a0071e881c2dc0056 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Wed, 29 Apr 2015 07:52:27 -0700 Subject: [PATCH 35/97] Move service template and project service settings into a shared view --- app/views/admin/services/_form.html.haml | 74 +------------------ app/views/projects/services/_form.html.haml | 75 +------------------- app/views/shared/_service_settings.html.haml | 75 ++++++++++++++++++++ 3 files changed, 77 insertions(+), 147 deletions(-) create mode 100644 app/views/shared/_service_settings.html.haml diff --git a/app/views/admin/services/_form.html.haml b/app/views/admin/services/_form.html.haml index 34ca7776c9..cdbfc60f9a 100644 --- a/app/views/admin/services/_form.html.haml +++ b/app/views/admin/services/_form.html.haml @@ -4,79 +4,7 @@ %p #{@service.description} template = form_for :service, url: admin_application_settings_service_path, method: :put, html: { class: 'form-horizontal fieldset-form' } do |form| - - if @service.errors.any? - #error_explanation - .alert.alert-danger - - @service.errors.full_messages.each do |msg| - %p= msg - - if @service.help.present? - .well - = preserve do - = markdown @service.help - - .form-group - = form.label :active, "Active", class: "control-label" - .col-sm-10 - = form.check_box :active - - - if @service.supported_events.length > 1 - .form-group - = form.label :url, "Trigger", class: 'control-label' - .col-sm-10 - - if @service.supported_events.include?("push") - %div - = form.check_box :push_events, class: 'pull-left' - .prepend-left-20 - = form.label :push_events, class: 'list-label' do - %strong Push events - %p.light - This url will be triggered by a push to the repository - - if @service.supported_events.include?("tag_push") - %div - = form.check_box :tag_push_events, class: 'pull-left' - .prepend-left-20 - = form.label :tag_push_events, class: 'list-label' do - %strong Tag push events - %p.light - This url will be triggered when a new tag is pushed to the repository - - if @service.supported_events.include?("note") - %div - = form.check_box :note_events, class: 'pull-left' - .prepend-left-20 - = form.label :note_events, class: 'list-label' do - %strong Comments - %p.light - This url will be triggered when someone adds a comment - - if @service.supported_events.include?("issue") - %div - = form.check_box :issues_events, class: 'pull-left' - .prepend-left-20 - = form.label :issues_events, class: 'list-label' do - %strong Issues events - %p.light - This url will be triggered when an issue is created - - if @service.supported_events.include?("merge_request") - %div - = form.check_box :merge_requests_events, class: 'pull-left' - .prepend-left-20 - = form.label :merge_requests_events, class: 'list-label' do - %strong Merge Request events - %p.light - This url will be triggered when a merge request is created - - - @service.fields.each do |field| - - type = field[:type] - - - if type == 'fieldset' - - fields = field[:fields] - - legend = field[:legend] - - %fieldset - %legend= legend - - fields.each do |subfield| - = render 'shared/field', form: form, field: subfield - - else - = render 'shared/field', form: form, field: field + = render 'shared/service_settings', form: form .form-actions = form.submit 'Save', class: 'btn btn-save' diff --git a/app/views/projects/services/_form.html.haml b/app/views/projects/services/_form.html.haml index 1b465e3add..e1823b5119 100644 --- a/app/views/projects/services/_form.html.haml +++ b/app/views/projects/services/_form.html.haml @@ -11,80 +11,7 @@ %hr = form_for(@service, as: :service, url: namespace_project_service_path(@project.namespace, @project, @service.to_param), method: :put, html: { class: 'form-horizontal' }) do |form| - - if @service.errors.any? - .alert.alert-danger - %ul - - @service.errors.full_messages.each do |msg| - %li= msg - - - if @service.help.present? - .well - = preserve do - = markdown @service.help - - .form-group - = form.label :active, "Active", class: "control-label" - .col-sm-10 - = form.check_box :active - - - if @service.supported_events.length > 1 - .form-group - = form.label :url, "Trigger", class: 'control-label' - .col-sm-10 - - if @service.supported_events.include?("push") - %div - = form.check_box :push_events, class: 'pull-left' - .prepend-left-20 - = form.label :push_events, class: 'list-label' do - %strong Push events - %p.light - This url will be triggered by a push to the repository - - if @service.supported_events.include?("tag_push") - %div - = form.check_box :tag_push_events, class: 'pull-left' - .prepend-left-20 - = form.label :tag_push_events, class: 'list-label' do - %strong Tag push events - %p.light - This url will be triggered when a new tag is pushed to the repository - - if @service.supported_events.include?("note") - %div - = form.check_box :note_events, class: 'pull-left' - .prepend-left-20 - = form.label :note_events, class: 'list-label' do - %strong Comments - %p.light - This url will be triggered when someone adds a comment - - if @service.supported_events.include?("issue") - %div - = form.check_box :issues_events, class: 'pull-left' - .prepend-left-20 - = form.label :issues_events, class: 'list-label' do - %strong Issues events - %p.light - This url will be triggered when an issue is created - - if @service.supported_events.include?("merge_request") - %div - = form.check_box :merge_requests_events, class: 'pull-left' - .prepend-left-20 - = form.label :merge_requests_events, class: 'list-label' do - %strong Merge Request events - %p.light - This url will be triggered when a merge request is created - - - @service.fields.each do |field| - - type = field[:type] - - - if type == 'fieldset' - - fields = field[:fields] - - legend = field[:legend] - - %fieldset - %legend= legend - - fields.each do |subfield| - = render 'shared/field', form: form, field: subfield - - else - = render 'shared/field', form: form, field: field + = render 'shared/service_settings', form: form .form-actions = form.submit 'Save', class: 'btn btn-save' diff --git a/app/views/shared/_service_settings.html.haml b/app/views/shared/_service_settings.html.haml new file mode 100644 index 0000000000..16a98a7233 --- /dev/null +++ b/app/views/shared/_service_settings.html.haml @@ -0,0 +1,75 @@ +- if @service.errors.any? + #error_explanation + .alert.alert-danger + %ul + - @service.errors.full_messages.each do |msg| + %li= msg + +- if @service.help.present? + .well + = preserve do + = markdown @service.help + +.form-group + = form.label :active, "Active", class: "control-label" + .col-sm-10 + = form.check_box :active + +- if @service.supported_events.length > 1 + .form-group + = form.label :url, "Trigger", class: 'control-label' + .col-sm-10 + - if @service.supported_events.include?("push") + %div + = form.check_box :push_events, class: 'pull-left' + .prepend-left-20 + = form.label :push_events, class: 'list-label' do + %strong Push events + %p.light + This url will be triggered by a push to the repository + - if @service.supported_events.include?("tag_push") + %div + = form.check_box :tag_push_events, class: 'pull-left' + .prepend-left-20 + = form.label :tag_push_events, class: 'list-label' do + %strong Tag push events + %p.light + This url will be triggered when a new tag is pushed to the repository + - if @service.supported_events.include?("note") + %div + = form.check_box :note_events, class: 'pull-left' + .prepend-left-20 + = form.label :note_events, class: 'list-label' do + %strong Comments + %p.light + This url will be triggered when someone adds a comment + - if @service.supported_events.include?("issue") + %div + = form.check_box :issues_events, class: 'pull-left' + .prepend-left-20 + = form.label :issues_events, class: 'list-label' do + %strong Issues events + %p.light + This url will be triggered when an issue is created + - if @service.supported_events.include?("merge_request") + %div + = form.check_box :merge_requests_events, class: 'pull-left' + .prepend-left-20 + = form.label :merge_requests_events, class: 'list-label' do + %strong Merge Request events + %p.light + This url will be triggered when a merge request is created + +- @service.fields.each do |field| + - type = field[:type] + + - if type == 'fieldset' + - fields = field[:fields] + - legend = field[:legend] + + %fieldset + %legend= legend + - fields.each do |subfield| + = render 'shared/field', form: form, field: subfield + - else + = render 'shared/field', form: form, field: field From 7534d0ef46debee418fa36d65670cd1e43810baa Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 29 Apr 2015 19:52:25 +0300 Subject: [PATCH 36/97] Fix tests Signed-off-by: Dmitriy Zaporozhets --- features/steps/project/source/search_code.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/steps/project/source/search_code.rb b/features/steps/project/source/search_code.rb index 9c2864cc93..b66c5a4123 100644 --- a/features/steps/project/source/search_code.rb +++ b/features/steps/project/source/search_code.rb @@ -14,6 +14,6 @@ class Spinach::Features::ProjectSourceSearchCode < Spinach::FeatureSteps end step 'I should see empty result' do - page.should have_content "We couldn't find any matching" + page.should have_content "We couldn't find any" end end From 5bf9f69df7f46b1c82bf3c02bf806a9f604480e5 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 29 Apr 2015 20:32:48 +0300 Subject: [PATCH 37/97] Fix visibility settings UI in admin area Signed-off-by: Dmitriy Zaporozhets --- app/views/admin/application_settings/_form.html.haml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/admin/application_settings/_form.html.haml b/app/views/admin/application_settings/_form.html.haml index 98d3e00153..87e7c9634e 100644 --- a/app/views/admin/application_settings/_form.html.haml +++ b/app/views/admin/application_settings/_form.html.haml @@ -42,11 +42,11 @@ = f.label :default_branch_protection, class: 'control-label col-sm-2' .col-sm-10 = f.select :default_branch_protection, options_for_select(Gitlab::Access.protection_options, @application_setting.default_branch_protection), {}, class: 'form-control' - .form-group + .form-group.project-visibility-level-holder = f.label :default_project_visibility, class: 'control-label col-sm-2' .col-sm-10 = render('shared/visibility_radios', model_method: :default_project_visibility, form: f, selected_level: @application_setting.default_project_visibility, form_model: 'Project') - .form-group + .form-group.project-visibility-level-holder = f.label :default_snippet_visibility, class: 'control-label col-sm-2' .col-sm-10 = render('shared/visibility_radios', model_method: :default_snippet_visibility, form: f, selected_level: @application_setting.default_snippet_visibility, form_model: 'Snippet') From 81f64958587099b1254a39cbb82dfc758523d6aa Mon Sep 17 00:00:00 2001 From: Joeri Verdeyen Date: Thu, 30 Apr 2015 13:22:28 +0200 Subject: [PATCH 38/97] Update 7.9-to-7.10.md --- doc/update/7.9-to-7.10.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/update/7.9-to-7.10.md b/doc/update/7.9-to-7.10.md index 0512e7cde7..d1179dc2ec 100644 --- a/doc/update/7.9-to-7.10.md +++ b/doc/update/7.9-to-7.10.md @@ -106,7 +106,7 @@ only contains a root URL (ex. `https://gitlab.example.com/`) ## Things went south? Revert to previous version (7.9) ### 1. Revert the code to the previous version -Follow the [upgrade guide from 7.8 to 7.8](7.8-to-7.9.md), except for the database migration +Follow the [upgrade guide from 7.8 to 7.9](7.8-to-7.9.md), except for the database migration (The backup is already migrated to the previous version) ### 2. Restore from the backup: @@ -115,4 +115,4 @@ Follow the [upgrade guide from 7.8 to 7.8](7.8-to-7.9.md), except for the databa cd /home/git/gitlab sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production ``` -If you have more than one backup *.tar file(s) please add `BACKUP=timestamp_of_backup` to the command above. \ No newline at end of file +If you have more than one backup *.tar file(s) please add `BACKUP=timestamp_of_backup` to the command above. From 7e0eb486ed150c0447bf245bdebe250f1771f7dc Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Thu, 30 Apr 2015 15:43:32 +0200 Subject: [PATCH 39/97] Don't allow a merge request to be merged when its title starts with "WIP". --- CHANGELOG | 1 + .../projects/merge_requests_controller.rb | 4 +-- app/models/merge_request.rb | 18 +++++++++++++ .../projects/merge_requests/_show.html.haml | 2 +- .../merge_requests/show/_mr_accept.html.haml | 18 +++++++++++-- lib/api/merge_requests.rb | 4 +-- spec/models/merge_request_spec.rb | 26 +++++++++++++++++++ spec/requests/api/merge_requests_spec.rb | 7 +++++ 8 files changed, 73 insertions(+), 7 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index ecffcb5262..305d2c2508 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ Please view this file on the master branch, on stable branches it's out of date. v 7.11.0 (unreleased) + - Don't allow a merge request to be merged when its title starts with "WIP". - Get Gitorious importer to work again. - Fix clone URL field and X11 Primary selection (Dmitry Medvinsky) - Ignore invalid lines in .gitmodules diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index 41b4e55a59..5b93e95866 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -124,13 +124,13 @@ class Projects::MergeRequestsController < Projects::ApplicationController @merge_request.check_if_can_be_merged end - render json: { merge_status: @merge_request.merge_status_name } + render json: { merge_status: @merge_request.automerge_status } end def automerge return access_denied! unless allowed_to_merge? - if @merge_request.open? && @merge_request.can_be_merged? + if @merge_request.automergeable? AutoMergeWorker.perform_async(@merge_request.id, current_user.id, params) @status = true else diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 49a00697ee..64f3c39f13 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -199,6 +199,8 @@ class MergeRequest < ActiveRecord::Base end def automerge!(current_user, commit_message = nil) + return unless automergeable? + MergeRequests::AutoMergeService. new(target_project, current_user). execute(self, commit_message) @@ -208,6 +210,22 @@ class MergeRequest < ActiveRecord::Base opened? || reopened? end + def work_in_progress? + title =~ /\A\[?WIP\]?:? /i + end + + def automergeable? + open? && !work_in_progress? && can_be_merged? + end + + def automerge_status + if work_in_progress? + "work_in_progress" + else + merge_status_name + end + end + def mr_and_commit_notes # Fetch comments only from last 100 commits commits_for_notes_limit = 100 diff --git a/app/views/projects/merge_requests/_show.html.haml b/app/views/projects/merge_requests/_show.html.haml index cec02de84c..45dd410dd1 100644 --- a/app/views/projects/merge_requests/_show.html.haml +++ b/app/views/projects/merge_requests/_show.html.haml @@ -72,6 +72,6 @@ check_enable: #{@merge_request.unchecked? ? "true" : "false"}, url_to_ci_check: "#{ci_status_namespace_project_merge_request_path(@project.namespace, @project, @merge_request)}", ci_enable: #{@project.ci_service ? "true" : "false"}, - current_status: "#{@merge_request.merge_status_name}", + current_status: "#{@merge_request.automerge_status}", action: "#{controller.action_name}" }); diff --git a/app/views/projects/merge_requests/show/_mr_accept.html.haml b/app/views/projects/merge_requests/show/_mr_accept.html.haml index 9f51f84d40..41f739a45b 100644 --- a/app/views/projects/merge_requests/show/_mr_accept.html.haml +++ b/app/views/projects/merge_requests/show/_mr_accept.html.haml @@ -4,9 +4,11 @@ %strong Archived projects cannot be committed to! - else .automerge_widget.cannot_be_merged.hide - %strong This can't be merged automatically, even if it could be merged you don't have the permission to do so. + %strong This request can't be merged automatically. Even if it could be merged, you don't have permission to do so. + .automerge_widget.work_in_progress.hide + %strong This request can't be merged automatically because it is marked a Work In Progress. Even if it could be merged, you don't have permission to do so. .automerge_widget.can_be_merged.hide - %strong This can be merged automatically but you don't have the permission to do so. + %strong This request can be merged automatically, but you don't have permission to do so. - if @show_merge_controls @@ -57,6 +59,18 @@   This usually happens when git can not resolve conflicts between branches automatically. + .automerge_widget.work_in_progress.hide + %h4 + This request can't be merged because it is marked a Work In Progress. + + %p + %button.btn.disabled + %i.fa.fa-warning + Accept Merge Request +   + + When the merge request is ready, remove the "WIP" prefix from the title to allow it to be merged. + .automerge_widget.unchecked %p %strong diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb index f3765f5ab0..b252c57fae 100644 --- a/lib/api/merge_requests.rb +++ b/lib/api/merge_requests.rb @@ -186,7 +186,7 @@ module API merge_request.check_if_can_be_merged end - if merge_request.open? + if merge_request.open? && !merge_request.work_in_progress? if merge_request.can_be_merged? merge_request.automerge!(current_user, params[:merge_commit_message] || merge_request.merge_commit_message) present merge_request, with: Entities::MergeRequest @@ -195,7 +195,7 @@ module API end else # Merge request can not be merged - # because it is already closed/merged + # because it is already closed/merged or marked as WIP not_allowed! end else diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index 3fcd063efe..97b8abc49d 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -115,6 +115,32 @@ describe MergeRequest do end end + describe "#work_in_progress?" do + it "detects the 'WIP ' prefix" do + subject.title = "WIP #{subject.title}" + expect(subject).to be_work_in_progress + end + + it "detects the 'WIP: ' prefix" do + subject.title = "WIP: #{subject.title}" + expect(subject).to be_work_in_progress + end + + it "detects the '[WIP] ' prefix" do + subject.title = "[WIP] #{subject.title}" + expect(subject).to be_work_in_progress + end + + it "doesn't detect WIP for words starting with WIP" do + subject.title = "Wipwap #{subject.title}" + expect(subject).not_to be_work_in_progress + end + + it "doesn't detect WIP by default" do + expect(subject).not_to be_work_in_progress + end + end + it_behaves_like 'an editable mentionable' do subject { create(:merge_request, source_project: project, target_project: project) } diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb index 9e252441a4..5fca831f9b 100644 --- a/spec/requests/api/merge_requests_spec.rb +++ b/spec/requests/api/merge_requests_spec.rb @@ -312,6 +312,13 @@ describe API::API, api: true do expect(json_response['message']).to eq('405 Method Not Allowed') end + it "should return 405 if merge_request is a work in progress" do + merge_request.update_attribute(:title, "WIP: #{merge_request.title}") + put api("/projects/#{project.id}/merge_request/#{merge_request.id}/merge", user) + expect(response.status).to eq(405) + expect(json_response['message']).to eq('405 Method Not Allowed') + end + it "should return 401 if user has no permissions to merge" do user2 = create(:user) project.team << [user2, :reporter] From 9c76a6fa96bd3c48dc1a64aecb082d4bd87dc2ba Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Wed, 29 Apr 2015 00:33:49 -0700 Subject: [PATCH 40/97] Show incompatible projects in Google Code import status Importing a JSON file with only one Subversion project lead to confusion over whether the system was working. Provide status why these projects could not be imported directly. Closes #1531 --- CHANGELOG | 2 +- .../import/google_code_controller.rb | 1 + app/views/import/google_code/status.html.haml | 38 ++++++++++++++----- lib/gitlab/google_code_import/client.rb | 4 ++ .../import/google_code_controller_spec.rb | 13 +++++++ .../gitlab/google_code_import/client_spec.rb | 1 + 6 files changed, 49 insertions(+), 10 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index ecffcb5262..63a5bd3d6b 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -19,7 +19,7 @@ v 7.11.0 (unreleased) - Include commit comments in MR from a forked project. - Fix adding new group members from admin area - Add default project and snippet visibility settings to the admin web UI. - - + - Show incompatible projects in Google Code import status (Stan Hu) - Fix bug where commit data would not appear in some subdirectories (Stan Hu) - Fix bug where Slack service channel was not saved in admin template settings. (Stan Hu) - Move snippets UI to fluid layout diff --git a/app/controllers/import/google_code_controller.rb b/app/controllers/import/google_code_controller.rb index 5adf6ed785..4aa6d28c9a 100644 --- a/app/controllers/import/google_code_controller.rb +++ b/app/controllers/import/google_code_controller.rb @@ -72,6 +72,7 @@ class Import::GoogleCodeController < Import::BaseController end @repos = client.repos + @incompatible_repos = client.incompatible_repos @already_added_projects = current_user.created_projects.where(import_type: "google_code") already_added_projects_names = @already_added_projects.pluck(:import_source) diff --git a/app/views/import/google_code/status.html.haml b/app/views/import/google_code/status.html.haml index 2013b8c03c..b01b63f2a7 100644 --- a/app/views/import/google_code/status.html.haml +++ b/app/views/import/google_code/status.html.haml @@ -2,15 +2,19 @@ %i.fa.fa-google Import projects from Google Code -%p.light - Select projects you want to import. -%p.light - Optionally, you can - = link_to "customize", new_user_map_import_google_code_path - how Google Code email addresses and usernames are imported into GitLab. -%hr -%p - = button_tag 'Import all projects', class: "btn btn-success js-import-all" +- if @repos.any? + %p.light + Select projects you want to import. + %p.light + Optionally, you can + = link_to "customize", new_user_map_import_google_code_path + how Google Code email addresses and usernames are imported into GitLab. + %hr + %p + - if @incompatible_repos.any? + = button_tag 'Import all compatible projects', class: "btn btn-success js-import-all" + - else + = button_tag 'Import all projects', class: "btn btn-success js-import-all" %table.table.import-jobs %thead @@ -44,6 +48,22 @@ = "#{current_user.username}/#{repo.name}" %td.import-actions.job-status = button_tag "Import", class: "btn js-add-to-import" + - @incompatible_repos.each do |repo| + %tr{id: "repo_#{repo.id}"} + %td + = link_to repo.name, "https://code.google.com/p/#{repo.name}", target: "_blank" + %td.import-target + %td.import-actions-job-status + = label_tag "Incompatible Project", nil, class: "label label-danger" + +- if @incompatible_repos.any? + %p + One or more of your Google Code projects cannot be imported into GitLab + directly because they use Subversion or Mercurial for version control, + rather than Git. Please convert them to Git on Google Code, and go + through the + = link_to "import flow", new_import_google_code_path + again. :coffeescript new ImporterStatus("#{jobs_import_google_code_path}", "#{import_google_code_path}") diff --git a/lib/gitlab/google_code_import/client.rb b/lib/gitlab/google_code_import/client.rb index 02f31e45f8..890bd9a355 100644 --- a/lib/gitlab/google_code_import/client.rb +++ b/lib/gitlab/google_code_import/client.rb @@ -21,6 +21,10 @@ module Gitlab @repos ||= raw_data["projects"].map { |raw_repo| GoogleCodeImport::Repository.new(raw_repo) }.select(&:git?) end + def incompatible_repos + @incompatible_repos ||= raw_data["projects"].map { |raw_repo| GoogleCodeImport::Repository.new(raw_repo) }.reject(&:git?) + end + def repo(id) repos.find { |repo| repo.id == id } end diff --git a/spec/controllers/import/google_code_controller_spec.rb b/spec/controllers/import/google_code_controller_spec.rb index 037cddb460..78c0f5079c 100644 --- a/spec/controllers/import/google_code_controller_spec.rb +++ b/spec/controllers/import/google_code_controller_spec.rb @@ -27,21 +27,34 @@ describe Import::GoogleCodeController do it "assigns variables" do @project = create(:project, import_type: 'google_code', creator_id: user.id) controller.stub_chain(:client, :repos).and_return([@repo]) + controller.stub_chain(:client, :incompatible_repos).and_return([]) get :status expect(assigns(:already_added_projects)).to eq([@project]) expect(assigns(:repos)).to eq([@repo]) + expect(assigns(:incompatible_repos)).to eq([]) end it "does not show already added project" do @project = create(:project, import_type: 'google_code', creator_id: user.id, import_source: 'vim') controller.stub_chain(:client, :repos).and_return([@repo]) + controller.stub_chain(:client, :incompatible_repos).and_return([]) get :status expect(assigns(:already_added_projects)).to eq([@project]) expect(assigns(:repos)).to eq([]) end + + it "does not show any invalid projects" do + controller.stub_chain(:client, :repos).and_return([]) + controller.stub_chain(:client, :incompatible_repos).and_return([@repo]) + + get :status + + expect(assigns(:repos)).to be_empty + expect(assigns(:incompatible_repos)).to eq([@repo]) + end end end diff --git a/spec/lib/gitlab/google_code_import/client_spec.rb b/spec/lib/gitlab/google_code_import/client_spec.rb index d2bf871daa..a66b811e0f 100644 --- a/spec/lib/gitlab/google_code_import/client_spec.rb +++ b/spec/lib/gitlab/google_code_import/client_spec.rb @@ -23,6 +23,7 @@ describe Gitlab::GoogleCodeImport::Client do describe "#repos" do it "returns only Git repositories" do expect(subject.repos.length).to eq(1) + expect(subject.incompatible_repos.length).to eq(1) end end From d386bb780864f4fc36490e19ea654f31bf193d0f Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Thu, 30 Apr 2015 16:17:03 +0200 Subject: [PATCH 41/97] Allow primary email to be set to an email that you've already added. --- CHANGELOG | 1 + app/controllers/admin/users_controller.rb | 3 +- app/controllers/profiles/emails_controller.rb | 11 ++++---- app/models/email.rb | 5 ---- app/models/user.rb | 28 +++++++++++++++++-- app/views/profiles/emails/index.html.haml | 16 ++++++++--- 6 files changed, 46 insertions(+), 18 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index ecffcb5262..72b0d697e7 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ Please view this file on the master branch, on stable branches it's out of date. v 7.11.0 (unreleased) + - Allow primary email to be set to an email that you've already added. - Get Gitorious importer to work again. - Fix clone URL field and X11 Primary selection (Dmitry Medvinsky) - Ignore invalid lines in .gitmodules diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb index adb83996f8..d36e359934 100644 --- a/app/controllers/admin/users_controller.rb +++ b/app/controllers/admin/users_controller.rb @@ -102,8 +102,7 @@ class Admin::UsersController < Admin::ApplicationController email = user.emails.find(params[:email_id]) email.destroy - user.set_notification_email - user.save if user.notification_email_changed? + user.update_secondary_emails! respond_to do |format| format.html { redirect_to :back, notice: "Successfully removed email." } diff --git a/app/controllers/profiles/emails_controller.rb b/app/controllers/profiles/emails_controller.rb index 954c98c0d9..dddca05ce2 100644 --- a/app/controllers/profiles/emails_controller.rb +++ b/app/controllers/profiles/emails_controller.rb @@ -3,14 +3,17 @@ class Profiles::EmailsController < ApplicationController def index @primary = current_user.email - @public_email = current_user.public_email @emails = current_user.emails end def create @email = current_user.emails.new(email_params) - flash[:alert] = @email.errors.full_messages.first unless @email.save + if @email.save + NotificationService.new.new_email(@email) + else + flash[:alert] = @email.errors.full_messages.first + end redirect_to profile_emails_url end @@ -19,9 +22,7 @@ class Profiles::EmailsController < ApplicationController @email = current_user.emails.find(params[:id]) @email.destroy - current_user.set_notification_email - current_user.set_public_email - current_user.save if current_user.notification_email_changed? or current_user.public_email_changed? + current_user.update_secondary_emails! respond_to do |format| format.html { redirect_to profile_emails_url } diff --git a/app/models/email.rb b/app/models/email.rb index 556b0e9586..935705e2ed 100644 --- a/app/models/email.rb +++ b/app/models/email.rb @@ -18,7 +18,6 @@ class Email < ActiveRecord::Base validates :email, presence: true, email: { strict_mode: true }, uniqueness: true validate :unique_email, if: ->(email) { email.email_changed? } - after_create :notify before_validation :cleanup_email def cleanup_email @@ -28,8 +27,4 @@ class Email < ActiveRecord::Base def unique_email self.errors.add(:email, 'has already been taken') if User.exists?(email: self.email) end - - def notify - NotificationService.new.new_email(self) - end end diff --git a/app/models/user.rb b/app/models/user.rb index d6b93afe73..847100de28 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -139,6 +139,7 @@ class User < ActiveRecord::Base validate :avatar_type, if: ->(user) { user.avatar_changed? } validate :unique_email, if: ->(user) { user.email_changed? } validate :owns_notification_email, if: ->(user) { user.notification_email_changed? } + validate :owns_public_email, if: ->(user) { user.public_email_changed? } validates :avatar, file_size: { maximum: 200.kilobytes.to_i } before_validation :generate_password, on: :create @@ -146,6 +147,7 @@ class User < ActiveRecord::Base before_validation :set_notification_email, if: ->(user) { user.email_changed? } before_validation :set_public_email, if: ->(user) { user.public_email_changed? } + after_update :update_emails_with_primary_email, if: ->(user) { user.email_changed? } before_save :ensure_authentication_token after_save :ensure_namespace_correct after_initialize :set_projects_limit @@ -276,13 +278,29 @@ class User < ActiveRecord::Base end def unique_email - self.errors.add(:email, 'has already been taken') if Email.exists?(email: self.email) + if !self.emails.exists?(email: self.email) && Email.exists?(email: self.email) + self.errors.add(:email, 'has already been taken') + end end def owns_notification_email self.errors.add(:notification_email, "is not an email you own") unless self.all_emails.include?(self.notification_email) end + def owns_public_email + self.errors.add(:public_email, "is not an email you own") unless self.all_emails.include?(self.public_email) + end + + def update_emails_with_primary_email + primary_email_record = self.emails.find_by(email: self.email) + if primary_email_record + primary_email_record.destroy + self.emails.create(email: self.email_was) + + self.update_secondary_emails! + end + end + # Groups user has access to def authorized_groups @authorized_groups ||= begin @@ -448,10 +466,16 @@ class User < ActiveRecord::Base def set_public_email if self.public_email.blank? || !self.all_emails.include?(self.public_email) - self.public_email = '' + self.public_email = nil end end + def update_secondary_emails! + self.set_notification_email + self.set_public_email + self.save if self.notification_email_changed? || self.public_email_changed? + end + def set_projects_limit connection_default_value_defined = new_record? && !projects_limit_changed? return unless self.projects_limit.nil? || connection_default_value_defined diff --git a/app/views/profiles/emails/index.html.haml b/app/views/profiles/emails/index.html.haml index 09f290429e..9ef49ef9ec 100644 --- a/app/views/profiles/emails/index.html.haml +++ b/app/views/profiles/emails/index.html.haml @@ -4,11 +4,15 @@ Your %b Primary Email will be used for avatar detection and web based operations, such as edits and merges. - %br +%p.light Your %b Notification Email will be used for account notifications. - %br +%p.light + Your + %b Public Email + will be displayed on your public profile. +%p.light All email addresses will be used to identify your commits. %hr @@ -20,13 +24,17 @@ %li %strong= @primary %span.label.label-success Primary Email - - if @primary === @public_email + - if @primary === current_user.public_email %span.label.label-info Public Email + - if @primary === current_user.notification_email + %span.label.label-info Notification Email - @emails.each do |email| %li %strong= email.email - - if email.email === @public_email + - if email.email === current_user.public_email %span.label.label-info Public Email + - if email.email === current_user.notification_email + %span.label.label-info Notification Email %span.cgray added #{time_ago_with_tooltip(email.created_at)} = link_to 'Remove', profile_email_path(email), data: { confirm: 'Are you sure?'}, method: :delete, class: 'btn btn-sm btn-remove pull-right' From d79348ab55c668883aa8d2a7fd5b59f28eb5118a Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Thu, 30 Apr 2015 08:40:21 -0700 Subject: [PATCH 42/97] Fix Error 500 when searching Wiki pages Closes #1547 --- CHANGELOG | 1 + app/helpers/wiki_helper.rb | 2 ++ features/search.feature | 6 ++++++ features/steps/project/wiki.rb | 5 +++++ features/steps/search.rb | 20 ++++++++++++++++++++ 5 files changed, 34 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index ecffcb5262..76aa94aed8 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ Please view this file on the master branch, on stable branches it's out of date. v 7.11.0 (unreleased) + - Fix Error 500 when searching Wiki pages (Stan Hu) - Get Gitorious importer to work again. - Fix clone URL field and X11 Primary selection (Dmitry Medvinsky) - Ignore invalid lines in .gitmodules diff --git a/app/helpers/wiki_helper.rb b/app/helpers/wiki_helper.rb index a3bc64c010..f8a96516e6 100644 --- a/app/helpers/wiki_helper.rb +++ b/app/helpers/wiki_helper.rb @@ -6,6 +6,8 @@ module WikiHelper case wiki_page when Symbol wiki_page + when String + wiki_page else wiki_page.slug end diff --git a/features/search.feature b/features/search.feature index def21e0092..1608e82467 100644 --- a/features/search.feature +++ b/features/search.feature @@ -44,3 +44,9 @@ Feature: Search Then I should see "Foo" link in the search results And I should not see "Bar" link in the search results + Scenario: I should see Wiki blobs + And project has Wiki content + When I click project "Shop" link + And I search for "Wiki content" + And I click "Wiki" link + Then I should see "test_wiki" link in the search results diff --git a/features/steps/project/wiki.rb b/features/steps/project/wiki.rb index bb93e582a1..717132da45 100644 --- a/features/steps/project/wiki.rb +++ b/features/steps/project/wiki.rb @@ -159,6 +159,11 @@ class Spinach::Features::ProjectWiki < Spinach::FeatureSteps page.should have_content('History for') end + step 'I search for Wiki content' do + fill_in "Search in this project", with: "wiki_content" + click_button "Search" + end + def wiki @project_wiki = ProjectWiki.new(project, current_user) end diff --git a/features/steps/search.rb b/features/steps/search.rb index 6f0e038c4d..8197cd410a 100644 --- a/features/steps/search.rb +++ b/features/steps/search.rb @@ -18,6 +18,11 @@ class Spinach::Features::Search < Spinach::FeatureSteps click_button "Search" end + step 'I search for "Wiki content"' do + fill_in "dashboard_search", with: "content" + click_button "Search" + end + step 'I click "Issues" link' do within '.search-filter' do click_link 'Issues' @@ -36,6 +41,12 @@ class Spinach::Features::Search < Spinach::FeatureSteps end end + step 'I click "Wiki" link' do + within '.search-filter' do + click_link 'Wiki' + end + end + step 'I should see "Shop" project link' do page.should have_link "Shop" end @@ -66,4 +77,13 @@ class Spinach::Features::Search < Spinach::FeatureSteps step 'I should not see "Bar" link in the search results' do find(:css, '.search-results').should_not have_link 'Bar' end + + step 'I should see "test_wiki" link in the search results' do + find(:css, '.search-results').should have_link 'test_wiki.md' + end + + step 'project has Wiki content' do + @wiki = ::ProjectWiki.new(project, current_user) + @wiki.create_page("test_wiki", "Some Wiki content", :markdown, "first commit") + end end From 26ad250989d82b496b131811f8a0ddd7e662b650 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Thu, 30 Apr 2015 19:06:18 +0200 Subject: [PATCH 43/97] Add a page title to every page. --- CHANGELOG | 1 + .../admin/application_controller.rb | 8 +- .../dashboard/application_controller.rb | 11 ++ .../dashboard/groups_controller.rb | 2 +- .../dashboard/milestones_controller.rb | 2 +- .../dashboard/projects_controller.rb | 2 +- app/controllers/dashboard_controller.rb | 6 +- .../explore/application_controller.rb | 11 ++ app/controllers/explore/groups_controller.rb | 4 +- .../explore/projects_controller.rb | 4 +- .../groups/application_controller.rb | 11 +- app/controllers/groups/avatars_controller.rb | 2 - .../groups/milestones_controller.rb | 4 +- app/controllers/groups_controller.rb | 13 +- app/controllers/help_controller.rb | 8 +- app/controllers/invites_controller.rb | 2 - .../oauth/applications_controller.rb | 8 +- .../oauth/authorizations_controller.rb | 8 +- .../authorized_applications_controller.rb | 10 +- .../profiles/accounts_controller.rb | 4 +- .../profiles/application_controller.rb | 11 ++ .../profiles/avatars_controller.rb | 4 +- app/controllers/profiles/emails_controller.rb | 4 +- app/controllers/profiles/keys_controller.rb | 3 +- .../profiles/notifications_controller.rb | 4 +- .../profiles/passwords_controller.rb | 10 +- app/controllers/profiles_controller.rb | 4 +- .../projects/application_controller.rb | 10 +- .../projects/avatars_controller.rb | 2 - app/controllers/projects/forks_controller.rb | 1 - .../projects/uploads_controller.rb | 2 - app/controllers/projects_controller.rb | 22 ++- app/controllers/search_controller.rb | 9 + app/controllers/snippets_controller.rb | 11 +- app/controllers/users_controller.rb | 9 - app/helpers/application_helper.rb | 8 + app/helpers/groups_helper.rb | 18 -- app/helpers/projects_helper.rb | 40 ----- .../admin/application_settings/show.html.haml | 1 + app/views/admin/applications/edit.html.haml | 3 +- app/views/admin/applications/index.html.haml | 1 + app/views/admin/applications/new.html.haml | 3 +- app/views/admin/applications/show.html.haml | 1 + .../admin/background_jobs/show.html.haml | 1 + .../admin/broadcast_messages/index.html.haml | 1 + app/views/admin/deploy_keys/index.html.haml | 1 + app/views/admin/deploy_keys/new.html.haml | 1 + app/views/admin/deploy_keys/show.html.haml | 1 + app/views/admin/groups/edit.html.haml | 1 + app/views/admin/groups/index.html.haml | 1 + app/views/admin/groups/new.html.haml | 1 + app/views/admin/groups/show.html.haml | 1 + app/views/admin/hooks/index.html.haml | 1 + app/views/admin/keys/show.html.haml | 1 + app/views/admin/logs/show.html.haml | 1 + app/views/admin/projects/index.html.haml | 1 + app/views/admin/projects/show.html.haml | 1 + app/views/admin/services/edit.html.haml | 1 + app/views/admin/services/index.html.haml | 1 + app/views/admin/users/edit.html.haml | 1 + app/views/admin/users/index.html.haml | 1 + app/views/admin/users/new.html.haml | 1 + app/views/admin/users/show.html.haml | 1 + app/views/dashboard/groups/index.html.haml | 1 + app/views/dashboard/issues.html.haml | 1 + app/views/dashboard/merge_requests.html.haml | 1 + .../dashboard/milestones/index.html.haml | 1 + app/views/dashboard/milestones/show.html.haml | 1 + .../dashboard/projects/starred.html.haml | 1 + app/views/devise/registrations/new.html.haml | 3 +- app/views/devise/sessions/new.html.haml | 1 + .../doorkeeper/applications/edit.html.haml | 3 +- .../doorkeeper/applications/index.html.haml | 3 +- .../doorkeeper/applications/show.html.haml | 1 + app/views/errors/access_denied.html.haml | 1 + app/views/errors/encoding.html.haml | 1 + app/views/errors/git_not_found.html.haml | 1 + app/views/errors/not_found.html.haml | 1 + app/views/errors/omniauth_error.html.haml | 1 + app/views/explore/groups/index.html.haml | 1 + app/views/explore/projects/index.html.haml | 1 + app/views/explore/projects/starred.html.haml | 1 + app/views/explore/projects/trending.html.haml | 1 + app/views/groups/_settings_nav.html.haml | 11 -- app/views/groups/edit.html.haml | 1 + .../groups/group_members/index.html.haml | 1 + app/views/groups/issues.html.haml | 1 + app/views/groups/merge_requests.html.haml | 1 + app/views/groups/milestones/index.html.haml | 1 + app/views/groups/milestones/show.html.haml | 1 + app/views/groups/projects.html.haml | 1 + app/views/help/index.html.haml | 1 + app/views/help/show.html.haml | 1 + app/views/help/ui.html.haml | 1 + app/views/import/bitbucket/status.html.haml | 1 + app/views/import/github/status.html.haml | 1 + app/views/import/gitlab/status.html.haml | 1 + app/views/import/gitorious/status.html.haml | 1 + app/views/import/google_code/new.html.haml | 1 + .../import/google_code/new_user_map.html.haml | 1 + app/views/import/google_code/status.html.haml | 1 + app/views/invites/show.html.haml | 1 + app/views/layouts/_head.html.haml | 5 +- app/views/layouts/_page.html.haml | 4 +- app/views/layouts/admin.html.haml | 6 - app/views/layouts/application.html.haml | 15 +- app/views/layouts/errors.html.haml | 2 +- app/views/layouts/explore.html.haml | 12 -- app/views/layouts/group.html.haml | 6 - app/views/layouts/nav/_group.html.haml | 13 +- app/views/layouts/nav/_project.html.haml | 156 ++++++++---------- .../layouts/nav/_project_settings.html.haml | 41 +++++ app/views/layouts/navless.html.haml | 7 - app/views/layouts/profile.html.haml | 6 - app/views/layouts/project.html.haml | 14 ++ app/views/layouts/project_settings.html.haml | 10 +- app/views/layouts/projects.html.haml | 7 - app/views/layouts/public_group.html.haml | 6 - app/views/layouts/public_projects.html.haml | 6 - app/views/layouts/public_users.html.haml | 6 - app/views/layouts/search.html.haml | 6 - app/views/layouts/snippets.html.haml | 6 - app/views/profiles/accounts/show.html.haml | 1 + app/views/profiles/applications.html.haml | 1 + app/views/profiles/design.html.haml | 1 + app/views/profiles/emails/index.html.haml | 1 + app/views/profiles/history.html.haml | 1 + app/views/profiles/keys/index.html.haml | 1 + app/views/profiles/keys/new.html.haml | 1 + app/views/profiles/keys/show.html.haml | 1 + .../profiles/notifications/show.html.haml | 1 + app/views/profiles/passwords/edit.html.haml | 1 + app/views/profiles/show.html.haml | 1 + app/views/projects/_settings_nav.html.haml | 31 ---- app/views/projects/blame/show.html.haml | 1 + app/views/projects/blob/edit.html.haml | 1 + app/views/projects/blob/new.html.haml | 1 + app/views/projects/blob/show.html.haml | 1 + app/views/projects/branches/index.html.haml | 1 + app/views/projects/branches/new.html.haml | 1 + app/views/projects/commit/show.html.haml | 1 + app/views/projects/commits/show.html.haml | 1 + app/views/projects/compare/index.html.haml | 1 + app/views/projects/compare/show.html.haml | 1 + .../projects/deploy_keys/index.html.haml | 1 + app/views/projects/deploy_keys/new.html.haml | 1 + app/views/projects/deploy_keys/show.html.haml | 1 + app/views/projects/edit.html.haml | 1 + app/views/projects/forks/error.html.haml | 1 + app/views/projects/forks/new.html.haml | 1 + app/views/projects/graphs/commits.html.haml | 1 + app/views/projects/graphs/show.html.haml | 1 + app/views/projects/hooks/index.html.haml | 1 + app/views/projects/imports/new.html.haml | 1 + app/views/projects/imports/show.html.haml | 1 + app/views/projects/issues/edit.html.haml | 1 + app/views/projects/issues/index.html.haml | 1 + app/views/projects/issues/new.html.haml | 1 + app/views/projects/issues/show.html.haml | 1 + app/views/projects/labels/edit.html.haml | 1 + app/views/projects/labels/index.html.haml | 1 + app/views/projects/labels/new.html.haml | 1 + .../projects/merge_requests/_show.html.haml | 1 + .../projects/merge_requests/edit.html.haml | 1 + .../projects/merge_requests/index.html.haml | 1 + .../projects/merge_requests/invalid.html.haml | 1 + .../projects/merge_requests/new.html.haml | 1 + app/views/projects/milestones/edit.html.haml | 1 + app/views/projects/milestones/index.html.haml | 1 + app/views/projects/milestones/new.html.haml | 1 + app/views/projects/milestones/show.html.haml | 1 + app/views/projects/network/show.html.haml | 1 + .../projects/project_members/import.html.haml | 1 + .../projects/project_members/index.html.haml | 1 + .../protected_branches/index.html.haml | 1 + app/views/projects/services/edit.html.haml | 1 + app/views/projects/services/index.html.haml | 1 + app/views/projects/snippets/edit.html.haml | 1 + app/views/projects/snippets/index.html.haml | 1 + app/views/projects/snippets/new.html.haml | 1 + app/views/projects/snippets/show.html.haml | 1 + app/views/projects/tags/index.html.haml | 1 + app/views/projects/tags/new.html.haml | 1 + app/views/projects/tree/show.html.haml | 1 + app/views/projects/wikis/edit.html.haml | 1 + app/views/projects/wikis/empty.html.haml | 1 + app/views/projects/wikis/git_access.html.haml | 1 + app/views/projects/wikis/history.html.haml | 1 + app/views/projects/wikis/pages.html.haml | 1 + app/views/projects/wikis/show.html.haml | 1 + app/views/search/show.html.haml | 1 + .../snippets/current_user_index.html.haml | 1 + app/views/snippets/edit.html.haml | 1 + app/views/snippets/index.html.haml | 1 + app/views/snippets/new.html.haml | 1 + app/views/snippets/show.html.haml | 1 + app/views/snippets/user_index.html.haml | 1 + 197 files changed, 426 insertions(+), 390 deletions(-) create mode 100644 app/controllers/dashboard/application_controller.rb create mode 100644 app/controllers/explore/application_controller.rb create mode 100644 app/controllers/profiles/application_controller.rb delete mode 100644 app/views/groups/_settings_nav.html.haml delete mode 100644 app/views/layouts/admin.html.haml delete mode 100644 app/views/layouts/explore.html.haml delete mode 100644 app/views/layouts/group.html.haml create mode 100644 app/views/layouts/nav/_project_settings.html.haml delete mode 100644 app/views/layouts/navless.html.haml delete mode 100644 app/views/layouts/profile.html.haml create mode 100644 app/views/layouts/project.html.haml delete mode 100644 app/views/layouts/projects.html.haml delete mode 100644 app/views/layouts/public_group.html.haml delete mode 100644 app/views/layouts/public_projects.html.haml delete mode 100644 app/views/layouts/public_users.html.haml delete mode 100644 app/views/layouts/search.html.haml delete mode 100644 app/views/layouts/snippets.html.haml delete mode 100644 app/views/projects/_settings_nav.html.haml diff --git a/CHANGELOG b/CHANGELOG index a98c911f1a..9b8d0cb250 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,6 +2,7 @@ Please view this file on the master branch, on stable branches it's out of date. v 7.11.0 (unreleased) - Don't allow a merge request to be merged when its title starts with "WIP". + - Add a page title to every page. - Get Gitorious importer to work again. - Fix clone URL field and X11 Primary selection (Dmitry Medvinsky) - Ignore invalid lines in .gitmodules diff --git a/app/controllers/admin/application_controller.rb b/app/controllers/admin/application_controller.rb index fe5456f820..cfbeb035c0 100644 --- a/app/controllers/admin/application_controller.rb +++ b/app/controllers/admin/application_controller.rb @@ -2,10 +2,16 @@ # # Automatically sets the layout and ensures an administrator is logged in class Admin::ApplicationController < ApplicationController - layout 'admin' before_action :authenticate_admin! + before_action :set_title def authenticate_admin! return render_404 unless current_user.is_admin? end + + def set_title + @title = "Admin area" + @title_url = admin_root_path + @sidebar = "admin" + end end diff --git a/app/controllers/dashboard/application_controller.rb b/app/controllers/dashboard/application_controller.rb new file mode 100644 index 0000000000..0a0af3d4ce --- /dev/null +++ b/app/controllers/dashboard/application_controller.rb @@ -0,0 +1,11 @@ +class Dashboard::ApplicationController < ApplicationController + before_action :set_title + + private + + def set_title + @title = "Dashboard" + @title_url = root_path + @sidebar = "dashboard" + end +end diff --git a/app/controllers/dashboard/groups_controller.rb b/app/controllers/dashboard/groups_controller.rb index ed14f4e1f3..3bc94ff218 100644 --- a/app/controllers/dashboard/groups_controller.rb +++ b/app/controllers/dashboard/groups_controller.rb @@ -1,4 +1,4 @@ -class Dashboard::GroupsController < ApplicationController +class Dashboard::GroupsController < Dashboard::ApplicationController def index @group_members = current_user.group_members.page(params[:page]).per(PER_PAGE) end diff --git a/app/controllers/dashboard/milestones_controller.rb b/app/controllers/dashboard/milestones_controller.rb index 33227e7f1d..53896d4f2c 100644 --- a/app/controllers/dashboard/milestones_controller.rb +++ b/app/controllers/dashboard/milestones_controller.rb @@ -1,4 +1,4 @@ -class Dashboard::MilestonesController < ApplicationController +class Dashboard::MilestonesController < Dashboard::ApplicationController before_action :load_projects def index diff --git a/app/controllers/dashboard/projects_controller.rb b/app/controllers/dashboard/projects_controller.rb index 426bc61541..da96171e88 100644 --- a/app/controllers/dashboard/projects_controller.rb +++ b/app/controllers/dashboard/projects_controller.rb @@ -1,4 +1,4 @@ -class Dashboard::ProjectsController < ApplicationController +class Dashboard::ProjectsController < Dashboard::ApplicationController before_action :event_filter def starred diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb index 40b5de1295..17ddde68f9 100644 --- a/app/controllers/dashboard_controller.rb +++ b/app/controllers/dashboard_controller.rb @@ -1,8 +1,8 @@ -class DashboardController < ApplicationController - respond_to :html - +class DashboardController < Dashboard::ApplicationController before_action :load_projects, except: [:projects] before_action :event_filter, only: :show + + respond_to :html def show @projects = @projects.includes(:namespace) diff --git a/app/controllers/explore/application_controller.rb b/app/controllers/explore/application_controller.rb new file mode 100644 index 0000000000..8d94fd238a --- /dev/null +++ b/app/controllers/explore/application_controller.rb @@ -0,0 +1,11 @@ +class Explore::ApplicationController < ApplicationController + before_action :set_title + + private + + def set_title + @title = "Explore GitLab" + @title_url = explore_root_path + @sidebar = "explore" + end +end diff --git a/app/controllers/explore/groups_controller.rb b/app/controllers/explore/groups_controller.rb index a7250b799f..55cda0cff1 100644 --- a/app/controllers/explore/groups_controller.rb +++ b/app/controllers/explore/groups_controller.rb @@ -1,9 +1,7 @@ -class Explore::GroupsController < ApplicationController +class Explore::GroupsController < Explore::ApplicationController skip_before_action :authenticate_user!, :reject_blocked, :set_current_user_for_observers - layout "explore" - def index @groups = GroupsFinder.new.execute(current_user) @groups = @groups.search(params[:search]) if params[:search].present? diff --git a/app/controllers/explore/projects_controller.rb b/app/controllers/explore/projects_controller.rb index b1b0a2514d..e9bcb44f6b 100644 --- a/app/controllers/explore/projects_controller.rb +++ b/app/controllers/explore/projects_controller.rb @@ -1,9 +1,7 @@ -class Explore::ProjectsController < ApplicationController +class Explore::ProjectsController < Explore::ApplicationController skip_before_action :authenticate_user!, :reject_blocked - layout 'explore' - def index @projects = ProjectsFinder.new.execute(current_user) @tags = @projects.tags_on(:tags) diff --git a/app/controllers/groups/application_controller.rb b/app/controllers/groups/application_controller.rb index 469a6813ee..e0fd4befae 100644 --- a/app/controllers/groups/application_controller.rb +++ b/app/controllers/groups/application_controller.rb @@ -1,4 +1,5 @@ class Groups::ApplicationController < ApplicationController + before_action :set_title private @@ -18,11 +19,9 @@ class Groups::ApplicationController < ApplicationController end end - def determine_layout - if current_user - 'group' - else - 'public_group' - end + def set_title + @title = group.name + @title_url = group_path(group) + @sidebar = "group" end end diff --git a/app/controllers/groups/avatars_controller.rb b/app/controllers/groups/avatars_controller.rb index 38071410f4..6aa64222f7 100644 --- a/app/controllers/groups/avatars_controller.rb +++ b/app/controllers/groups/avatars_controller.rb @@ -1,6 +1,4 @@ class Groups::AvatarsController < ApplicationController - layout "profile" - def destroy @group = Group.find_by(path: params[:group_id]) @group.remove_avatar! diff --git a/app/controllers/groups/milestones_controller.rb b/app/controllers/groups/milestones_controller.rb index 41564b04a9..669f7f3126 100644 --- a/app/controllers/groups/milestones_controller.rb +++ b/app/controllers/groups/milestones_controller.rb @@ -1,6 +1,4 @@ -class Groups::MilestonesController < ApplicationController - layout 'group' - +class Groups::MilestonesController < Groups::ApplicationController before_action :authorize_group_milestone!, only: :update def index diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index 294af0b170..66e92abff8 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -11,9 +11,6 @@ class GroupsController < Groups::ApplicationController # Load group projects before_action :load_projects, except: [:new, :create, :projects, :edit, :update] before_action :event_filter, only: :show - before_action :set_title, only: [:new, :create] - - layout :determine_layout def new @group = Group.new @@ -120,16 +117,10 @@ class GroupsController < Groups::ApplicationController end def set_title - @title = 'New Group' - end - - def determine_layout if [:new, :create].include?(action_name.to_sym) - 'navless' - elsif current_user - 'group' + @title = 'New Group' else - 'public_group' + super end end diff --git a/app/controllers/help_controller.rb b/app/controllers/help_controller.rb index 35ece5b270..b405cc7e68 100644 --- a/app/controllers/help_controller.rb +++ b/app/controllers/help_controller.rb @@ -3,12 +3,12 @@ class HelpController < ApplicationController end def show - category = clean_path_info(path_params[:category]) - file = path_params[:file] + @category = clean_path_info(path_params[:category]) + @file = path_params[:file] respond_to do |format| format.any(:markdown, :md, :html) do - path = Rails.root.join('doc', category, "#{file}.md") + path = Rails.root.join('doc', @category, "#{@file}.md") if File.exist?(path) @markdown = File.read(path) @@ -22,7 +22,7 @@ class HelpController < ApplicationController # Allow access to images in the doc folder format.any(:png, :gif, :jpeg) do - path = Rails.root.join('doc', category, "#{file}.#{params[:format]}") + path = Rails.root.join('doc', @category, "#{@file}.#{params[:format]}") if File.exist?(path) send_file(path, disposition: 'inline') diff --git a/app/controllers/invites_controller.rb b/app/controllers/invites_controller.rb index a29c03395f..eb3c823353 100644 --- a/app/controllers/invites_controller.rb +++ b/app/controllers/invites_controller.rb @@ -4,8 +4,6 @@ class InvitesController < ApplicationController respond_to :html - layout 'navless' - def show end diff --git a/app/controllers/oauth/applications_controller.rb b/app/controllers/oauth/applications_controller.rb index ea256de2c3..f30a85564d 100644 --- a/app/controllers/oauth/applications_controller.rb +++ b/app/controllers/oauth/applications_controller.rb @@ -1,6 +1,6 @@ class Oauth::ApplicationsController < Doorkeeper::ApplicationsController before_action :authenticate_user! - layout "profile" + before_action :set_title def index head :forbidden and return @@ -36,4 +36,10 @@ class Oauth::ApplicationsController < Doorkeeper::ApplicationsController rescue_from ActiveRecord::RecordNotFound do |exception| render "errors/not_found", layout: "errors", status: 404 end + + def set_title + @title = "Profile" + @title_url = profile_path + @sidebar = "profile" + end end diff --git a/app/controllers/oauth/authorizations_controller.rb b/app/controllers/oauth/authorizations_controller.rb index 6d3c1a320d..c62890ba85 100644 --- a/app/controllers/oauth/authorizations_controller.rb +++ b/app/controllers/oauth/authorizations_controller.rb @@ -1,6 +1,6 @@ class Oauth::AuthorizationsController < Doorkeeper::AuthorizationsController before_action :authenticate_resource_owner! - layout "profile" + before_action :set_title def new if pre_auth.authorizable? @@ -54,4 +54,10 @@ class Oauth::AuthorizationsController < Doorkeeper::AuthorizationsController def strategy @strategy ||= server.authorization_request(pre_auth.response_type) end + + def set_title + @title = "Profile" + @title_url = profile_path + @sidebar = "profile" + end end diff --git a/app/controllers/oauth/authorized_applications_controller.rb b/app/controllers/oauth/authorized_applications_controller.rb index 0b27ce7da7..6d0bf9889e 100644 --- a/app/controllers/oauth/authorized_applications_controller.rb +++ b/app/controllers/oauth/authorized_applications_controller.rb @@ -1,8 +1,16 @@ class Oauth::AuthorizedApplicationsController < Doorkeeper::AuthorizedApplicationsController - layout "profile" + before_filter :set_title def destroy Doorkeeper::AccessToken.revoke_all_for(params[:id], current_resource_owner) redirect_to applications_profile_url, notice: I18n.t(:notice, scope: [:doorkeeper, :flash, :authorized_applications, :destroy]) end + + private + + def set_title + @title = "Profile" + @title_url = profile_path + @sidebar = "profile" + end end diff --git a/app/controllers/profiles/accounts_controller.rb b/app/controllers/profiles/accounts_controller.rb index 9bd34fe226..175afbf842 100644 --- a/app/controllers/profiles/accounts_controller.rb +++ b/app/controllers/profiles/accounts_controller.rb @@ -1,6 +1,4 @@ -class Profiles::AccountsController < ApplicationController - layout "profile" - +class Profiles::AccountsController < Profiles::ApplicationController def show @user = current_user end diff --git a/app/controllers/profiles/application_controller.rb b/app/controllers/profiles/application_controller.rb new file mode 100644 index 0000000000..8373ff7a75 --- /dev/null +++ b/app/controllers/profiles/application_controller.rb @@ -0,0 +1,11 @@ +class Profiles::ApplicationController < ApplicationController + before_action :set_title + + private + + def set_title + @title = "Profile" + @title_url = profile_path + @sidebar = "profile" + end +end diff --git a/app/controllers/profiles/avatars_controller.rb b/app/controllers/profiles/avatars_controller.rb index 57f3bbf062..f193adb46b 100644 --- a/app/controllers/profiles/avatars_controller.rb +++ b/app/controllers/profiles/avatars_controller.rb @@ -1,6 +1,4 @@ -class Profiles::AvatarsController < ApplicationController - layout "profile" - +class Profiles::AvatarsController < Profiles::ApplicationController def destroy @user = current_user @user.remove_avatar! diff --git a/app/controllers/profiles/emails_controller.rb b/app/controllers/profiles/emails_controller.rb index 954c98c0d9..3e904700de 100644 --- a/app/controllers/profiles/emails_controller.rb +++ b/app/controllers/profiles/emails_controller.rb @@ -1,6 +1,4 @@ -class Profiles::EmailsController < ApplicationController - layout "profile" - +class Profiles::EmailsController < Profiles::ApplicationController def index @primary = current_user.email @public_email = current_user.public_email diff --git a/app/controllers/profiles/keys_controller.rb b/app/controllers/profiles/keys_controller.rb index b0a5a631c6..f3224148fd 100644 --- a/app/controllers/profiles/keys_controller.rb +++ b/app/controllers/profiles/keys_controller.rb @@ -1,5 +1,4 @@ -class Profiles::KeysController < ApplicationController - layout "profile" +class Profiles::KeysController < Profiles::ApplicationController skip_before_action :authenticate_user!, only: [:get_keys] def index diff --git a/app/controllers/profiles/notifications_controller.rb b/app/controllers/profiles/notifications_controller.rb index 3fdcbbab61..22423651c1 100644 --- a/app/controllers/profiles/notifications_controller.rb +++ b/app/controllers/profiles/notifications_controller.rb @@ -1,6 +1,4 @@ -class Profiles::NotificationsController < ApplicationController - layout 'profile' - +class Profiles::NotificationsController < Profiles::ApplicationController def show @user = current_user @notification = current_user.notification diff --git a/app/controllers/profiles/passwords_controller.rb b/app/controllers/profiles/passwords_controller.rb index b719a7fe9a..94ac62cb32 100644 --- a/app/controllers/profiles/passwords_controller.rb +++ b/app/controllers/profiles/passwords_controller.rb @@ -1,6 +1,4 @@ class Profiles::PasswordsController < ApplicationController - layout :determine_layout - skip_before_action :check_password_expiration, only: [:new, :create] before_action :set_user @@ -67,14 +65,10 @@ class Profiles::PasswordsController < ApplicationController end def set_title - @title = "New password" - end - - def determine_layout if [:new, :create].include?(action_name.to_sym) - 'navless' + @title = "New password" else - 'profile' + super end end diff --git a/app/controllers/profiles_controller.rb b/app/controllers/profiles_controller.rb index eb001e8d73..f4366c18e7 100644 --- a/app/controllers/profiles_controller.rb +++ b/app/controllers/profiles_controller.rb @@ -1,12 +1,10 @@ -class ProfilesController < ApplicationController +class ProfilesController < Profiles::ApplicationController include ActionView::Helpers::SanitizeHelper before_action :user before_action :authorize_change_username!, only: :update_username skip_before_action :require_email, only: [:show, :update] - layout 'profile' - def show end diff --git a/app/controllers/projects/application_controller.rb b/app/controllers/projects/application_controller.rb index f7a28e920d..ee88d49b40 100644 --- a/app/controllers/projects/application_controller.rb +++ b/app/controllers/projects/application_controller.rb @@ -1,7 +1,7 @@ class Projects::ApplicationController < ApplicationController before_action :project before_action :repository - layout :determine_layout + layout 'project' def authenticate_user! # Restrict access to Projects area only @@ -17,14 +17,6 @@ class Projects::ApplicationController < ApplicationController super end - def determine_layout - if current_user - 'projects' - else - 'public_projects' - end - end - def require_branch_head unless @repository.branch_names.include?(@ref) redirect_to( diff --git a/app/controllers/projects/avatars_controller.rb b/app/controllers/projects/avatars_controller.rb index 22a12c4b9a..9c3763d593 100644 --- a/app/controllers/projects/avatars_controller.rb +++ b/app/controllers/projects/avatars_controller.rb @@ -1,6 +1,4 @@ class Projects::AvatarsController < Projects::ApplicationController - layout 'project' - before_action :project def show diff --git a/app/controllers/projects/forks_controller.rb b/app/controllers/projects/forks_controller.rb index 01a079d2e6..9e72597ea8 100644 --- a/app/controllers/projects/forks_controller.rb +++ b/app/controllers/projects/forks_controller.rb @@ -18,7 +18,6 @@ class Projects::ForksController < Projects::ApplicationController notice: 'Project was successfully forked.' ) else - @title = 'Fork project' render :error end end diff --git a/app/controllers/projects/uploads_controller.rb b/app/controllers/projects/uploads_controller.rb index e2d0b0d945..71ecc20dd9 100644 --- a/app/controllers/projects/uploads_controller.rb +++ b/app/controllers/projects/uploads_controller.rb @@ -1,6 +1,4 @@ class Projects::UploadsController < Projects::ApplicationController - layout 'project' - skip_before_action :authenticate_user!, :reject_blocked!, :project, :repository, if: -> { action_name == 'show' && image? } diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 883e5865a2..da6b0c3c91 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -9,14 +9,14 @@ class ProjectsController < ApplicationController before_action :set_title, only: [:new, :create] before_action :event_filter, only: :show - layout 'navless', only: [:new, :create, :fork] + layout :determine_layout def new @project = Project.new end def edit - render 'edit', layout: 'project_settings' + render 'edit' end def create @@ -46,7 +46,7 @@ class ProjectsController < ApplicationController end format.js else - format.html { render 'edit', layout: 'project_settings' } + format.html { render 'edit' } format.js end end @@ -72,13 +72,13 @@ class ProjectsController < ApplicationController format.html do if @project.repository_exists? if @project.empty_repo? - render 'projects/empty', layout: user_layout + render 'projects/empty' else @last_push = current_user.recent_push(@project.id) if current_user - render :show, layout: user_layout + render :show end else - render 'projects/no_repo', layout: user_layout + render 'projects/no_repo' end end @@ -164,8 +164,14 @@ class ProjectsController < ApplicationController @title = 'New Project' end - def user_layout - current_user ? 'projects' : 'public_projects' + def determine_layout + if [:new, :create].include?(action_name.to_sym) + 'application' + elsif [:edit, :update].include?(action_name.to_sym) + 'project_settings' + else + 'project' + end end def load_events diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb index ad9e9e8487..ba6f2a41fd 100644 --- a/app/controllers/search_controller.rb +++ b/app/controllers/search_controller.rb @@ -1,6 +1,8 @@ class SearchController < ApplicationController include SearchHelper + before_action :set_title + def show return if params[:search].nil? || params[:search].blank? @@ -55,4 +57,11 @@ class SearchController < ApplicationController render json: search_autocomplete_opts(term).to_json end + + private + + def set_title + @title = "Search" + @title_url = search_path + end end diff --git a/app/controllers/snippets_controller.rb b/app/controllers/snippets_controller.rb index a5259466cb..c960724b47 100644 --- a/app/controllers/snippets_controller.rb +++ b/app/controllers/snippets_controller.rb @@ -13,8 +13,6 @@ class SnippetsController < ApplicationController respond_to :html - layout :determine_layout - def index if params[:username].present? @user = User.find_by(username: params[:username]) @@ -99,15 +97,12 @@ class SnippetsController < ApplicationController end def set_title - @title = 'Snippets' - @title_url = snippets_path + @title = 'Snippets' + @title_url = snippets_path + @sidebar = "snippets" end def snippet_params params.require(:personal_snippet).permit(:title, :content, :file_name, :private, :visibility_level) end - - def determine_layout - current_user ? 'snippets' : 'public_users' - end end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 460cc868b3..7285098435 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -1,7 +1,6 @@ class UsersController < ApplicationController skip_before_action :authenticate_user! before_action :set_user - layout :determine_layout def show @contributed_projects = contributed_projects.joined(@user). @@ -51,14 +50,6 @@ class UsersController < ApplicationController render 'calendar_activities', layout: false end - def determine_layout - if current_user - 'navless' - else - 'public_users' - end - end - private def set_user diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 6e86400a4f..399e49e352 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -332,4 +332,12 @@ module ApplicationHelper end "#{entity_title}#{count}" end + + def page_title(*titles) + @page_title ||= [] + + @page_title.push(*titles.compact) if titles.any? + + @page_title.join(" | ") + end end diff --git a/app/helpers/groups_helper.rb b/app/helpers/groups_helper.rb index add0a776a6..3569ac2af6 100644 --- a/app/helpers/groups_helper.rb +++ b/app/helpers/groups_helper.rb @@ -19,24 +19,6 @@ module GroupsHelper end end - def group_head_title - title = @group.name - - title = if current_action?(:issues) - "Issues - " + title - elsif current_action?(:merge_requests) - "Merge requests - " + title - elsif current_action?(:members) - "Members - " + title - elsif current_action?(:edit) - "Settings - " + title - else - title - end - - title - end - def group_settings_page? if current_controller?('groups') current_action?('edit') || current_action?('projects') diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index c2a7732e6f..96d2606f1a 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -192,46 +192,6 @@ module ProjectsHelper 'unknown' end - def project_head_title - title = @project.name_with_namespace - - title = if current_controller?(:tree) - "#{@project.path}\/#{@path} at #{@ref} - " + title - elsif current_controller?(:issues) - if current_action?(:show) - "Issue ##{@issue.iid} - #{@issue.title} - " + title - else - "Issues - " + title - end - elsif current_controller?(:blob) - if current_action?(:new) || current_action?(:create) - "New file at #{@ref}" - elsif current_action?(:show) - "#{@blob.path} at #{@ref}" - elsif @blob - "Edit file #{@blob.path} at #{@ref}" - end - elsif current_controller?(:commits) - "Commits at #{@ref} - " + title - elsif current_controller?(:merge_requests) - if current_action?(:show) - "Merge request ##{@merge_request.iid} - " + title - else - "Merge requests - " + title - end - elsif current_controller?(:wikis) - "Wiki - " + title - elsif current_controller?(:network) - "Network graph - " + title - elsif current_controller?(:graphs) - "Graphs - " + title - else - title - end - - title - end - def default_url_to_repo(project = nil) project = project || @project current_user ? project.url_to_repo : project.http_url_to_repo diff --git a/app/views/admin/application_settings/show.html.haml b/app/views/admin/application_settings/show.html.haml index 39b66647a5..1632dd8aff 100644 --- a/app/views/admin/application_settings/show.html.haml +++ b/app/views/admin/application_settings/show.html.haml @@ -1,3 +1,4 @@ +- page_title "Settings" %h3.page-title Application settings %hr = render 'form' diff --git a/app/views/admin/applications/edit.html.haml b/app/views/admin/applications/edit.html.haml index e408ae2f29..c596866bde 100644 --- a/app/views/admin/applications/edit.html.haml +++ b/app/views/admin/applications/edit.html.haml @@ -1,3 +1,4 @@ +- page_title "Edit", @application.name, "Applications" %h3.page-title Edit application - @url = admin_application_path(@application) -= render 'form', application: @application \ No newline at end of file += render 'form', application: @application diff --git a/app/views/admin/applications/index.html.haml b/app/views/admin/applications/index.html.haml index d550278710..fc921a966f 100644 --- a/app/views/admin/applications/index.html.haml +++ b/app/views/admin/applications/index.html.haml @@ -1,3 +1,4 @@ +- page_title "Applications" %h3.page-title System OAuth applications %p.light diff --git a/app/views/admin/applications/new.html.haml b/app/views/admin/applications/new.html.haml index 7c62425f19..2884ee93d5 100644 --- a/app/views/admin/applications/new.html.haml +++ b/app/views/admin/applications/new.html.haml @@ -1,3 +1,4 @@ +- page_title "New application" %h3.page-title New application - @url = admin_applications_path -= render 'form', application: @application \ No newline at end of file += render 'form', application: @application diff --git a/app/views/admin/applications/show.html.haml b/app/views/admin/applications/show.html.haml index 2abe390ce1..0ea2ffeda9 100644 --- a/app/views/admin/applications/show.html.haml +++ b/app/views/admin/applications/show.html.haml @@ -1,3 +1,4 @@ +- page_title @application.name, "Applications" %h3.page-title Application: #{@application.name} diff --git a/app/views/admin/background_jobs/show.html.haml b/app/views/admin/background_jobs/show.html.haml index 4ef8e878a7..3a01e11510 100644 --- a/app/views/admin/background_jobs/show.html.haml +++ b/app/views/admin/background_jobs/show.html.haml @@ -1,3 +1,4 @@ +- page_title "Background Jobs" %h3.page-title Background Jobs %p.light GitLab uses #{link_to "sidekiq", "http://sidekiq.org/"} library for async job processing diff --git a/app/views/admin/broadcast_messages/index.html.haml b/app/views/admin/broadcast_messages/index.html.haml index 7e29311bf4..267c9a5292 100644 --- a/app/views/admin/broadcast_messages/index.html.haml +++ b/app/views/admin/broadcast_messages/index.html.haml @@ -1,3 +1,4 @@ +- page_title "Broadcast Messages" %h3.page-title Broadcast Messages %p.light diff --git a/app/views/admin/deploy_keys/index.html.haml b/app/views/admin/deploy_keys/index.html.haml index 2ae83ab95f..367d25cd6a 100644 --- a/app/views/admin/deploy_keys/index.html.haml +++ b/app/views/admin/deploy_keys/index.html.haml @@ -1,3 +1,4 @@ +- page_title "Deploy Keys" .panel.panel-default .panel-heading Public deploy keys (#{@deploy_keys.count}) diff --git a/app/views/admin/deploy_keys/new.html.haml b/app/views/admin/deploy_keys/new.html.haml index c00049424c..5b46b3222a 100644 --- a/app/views/admin/deploy_keys/new.html.haml +++ b/app/views/admin/deploy_keys/new.html.haml @@ -1,3 +1,4 @@ +- page_title "New Deploy Key" %h3.page-title New public deploy key %hr diff --git a/app/views/admin/deploy_keys/show.html.haml b/app/views/admin/deploy_keys/show.html.haml index cfa2adf92e..ea361ca4bd 100644 --- a/app/views/admin/deploy_keys/show.html.haml +++ b/app/views/admin/deploy_keys/show.html.haml @@ -1,3 +1,4 @@ +- page_title @deploy_key.title, "Deploy Keys" .row .col-md-4 .panel.panel-default diff --git a/app/views/admin/groups/edit.html.haml b/app/views/admin/groups/edit.html.haml index 824e51c1cf..eb09a6328e 100644 --- a/app/views/admin/groups/edit.html.haml +++ b/app/views/admin/groups/edit.html.haml @@ -1,3 +1,4 @@ +- page_title "Edit", @group.name, "Groups" %h3.page-title Edit group: #{@group.name} %hr = render 'form' diff --git a/app/views/admin/groups/index.html.haml b/app/views/admin/groups/index.html.haml index 4c53ff5570..e00b23ad99 100644 --- a/app/views/admin/groups/index.html.haml +++ b/app/views/admin/groups/index.html.haml @@ -1,3 +1,4 @@ +- page_title "Groups" %h3.page-title Groups (#{@groups.total_count}) = link_to 'New Group', new_admin_group_path, class: "btn btn-new pull-right" diff --git a/app/views/admin/groups/new.html.haml b/app/views/admin/groups/new.html.haml index f46f45c551..9dccda1f76 100644 --- a/app/views/admin/groups/new.html.haml +++ b/app/views/admin/groups/new.html.haml @@ -1,3 +1,4 @@ +- page_title "New group" %h3.page-title New group %hr = render 'form' diff --git a/app/views/admin/groups/show.html.haml b/app/views/admin/groups/show.html.haml index 427f38018b..187314872d 100644 --- a/app/views/admin/groups/show.html.haml +++ b/app/views/admin/groups/show.html.haml @@ -1,3 +1,4 @@ +- page_title @group.name, "Groups" %h3.page-title Group: #{@group.name} diff --git a/app/views/admin/hooks/index.html.haml b/app/views/admin/hooks/index.html.haml index 7a9dc113f2..e74e1e85f4 100644 --- a/app/views/admin/hooks/index.html.haml +++ b/app/views/admin/hooks/index.html.haml @@ -1,3 +1,4 @@ +- page_title "System Hooks" %h3.page-title System hooks diff --git a/app/views/admin/keys/show.html.haml b/app/views/admin/keys/show.html.haml index 5b23027b3a..9ee77c7739 100644 --- a/app/views/admin/keys/show.html.haml +++ b/app/views/admin/keys/show.html.haml @@ -1 +1,2 @@ +- page_title @key.title, "Keys" = render "profiles/keys/key_details", admin: true diff --git a/app/views/admin/logs/show.html.haml b/app/views/admin/logs/show.html.haml index 384c6ee9af..1484baa78e 100644 --- a/app/views/admin/logs/show.html.haml +++ b/app/views/admin/logs/show.html.haml @@ -1,3 +1,4 @@ +- page_title "Logs" - loggers = [Gitlab::GitLogger, Gitlab::AppLogger, Gitlab::ProductionLogger, Gitlab::SidekiqLogger] %ul.nav.nav-tabs.log-tabs diff --git a/app/views/admin/projects/index.html.haml b/app/views/admin/projects/index.html.haml index 0a13791029..f43d46356f 100644 --- a/app/views/admin/projects/index.html.haml +++ b/app/views/admin/projects/index.html.haml @@ -1,3 +1,4 @@ +- page_title "Projects" = render 'shared/show_aside' .row diff --git a/app/views/admin/projects/show.html.haml b/app/views/admin/projects/show.html.haml index 78684c692c..4c2865ac3f 100644 --- a/app/views/admin/projects/show.html.haml +++ b/app/views/admin/projects/show.html.haml @@ -1,3 +1,4 @@ +- page_title @project.name_with_namespace, "Projects" %h3.page-title Project: #{@project.name_with_namespace} = link_to edit_project_path(@project), class: "btn pull-right" do diff --git a/app/views/admin/services/edit.html.haml b/app/views/admin/services/edit.html.haml index bcc5832792..53d970e33c 100644 --- a/app/views/admin/services/edit.html.haml +++ b/app/views/admin/services/edit.html.haml @@ -1 +1,2 @@ +- page_title @service.title, "Service Templates" = render 'form' diff --git a/app/views/admin/services/index.html.haml b/app/views/admin/services/index.html.haml index 0093fb9776..e237729114 100644 --- a/app/views/admin/services/index.html.haml +++ b/app/views/admin/services/index.html.haml @@ -1,3 +1,4 @@ +- page_title "Service Templates" %h3.page-title Service templates %p.light Service template allows you to set default values for project services diff --git a/app/views/admin/users/edit.html.haml b/app/views/admin/users/edit.html.haml index d71d8189c5..a8837d74dd 100644 --- a/app/views/admin/users/edit.html.haml +++ b/app/views/admin/users/edit.html.haml @@ -1,3 +1,4 @@ +- page_title "Edit", @user.name, "Users" %h3.page-title Edit user: #{@user.name} .back-link diff --git a/app/views/admin/users/index.html.haml b/app/views/admin/users/index.html.haml index 23a9d76963..fe64847023 100644 --- a/app/views/admin/users/index.html.haml +++ b/app/views/admin/users/index.html.haml @@ -1,3 +1,4 @@ +- page_title "Users" = render 'shared/show_aside' .row diff --git a/app/views/admin/users/new.html.haml b/app/views/admin/users/new.html.haml index 8fbb757f42..cabce1f516 100644 --- a/app/views/admin/users/new.html.haml +++ b/app/views/admin/users/new.html.haml @@ -1,3 +1,4 @@ +- page_title "New user" %h3.page-title New user %hr diff --git a/app/views/admin/users/show.html.haml b/app/views/admin/users/show.html.haml index 3524f04c5e..7fc8520610 100644 --- a/app/views/admin/users/show.html.haml +++ b/app/views/admin/users/show.html.haml @@ -1,3 +1,4 @@ +- page_title @user.name, "Users" %h3.page-title User: = @user.name diff --git a/app/views/dashboard/groups/index.html.haml b/app/views/dashboard/groups/index.html.haml index 0cb7f764fa..5ecd53cff8 100644 --- a/app/views/dashboard/groups/index.html.haml +++ b/app/views/dashboard/groups/index.html.haml @@ -1,3 +1,4 @@ +- page_title "Groups" %h3.page-title Group Membership - if current_user.can_create_group? diff --git a/app/views/dashboard/issues.html.haml b/app/views/dashboard/issues.html.haml index 62cc80a30d..dfdf0d68c8 100644 --- a/app/views/dashboard/issues.html.haml +++ b/app/views/dashboard/issues.html.haml @@ -1,3 +1,4 @@ +- page_title "Issues" = content_for :meta_tags do - if current_user = auto_discovery_link_tag(:atom, issues_dashboard_url(format: :atom, private_token: current_user.private_token), title: "#{current_user.name} issues") diff --git a/app/views/dashboard/merge_requests.html.haml b/app/views/dashboard/merge_requests.html.haml index 97a42461b4..a7e1b08a0a 100644 --- a/app/views/dashboard/merge_requests.html.haml +++ b/app/views/dashboard/merge_requests.html.haml @@ -1,3 +1,4 @@ +- page_title "Merge Requests" %h3.page-title Merge Requests diff --git a/app/views/dashboard/milestones/index.html.haml b/app/views/dashboard/milestones/index.html.haml index 9944c0df81..9a9a5e139a 100644 --- a/app/views/dashboard/milestones/index.html.haml +++ b/app/views/dashboard/milestones/index.html.haml @@ -1,3 +1,4 @@ +- page_title "Milestones" %h3.page-title Milestones %span.pull-right #{@dashboard_milestones.count} milestones diff --git a/app/views/dashboard/milestones/show.html.haml b/app/views/dashboard/milestones/show.html.haml index 57cce9ab74..24f0bcb60d 100644 --- a/app/views/dashboard/milestones/show.html.haml +++ b/app/views/dashboard/milestones/show.html.haml @@ -1,3 +1,4 @@ +- page_title @dashboard_milestone.title, "Milestones" %h4.page-title .issue-box{ class: "issue-box-#{@dashboard_milestone.closed? ? 'closed' : 'open'}" } - if @dashboard_milestone.closed? diff --git a/app/views/dashboard/projects/starred.html.haml b/app/views/dashboard/projects/starred.html.haml index 67943f2267..8aaa0a7f07 100644 --- a/app/views/dashboard/projects/starred.html.haml +++ b/app/views/dashboard/projects/starred.html.haml @@ -1,3 +1,4 @@ +- page_title "Starred Projects" - if @projects.any? = render 'shared/show_aside' diff --git a/app/views/devise/registrations/new.html.haml b/app/views/devise/registrations/new.html.haml index d3e37f7494..42cfbbf84f 100644 --- a/app/views/devise/registrations/new.html.haml +++ b/app/views/devise/registrations/new.html.haml @@ -1,3 +1,4 @@ +- page_title "Sign up" = render 'devise/shared/signup_box' -= render 'devise/shared/sign_in_link' \ No newline at end of file += render 'devise/shared/sign_in_link' diff --git a/app/views/devise/sessions/new.html.haml b/app/views/devise/sessions/new.html.haml index 89e4e229ac..dbc8eda619 100644 --- a/app/views/devise/sessions/new.html.haml +++ b/app/views/devise/sessions/new.html.haml @@ -1,3 +1,4 @@ +- page_title "Sign in" %div - if signin_enabled? || ldap_enabled? = render 'devise/shared/signin_box' diff --git a/app/views/doorkeeper/applications/edit.html.haml b/app/views/doorkeeper/applications/edit.html.haml index 61584eb9c4..fb6aa30ace 100644 --- a/app/views/doorkeeper/applications/edit.html.haml +++ b/app/views/doorkeeper/applications/edit.html.haml @@ -1,2 +1,3 @@ +- page_title "Edit", @application.name, "Applications" %h3.page-title Edit application -= render 'form', application: @application \ No newline at end of file += render 'form', application: @application diff --git a/app/views/doorkeeper/applications/index.html.haml b/app/views/doorkeeper/applications/index.html.haml index e5be4b4bca..3b0b19107c 100644 --- a/app/views/doorkeeper/applications/index.html.haml +++ b/app/views/doorkeeper/applications/index.html.haml @@ -1,3 +1,4 @@ +- page_title "Applications" %h3.page-title Your applications %p= link_to 'New Application', new_oauth_application_path, class: 'btn btn-success' %table.table.table-striped @@ -13,4 +14,4 @@ %td= link_to application.name, oauth_application_path(application) %td= application.redirect_uri %td= link_to 'Edit', edit_oauth_application_path(application), class: 'btn btn-link' - %td= render 'delete_form', application: application \ No newline at end of file + %td= render 'delete_form', application: application diff --git a/app/views/doorkeeper/applications/show.html.haml b/app/views/doorkeeper/applications/show.html.haml index 82e78b4af1..b2dc86e89c 100644 --- a/app/views/doorkeeper/applications/show.html.haml +++ b/app/views/doorkeeper/applications/show.html.haml @@ -1,3 +1,4 @@ +- page_title @application.name, "Application" %h3.page-title Application: #{@application.name} diff --git a/app/views/errors/access_denied.html.haml b/app/views/errors/access_denied.html.haml index a1d8664c4c..012e985764 100644 --- a/app/views/errors/access_denied.html.haml +++ b/app/views/errors/access_denied.html.haml @@ -1,3 +1,4 @@ +- page_title "Access Denied" %h1 403 %h3 Access Denied %hr diff --git a/app/views/errors/encoding.html.haml b/app/views/errors/encoding.html.haml index 64c7451a8d..90cfbebfcc 100644 --- a/app/views/errors/encoding.html.haml +++ b/app/views/errors/encoding.html.haml @@ -1,3 +1,4 @@ +- page_title "Encoding Error" %h1 500 %h3 Encoding Error %hr diff --git a/app/views/errors/git_not_found.html.haml b/app/views/errors/git_not_found.html.haml index 189e53bca5..ff5d4cc150 100644 --- a/app/views/errors/git_not_found.html.haml +++ b/app/views/errors/git_not_found.html.haml @@ -1,3 +1,4 @@ +- page_title "Git Resource Not Found" %h1 404 %h3 Git Resource Not found %hr diff --git a/app/views/errors/not_found.html.haml b/app/views/errors/not_found.html.haml index 7bf88f592c..3756b98ebb 100644 --- a/app/views/errors/not_found.html.haml +++ b/app/views/errors/not_found.html.haml @@ -1,3 +1,4 @@ +- page_title "Not Found" %h1 404 %h3 The resource you were looking for doesn't exist. %hr diff --git a/app/views/errors/omniauth_error.html.haml b/app/views/errors/omniauth_error.html.haml index f3c8221a9d..3e70e98a24 100644 --- a/app/views/errors/omniauth_error.html.haml +++ b/app/views/errors/omniauth_error.html.haml @@ -1,3 +1,4 @@ +- page_title "Auth Error" %h1 422 %h3 Sign-in using #{@provider} auth failed %hr diff --git a/app/views/explore/groups/index.html.haml b/app/views/explore/groups/index.html.haml index 2ea6cb1865..c05d45e010 100644 --- a/app/views/explore/groups/index.html.haml +++ b/app/views/explore/groups/index.html.haml @@ -1,3 +1,4 @@ +- page_title "Groups" .clearfix .pull-left = form_tag explore_groups_path, method: :get, class: 'form-inline form-tiny' do |f| diff --git a/app/views/explore/projects/index.html.haml b/app/views/explore/projects/index.html.haml index 5086b58cd0..ba2276f51c 100644 --- a/app/views/explore/projects/index.html.haml +++ b/app/views/explore/projects/index.html.haml @@ -1,3 +1,4 @@ +- page_title "Projects" .clearfix = render 'filter' diff --git a/app/views/explore/projects/starred.html.haml b/app/views/explore/projects/starred.html.haml index 420f069375..b5d146b1f2 100644 --- a/app/views/explore/projects/starred.html.haml +++ b/app/views/explore/projects/starred.html.haml @@ -1,3 +1,4 @@ +- page_title "Starred Projects" .explore-trending-block %p.lead %i.fa.fa-star diff --git a/app/views/explore/projects/trending.html.haml b/app/views/explore/projects/trending.html.haml index 18749ac00a..5ae2653fed 100644 --- a/app/views/explore/projects/trending.html.haml +++ b/app/views/explore/projects/trending.html.haml @@ -1,3 +1,4 @@ +- page_title "Trending Projects" .explore-title %h3 Explore GitLab diff --git a/app/views/groups/_settings_nav.html.haml b/app/views/groups/_settings_nav.html.haml deleted file mode 100644 index f93caf9007..0000000000 --- a/app/views/groups/_settings_nav.html.haml +++ /dev/null @@ -1,11 +0,0 @@ -%ul.sidebar-subnav - = nav_link(path: 'groups#edit') do - = link_to edit_group_path(@group), title: 'Group', data: {placement: 'right'} do - = icon('pencil-square-o') - %span - Group - = nav_link(path: 'groups#projects') do - = link_to projects_group_path(@group), title: 'Projects', data: {placement: 'right'} do - = icon('folder') - %span - Projects diff --git a/app/views/groups/edit.html.haml b/app/views/groups/edit.html.haml index 49e7180bf9..85179d4c4a 100644 --- a/app/views/groups/edit.html.haml +++ b/app/views/groups/edit.html.haml @@ -1,3 +1,4 @@ +- page_title "Settings" .panel.panel-default .panel-heading %strong= @group.name diff --git a/app/views/groups/group_members/index.html.haml b/app/views/groups/group_members/index.html.haml index c0c9cd170a..903ca87721 100644 --- a/app/views/groups/group_members/index.html.haml +++ b/app/views/groups/group_members/index.html.haml @@ -1,3 +1,4 @@ +- page_title "Members" - show_roles = should_user_see_group_roles?(current_user, @group) %h3.page-title diff --git a/app/views/groups/issues.html.haml b/app/views/groups/issues.html.haml index cf0da2da46..6a3da6adac 100644 --- a/app/views/groups/issues.html.haml +++ b/app/views/groups/issues.html.haml @@ -1,3 +1,4 @@ +- page_title "Issues" = content_for :meta_tags do - if current_user = auto_discovery_link_tag(:atom, issues_group_url(@group, format: :atom, private_token: current_user.private_token), title: "#{@group.name} issues") diff --git a/app/views/groups/merge_requests.html.haml b/app/views/groups/merge_requests.html.haml index 1ad7490563..268f33d576 100644 --- a/app/views/groups/merge_requests.html.haml +++ b/app/views/groups/merge_requests.html.haml @@ -1,3 +1,4 @@ +- page_title "Merge Requests" %h3.page-title Merge Requests diff --git a/app/views/groups/milestones/index.html.haml b/app/views/groups/milestones/index.html.haml index 008d5a6bd2..385222fa5b 100644 --- a/app/views/groups/milestones/index.html.haml +++ b/app/views/groups/milestones/index.html.haml @@ -1,3 +1,4 @@ +- page_title "Milestones" %h3.page-title Milestones %span.pull-right #{@group_milestones.count} milestones diff --git a/app/views/groups/milestones/show.html.haml b/app/views/groups/milestones/show.html.haml index fb32f2caa4..0ab15c90af 100644 --- a/app/views/groups/milestones/show.html.haml +++ b/app/views/groups/milestones/show.html.haml @@ -1,3 +1,4 @@ +- page_title @group_milestone.title, "Milestone" %h4.page-title .issue-box{ class: "issue-box-#{@group_milestone.closed? ? 'closed' : 'open'}" } - if @group_milestone.closed? diff --git a/app/views/groups/projects.html.haml b/app/views/groups/projects.html.haml index 0d547984cc..6b7efa83de 100644 --- a/app/views/groups/projects.html.haml +++ b/app/views/groups/projects.html.haml @@ -1,3 +1,4 @@ +- page_title "Projects" .panel.panel-default .panel-heading %strong= @group.name diff --git a/app/views/help/index.html.haml b/app/views/help/index.html.haml index af39dfeac5..9ebdd373f3 100644 --- a/app/views/help/index.html.haml +++ b/app/views/help/index.html.haml @@ -1,3 +1,4 @@ +- page_title "Help" %div %h1 GitLab diff --git a/app/views/help/show.html.haml b/app/views/help/show.html.haml index cc1be6a717..1ff5ddb4c1 100644 --- a/app/views/help/show.html.haml +++ b/app/views/help/show.html.haml @@ -1,2 +1,3 @@ +- page_title @file, *@category.split("/").reverse, "Help" .documentation.wiki = markdown @markdown.gsub('$your_email', current_user.email) diff --git a/app/views/help/ui.html.haml b/app/views/help/ui.html.haml index 246a6c1bdf..7c89457ace 100644 --- a/app/views/help/ui.html.haml +++ b/app/views/help/ui.html.haml @@ -1,3 +1,4 @@ +- page_title "UI Development Kit", "Help" - lorem = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed fermentum nisi sapien, non consequat lectus aliquam ultrices. Suspendisse sodales est euismod nunc condimentum, a consectetur diam ornare." .gitlab-ui-dev-kit diff --git a/app/views/import/bitbucket/status.html.haml b/app/views/import/bitbucket/status.html.haml index 4e49bbbc7f..9d2858e4e7 100644 --- a/app/views/import/bitbucket/status.html.haml +++ b/app/views/import/bitbucket/status.html.haml @@ -1,3 +1,4 @@ +- page_title "Bitbucket import" %h3.page-title %i.fa.fa-bitbucket Import projects from Bitbucket diff --git a/app/views/import/github/status.html.haml b/app/views/import/github/status.html.haml index f0bc3e6b1a..ef55249823 100644 --- a/app/views/import/github/status.html.haml +++ b/app/views/import/github/status.html.haml @@ -1,3 +1,4 @@ +- page_title "GitHub import" %h3.page-title %i.fa.fa-github Import projects from GitHub diff --git a/app/views/import/gitlab/status.html.haml b/app/views/import/gitlab/status.html.haml index 33b0a21acf..727f3c7e7f 100644 --- a/app/views/import/gitlab/status.html.haml +++ b/app/views/import/gitlab/status.html.haml @@ -1,3 +1,4 @@ +- page_title "GitLab.com import" %h3.page-title %i.fa.fa-heart Import projects from GitLab.com diff --git a/app/views/import/gitorious/status.html.haml b/app/views/import/gitorious/status.html.haml index 78c5e957be..bff7ee7c85 100644 --- a/app/views/import/gitorious/status.html.haml +++ b/app/views/import/gitorious/status.html.haml @@ -1,3 +1,4 @@ +- page_title "Gitorious import" %h3.page-title %i.icon-gitorious.icon-gitorious-big Import projects from Gitorious.org diff --git a/app/views/import/google_code/new.html.haml b/app/views/import/google_code/new.html.haml index ce78fec205..9c64e0a009 100644 --- a/app/views/import/google_code/new.html.haml +++ b/app/views/import/google_code/new.html.haml @@ -1,3 +1,4 @@ +- page_title "Google Code import" %h3.page-title %i.fa.fa-google Import projects from Google Code diff --git a/app/views/import/google_code/new_user_map.html.haml b/app/views/import/google_code/new_user_map.html.haml index 9c6824ecad..e53ebda7dc 100644 --- a/app/views/import/google_code/new_user_map.html.haml +++ b/app/views/import/google_code/new_user_map.html.haml @@ -1,3 +1,4 @@ +- page_title "User map", "Google Code import" %h3.page-title %i.fa.fa-google Import projects from Google Code diff --git a/app/views/import/google_code/status.html.haml b/app/views/import/google_code/status.html.haml index b01b63f2a7..e8ec79e72f 100644 --- a/app/views/import/google_code/status.html.haml +++ b/app/views/import/google_code/status.html.haml @@ -1,3 +1,4 @@ +- page_title "Google Code import" %h3.page-title %i.fa.fa-google Import projects from Google Code diff --git a/app/views/invites/show.html.haml b/app/views/invites/show.html.haml index ab0ecffe4d..2fd4859c1c 100644 --- a/app/views/invites/show.html.haml +++ b/app/views/invites/show.html.haml @@ -1,3 +1,4 @@ +- page_title "Invitation" %h3.page-title Invitation %p diff --git a/app/views/layouts/_head.html.haml b/app/views/layouts/_head.html.haml index f72882d883..b1a57d9824 100644 --- a/app/views/layouts/_head.html.haml +++ b/app/views/layouts/_head.html.haml @@ -1,11 +1,10 @@ +- page_title "GitLab" %head %meta{charset: "utf-8"} %meta{'http-equiv' => 'X-UA-Compatible', content: 'IE=edge'} %meta{content: "GitLab Community Edition", name: "description"} - %title - = "#{title} | " if defined?(title) - GitLab + %title= page_title = favicon_link_tag 'favicon.ico' = stylesheet_link_tag "application", :media => "all" diff --git a/app/views/layouts/_page.html.haml b/app/views/layouts/_page.html.haml index 0fa2ec9824..5c55bdb546 100644 --- a/app/views/layouts/_page.html.haml +++ b/app/views/layouts/_page.html.haml @@ -1,8 +1,8 @@ .page-with-sidebar{ class: nav_sidebar_class } = render "layouts/broadcast" .sidebar-wrapper - - if defined?(sidebar) - = render(sidebar) + - if defined?(sidebar) && sidebar + = render "layouts/nav/#{sidebar}" - elsif current_user = render 'layouts/nav/dashboard' .collapse-nav diff --git a/app/views/layouts/admin.html.haml b/app/views/layouts/admin.html.haml deleted file mode 100644 index ab84e87c30..0000000000 --- a/app/views/layouts/admin.html.haml +++ /dev/null @@ -1,6 +0,0 @@ -!!! 5 -%html{ lang: "en"} - = render "layouts/head", title: "Admin area" - %body{class: "#{app_theme} admin", :'data-page' => body_data_page} - = render "layouts/head_panel", title: link_to("Admin area", admin_root_path) - = render 'layouts/page', sidebar: 'layouts/nav/admin' diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index 6bd8ac4adb..e0829d40bc 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -1,6 +1,13 @@ +- page_title @title !!! 5 %html{ lang: "en"} - = render "layouts/head", title: "Dashboard" - %body{class: "#{app_theme} application", :'data-page' => body_data_page } - = render "layouts/head_panel", title: link_to("Dashboard", root_path) - = render 'layouts/page', sidebar: 'layouts/nav/dashboard' + = render "layouts/head" + %body{class: "#{app_theme} application", :'data-page' => body_data_page} + - title = defined?(@title_url) ? link_to(@title, @title_url) : @title + + - if current_user + = render "layouts/head_panel", title: title + - else + = render "layouts/public_head_panel", title: title + + = render 'layouts/page', sidebar: @sidebar diff --git a/app/views/layouts/errors.html.haml b/app/views/layouts/errors.html.haml index e51fd4cb82..aa0f3f0a81 100644 --- a/app/views/layouts/errors.html.haml +++ b/app/views/layouts/errors.html.haml @@ -1,6 +1,6 @@ !!! 5 %html{ lang: "en"} - = render "layouts/head", title: "Error" + = render "layouts/head" %body{class: "#{app_theme} application"} = render "layouts/head_panel", title: "" if current_user .container.navless-container diff --git a/app/views/layouts/explore.html.haml b/app/views/layouts/explore.html.haml deleted file mode 100644 index ca79382324..0000000000 --- a/app/views/layouts/explore.html.haml +++ /dev/null @@ -1,12 +0,0 @@ -- page_title = 'Explore GitLab' -!!! 5 -%html{ lang: "en"} - = render "layouts/head", title: page_title - %body{class: "#{app_theme} application", :'data-page' => body_data_page} - = render "layouts/broadcast" - - if current_user - = render "layouts/head_panel", title: link_to(page_title, explore_root_path) - - else - = render "layouts/public_head_panel", title: link_to(page_title, explore_root_path) - - = render 'layouts/page', sidebar: 'layouts/nav/explore' diff --git a/app/views/layouts/group.html.haml b/app/views/layouts/group.html.haml deleted file mode 100644 index f4a6bee15f..0000000000 --- a/app/views/layouts/group.html.haml +++ /dev/null @@ -1,6 +0,0 @@ -!!! 5 -%html{ lang: "en"} - = render "layouts/head", title: group_head_title - %body{class: "#{app_theme} application", :'data-page' => body_data_page} - = render "layouts/head_panel", title: link_to(@group.name, group_path(@group)) - = render 'layouts/page', sidebar: 'layouts/nav/group' diff --git a/app/views/layouts/nav/_group.html.haml b/app/views/layouts/nav/_group.html.haml index 74a8526dbd..62f0579d48 100644 --- a/app/views/layouts/nav/_group.html.haml +++ b/app/views/layouts/nav/_group.html.haml @@ -39,4 +39,15 @@ = icon ('angle-down fw') - if group_settings_page? - = render 'groups/settings_nav' + %ul.sidebar-subnav + = nav_link(path: 'groups#edit') do + = link_to edit_group_path(@group), title: 'Group', data: {placement: 'right'} do + = icon('pencil-square-o') + %span + Group + = nav_link(path: 'groups#projects') do + = link_to projects_group_path(@group), title: 'Projects', data: {placement: 'right'} do + = icon('folder') + %span + Projects + diff --git a/app/views/layouts/nav/_project.html.haml b/app/views/layouts/nav/_project.html.haml index 01b3d70194..172f5197b2 100644 --- a/app/views/layouts/nav/_project.html.haml +++ b/app/views/layouts/nav/_project.html.haml @@ -1,97 +1,85 @@ %ul.project-navigation.nav.nav-sidebar - - if @project_settings_nav - = nav_link do - = link_to project_path(@project), title: 'Back to project', data: {placement: 'right'} do - = icon('caret-square-o-left fw') + = nav_link(path: 'projects#show', html_options: {class: 'home'}) do + = link_to project_path(@project), title: 'Project', class: 'shortcuts-project', data: {placement: 'right'} do + = icon('dashboard fw') + %span + Project + - if project_nav_tab? :files + = nav_link(controller: %w(tree blob blame edit_tree new_tree)) do + = link_to namespace_project_tree_path(@project.namespace, @project, @ref || @repository.root_ref), title: 'Files', class: 'shortcuts-tree', data: {placement: 'right'} do + = icon('files-o fw') %span - Back to project + Files - %li.separate-item - - = render 'projects/settings_nav' - - - else - = nav_link(path: 'projects#show', html_options: {class: 'home'}) do - = link_to project_path(@project), title: 'Project', class: 'shortcuts-project', data: {placement: 'right'} do - = icon('dashboard fw') + - if project_nav_tab? :commits + = nav_link(controller: %w(commit commits compare repositories tags branches)) do + = link_to namespace_project_commits_path(@project.namespace, @project, @ref || @repository.root_ref), title: 'Commits', class: 'shortcuts-commits', data: {placement: 'right'} do + = icon('history fw') %span - Project - - if project_nav_tab? :files - = nav_link(controller: %w(tree blob blame edit_tree new_tree)) do - = link_to namespace_project_tree_path(@project.namespace, @project, @ref || @repository.root_ref), title: 'Files', class: 'shortcuts-tree', data: {placement: 'right'} do - = icon('files-o fw') - %span - Files + Commits - - if project_nav_tab? :commits - = nav_link(controller: %w(commit commits compare repositories tags branches)) do - = link_to namespace_project_commits_path(@project.namespace, @project, @ref || @repository.root_ref), title: 'Commits', class: 'shortcuts-commits', data: {placement: 'right'} do - = icon('history fw') - %span - Commits + - if project_nav_tab? :network + = nav_link(controller: %w(network)) do + = link_to namespace_project_network_path(@project.namespace, @project, @ref || @repository.root_ref), title: 'Network', class: 'shortcuts-network', data: {placement: 'right'} do + = icon('code-fork fw') + %span + Network - - if project_nav_tab? :network - = nav_link(controller: %w(network)) do - = link_to namespace_project_network_path(@project.namespace, @project, @ref || @repository.root_ref), title: 'Network', class: 'shortcuts-network', data: {placement: 'right'} do - = icon('code-fork fw') - %span - Network + - if project_nav_tab? :graphs + = nav_link(controller: %w(graphs)) do + = link_to namespace_project_graph_path(@project.namespace, @project, @ref || @repository.root_ref), title: 'Graphs', class: 'shortcuts-graphs', data: {placement: 'right'} do + = icon('area-chart fw') + %span + Graphs - - if project_nav_tab? :graphs - = nav_link(controller: %w(graphs)) do - = link_to namespace_project_graph_path(@project.namespace, @project, @ref || @repository.root_ref), title: 'Graphs', class: 'shortcuts-graphs', data: {placement: 'right'} do - = icon('area-chart fw') - %span - Graphs + - if project_nav_tab? :milestones + = nav_link(controller: :milestones) do + = link_to namespace_project_milestones_path(@project.namespace, @project), title: 'Milestones', data: {placement: 'right'} do + = icon('clock-o fw') + %span + Milestones - - if project_nav_tab? :milestones - = nav_link(controller: :milestones) do - = link_to namespace_project_milestones_path(@project.namespace, @project), title: 'Milestones', data: {placement: 'right'} do - = icon('clock-o fw') - %span - Milestones + - if project_nav_tab? :issues + = nav_link(controller: :issues) do + = link_to url_for_project_issues(@project, only_path: true), title: 'Issues', class: 'shortcuts-issues', data: {placement: 'right'} do + = icon('exclamation-circle fw') + %span + Issues + - if @project.default_issues_tracker? + %span.count.issue_counter= @project.issues.opened.count - - if project_nav_tab? :issues - = nav_link(controller: :issues) do - = link_to url_for_project_issues(@project, only_path: true), title: 'Issues', class: 'shortcuts-issues', data: {placement: 'right'} do - = icon('exclamation-circle fw') - %span - Issues - - if @project.default_issues_tracker? - %span.count.issue_counter= @project.issues.opened.count + - if project_nav_tab? :merge_requests + = nav_link(controller: :merge_requests) do + = link_to namespace_project_merge_requests_path(@project.namespace, @project), title: 'Merge Requests', class: 'shortcuts-merge_requests', data: {placement: 'right'} do + = icon('tasks fw') + %span + Merge Requests + %span.count.merge_counter= @project.merge_requests.opened.count - - if project_nav_tab? :merge_requests - = nav_link(controller: :merge_requests) do - = link_to namespace_project_merge_requests_path(@project.namespace, @project), title: 'Merge Requests', class: 'shortcuts-merge_requests', data: {placement: 'right'} do - = icon('tasks fw') - %span - Merge Requests - %span.count.merge_counter= @project.merge_requests.opened.count + - if project_nav_tab? :labels + = nav_link(controller: :labels) do + = link_to namespace_project_labels_path(@project.namespace, @project), title: 'Labels', data: {placement: 'right'} do + = icon('tags fw') + %span + Labels - - if project_nav_tab? :labels - = nav_link(controller: :labels) do - = link_to namespace_project_labels_path(@project.namespace, @project), title: 'Labels', data: {placement: 'right'} do - = icon('tags fw') - %span - Labels + - if project_nav_tab? :wiki + = nav_link(controller: :wikis) do + = link_to get_project_wiki_path(@project), title: 'Wiki', class: 'shortcuts-wiki', data: {placement: 'right'} do + = icon('book fw') + %span + Wiki - - if project_nav_tab? :wiki - = nav_link(controller: :wikis) do - = link_to get_project_wiki_path(@project), title: 'Wiki', class: 'shortcuts-wiki', data: {placement: 'right'} do - = icon('book fw') - %span - Wiki + - if project_nav_tab? :snippets + = nav_link(controller: :snippets) do + = link_to namespace_project_snippets_path(@project.namespace, @project), title: 'Snippets', class: 'shortcuts-snippets', data: {placement: 'right'} do + = icon('file-text-o fw') + %span + Snippets - - if project_nav_tab? :snippets - = nav_link(controller: :snippets) do - = link_to namespace_project_snippets_path(@project.namespace, @project), title: 'Snippets', class: 'shortcuts-snippets', data: {placement: 'right'} do - = icon('file-text-o fw') - %span - Snippets - - - if project_nav_tab? :settings - = nav_link(html_options: {class: "#{project_tab_class} separate-item"}) do - = link_to edit_project_path(@project), title: 'Settings', class: 'stat-tab tab no-highlight', data: {placement: 'right'} do - = icon('cogs fw') - %span - Settings + - if project_nav_tab? :settings + = nav_link(html_options: {class: "#{project_tab_class} separate-item"}) do + = link_to edit_project_path(@project), title: 'Settings', class: 'stat-tab tab no-highlight', data: {placement: 'right'} do + = icon('cogs fw') + %span + Settings diff --git a/app/views/layouts/nav/_project_settings.html.haml b/app/views/layouts/nav/_project_settings.html.haml new file mode 100644 index 0000000000..21260302a0 --- /dev/null +++ b/app/views/layouts/nav/_project_settings.html.haml @@ -0,0 +1,41 @@ +%ul.project-navigation.nav.nav-sidebar + = nav_link do + = link_to project_path(@project), title: 'Back to project', data: {placement: 'right'} do + = icon('caret-square-o-left fw') + %span + Back to project + + %li.separate-item + + %ul.project-settings-nav.sidebar-subnav + = nav_link(path: 'projects#edit') do + = link_to edit_project_path(@project), title: 'Project', class: 'stat-tab tab', data: {placement: 'right'} do + = icon('pencil-square-o') + %span + Project + = nav_link(controller: [:project_members, :teams]) do + = link_to namespace_project_project_members_path(@project.namespace, @project), title: 'Members', class: 'team-tab tab', data: {placement: 'right'} do + = icon('users') + %span + Members + = nav_link(controller: :deploy_keys) do + = link_to namespace_project_deploy_keys_path(@project.namespace, @project), title: 'Deploy Keys', data: {placement: 'right'} do + = icon('key') + %span + Deploy Keys + = nav_link(controller: :hooks) do + = link_to namespace_project_hooks_path(@project.namespace, @project), title: 'Web Hooks', data: {placement: 'right'} do + = icon('link') + %span + Web Hooks + = nav_link(controller: :services) do + = link_to namespace_project_services_path(@project.namespace, @project), title: 'Services', data: {placement: 'right'} do + = icon('cogs') + %span + Services + = nav_link(controller: :protected_branches) do + = link_to namespace_project_protected_branches_path(@project.namespace, @project), title: 'Protected Branches', data: {placement: 'right'} do + = icon('lock') + %span + Protected branches + diff --git a/app/views/layouts/navless.html.haml b/app/views/layouts/navless.html.haml deleted file mode 100644 index 10a0fcea2f..0000000000 --- a/app/views/layouts/navless.html.haml +++ /dev/null @@ -1,7 +0,0 @@ -!!! 5 -%html{ lang: "en"} - = render "layouts/head", title: @title - %body{class: "#{app_theme} application", :'data-page' => body_data_page} - = render "layouts/broadcast" - = render "layouts/head_panel", title: defined?(@title_url) ? link_to(@title, @title_url) : @title - = render 'layouts/page' diff --git a/app/views/layouts/profile.html.haml b/app/views/layouts/profile.html.haml deleted file mode 100644 index 2b5be7fc37..0000000000 --- a/app/views/layouts/profile.html.haml +++ /dev/null @@ -1,6 +0,0 @@ -!!! 5 -%html{ lang: "en"} - = render "layouts/head", title: "Profile" - %body{class: "#{app_theme} profile", :'data-page' => body_data_page} - = render "layouts/head_panel", title: link_to("Profile", profile_path) - = render 'layouts/page', sidebar: 'layouts/nav/profile' diff --git a/app/views/layouts/project.html.haml b/app/views/layouts/project.html.haml new file mode 100644 index 0000000000..62a6f5ddf4 --- /dev/null +++ b/app/views/layouts/project.html.haml @@ -0,0 +1,14 @@ +- page_title @project.name_with_namespace +!!! 5 +%html{ lang: "en"} + = render "layouts/head" + %body{class: "#{app_theme} project", :'data-page' => body_data_page, :'data-project-id' => @project.id } + - title = project_title(@project) + + - if current_user + = render "layouts/head_panel", title: project_title(@project) + = render "layouts/init_auto_complete" + - else + = render "layouts/public_head_panel", title: project_title(@project) + + = render 'layouts/page', sidebar: @sidebar || 'project' diff --git a/app/views/layouts/project_settings.html.haml b/app/views/layouts/project_settings.html.haml index 0a0039dec1..d12d07273f 100644 --- a/app/views/layouts/project_settings.html.haml +++ b/app/views/layouts/project_settings.html.haml @@ -1,8 +1,2 @@ -!!! 5 -%html{ lang: "en"} - = render "layouts/head", title: @project.name_with_namespace - %body{class: "#{app_theme} project", :'data-page' => body_data_page, :'data-project-id' => @project.id } - = render "layouts/head_panel", title: project_title(@project) - = render "layouts/init_auto_complete" - - @project_settings_nav = true - = render 'layouts/page', sidebar: 'layouts/nav/project' +- @sidebar = "project_settings" += render template: "layouts/project" diff --git a/app/views/layouts/projects.html.haml b/app/views/layouts/projects.html.haml deleted file mode 100644 index dde0964f47..0000000000 --- a/app/views/layouts/projects.html.haml +++ /dev/null @@ -1,7 +0,0 @@ -!!! 5 -%html{ lang: "en"} - = render "layouts/head", title: project_head_title - %body{class: "#{app_theme} project", :'data-page' => body_data_page, :'data-project-id' => @project.id } - = render "layouts/head_panel", title: project_title(@project) - = render "layouts/init_auto_complete" - = render 'layouts/page', sidebar: 'layouts/nav/project' diff --git a/app/views/layouts/public_group.html.haml b/app/views/layouts/public_group.html.haml deleted file mode 100644 index b9b1d03e08..0000000000 --- a/app/views/layouts/public_group.html.haml +++ /dev/null @@ -1,6 +0,0 @@ -!!! 5 -%html{ lang: "en"} - = render "layouts/head", title: group_head_title - %body{class: "#{app_theme} application", :'data-page' => body_data_page} - = render "layouts/public_head_panel", title: link_to(@group.name, group_path(@group)) - = render 'layouts/page', sidebar: 'layouts/nav/group' diff --git a/app/views/layouts/public_projects.html.haml b/app/views/layouts/public_projects.html.haml deleted file mode 100644 index 04fa7c84e7..0000000000 --- a/app/views/layouts/public_projects.html.haml +++ /dev/null @@ -1,6 +0,0 @@ -!!! 5 -%html{ lang: "en"} - = render "layouts/head", title: @project.name_with_namespace - %body{class: "#{app_theme} application", :'data-page' => body_data_page} - = render "layouts/public_head_panel", title: project_title(@project) - = render 'layouts/page', sidebar: 'layouts/nav/project' diff --git a/app/views/layouts/public_users.html.haml b/app/views/layouts/public_users.html.haml deleted file mode 100644 index 71c16bd168..0000000000 --- a/app/views/layouts/public_users.html.haml +++ /dev/null @@ -1,6 +0,0 @@ -!!! 5 -%html{ lang: "en"} - = render "layouts/head", title: @title - %body{class: "#{app_theme} application", :'data-page' => body_data_page} - = render "layouts/public_head_panel", title: defined?(@title_url) ? link_to(@title, @title_url) : @title - = render 'layouts/page' diff --git a/app/views/layouts/search.html.haml b/app/views/layouts/search.html.haml deleted file mode 100644 index 4b526686be..0000000000 --- a/app/views/layouts/search.html.haml +++ /dev/null @@ -1,6 +0,0 @@ -!!! 5 -%html{ lang: "en"} - = render "layouts/head", title: "Search" - %body{class: "#{app_theme} application", :'data-page' => body_data_page} - = render "layouts/head_panel", title: link_to("Search", search_path) - = render 'layouts/page' diff --git a/app/views/layouts/snippets.html.haml b/app/views/layouts/snippets.html.haml deleted file mode 100644 index fbd29eb23a..0000000000 --- a/app/views/layouts/snippets.html.haml +++ /dev/null @@ -1,6 +0,0 @@ -!!! 5 -%html{ lang: "en"} - = render "layouts/head", title: "Dashboard" - %body{class: "#{app_theme} application", :'data-page' => body_data_page } - = render "layouts/head_panel", title: link_to("Snippets", snippets_path) - = render 'layouts/page', sidebar: 'layouts/nav/snippets' diff --git a/app/views/profiles/accounts/show.html.haml b/app/views/profiles/accounts/show.html.haml index 5bffb4acc1..1c3a3d68ac 100644 --- a/app/views/profiles/accounts/show.html.haml +++ b/app/views/profiles/accounts/show.html.haml @@ -1,3 +1,4 @@ +- page_title "Account" - if current_user.ldap_user? .alert.alert-info Some options are unavailable for LDAP accounts diff --git a/app/views/profiles/applications.html.haml b/app/views/profiles/applications.html.haml index 97e98948f3..c4f6f59624 100644 --- a/app/views/profiles/applications.html.haml +++ b/app/views/profiles/applications.html.haml @@ -1,3 +1,4 @@ +- page_title "Applications" %h3.page-title Application Settings %p.light diff --git a/app/views/profiles/design.html.haml b/app/views/profiles/design.html.haml index 646576c316..af284f6040 100644 --- a/app/views/profiles/design.html.haml +++ b/app/views/profiles/design.html.haml @@ -1,3 +1,4 @@ +- page_title "Design" %h3.page-title Design Settings %p.light diff --git a/app/views/profiles/emails/index.html.haml b/app/views/profiles/emails/index.html.haml index 09f290429e..c17e01425d 100644 --- a/app/views/profiles/emails/index.html.haml +++ b/app/views/profiles/emails/index.html.haml @@ -1,3 +1,4 @@ +- page_title "Emails" %h3.page-title Email Settings %p.light diff --git a/app/views/profiles/history.html.haml b/app/views/profiles/history.html.haml index b1ab433f48..b414fb69f4 100644 --- a/app/views/profiles/history.html.haml +++ b/app/views/profiles/history.html.haml @@ -1,3 +1,4 @@ +- page_title "History" %h3.page-title Your Account History %p.light diff --git a/app/views/profiles/keys/index.html.haml b/app/views/profiles/keys/index.html.haml index 0904c50c88..e3af0d4e18 100644 --- a/app/views/profiles/keys/index.html.haml +++ b/app/views/profiles/keys/index.html.haml @@ -1,3 +1,4 @@ +- page_title "SSH Keys" %h3.page-title SSH Keys Settings .pull-right diff --git a/app/views/profiles/keys/new.html.haml b/app/views/profiles/keys/new.html.haml index ccec716d0c..2bf207a322 100644 --- a/app/views/profiles/keys/new.html.haml +++ b/app/views/profiles/keys/new.html.haml @@ -1,3 +1,4 @@ +- page_title "Add SSH Keys" %h3.page-title Add an SSH Key %p.light Paste your public key here. Read more about how to generate a key on #{link_to "the SSH help page", help_page_path("ssh", "README")}. diff --git a/app/views/profiles/keys/show.html.haml b/app/views/profiles/keys/show.html.haml index cfd5329896..89f6f01581 100644 --- a/app/views/profiles/keys/show.html.haml +++ b/app/views/profiles/keys/show.html.haml @@ -1 +1,2 @@ +- page_title @key.title, "SSH Keys" = render "key_details" diff --git a/app/views/profiles/notifications/show.html.haml b/app/views/profiles/notifications/show.html.haml index 273e72f8a4..a74d97dac3 100644 --- a/app/views/profiles/notifications/show.html.haml +++ b/app/views/profiles/notifications/show.html.haml @@ -1,3 +1,4 @@ +- page_title "Notifications" %h3.page-title Notifications Settings %p.light diff --git a/app/views/profiles/passwords/edit.html.haml b/app/views/profiles/passwords/edit.html.haml index 4b04b113e8..21dabbdfe2 100644 --- a/app/views/profiles/passwords/edit.html.haml +++ b/app/views/profiles/passwords/edit.html.haml @@ -1,3 +1,4 @@ +- page_title "Password" %h3.page-title Password Settings %p.light - if @user.password_automatically_set? diff --git a/app/views/profiles/show.html.haml b/app/views/profiles/show.html.haml index 6c745e69e4..29c3090511 100644 --- a/app/views/profiles/show.html.haml +++ b/app/views/profiles/show.html.haml @@ -1,3 +1,4 @@ +- page_title "Settings" %h3.page-title Profile Settings %p.light diff --git a/app/views/projects/_settings_nav.html.haml b/app/views/projects/_settings_nav.html.haml deleted file mode 100644 index f8b74809b7..0000000000 --- a/app/views/projects/_settings_nav.html.haml +++ /dev/null @@ -1,31 +0,0 @@ -%ul.project-settings-nav.sidebar-subnav - = nav_link(path: 'projects#edit') do - = link_to edit_project_path(@project), title: 'Project', class: 'stat-tab tab', data: {placement: 'right'} do - = icon('pencil-square-o') - %span - Project - = nav_link(controller: [:project_members, :teams]) do - = link_to namespace_project_project_members_path(@project.namespace, @project), title: 'Members', class: 'team-tab tab', data: {placement: 'right'} do - = icon('users') - %span - Members - = nav_link(controller: :deploy_keys) do - = link_to namespace_project_deploy_keys_path(@project.namespace, @project), title: 'Deploy Keys', data: {placement: 'right'} do - = icon('key') - %span - Deploy Keys - = nav_link(controller: :hooks) do - = link_to namespace_project_hooks_path(@project.namespace, @project), title: 'Web Hooks', data: {placement: 'right'} do - = icon('link') - %span - Web Hooks - = nav_link(controller: :services) do - = link_to namespace_project_services_path(@project.namespace, @project), title: 'Services', data: {placement: 'right'} do - = icon('cogs') - %span - Services - = nav_link(controller: :protected_branches) do - = link_to namespace_project_protected_branches_path(@project.namespace, @project), title: 'Protected Branches', data: {placement: 'right'} do - = icon('lock') - %span - Protected branches diff --git a/app/views/projects/blame/show.html.haml b/app/views/projects/blame/show.html.haml index 89dd68d647..462f5b7afb 100644 --- a/app/views/projects/blame/show.html.haml +++ b/app/views/projects/blame/show.html.haml @@ -1,3 +1,4 @@ +- page_title "Blame", @blob.path, @ref %h3.page-title Blame view #tree-holder.tree-holder diff --git a/app/views/projects/blob/edit.html.haml b/app/views/projects/blob/edit.html.haml index 1f61a0b940..e78181f880 100644 --- a/app/views/projects/blob/edit.html.haml +++ b/app/views/projects/blob/edit.html.haml @@ -1,3 +1,4 @@ +- page_title "Edit", @blob.path, @ref .file-editor %ul.nav.nav-tabs.js-edit-mode %li.active diff --git a/app/views/projects/blob/new.html.haml b/app/views/projects/blob/new.html.haml index d78a01f642..eb0d99d015 100644 --- a/app/views/projects/blob/new.html.haml +++ b/app/views/projects/blob/new.html.haml @@ -1,3 +1,4 @@ +- page_title "New file", @ref %h3.page-title New file .file-editor = form_tag(namespace_project_create_blob_path(@project.namespace, @project, @id), method: :post, class: 'form-horizontal form-new-file') do diff --git a/app/views/projects/blob/show.html.haml b/app/views/projects/blob/show.html.haml index 69167654c3..a1d464bac5 100644 --- a/app/views/projects/blob/show.html.haml +++ b/app/views/projects/blob/show.html.haml @@ -1,3 +1,4 @@ +- page_title @blob.path, @ref %div.tree-ref-holder = render 'shared/ref_switcher', destination: 'blob', path: @path diff --git a/app/views/projects/branches/index.html.haml b/app/views/projects/branches/index.html.haml index a313ffcf27..80acc93790 100644 --- a/app/views/projects/branches/index.html.haml +++ b/app/views/projects/branches/index.html.haml @@ -1,3 +1,4 @@ +- page_title "Branches" = render "projects/commits/head" %h3.page-title Branches diff --git a/app/views/projects/branches/new.html.haml b/app/views/projects/branches/new.html.haml index e5fcb98c68..7ca0b78a0b 100644 --- a/app/views/projects/branches/new.html.haml +++ b/app/views/projects/branches/new.html.haml @@ -1,3 +1,4 @@ +- page_title "New branch" - if @error .alert.alert-danger %button{ type: "button", class: "close", "data-dismiss" => "alert"} × diff --git a/app/views/projects/commit/show.html.haml b/app/views/projects/commit/show.html.haml index fc721067ed..fcf75bb3ce 100644 --- a/app/views/projects/commit/show.html.haml +++ b/app/views/projects/commit/show.html.haml @@ -1,3 +1,4 @@ +- page_title @commit.id, "Commits" = render "commit_box" = render "projects/diffs/diffs", diffs: @diffs, project: @project = render "projects/notes/notes_with_form" diff --git a/app/views/projects/commits/show.html.haml b/app/views/projects/commits/show.html.haml index fb1012deb7..c8531b090a 100644 --- a/app/views/projects/commits/show.html.haml +++ b/app/views/projects/commits/show.html.haml @@ -1,3 +1,4 @@ +- page_title "Commits", @ref = content_for :meta_tags do - if current_user = auto_discovery_link_tag(:atom, namespace_project_commits_url(@project.namespace, @project, @ref, format: :atom, private_token: current_user.private_token), title: "#{@project.name}:#{@ref} commits") diff --git a/app/views/projects/compare/index.html.haml b/app/views/projects/compare/index.html.haml index 4745bfbeaa..d1e579a2ed 100644 --- a/app/views/projects/compare/index.html.haml +++ b/app/views/projects/compare/index.html.haml @@ -1,3 +1,4 @@ +- page_title "Compare" = render "projects/commits/head" %h3.page-title diff --git a/app/views/projects/compare/show.html.haml b/app/views/projects/compare/show.html.haml index 214b5bd337..3670dd5c13 100644 --- a/app/views/projects/compare/show.html.haml +++ b/app/views/projects/compare/show.html.haml @@ -1,3 +1,4 @@ +- page_title "#{params[:from]}...#{params[:to]}" = render "projects/commits/head" %h3.page-title diff --git a/app/views/projects/deploy_keys/index.html.haml b/app/views/projects/deploy_keys/index.html.haml index 472a13a852..2e9c5dc08c 100644 --- a/app/views/projects/deploy_keys/index.html.haml +++ b/app/views/projects/deploy_keys/index.html.haml @@ -1,3 +1,4 @@ +- page_title "Deploy Keys" %h3.page-title Deploy keys allow read-only access to the repository diff --git a/app/views/projects/deploy_keys/new.html.haml b/app/views/projects/deploy_keys/new.html.haml index 186d6b5897..01c810aee1 100644 --- a/app/views/projects/deploy_keys/new.html.haml +++ b/app/views/projects/deploy_keys/new.html.haml @@ -1,3 +1,4 @@ +- page_title "New Deploy Key" %h3.page-title New Deploy key %hr diff --git a/app/views/projects/deploy_keys/show.html.haml b/app/views/projects/deploy_keys/show.html.haml index 405b5bcd0d..7d44652af7 100644 --- a/app/views/projects/deploy_keys/show.html.haml +++ b/app/views/projects/deploy_keys/show.html.haml @@ -1,3 +1,4 @@ +- page_title @key.title, "Deploy Keys" %h3.page-title Deploy key: = @key.title diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml index c09d794ef7..1fe6a24e89 100644 --- a/app/views/projects/edit.html.haml +++ b/app/views/projects/edit.html.haml @@ -1,3 +1,4 @@ +- page_title "Settings" .project-edit-container .project-edit-errors .project-edit-content diff --git a/app/views/projects/forks/error.html.haml b/app/views/projects/forks/error.html.haml index 8eb4f79597..3d0ab5b85d 100644 --- a/app/views/projects/forks/error.html.haml +++ b/app/views/projects/forks/error.html.haml @@ -1,3 +1,4 @@ +- page_title "Fork project" - if @forked_project && !@forked_project.saved? .alert.alert-danger.alert-block %h4 diff --git a/app/views/projects/forks/new.html.haml b/app/views/projects/forks/new.html.haml index 5a6c46f320..b7a2ed68e2 100644 --- a/app/views/projects/forks/new.html.haml +++ b/app/views/projects/forks/new.html.haml @@ -1,3 +1,4 @@ +- page_title "Fork project" %h3.page-title Fork project %p.lead Click to fork the project to a user or group diff --git a/app/views/projects/graphs/commits.html.haml b/app/views/projects/graphs/commits.html.haml index 78b4c1923d..254a76e108 100644 --- a/app/views/projects/graphs/commits.html.haml +++ b/app/views/projects/graphs/commits.html.haml @@ -1,3 +1,4 @@ +- page_title "Commit statistics" = render 'head' %p.lead diff --git a/app/views/projects/graphs/show.html.haml b/app/views/projects/graphs/show.html.haml index e3d5094ddc..3a8dc89f84 100644 --- a/app/views/projects/graphs/show.html.haml +++ b/app/views/projects/graphs/show.html.haml @@ -1,3 +1,4 @@ +- page_title "Contributor statistics" = render 'head' .loading-graph .center diff --git a/app/views/projects/hooks/index.html.haml b/app/views/projects/hooks/index.html.haml index bbaddba31b..808c03148f 100644 --- a/app/views/projects/hooks/index.html.haml +++ b/app/views/projects/hooks/index.html.haml @@ -1,3 +1,4 @@ +- page_title "Web Hooks" %h3.page-title Web hooks diff --git a/app/views/projects/imports/new.html.haml b/app/views/projects/imports/new.html.haml index 934b6b8c01..f8f2e192e2 100644 --- a/app/views/projects/imports/new.html.haml +++ b/app/views/projects/imports/new.html.haml @@ -1,3 +1,4 @@ +- page_title "Import repository" %h3.page-title - if @project.import_failed? Import failed. Retry? diff --git a/app/views/projects/imports/show.html.haml b/app/views/projects/imports/show.html.haml index 2d1fdafed2..39fe0fc1c4 100644 --- a/app/views/projects/imports/show.html.haml +++ b/app/views/projects/imports/show.html.haml @@ -1,3 +1,4 @@ +- page_title "Import in progress" .save-project-loader .center %h2 diff --git a/app/views/projects/issues/edit.html.haml b/app/views/projects/issues/edit.html.haml index b1bc3ba0eb..53b6f0879c 100644 --- a/app/views/projects/issues/edit.html.haml +++ b/app/views/projects/issues/edit.html.haml @@ -1 +1,2 @@ +- page_title "Edit", "#{@issue.title} (##{@issue.iid})", "Issues" = render "form" diff --git a/app/views/projects/issues/index.html.haml b/app/views/projects/issues/index.html.haml index c2522816f3..709ea1f789 100644 --- a/app/views/projects/issues/index.html.haml +++ b/app/views/projects/issues/index.html.haml @@ -1,3 +1,4 @@ +- page_title "Issues" = content_for :meta_tags do - if current_user = auto_discovery_link_tag(:atom, namespace_project_issues_url(@project.namespace, @project, :atom, private_token: current_user.private_token), title: "#{@project.name} issues") diff --git a/app/views/projects/issues/new.html.haml b/app/views/projects/issues/new.html.haml index b1bc3ba0eb..96e4385562 100644 --- a/app/views/projects/issues/new.html.haml +++ b/app/views/projects/issues/new.html.haml @@ -1 +1,2 @@ +- page_title "New issue" = render "form" diff --git a/app/views/projects/issues/show.html.haml b/app/views/projects/issues/show.html.haml index bd28d8a1db..81478dfe56 100644 --- a/app/views/projects/issues/show.html.haml +++ b/app/views/projects/issues/show.html.haml @@ -1,3 +1,4 @@ +- page_title "#{@issue.title} (##{@issue.iid})", "Issues" .issue .issue-details %h4.page-title diff --git a/app/views/projects/labels/edit.html.haml b/app/views/projects/labels/edit.html.haml index e003d1dfe7..645402667f 100644 --- a/app/views/projects/labels/edit.html.haml +++ b/app/views/projects/labels/edit.html.haml @@ -1,3 +1,4 @@ +- page_title "Edit", @label.name, "Labels" %h3 Edit label %span.light #{@label.name} diff --git a/app/views/projects/labels/index.html.haml b/app/views/projects/labels/index.html.haml index 0700e72d39..7d19415a7f 100644 --- a/app/views/projects/labels/index.html.haml +++ b/app/views/projects/labels/index.html.haml @@ -1,3 +1,4 @@ +- page_title "Labels" - if can? current_user, :admin_label, @project = link_to new_namespace_project_label_path(@project.namespace, @project), class: "pull-right btn btn-new" do New label diff --git a/app/views/projects/labels/new.html.haml b/app/views/projects/labels/new.html.haml index 0683ed5d4f..7cacbd0f30 100644 --- a/app/views/projects/labels/new.html.haml +++ b/app/views/projects/labels/new.html.haml @@ -1,3 +1,4 @@ +- page_title "New label" %h3 New label .back-link = link_to namespace_project_labels_path(@project.namespace, @project) do diff --git a/app/views/projects/merge_requests/_show.html.haml b/app/views/projects/merge_requests/_show.html.haml index 45dd410dd1..c2f5cdacae 100644 --- a/app/views/projects/merge_requests/_show.html.haml +++ b/app/views/projects/merge_requests/_show.html.haml @@ -1,3 +1,4 @@ +- page_title "#{@merge_request.title} (##{@merge_request.iid})", "Merge Requests" .merge-request{'data-url' => merge_request_path(@merge_request)} .merge-request-details = render "projects/merge_requests/show/mr_title" diff --git a/app/views/projects/merge_requests/edit.html.haml b/app/views/projects/merge_requests/edit.html.haml index 839c63986a..7e5cb07f24 100644 --- a/app/views/projects/merge_requests/edit.html.haml +++ b/app/views/projects/merge_requests/edit.html.haml @@ -1,3 +1,4 @@ +- page_title "Edit", "#{@merge_request.title} (##{@merge_request.iid})", "Merge Requests" %h3.page-title = "Edit merge request ##{@merge_request.iid}" %hr diff --git a/app/views/projects/merge_requests/index.html.haml b/app/views/projects/merge_requests/index.html.haml index d7992bdd19..ab845a7e71 100644 --- a/app/views/projects/merge_requests/index.html.haml +++ b/app/views/projects/merge_requests/index.html.haml @@ -1,3 +1,4 @@ +- page_title "Merge Requests" .append-bottom-10 .pull-right = render 'shared/issuable_search_form', path: namespace_project_merge_requests_path(@project.namespace, @project) diff --git a/app/views/projects/merge_requests/invalid.html.haml b/app/views/projects/merge_requests/invalid.html.haml index b9c466657d..15bd4e2faf 100644 --- a/app/views/projects/merge_requests/invalid.html.haml +++ b/app/views/projects/merge_requests/invalid.html.haml @@ -1,3 +1,4 @@ +- page_title "#{@merge_request.title} (##{@merge_request.iid})", "Merge Requests" .merge-request = render "projects/merge_requests/show/mr_title" = render "projects/merge_requests/show/mr_box" diff --git a/app/views/projects/merge_requests/new.html.haml b/app/views/projects/merge_requests/new.html.haml index 4756903d0e..b1c7bea7de 100644 --- a/app/views/projects/merge_requests/new.html.haml +++ b/app/views/projects/merge_requests/new.html.haml @@ -1,3 +1,4 @@ +- page_title "New merge request" - if @merge_request.can_be_created = render 'new_submit' - else diff --git a/app/views/projects/milestones/edit.html.haml b/app/views/projects/milestones/edit.html.haml index b1bc3ba0eb..c09815a212 100644 --- a/app/views/projects/milestones/edit.html.haml +++ b/app/views/projects/milestones/edit.html.haml @@ -1 +1,2 @@ +- page_title "Edit", @milestone.title, "Milestones" = render "form" diff --git a/app/views/projects/milestones/index.html.haml b/app/views/projects/milestones/index.html.haml index d3eab8d6d7..995eecd783 100644 --- a/app/views/projects/milestones/index.html.haml +++ b/app/views/projects/milestones/index.html.haml @@ -1,3 +1,4 @@ +- page_title "Milestones" .pull-right - if can? current_user, :admin_milestone, @project = link_to new_namespace_project_milestone_path(@project.namespace, @project), class: "pull-right btn btn-new", title: "New Milestone" do diff --git a/app/views/projects/milestones/new.html.haml b/app/views/projects/milestones/new.html.haml index b1bc3ba0eb..d76e417b3c 100644 --- a/app/views/projects/milestones/new.html.haml +++ b/app/views/projects/milestones/new.html.haml @@ -1 +1,2 @@ +- page_title "New milestone" = render "form" diff --git a/app/views/projects/milestones/show.html.haml b/app/views/projects/milestones/show.html.haml index 25cc003096..bba2b8764a 100644 --- a/app/views/projects/milestones/show.html.haml +++ b/app/views/projects/milestones/show.html.haml @@ -1,3 +1,4 @@ +- page_title @milestone.title, "Milestones" %h4.page-title .issue-box{ class: issue_box_class(@milestone) } - if @milestone.closed? diff --git a/app/views/projects/network/show.html.haml b/app/views/projects/network/show.html.haml index c36bad1e94..4d3f118f2d 100644 --- a/app/views/projects/network/show.html.haml +++ b/app/views/projects/network/show.html.haml @@ -1,3 +1,4 @@ +- page_title "Network" = render "head" .project-network .controls diff --git a/app/views/projects/project_members/import.html.haml b/app/views/projects/project_members/import.html.haml index 293754cd0c..6914543f6d 100644 --- a/app/views/projects/project_members/import.html.haml +++ b/app/views/projects/project_members/import.html.haml @@ -1,3 +1,4 @@ +- page_title "Import members" %h3.page-title Import members from another project %p.light diff --git a/app/views/projects/project_members/index.html.haml b/app/views/projects/project_members/index.html.haml index 36a6f6a155..6edb92acd4 100644 --- a/app/views/projects/project_members/index.html.haml +++ b/app/views/projects/project_members/index.html.haml @@ -1,3 +1,4 @@ +- page_title "Members" %h3.page-title Users with access to this project diff --git a/app/views/projects/protected_branches/index.html.haml b/app/views/projects/protected_branches/index.html.haml index a3464c0e5e..52b3a50c1e 100644 --- a/app/views/projects/protected_branches/index.html.haml +++ b/app/views/projects/protected_branches/index.html.haml @@ -1,3 +1,4 @@ +- page_title "Protected branches" %h3.page-title Protected branches %p.light Keep stable branches secure and force developers to use Merge Requests %hr diff --git a/app/views/projects/services/edit.html.haml b/app/views/projects/services/edit.html.haml index bcc5832792..50ed78286d 100644 --- a/app/views/projects/services/edit.html.haml +++ b/app/views/projects/services/edit.html.haml @@ -1 +1,2 @@ +- page_title @service.title, "Services" = render 'form' diff --git a/app/views/projects/services/index.html.haml b/app/views/projects/services/index.html.haml index 0d3ccb6bb8..1065def693 100644 --- a/app/views/projects/services/index.html.haml +++ b/app/views/projects/services/index.html.haml @@ -1,3 +1,4 @@ +- page_title "Services" %h3.page-title Project services %p.light Project services allow you to integrate GitLab with other applications diff --git a/app/views/projects/snippets/edit.html.haml b/app/views/projects/snippets/edit.html.haml index 7baddebde4..945f0084df 100644 --- a/app/views/projects/snippets/edit.html.haml +++ b/app/views/projects/snippets/edit.html.haml @@ -1,3 +1,4 @@ +- page_title "Edit", @snippet.title, "Snippets" %h3.page-title Edit snippet %hr diff --git a/app/views/projects/snippets/index.html.haml b/app/views/projects/snippets/index.html.haml index e2d8ec673a..da9401bd8c 100644 --- a/app/views/projects/snippets/index.html.haml +++ b/app/views/projects/snippets/index.html.haml @@ -1,3 +1,4 @@ +- page_title "Snippets" %h3.page-title Snippets - if can? current_user, :write_project_snippet, @project diff --git a/app/views/projects/snippets/new.html.haml b/app/views/projects/snippets/new.html.haml index 5efe662665..2d9beef1cb 100644 --- a/app/views/projects/snippets/new.html.haml +++ b/app/views/projects/snippets/new.html.haml @@ -1,3 +1,4 @@ +- page_title "New snippets" %h3.page-title New snippet %hr diff --git a/app/views/projects/snippets/show.html.haml b/app/views/projects/snippets/show.html.haml index d19689a105..5725d804df 100644 --- a/app/views/projects/snippets/show.html.haml +++ b/app/views/projects/snippets/show.html.haml @@ -1,3 +1,4 @@ +- page_title @snippet.title, "Snippets" %h3.page-title = @snippet.title diff --git a/app/views/projects/tags/index.html.haml b/app/views/projects/tags/index.html.haml index f1bc2bc9a2..d4652a47cb 100644 --- a/app/views/projects/tags/index.html.haml +++ b/app/views/projects/tags/index.html.haml @@ -1,3 +1,4 @@ +- page_title "Tags" = render "projects/commits/head" %h3.page-title diff --git a/app/views/projects/tags/new.html.haml b/app/views/projects/tags/new.html.haml index 655044438d..61c35e4a5e 100644 --- a/app/views/projects/tags/new.html.haml +++ b/app/views/projects/tags/new.html.haml @@ -1,3 +1,4 @@ +- page_title "New tag" - if @error .alert.alert-danger %button{ type: "button", class: "close", "data-dismiss" => "alert"} × diff --git a/app/views/projects/tree/show.html.haml b/app/views/projects/tree/show.html.haml index a8a580944e..d0a3f522e2 100644 --- a/app/views/projects/tree/show.html.haml +++ b/app/views/projects/tree/show.html.haml @@ -1,3 +1,4 @@ +- page_title @path.presence, @ref = content_for :meta_tags do - if current_user = auto_discovery_link_tag(:atom, namespace_project_commits_url(@project.namespace, @project, @ref, format: :atom, private_token: current_user.private_token), title: "#{@project.name}:#{@ref} commits") diff --git a/app/views/projects/wikis/edit.html.haml b/app/views/projects/wikis/edit.html.haml index 566850cb78..3f1dce1050 100644 --- a/app/views/projects/wikis/edit.html.haml +++ b/app/views/projects/wikis/edit.html.haml @@ -1,3 +1,4 @@ +- page_title "Edit", @page.title, "Wiki" = render 'nav' .pull-right = render 'main_links' diff --git a/app/views/projects/wikis/empty.html.haml b/app/views/projects/wikis/empty.html.haml index 48058124f9..ead9941240 100644 --- a/app/views/projects/wikis/empty.html.haml +++ b/app/views/projects/wikis/empty.html.haml @@ -1,3 +1,4 @@ +- page_title "Wiki" %h3.page-title Empty page %hr .error_message diff --git a/app/views/projects/wikis/git_access.html.haml b/app/views/projects/wikis/git_access.html.haml index 365edb524f..b47dffe00b 100644 --- a/app/views/projects/wikis/git_access.html.haml +++ b/app/views/projects/wikis/git_access.html.haml @@ -1,3 +1,4 @@ +- page_title "Git access", "Wiki" = render 'nav' .row .col-sm-6 diff --git a/app/views/projects/wikis/history.html.haml b/app/views/projects/wikis/history.html.haml index 91291f753f..673ec2d20e 100644 --- a/app/views/projects/wikis/history.html.haml +++ b/app/views/projects/wikis/history.html.haml @@ -1,3 +1,4 @@ +- page_title "History", @page.title, "Wiki" = render 'nav' %h3.page-title %span.light History for diff --git a/app/views/projects/wikis/pages.html.haml b/app/views/projects/wikis/pages.html.haml index ee233d9086..890ff1aed7 100644 --- a/app/views/projects/wikis/pages.html.haml +++ b/app/views/projects/wikis/pages.html.haml @@ -1,3 +1,4 @@ +- page_title "All Pages", "Wiki" = render 'nav' %h3.page-title All Pages diff --git a/app/views/projects/wikis/show.html.haml b/app/views/projects/wikis/show.html.haml index a6263e93f6..83cd4c6667 100644 --- a/app/views/projects/wikis/show.html.haml +++ b/app/views/projects/wikis/show.html.haml @@ -1,3 +1,4 @@ +- page_title @page.title, "Wiki" = render 'nav' %h3.page-title = @page.title diff --git a/app/views/search/show.html.haml b/app/views/search/show.html.haml index e9f2711be2..60f9e9ac9d 100644 --- a/app/views/search/show.html.haml +++ b/app/views/search/show.html.haml @@ -1,3 +1,4 @@ +- page_title @search_term = render 'search/form' %hr - if @search_term diff --git a/app/views/snippets/current_user_index.html.haml b/app/views/snippets/current_user_index.html.haml index 6bb2237a75..0718f74382 100644 --- a/app/views/snippets/current_user_index.html.haml +++ b/app/views/snippets/current_user_index.html.haml @@ -1,3 +1,4 @@ +- page_title "Your Snippets" %h3.page-title Your Snippets .pull-right diff --git a/app/views/snippets/edit.html.haml b/app/views/snippets/edit.html.haml index 30aa174edf..1a38003566 100644 --- a/app/views/snippets/edit.html.haml +++ b/app/views/snippets/edit.html.haml @@ -1,3 +1,4 @@ +- page_title "Edit", @snippet.title, "Snippets" %h3.page-title Edit snippet %hr diff --git a/app/views/snippets/index.html.haml b/app/views/snippets/index.html.haml index 108dd0cca3..e9bb6a908d 100644 --- a/app/views/snippets/index.html.haml +++ b/app/views/snippets/index.html.haml @@ -1,3 +1,4 @@ +- page_title "Public Snippets" %h3.page-title Public snippets diff --git a/app/views/snippets/new.html.haml b/app/views/snippets/new.html.haml index 77cfd9af33..2c92041351 100644 --- a/app/views/snippets/new.html.haml +++ b/app/views/snippets/new.html.haml @@ -1,3 +1,4 @@ +- page_title "New snippet" %h3.page-title New snippet %hr diff --git a/app/views/snippets/show.html.haml b/app/views/snippets/show.html.haml index 5204fb9a90..903f51ff6c 100644 --- a/app/views/snippets/show.html.haml +++ b/app/views/snippets/show.html.haml @@ -1,3 +1,4 @@ +- page_title @snippet.title, "Snippet" %h3.page-title = @snippet.title diff --git a/app/views/snippets/user_index.html.haml b/app/views/snippets/user_index.html.haml index df524cd18b..23700eb39d 100644 --- a/app/views/snippets/user_index.html.haml +++ b/app/views/snippets/user_index.html.haml @@ -1,3 +1,4 @@ +- page_title "Snippets", @user.name %h3.page-title = image_tag avatar_icon(@user.email), class: "avatar s24" = @user.name From a3bd323cd3db718e0aeda9dac29102c3b4656174 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Thu, 30 Apr 2015 20:02:00 +0200 Subject: [PATCH 44/97] Remove an old determine_layout call. --- app/controllers/groups/group_members_controller.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/controllers/groups/group_members_controller.rb b/app/controllers/groups/group_members_controller.rb index 5648a652e8..a11c554a2a 100644 --- a/app/controllers/groups/group_members_controller.rb +++ b/app/controllers/groups/group_members_controller.rb @@ -6,8 +6,6 @@ class Groups::GroupMembersController < Groups::ApplicationController before_action :authorize_read_group! before_action :authorize_admin_group!, except: [:index, :leave] - layout :determine_layout - def index @project = @group.projects.find(params[:project_id]) if params[:project_id] @members = @group.group_members From 5121576e0c18a3133a12e8c90d5faadb91c70888 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Thu, 30 Apr 2015 20:02:21 +0200 Subject: [PATCH 45/97] before_action > before_filter. --- app/controllers/oauth/authorized_applications_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/oauth/authorized_applications_controller.rb b/app/controllers/oauth/authorized_applications_controller.rb index 6d0bf9889e..63c634f376 100644 --- a/app/controllers/oauth/authorized_applications_controller.rb +++ b/app/controllers/oauth/authorized_applications_controller.rb @@ -1,5 +1,5 @@ class Oauth::AuthorizedApplicationsController < Doorkeeper::AuthorizedApplicationsController - before_filter :set_title + before_action :set_title def destroy Doorkeeper::AccessToken.revoke_all_for(params[:id], current_resource_owner) From 280a212443481dd4a5b470611c87a57f9ab129a6 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Thu, 30 Apr 2015 20:37:25 +0200 Subject: [PATCH 46/97] Fix Profiles::PasswordsController. --- app/controllers/profiles/passwords_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/profiles/passwords_controller.rb b/app/controllers/profiles/passwords_controller.rb index 94ac62cb32..86976ae39e 100644 --- a/app/controllers/profiles/passwords_controller.rb +++ b/app/controllers/profiles/passwords_controller.rb @@ -1,4 +1,4 @@ -class Profiles::PasswordsController < ApplicationController +class Profiles::PasswordsController < Profiles::ApplicationController skip_before_action :check_password_expiration, only: [:new, :create] before_action :set_user From 635c86114fdc2843b14ab5c38fdc8e92abfbed13 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Thu, 30 Apr 2015 21:10:34 +0200 Subject: [PATCH 47/97] Fix snippest sidebar when signed out. --- app/views/layouts/nav/_snippets.html.haml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/app/views/layouts/nav/_snippets.html.haml b/app/views/layouts/nav/_snippets.html.haml index 0de3a9e5bb..458b76a2c9 100644 --- a/app/views/layouts/nav/_snippets.html.haml +++ b/app/views/layouts/nav/_snippets.html.haml @@ -1,9 +1,10 @@ %ul.nav.nav-sidebar - = nav_link(path: user_snippets_path(current_user), html_options: {class: 'home'}) do - = link_to user_snippets_path(current_user), title: 'Your snippets', data: {placement: 'right'} do - = icon('dashboard fw') - %span - Your Snippets + - if current_user + = nav_link(path: user_snippets_path(current_user), html_options: {class: 'home'}) do + = link_to user_snippets_path(current_user), title: 'Your snippets', data: {placement: 'right'} do + = icon('dashboard fw') + %span + Your Snippets = nav_link(path: snippets_path) do = link_to snippets_path, title: 'Discover snippets', data: {placement: 'right'} do = icon('globe fw') From 4d7759156be3ed5690b786100f558fa368fa24ed Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Thu, 30 Apr 2015 21:10:42 +0200 Subject: [PATCH 48/97] Plural instead of singular. --- app/views/doorkeeper/applications/show.html.haml | 2 +- app/views/groups/milestones/show.html.haml | 2 +- app/views/snippets/show.html.haml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/views/doorkeeper/applications/show.html.haml b/app/views/doorkeeper/applications/show.html.haml index b2dc86e89c..80340aca54 100644 --- a/app/views/doorkeeper/applications/show.html.haml +++ b/app/views/doorkeeper/applications/show.html.haml @@ -1,4 +1,4 @@ -- page_title @application.name, "Application" +- page_title @application.name, "Applications" %h3.page-title Application: #{@application.name} diff --git a/app/views/groups/milestones/show.html.haml b/app/views/groups/milestones/show.html.haml index 0ab15c90af..6c41cd6b9e 100644 --- a/app/views/groups/milestones/show.html.haml +++ b/app/views/groups/milestones/show.html.haml @@ -1,4 +1,4 @@ -- page_title @group_milestone.title, "Milestone" +- page_title @group_milestone.title, "Milestones" %h4.page-title .issue-box{ class: "issue-box-#{@group_milestone.closed? ? 'closed' : 'open'}" } - if @group_milestone.closed? diff --git a/app/views/snippets/show.html.haml b/app/views/snippets/show.html.haml index 903f51ff6c..70a95abde6 100644 --- a/app/views/snippets/show.html.haml +++ b/app/views/snippets/show.html.haml @@ -1,4 +1,4 @@ -- page_title @snippet.title, "Snippet" +- page_title @snippet.title, "Snippets" %h3.page-title = @snippet.title From f723968374d8ef32d4788b166f0d782b879fa11a Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Thu, 30 Apr 2015 21:12:31 +0200 Subject: [PATCH 49/97] Include commit message in page title. --- app/views/projects/commit/show.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/projects/commit/show.html.haml b/app/views/projects/commit/show.html.haml index fcf75bb3ce..fc91f71e8d 100644 --- a/app/views/projects/commit/show.html.haml +++ b/app/views/projects/commit/show.html.haml @@ -1,4 +1,4 @@ -- page_title @commit.id, "Commits" +- page_title "#{@commit.title} (#{@commit.short_id})", "Commits" = render "commit_box" = render "projects/diffs/diffs", diffs: @diffs, project: @project = render "projects/notes/notes_with_form" From 9508bdc0c9c2c01e38eefe0f8248d9abffca237f Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Thu, 30 Apr 2015 21:14:26 +0200 Subject: [PATCH 50/97] Include ref in network page title. --- app/views/projects/network/show.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/projects/network/show.html.haml b/app/views/projects/network/show.html.haml index 4d3f118f2d..c67a7d256a 100644 --- a/app/views/projects/network/show.html.haml +++ b/app/views/projects/network/show.html.haml @@ -1,4 +1,4 @@ -- page_title "Network" +- page_title "Network", @ref = render "head" .project-network .controls From 6fcdd1504e617891c718d567d252181957142bea Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Thu, 30 Apr 2015 21:15:50 +0200 Subject: [PATCH 51/97] Capitalize "Git Access" in page title. --- app/views/projects/wikis/git_access.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/projects/wikis/git_access.html.haml b/app/views/projects/wikis/git_access.html.haml index b47dffe00b..825f2a161c 100644 --- a/app/views/projects/wikis/git_access.html.haml +++ b/app/views/projects/wikis/git_access.html.haml @@ -1,4 +1,4 @@ -- page_title "Git access", "Wiki" +- page_title "Git Access", "Wiki" = render 'nav' .row .col-sm-6 From 0a63c1d2abdb63366448bb7cbbf2836fa8881f18 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Thu, 30 Apr 2015 21:18:27 +0200 Subject: [PATCH 52/97] Have tree page title read "Files" for root. --- app/views/projects/tree/show.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/projects/tree/show.html.haml b/app/views/projects/tree/show.html.haml index d0a3f522e2..72916cad18 100644 --- a/app/views/projects/tree/show.html.haml +++ b/app/views/projects/tree/show.html.haml @@ -1,4 +1,4 @@ -- page_title @path.presence, @ref +- page_title @path.presence || "Files", @ref = content_for :meta_tags do - if current_user = auto_discovery_link_tag(:atom, namespace_project_commits_url(@project.namespace, @project, @ref, format: :atom, private_token: current_user.private_token), title: "#{@project.name}:#{@ref} commits") From 610ed70f77dd9a31c63a7b378df5940bcb84300c Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Thu, 30 Apr 2015 21:26:24 +0200 Subject: [PATCH 53/97] Humanize help page titles. --- app/views/help/show.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/help/show.html.haml b/app/views/help/show.html.haml index 1ff5ddb4c1..bc8e08eeae 100644 --- a/app/views/help/show.html.haml +++ b/app/views/help/show.html.haml @@ -1,3 +1,3 @@ -- page_title @file, *@category.split("/").reverse, "Help" +- page_title @file.humanize, *@category.split("/").reverse.map(&:humanize), "Help" .documentation.wiki = markdown @markdown.gsub('$your_email', current_user.email) From 8c4b6d426d11de682db601a5ca585c11bcd0cd23 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Thu, 30 Apr 2015 21:28:07 +0200 Subject: [PATCH 54/97] Set head panel title of help section. --- app/controllers/help_controller.rb | 7 +++++++ app/views/help/index.html.haml | 1 - app/views/help/show.html.haml | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/app/controllers/help_controller.rb b/app/controllers/help_controller.rb index b405cc7e68..2842151e3b 100644 --- a/app/controllers/help_controller.rb +++ b/app/controllers/help_controller.rb @@ -1,4 +1,6 @@ class HelpController < ApplicationController + before_action :set_title + def index end @@ -44,6 +46,11 @@ class HelpController < ApplicationController private + def set_title + @title = "Help" + @title_url = help_path + end + def path_params params.require(:category) params.require(:file) diff --git a/app/views/help/index.html.haml b/app/views/help/index.html.haml index 9ebdd373f3..af39dfeac5 100644 --- a/app/views/help/index.html.haml +++ b/app/views/help/index.html.haml @@ -1,4 +1,3 @@ -- page_title "Help" %div %h1 GitLab diff --git a/app/views/help/show.html.haml b/app/views/help/show.html.haml index bc8e08eeae..8551496b98 100644 --- a/app/views/help/show.html.haml +++ b/app/views/help/show.html.haml @@ -1,3 +1,3 @@ -- page_title @file.humanize, *@category.split("/").reverse.map(&:humanize), "Help" +- page_title @file.humanize, *@category.split("/").reverse.map(&:humanize) .documentation.wiki = markdown @markdown.gsub('$your_email', current_user.email) From e0a1d54e1a3f127c74a71cc09b14e884880d7d7c Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Thu, 30 Apr 2015 21:32:44 +0200 Subject: [PATCH 55/97] Don't ignore any folder called tags :| --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 7a7b5c9393..3e30fb8cf7 100644 --- a/.gitignore +++ b/.gitignore @@ -37,6 +37,6 @@ public/assets/ public/uploads.* public/uploads/ rails_best_practices_output.html -tags +/tags tmp/ vendor/bundle/* From ae09c2a6db0d15caedc080c319add147c79fd02a Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Thu, 30 Apr 2015 21:33:02 +0200 Subject: [PATCH 56/97] Capitalize "X" in "New X". --- app/views/admin/applications/new.html.haml | 2 +- app/views/admin/groups/new.html.haml | 2 +- app/views/admin/users/new.html.haml | 2 +- app/views/projects/blob/new.html.haml | 2 +- app/views/projects/branches/new.html.haml | 2 +- app/views/projects/issues/new.html.haml | 2 +- app/views/projects/labels/new.html.haml | 2 +- app/views/projects/merge_requests/new.html.haml | 2 +- app/views/projects/milestones/new.html.haml | 2 +- app/views/projects/snippets/new.html.haml | 2 +- app/views/projects/tags/new.html.haml | 2 +- app/views/snippets/new.html.haml | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/app/views/admin/applications/new.html.haml b/app/views/admin/applications/new.html.haml index 2884ee93d5..6310d89bd6 100644 --- a/app/views/admin/applications/new.html.haml +++ b/app/views/admin/applications/new.html.haml @@ -1,4 +1,4 @@ -- page_title "New application" +- page_title "New Application" %h3.page-title New application - @url = admin_applications_path = render 'form', application: @application diff --git a/app/views/admin/groups/new.html.haml b/app/views/admin/groups/new.html.haml index 9dccda1f76..c81ee552ac 100644 --- a/app/views/admin/groups/new.html.haml +++ b/app/views/admin/groups/new.html.haml @@ -1,4 +1,4 @@ -- page_title "New group" +- page_title "New Group" %h3.page-title New group %hr = render 'form' diff --git a/app/views/admin/users/new.html.haml b/app/views/admin/users/new.html.haml index cabce1f516..bfc36ed737 100644 --- a/app/views/admin/users/new.html.haml +++ b/app/views/admin/users/new.html.haml @@ -1,4 +1,4 @@ -- page_title "New user" +- page_title "New User" %h3.page-title New user %hr diff --git a/app/views/projects/blob/new.html.haml b/app/views/projects/blob/new.html.haml index eb0d99d015..9b1d03b820 100644 --- a/app/views/projects/blob/new.html.haml +++ b/app/views/projects/blob/new.html.haml @@ -1,4 +1,4 @@ -- page_title "New file", @ref +- page_title "New File", @ref %h3.page-title New file .file-editor = form_tag(namespace_project_create_blob_path(@project.namespace, @project, @id), method: :post, class: 'form-horizontal form-new-file') do diff --git a/app/views/projects/branches/new.html.haml b/app/views/projects/branches/new.html.haml index 7ca0b78a0b..cac5dc91af 100644 --- a/app/views/projects/branches/new.html.haml +++ b/app/views/projects/branches/new.html.haml @@ -1,4 +1,4 @@ -- page_title "New branch" +- page_title "New Branch" - if @error .alert.alert-danger %button{ type: "button", class: "close", "data-dismiss" => "alert"} × diff --git a/app/views/projects/issues/new.html.haml b/app/views/projects/issues/new.html.haml index 96e4385562..da6edd5c2d 100644 --- a/app/views/projects/issues/new.html.haml +++ b/app/views/projects/issues/new.html.haml @@ -1,2 +1,2 @@ -- page_title "New issue" +- page_title "New Issue" = render "form" diff --git a/app/views/projects/labels/new.html.haml b/app/views/projects/labels/new.html.haml index 7cacbd0f30..b3ef17025c 100644 --- a/app/views/projects/labels/new.html.haml +++ b/app/views/projects/labels/new.html.haml @@ -1,4 +1,4 @@ -- page_title "New label" +- page_title "New Label" %h3 New label .back-link = link_to namespace_project_labels_path(@project.namespace, @project) do diff --git a/app/views/projects/merge_requests/new.html.haml b/app/views/projects/merge_requests/new.html.haml index b1c7bea7de..b038a640f6 100644 --- a/app/views/projects/merge_requests/new.html.haml +++ b/app/views/projects/merge_requests/new.html.haml @@ -1,4 +1,4 @@ -- page_title "New merge request" +- page_title "New Merge Request" - if @merge_request.can_be_created = render 'new_submit' - else diff --git a/app/views/projects/milestones/new.html.haml b/app/views/projects/milestones/new.html.haml index d76e417b3c..47149dfea4 100644 --- a/app/views/projects/milestones/new.html.haml +++ b/app/views/projects/milestones/new.html.haml @@ -1,2 +1,2 @@ -- page_title "New milestone" +- page_title "New Milestone" = render "form" diff --git a/app/views/projects/snippets/new.html.haml b/app/views/projects/snippets/new.html.haml index 2d9beef1cb..e38d95c45e 100644 --- a/app/views/projects/snippets/new.html.haml +++ b/app/views/projects/snippets/new.html.haml @@ -1,4 +1,4 @@ -- page_title "New snippets" +- page_title "New Snippets" %h3.page-title New snippet %hr diff --git a/app/views/projects/tags/new.html.haml b/app/views/projects/tags/new.html.haml index 61c35e4a5e..172fafdeef 100644 --- a/app/views/projects/tags/new.html.haml +++ b/app/views/projects/tags/new.html.haml @@ -1,4 +1,4 @@ -- page_title "New tag" +- page_title "New Tag" - if @error .alert.alert-danger %button{ type: "button", class: "close", "data-dismiss" => "alert"} × diff --git a/app/views/snippets/new.html.haml b/app/views/snippets/new.html.haml index 2c92041351..a74d5e792a 100644 --- a/app/views/snippets/new.html.haml +++ b/app/views/snippets/new.html.haml @@ -1,4 +1,4 @@ -- page_title "New snippet" +- page_title "New Snippet" %h3.page-title New snippet %hr From ee92dd1683febd03e1d7ade40449ba114a67e1f5 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Sun, 26 Apr 2015 23:42:29 -0700 Subject: [PATCH 57/97] Unescape branch names in compare commit Closes #1399 Closes https://github.com/gitlabhq/gitlabhq/issues/9105 --- CHANGELOG | 2 ++ .../projects/compare_controller.rb | 6 +++-- .../projects/compare_controller_spec.rb | 22 +++++++++++++++++++ 3 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 spec/controllers/projects/compare_controller_spec.rb diff --git a/CHANGELOG b/CHANGELOG index ecffcb5262..37141a00c4 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -21,6 +21,8 @@ v 7.11.0 (unreleased) - Add default project and snippet visibility settings to the admin web UI. - - Fix bug where commit data would not appear in some subdirectories (Stan Hu) + - Unescape branch names in compare commit (Stan Hu) + - - Fix bug where Slack service channel was not saved in admin template settings. (Stan Hu) - Move snippets UI to fluid layout - Improve UI for sidebar. Increase separation between navigation and content diff --git a/app/controllers/projects/compare_controller.rb b/app/controllers/projects/compare_controller.rb index 03e6c38127..7c20b81c0b 100644 --- a/app/controllers/projects/compare_controller.rb +++ b/app/controllers/projects/compare_controller.rb @@ -1,3 +1,5 @@ +require 'addressable/uri' + class Projects::CompareController < Projects::ApplicationController # Authorize before_action :require_non_empty_project @@ -7,8 +9,8 @@ class Projects::CompareController < Projects::ApplicationController end def show - base_ref = params[:from] - head_ref = params[:to] + base_ref = Addressable::URI.unescape(params[:from]) + head_ref = Addressable::URI.unescape(params[:to]) compare_result = CompareService.new.execute( current_user, diff --git a/spec/controllers/projects/compare_controller_spec.rb b/spec/controllers/projects/compare_controller_spec.rb new file mode 100644 index 0000000000..23e1566b8f --- /dev/null +++ b/spec/controllers/projects/compare_controller_spec.rb @@ -0,0 +1,22 @@ +require 'spec_helper' + +describe Projects::CompareController do + let(:project) { create(:project) } + let(:user) { create(:user) } + let(:ref_from) { "improve%2Fawesome" } + let(:ref_to) { "feature" } + + before do + sign_in(user) + project.team << [user, :master] + end + + it 'compare should show some diffs' do + get(:show, namespace_id: project.namespace.to_param, + project_id: project.to_param, from: ref_from, to: ref_to) + + expect(response).to be_success + expect(assigns(:diffs).length).to be >= 1 + expect(assigns(:commits).length).to be >= 1 + end +end From cb40918930c823d6b5132f6ac8581b5c3148e0bd Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Thu, 30 Apr 2015 22:14:19 +0200 Subject: [PATCH 58/97] Update upgrader doc to point to 7.10.1. --- doc/update/upgrader.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/update/upgrader.md b/doc/update/upgrader.md index e32984c4e6..2cca46c86a 100644 --- a/doc/update/upgrader.md +++ b/doc/update/upgrader.md @@ -27,10 +27,10 @@ If you have local changes to your GitLab repository the script will stash them a Note: GitLab 7.9 adds `nodejs` as a dependency. GitLab 7.6 adds `libkrb5-dev` as a dependency (installed by default on Ubuntu and OSX). GitLab 7.2 adds `pkg-config` and `cmake` as dependency. Please check the dependencies in the [installation guide.](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/install/installation.md#1-packages-dependencies) cd /home/git/gitlab - sudo -u git -H ruby -Ilib -e 'require "gitlab/upgrader"' -e 'class Gitlab::Upgrader' -e 'def latest_version_raw' -e '"v7.10.0"' -e 'end' -e 'end' -e 'Gitlab::Upgrader.new.execute' + sudo -u git -H ruby -Ilib -e 'require "gitlab/upgrader"' -e 'class Gitlab::Upgrader' -e 'def latest_version_raw' -e '"v7.10.1"' -e 'end' -e 'end' -e 'Gitlab::Upgrader.new.execute' # to perform a non-interactive install (no user input required) you can add -y - # sudo -u git -H ruby -Ilib -e 'require "gitlab/upgrader"' -e 'class Gitlab::Upgrader' -e 'def latest_version_raw' -e '"v7.10.0"' -e 'end' -e 'end' -e 'Gitlab::Upgrader.new.execute' -- -y + # sudo -u git -H ruby -Ilib -e 'require "gitlab/upgrader"' -e 'class Gitlab::Upgrader' -e 'def latest_version_raw' -e '"v7.10.1"' -e 'end' -e 'end' -e 'Gitlab::Upgrader.new.execute' -- -y ## 3. Start application @@ -65,7 +65,7 @@ Here is a one line command with step 1 to 5 for the next time you upgrade: cd /home/git/gitlab; \ sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production; \ sudo service gitlab stop; \ - sudo -u git -H ruby -Ilib -e 'require "gitlab/upgrader"' -e 'class Gitlab::Upgrader' -e 'def latest_version_raw' -e '"v7.10.0"' -e 'end' -e 'end' -e 'Gitlab::Upgrader.new.execute' -- -y; \ + sudo -u git -H ruby -Ilib -e 'require "gitlab/upgrader"' -e 'class Gitlab::Upgrader' -e 'def latest_version_raw' -e '"v7.10.1"' -e 'end' -e 'end' -e 'Gitlab::Upgrader.new.execute' -- -y; \ cd /home/git/gitlab-shell; \ sudo -u git -H git fetch; \ sudo -u git -H git checkout v`cat /home/git/gitlab/GITLAB_SHELL_VERSION`; \ From 286c9e68860aed365ecad0baa9e5466f9153bbc2 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Thu, 23 Apr 2015 00:21:11 -0400 Subject: [PATCH 59/97] Add a feature spec for our entire Markdown parsing stack --- spec/features/markdown_spec.rb | 393 +++++++++++++++++++++++++++++++++ spec/fixtures/markdown.md.erb | 179 +++++++++++++++ 2 files changed, 572 insertions(+) create mode 100644 spec/features/markdown_spec.rb create mode 100644 spec/fixtures/markdown.md.erb diff --git a/spec/features/markdown_spec.rb b/spec/features/markdown_spec.rb new file mode 100644 index 0000000000..9db1a0a241 --- /dev/null +++ b/spec/features/markdown_spec.rb @@ -0,0 +1,393 @@ +require 'spec_helper' +require 'erb' + +# This feature spec is intended to be a comprehensive exercising of all of +# GitLab's non-standard Markdown parsing and the integration thereof. +# +# These tests should be very high-level. Anything low-level belongs in the specs +# for the corresponding HTML::Pipeline filter or helper method. +# +# The idea is to pass a Markdown document through our entire processing stack. +# +# The process looks like this: +# +# Raw Markdown +# -> `markdown` helper +# -> Redcarpet::Render::GitlabHTML converts Markdown to HTML +# -> Post-process HTML +# -> `gfm_with_options` helper +# -> HTML::Pipeline +# -> Sanitize +# -> Emoji +# -> Table of Contents +# -> Autolinks +# -> Rinku (http, https, ftp) +# -> Other schemes +# -> References +# -> `html_safe` +# -> Template +# +# See the MarkdownFeature class for setup details. + +describe 'GitLab Markdown' do + include ActionView::Helpers::TagHelper + include ActionView::Helpers::UrlHelper + include Capybara::Node::Matchers + include GitlabMarkdownHelper + + # `markdown` calls these two methods + def current_user + @feat.user + end + + def user_color_scheme_class + :white + end + + # Let's only parse this thing once + before(:all) do + @feat = MarkdownFeature.new + + # `markdown` expects a `@project` variable + @project = @feat.project + + @md = markdown(@feat.raw_markdown) + @doc = Nokogiri::HTML::DocumentFragment.parse(@md) + end + + after(:all) do + @feat.teardown + end + + # Given a header ID, goes to that element's parent (the header), then to its + # second sibling (the body). + def get_section(id) + @doc.at_css("##{id}").parent.next.next + end + + # it 'writes to a file' do + # File.open(Rails.root.join('tmp/capybara/markdown_spec.html'), 'w') do |file| + # file.puts @md + # end + # end + + describe 'Markdown' do + describe 'No Intra Emphasis' do + it 'does not parse emphasis inside of words' do + body = get_section('no-intra-emphasis') + expect(body.to_html).not_to match('foobarbaz') + end + end + + describe 'Tables' do + it 'parses table Markdown' do + body = get_section('tables') + expect(body).to have_selector('th:contains("Header")') + expect(body).to have_selector('th:contains("Row")') + expect(body).to have_selector('th:contains("Example")') + end + + it 'allows Markdown in tables' do + expect(@doc.at_css('td:contains("Baz")').children.to_html). + to eq 'Baz' + end + end + + describe 'Fenced Code Blocks' do + it 'parses fenced code blocks' do + expect(@doc).to have_selector('pre.code.highlight.white.c') + expect(@doc).to have_selector('pre.code.highlight.white.python') + end + end + + describe 'Strikethrough' do + it 'parses strikethroughs' do + expect(@doc).to have_selector(%{del:contains("and this text doesn't")}) + end + end + + describe 'Superscript' do + it 'parses superscript' do + body = get_section('superscript') + expect(body.to_html).to match('1st') + expect(body.to_html).to match('2nd') + end + end + end + + describe 'HTML::Pipeline' do + describe 'SanitizationFilter' do + it 'uses a permissive whitelist' do + expect(@doc).to have_selector('b#manual-b') + expect(@doc).to have_selector('em#manual-em') + expect(@doc).to have_selector("code#manual-code") + expect(@doc).to have_selector('kbd:contains("s")') + expect(@doc).to have_selector('strike:contains(Emoji)') + expect(@doc).to have_selector('img#manual-img') + expect(@doc).to have_selector('br#manual-br') + expect(@doc).to have_selector('hr#manual-hr') + end + + it 'permits span elements' do + expect(@doc).to have_selector('span#span-class-light.light') + end + + it 'permits table alignment' do + expect(@doc.at_css('th:contains("Header")')['style']).to eq 'text-align: center' + expect(@doc.at_css('th:contains("Row")')['style']).to eq 'text-align: right' + expect(@doc.at_css('th:contains("Example")')['style']).to eq 'text-align: left' + + expect(@doc.at_css('td:contains("Foo")')['style']).to eq 'text-align: center' + expect(@doc.at_css('td:contains("Bar")')['style']).to eq 'text-align: right' + expect(@doc.at_css('td:contains("Baz")')['style']).to eq 'text-align: left' + end + + it 'removes `rel` attribute from links' do + expect(@doc).to have_selector('a#a-rel-nofollow') + expect(@doc).not_to have_selector('a#a-rel-nofollow[rel]') + end + + it "removes `href` from `a` elements if it's fishy" do + expect(@doc).to have_selector('a#a-href-javascript') + expect(@doc).not_to have_selector('a#a-href-javascript[href]') + end + end + + describe 'Escaping' do + let(:table) { @doc.css('table').last.at_css('tbody') } + + it 'escapes non-tag angle brackets' do + expect(table.at_xpath('.//tr[1]/td[3]').inner_html).to eq '1 < 3 & 5' + end + end + + describe 'EmojiFilter' do + it 'parses Emoji' do + expect(@doc).to have_selector('img.emoji', count: 10) + end + end + + describe 'TableOfContentsFilter' do + it 'creates anchors inside header elements' do + expect(@doc).to have_selector('h1 a#gitlab-markdown') + expect(@doc).to have_selector('h2 a#markdown') + expect(@doc).to have_selector('h3 a#autolinkfilter') + end + end + + describe 'AutolinkFilter' do + let(:list) { get_section('autolinkfilter').parent.search('ul') } + + def item(index) + list.at_css("li:nth-child(#{index})") + end + + it 'autolinks http://' do + expect(item(1).children.first.name).to eq 'a' + expect(item(1).children.first['href']).to eq 'http://about.gitlab.com/' + end + + it 'autolinks https://' do + expect(item(2).children.first.name).to eq 'a' + expect(item(2).children.first['href']).to eq 'https://google.com/' + end + + it 'autolinks ftp://' do + expect(item(3).children.first.name).to eq 'a' + expect(item(3).children.first['href']).to eq 'ftp://ftp.us.debian.org/debian/' + end + + it 'autolinks smb://' do + expect(item(4).children.first.name).to eq 'a' + expect(item(4).children.first['href']).to eq 'smb://foo/bar/baz' + end + + it 'autolinks irc://' do + expect(item(5).children.first.name).to eq 'a' + expect(item(5).children.first['href']).to eq 'irc://irc.freenode.net/git' + end + + # TODO (rspeicher): Do we really want this? + it 'autolinks short, invalid URLs' do + skip 'rspeicher: Pending decision' + expect(item(6).children.first.name).to eq 'a' + expect(item(6).children.first['href']).to eq 'http://foo' + end + + %w(code a kbd).each do |elem| + it "ignores links inside '#{elem}' element" do + expect(@doc.at_css("#{elem}#autolink-#{elem}").child).to be_text + end + end + end + + describe 'ReferenceFilter' do + it 'handles references in headers' do + header = @doc.at_css('#reference-filters-eg-1').parent + + expect(header.css('a').size).to eq 2 + end + + it "handles references in Markdown" do + body = get_section('reference-filters-eg-1') + expect(body).to have_selector('em a.gfm-merge_request', count: 1) + end + + it 'parses user references' do + body = get_section('userreferencefilter') + expect(body).to have_selector('a.gfm.gfm-project_member', count: 3) + end + + it 'parses issue references' do + body = get_section('issuereferencefilter') + expect(body).to have_selector('a.gfm.gfm-issue', count: 2) + end + + it 'parses merge request references' do + body = get_section('mergerequestreferencefilter') + expect(body).to have_selector('a.gfm.gfm-merge_request', count: 2) + end + + it 'parses snippet references' do + body = get_section('snippetreferencefilter') + expect(body).to have_selector('a.gfm.gfm-snippet', count: 2) + end + + it 'parses commit range references' do + body = get_section('commitrangereferencefilter') + expect(body).to have_selector('a.gfm.gfm-commit_range', count: 2) + end + + it 'parses commit references' do + body = get_section('commitreferencefilter') + expect(body).to have_selector('a.gfm.gfm-commit', count: 2) + end + + it 'parses label references' do + body = get_section('labelreferencefilter') + expect(body).to have_selector('a.gfm.gfm-label', count: 3) + end + end + end +end + +# This is a helper class used by the GitLab Markdown feature spec +# +# Because the feature spec only cares about the output of the Markdown, and the +# test setup and teardown and parsing is fairly expensive, we only want to do it +# once. Unfortunately RSpec will not let you access `let`s in a `before(:all)` +# block, so we fake it by encapsulating all the shared setup in this class. +# +# The class contains the raw Markup used in the test, dynamically substituting +# real objects, created from factories and setup on-demand, when referenced in +# the Markdown. +class MarkdownFeature + include FactoryGirl::Syntax::Methods + + def initialize + DatabaseCleaner.start + end + + def teardown + DatabaseCleaner.clean + end + + def user + @user ||= create(:user) + end + + def group + unless @group + @group = create(:group) + @group.add_user(user, Gitlab::Access::DEVELOPER) + end + + @group + end + + # Direct references ---------------------------------------------------------- + + def project + @project ||= create(:project) + end + + def issue + @issue ||= create(:issue, project: project) + end + + def merge_request + @merge_request ||= create(:merge_request, :simple, source_project: project) + end + + def snippet + @snippet ||= create(:project_snippet, project: project) + end + + def commit + @commit ||= project.repository.commit + end + + def commit_range + unless @commit_range + commit2 = project.repository.commit('HEAD~3') + @commit_range = CommitRange.new("#{commit.id}...#{commit2.id}") + end + + @commit_range + end + + def simple_label + @simple_label ||= create(:label, name: 'gfm', project: project) + end + + def label + @label ||= create(:label, name: 'awaiting feedback', project: project) + end + + # Cross-references ----------------------------------------------------------- + + def xproject + unless @xproject + namespace = create(:namespace, name: 'cross-reference') + @xproject = create(:project, namespace: namespace) + @xproject.team << [user, :developer] + end + + @xproject + end + + # Shortcut to "cross-reference/project" + def xref + xproject.path_with_namespace + end + + def xissue + @xissue ||= create(:issue, project: xproject) + end + + def xmerge_request + @xmerge_request ||= create(:merge_request, :simple, source_project: xproject) + end + + def xsnippet + @xsnippet ||= create(:project_snippet, project: xproject) + end + + def xcommit + @xcommit ||= xproject.repository.commit + end + + def xcommit_range + unless @xcommit_range + xcommit2 = xproject.repository.commit('HEAD~2') + @xcommit_range = CommitRange.new("#{xcommit.id}...#{xcommit2.id}") + end + + @xcommit_range + end + + def raw_markdown + fixture = Rails.root.join('spec/fixtures/markdown.md.erb') + ERB.new(File.read(fixture)).result(binding) + end +end diff --git a/spec/fixtures/markdown.md.erb b/spec/fixtures/markdown.md.erb new file mode 100644 index 0000000000..b00fc099b4 --- /dev/null +++ b/spec/fixtures/markdown.md.erb @@ -0,0 +1,179 @@ +# GitLab Markdown + +This document is intended to be a comprehensive example of custom GitLab +Markdown usage. It will be parsed and then tested for accuracy. Let's get +started. + +## Markdown + +GitLab uses [Redcarpet](http://git.io/ld_NVQ) to parse all Markdown into +HTML. + +It has some special features. Let's try 'em out! + +### No Intra Emphasis + +This string should have no emphasis: foo_bar_baz + +### Tables + +| Header | Row | Example | +| :------: | ---: | :------ | +| Foo | Bar | **Baz** | + +### Fenced Code Blocks + +```c +#include + +main() +{ + printf("Hello World"); + +} +``` + +```python +print "Hello, World!" +``` + +### Strikethrough + +This text says this, ~~and this text doesn't~~. + +### Superscript + +This is my 1^(st) time using superscript in Markdown. Now this is my +2^(nd). + +### Next step + +After the Markdown has been turned into HTML, it gets passed through... + +## HTML::Pipeline + +### SanitizationFilter + +GitLab uses HTML::Pipeline::SanitizationFilter +to sanitize the generated HTML, stripping dangerous or unwanted tags. + +Its default whitelist is pretty permissive. Check it: + +This text is bold and this text is emphasized. + +echo "Hello, world!" + +Press s to search. + +Emoji Plain old images! + +Here comes a line break: + +
+ +And a horizontal rule: + +
+ +As permissive as it is, we've allowed even more stuff: + +Span elements + +This is a link with a defined rel attribute, which should be removed + +This is a link trying to be sneaky. It gets its link removed entirely. + +### Escaping + +The problem with SanitizationFilter is that it can be too aggressive. + +| Input | Expected | Actual | +| ----------- | ---------------- | --------- | +| `1 < 3 & 5` | 1 < 3 & 5 | 1 < 3 & 5 | +| `` | <foo> | | + +### EmojiFilter + +Because life would be :zzz: without Emoji, right? :rocket: + +Get ready for the Emoji :bomb:: :+1::-1::ok_hand::wave::v::raised_hand::muscle: + +### TableOfContentsFilter + +All headers in this document should be linkable. Try it. + +### AutolinkFilter + +These are all plain text that should get turned into links: + +- http://about.gitlab.com/ +- https://google.com/ +- ftp://ftp.us.debian.org/debian/ +- smb://foo/bar/baz +- irc://irc.freenode.net/git +- http://localhost:3000 + +But it shouldn't autolink text inside certain tags: + +- http://about.gitlab.com/ +- http://about.gitlab.com/ +- http://about.gitlab.com/ + +### Reference Filters (e.g., #<%= issue.iid %>) + +References should be parseable even inside _!<%= merge_request.iid %>_ emphasis. + +#### UserReferenceFilter + +- All: @all +- User: @<%= user.username %> +- Group: @<%= group.name %> +- Ignores invalid: @fake_user +- Ignored in code: `@<%= user.username %>` +- Ignored in links: [Link to @<%= user.username %>](#user-link) + +#### IssueReferenceFilter + +- Issue: #<%= issue.iid %> +- Issue in another project: <%= xref %>#<%= xissue.iid %> +- Ignores HTML entities: TODO:' +- Ignored in code: `#<%= issue.iid %>` +- Ignored in links: [Link to #<%= issue.iid %>](#issue-link) + +#### MergeRequestReferenceFilter + +- Merge request: !<%= merge_request.iid %> +- Merge request in another project: <%= xref %>!<%= xmerge_request.iid %> +- Ignored in code: `!<%= merge_request.iid %>` +- Ignored in links: [Link to !<%= merge_request.iid %>](#merge-request-link) + +#### SnippetReferenceFilter + +- Snippet: $<%= snippet.id %> +- Snippet in another project: <%= xref %>$<%= xsnippet.id %> +- Ignored in code: `$<%= snippet.id %>` +- Ignored in links: [Link to $<%= snippet.id %>](#snippet-link) + +#### CommitRangeReferenceFilter + +- Range: <%= commit_range %> +- Range in another project: <%= xref %>@<%= xcommit_range %> +- Ignored in code: `<%= commit_range %>` +- Ignored in links: [Link to <%= commit_range %>](#commit-range-link) + +#### CommitReferenceFilter + +- Commit: <%= commit.id %> +- Commit in another project: <%= xref %>@<%= xcommit.id %> +- Ignored in code: `<%= commit.id %>` +- Ignored in links: [Link to <%= commit.id %>](#commit-link) + +#### LabelReferenceFilter + +- Label by ID: ~<%= simple_label.id %> +- Label by name: ~<%= simple_label.name %> +- Label by name in quotes: ~"<%= label.name %>" +- Ignored in code: `~<%= simple_label.name %>` +- Ignored in links: [Link to ~<%= simple_label.id %>](#label-link) From 382a0aa6efd6141ff184a1a91ab586218c340fec Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Wed, 22 Apr 2015 16:40:25 -0400 Subject: [PATCH 60/97] Add Gitlab::Markdown::TableOfContentsFilter Removes header and table of contents processing from Redcarpet renderer. --- app/helpers/gitlab_markdown_helper.rb | 1 - lib/gitlab/markdown.rb | 5 + .../markdown/table_of_contents_filter.rb | 62 +++++++++++ lib/redcarpet/render/gitlab_html.rb | 10 -- spec/helpers/gitlab_markdown_helper_spec.rb | 17 --- .../markdown/table_of_contents_filter_spec.rb | 101 ++++++++++++++++++ 6 files changed, 168 insertions(+), 28 deletions(-) create mode 100644 lib/gitlab/markdown/table_of_contents_filter.rb create mode 100644 spec/lib/gitlab/markdown/table_of_contents_filter_spec.rb diff --git a/app/helpers/gitlab_markdown_helper.rb b/app/helpers/gitlab_markdown_helper.rb index bc23450000..48d754dcf7 100644 --- a/app/helpers/gitlab_markdown_helper.rb +++ b/app/helpers/gitlab_markdown_helper.rb @@ -34,7 +34,6 @@ module GitlabMarkdownHelper # see https://github.com/vmg/redcarpet#darling-i-packed-you-a-couple-renderers-for-lunch rend = Redcarpet::Render::GitlabHTML.new(self, user_color_scheme_class, { - with_toc_data: true, safe_links_only: true, # Handled further down the line by HTML::Pipeline::SanitizationFilter escape_html: false diff --git a/lib/gitlab/markdown.rb b/lib/gitlab/markdown.rb index 44779d7fdd..ffb7e16aed 100644 --- a/lib/gitlab/markdown.rb +++ b/lib/gitlab/markdown.rb @@ -38,6 +38,7 @@ module Gitlab autoload :LabelReferenceFilter, 'gitlab/markdown/label_reference_filter' autoload :MergeRequestReferenceFilter, 'gitlab/markdown/merge_request_reference_filter' autoload :SnippetReferenceFilter, 'gitlab/markdown/snippet_reference_filter' + autoload :TableOfContentsFilter, 'gitlab/markdown/table_of_contents_filter' autoload :UserReferenceFilter, 'gitlab/markdown/user_reference_filter' # Public: Parse the provided text with GitLab-Flavored Markdown @@ -81,6 +82,9 @@ module Gitlab asset_root: Gitlab.config.gitlab.url, asset_host: Gitlab::Application.config.asset_host, + # TableOfContentsFilter + no_header_anchors: options[:no_header_anchors], + # ReferenceFilter current_user: current_user, only_path: options[:reference_only_path], @@ -117,6 +121,7 @@ module Gitlab HTML::Pipeline::SanitizationFilter, Gitlab::Markdown::EmojiFilter, + Gitlab::Markdown::TableOfContentsFilter, Gitlab::Markdown::UserReferenceFilter, Gitlab::Markdown::IssueReferenceFilter, diff --git a/lib/gitlab/markdown/table_of_contents_filter.rb b/lib/gitlab/markdown/table_of_contents_filter.rb new file mode 100644 index 0000000000..c97612dafb --- /dev/null +++ b/lib/gitlab/markdown/table_of_contents_filter.rb @@ -0,0 +1,62 @@ +require 'html/pipeline/filter' + +module Gitlab + module Markdown + # HTML filter that adds an anchor child element to all Headers in a + # document, so that they can be linked to. + # + # Generates the Table of Contents with links to each header. See Results. + # + # Based on HTML::Pipeline::TableOfContentsFilter. + # + # Context options: + # :no_header_anchors - Skips all processing done by this filter. + # + # Results: + # :toc - String containing Table of Contents data as a `ul` element with + # `li` child elements. + class TableOfContentsFilter < HTML::Pipeline::Filter + PUNCTUATION_REGEXP = /[^\p{Word}\- ]/u + + def call + return doc if context[:no_header_anchors] + + result[:toc] = "" + + headers = Hash.new(0) + + doc.css('h1, h2, h3, h4, h5, h6').each do |node| + text = node.text + + id = text.downcase + id.gsub!(PUNCTUATION_REGEXP, '') # remove punctuation + id.gsub!(' ', '-') # replace spaces with dash + id.squeeze!(' -') # replace multiple spaces or dashes with one + + uniq = (headers[id] > 0) ? "-#{headers[id]}" : '' + headers[id] += 1 + + if header_content = node.children.first + href = "#{id}#{uniq}" + push_toc(href, text) + header_content.add_previous_sibling(anchor_tag(href)) + end + end + + result[:toc] = %Q{
    \n#{result[:toc]}
} unless result[:toc].empty? + + doc + end + + private + + def anchor_tag(href) + %Q{} + end + + def push_toc(href, text) + result[:toc] << %Q{
  • #{text}
  • \n} + end + end + end +end diff --git a/lib/redcarpet/render/gitlab_html.rb b/lib/redcarpet/render/gitlab_html.rb index 10efff2ae9..dc5fbe3c8e 100644 --- a/lib/redcarpet/render/gitlab_html.rb +++ b/lib/redcarpet/render/gitlab_html.rb @@ -50,16 +50,6 @@ class Redcarpet::Render::GitlabHTML < Redcarpet::Render::HTML h.link_to_gfm(content, link, title: title) end - def header(text, level) - if @options[:no_header_anchors] - "#{text}" - else - id = ActionController::Base.helpers.strip_tags(h.gfm(text)).downcase() \ - .gsub(/[^a-z0-9_-]/, '-').gsub(/-+/, '-').gsub(/^-/, '').gsub(/-$/, '') - "#{text}" - end - end - def postprocess(full_document) full_document.gsub!("ftp://smb:", "smb://") diff --git a/spec/helpers/gitlab_markdown_helper_spec.rb b/spec/helpers/gitlab_markdown_helper_spec.rb index e309dbb6a2..bd2240c599 100644 --- a/spec/helpers/gitlab_markdown_helper_spec.rb +++ b/spec/helpers/gitlab_markdown_helper_spec.rb @@ -207,23 +207,6 @@ describe GitlabMarkdownHelper do end describe "#markdown" do - # TODO (rspeicher) - This block tests multiple different contexts. Break this up! - - it "should add ids and links to headers" do - # Test every rule except nested tags. - text = '..Ab_c-d. e..' - id = 'ab_c-d-e' - expect(markdown("# #{text}")). - to match(%r{

    #{text}

    }) - expect(markdown("# #{text}", {no_header_anchors:true})). - to eq("

    #{text}

    ") - - id = 'link-text' - expect(markdown("# [link text](url) ![img alt](url)")).to match( - %r{

    link text ]*>

    } - ) - end - # REFERENCES (PART TWO: THE REVENGE) --------------------------------------- it "should handle references in headers" do diff --git a/spec/lib/gitlab/markdown/table_of_contents_filter_spec.rb b/spec/lib/gitlab/markdown/table_of_contents_filter_spec.rb new file mode 100644 index 0000000000..f383a5850d --- /dev/null +++ b/spec/lib/gitlab/markdown/table_of_contents_filter_spec.rb @@ -0,0 +1,101 @@ +# encoding: UTF-8 + +require 'spec_helper' + +module Gitlab::Markdown + describe TableOfContentsFilter do + def filter(html, options = {}) + described_class.call(html, options) + end + + def header(level, text) + "#{text}\n" + end + + it 'does nothing when :no_header_anchors is truthy' do + exp = act = header(1, 'Header') + expect(filter(act, no_header_anchors: 1).to_html).to eq exp + end + + it 'does nothing with empty headers' do + exp = act = header(1, nil) + expect(filter(act).to_html).to eq exp + end + + 1.upto(6) do |i| + it "processes h#{i} elements" do + html = header(i, "Header #{i}") + doc = filter(html) + + expect(doc.css("h#{i} a").first.attr('id')).to eq "header-#{i}" + end + end + + describe 'anchor tag' do + it 'has an `anchor` class' do + doc = filter(header(1, 'Header')) + expect(doc.css('h1 a').first.attr('class')).to eq 'anchor' + end + + it 'links to the id' do + doc = filter(header(1, 'Header')) + expect(doc.css('h1 a').first.attr('href')).to eq '#header' + end + + describe 'generated IDs' do + it 'translates spaces to dashes' do + doc = filter(header(1, 'This header has spaces in it')) + expect(doc.css('h1 a').first.attr('id')).to eq 'this-header-has-spaces-in-it' + end + + it 'squeezes multiple spaces and dashes' do + doc = filter(header(1, 'This---header is poorly-formatted')) + expect(doc.css('h1 a').first.attr('id')).to eq 'this-header-is-poorly-formatted' + end + + it 'removes punctuation' do + doc = filter(header(1, "This, header! is, filled. with @ punctuation?")) + expect(doc.css('h1 a').first.attr('id')).to eq 'this-header-is-filled-with-punctuation' + end + + it 'appends a unique number to duplicates' do + doc = filter(header(1, 'One') + header(2, 'One')) + + expect(doc.css('h1 a').first.attr('id')).to eq 'one' + expect(doc.css('h2 a').first.attr('id')).to eq 'one-1' + end + + it 'supports Unicode' do + doc = filter(header(1, '한글')) + expect(doc.css('h1 a').first.attr('id')).to eq '한글' + expect(doc.css('h1 a').first.attr('href')).to eq '#한글' + end + end + end + + describe 'result' do + def result(html) + HTML::Pipeline.new([described_class]).call(html) + end + + let(:results) { result(header(1, 'Header 1') + header(2, 'Header 2')) } + let(:doc) { Nokogiri::XML::DocumentFragment.parse(results[:toc]) } + + it 'is contained within a `ul` element' do + expect(doc.children.first.name).to eq 'ul' + expect(doc.children.first.attr('class')).to eq 'section-nav' + end + + it 'contains an `li` element for each header' do + expect(doc.css('li').length).to eq 2 + + links = doc.css('li a') + + expect(links.first.attr('href')).to eq '#header-1' + expect(links.first.text).to eq 'Header 1' + expect(links.last.attr('href')).to eq '#header-2' + expect(links.last.text).to eq 'Header 2' + end + end + end +end From 2d9edcada5135d1f72a2c284e93d8e5b18e00008 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Wed, 22 Apr 2015 16:42:24 -0400 Subject: [PATCH 61/97] Fix header styles for anchors generated by TableOfContentsFilter --- app/assets/stylesheets/generic/typography.scss | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/assets/stylesheets/generic/typography.scss b/app/assets/stylesheets/generic/typography.scss index 80190424c1..36a9a54074 100644 --- a/app/assets/stylesheets/generic/typography.scss +++ b/app/assets/stylesheets/generic/typography.scss @@ -35,7 +35,12 @@ pre { /* Link to current header. */ h1, h2, h3, h4, h5, h6 { position: relative; - &:hover > :last-child { + + a.anchor { + display: none; + } + + &:hover > a.anchor { $size: 16px; position: absolute; right: 100%; From aa2cc670fe2c9de772c82d90df4ee2d8a77c23fc Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Mon, 27 Apr 2015 18:54:13 -0400 Subject: [PATCH 62/97] Add Gitlab::Markdown::AutolinkFilter --- app/helpers/gitlab_markdown_helper.rb | 4 +- lib/gitlab/markdown.rb | 4 +- lib/gitlab/markdown/autolink_filter.rb | 95 ++++++++++++++++++ lib/redcarpet/render/gitlab_html.rb | 18 +--- .../gitlab/markdown/autolink_filter_spec.rb | 98 +++++++++++++++++++ 5 files changed, 202 insertions(+), 17 deletions(-) create mode 100644 lib/gitlab/markdown/autolink_filter.rb create mode 100644 spec/lib/gitlab/markdown/autolink_filter_spec.rb diff --git a/app/helpers/gitlab_markdown_helper.rb b/app/helpers/gitlab_markdown_helper.rb index 48d754dcf7..7dbffaae5f 100644 --- a/app/helpers/gitlab_markdown_helper.rb +++ b/app/helpers/gitlab_markdown_helper.rb @@ -34,9 +34,8 @@ module GitlabMarkdownHelper # see https://github.com/vmg/redcarpet#darling-i-packed-you-a-couple-renderers-for-lunch rend = Redcarpet::Render::GitlabHTML.new(self, user_color_scheme_class, { - safe_links_only: true, # Handled further down the line by HTML::Pipeline::SanitizationFilter - escape_html: false + escape_html: false }.merge(options)) # see https://github.com/vmg/redcarpet#and-its-like-really-simple-to-use @@ -44,7 +43,6 @@ module GitlabMarkdownHelper no_intra_emphasis: true, tables: true, fenced_code_blocks: true, - autolink: true, strikethrough: true, lax_spacing: true, space_after_headers: true, diff --git a/lib/gitlab/markdown.rb b/lib/gitlab/markdown.rb index ffb7e16aed..beb97bbdf4 100644 --- a/lib/gitlab/markdown.rb +++ b/lib/gitlab/markdown.rb @@ -30,6 +30,7 @@ module Gitlab # => "\":trollface:\" module Markdown # Provide autoload paths for filters to prevent a circular dependency error + autoload :AutolinkFilter, 'gitlab/markdown/autolink_filter' autoload :CommitRangeReferenceFilter, 'gitlab/markdown/commit_range_reference_filter' autoload :CommitReferenceFilter, 'gitlab/markdown/commit_reference_filter' autoload :EmojiFilter, 'gitlab/markdown/emoji_filter' @@ -122,6 +123,7 @@ module Gitlab Gitlab::Markdown::EmojiFilter, Gitlab::Markdown::TableOfContentsFilter, + Gitlab::Markdown::AutolinkFilter, Gitlab::Markdown::UserReferenceFilter, Gitlab::Markdown::IssueReferenceFilter, @@ -130,7 +132,7 @@ module Gitlab Gitlab::Markdown::SnippetReferenceFilter, Gitlab::Markdown::CommitRangeReferenceFilter, Gitlab::Markdown::CommitReferenceFilter, - Gitlab::Markdown::LabelReferenceFilter, + Gitlab::Markdown::LabelReferenceFilter ] end diff --git a/lib/gitlab/markdown/autolink_filter.rb b/lib/gitlab/markdown/autolink_filter.rb new file mode 100644 index 0000000000..97cfc1893a --- /dev/null +++ b/lib/gitlab/markdown/autolink_filter.rb @@ -0,0 +1,95 @@ +require 'html/pipeline/filter' +require 'uri' + +module Gitlab + module Markdown + # HTML Filter for auto-linking URLs in HTML. + # + # Based on HTML::Pipeline::AutolinkFilter + # + # Context options: + # :autolink - Boolean, skips all processing done by this filter when false + # :link_attr - Hash of attributes for the generated links + # + class AutolinkFilter < HTML::Pipeline::Filter + include ActionView::Helpers::TagHelper + + # Pattern to match text that should be autolinked. + # + # A URI scheme begins with a letter and may contain letters, numbers, + # plus, period and hyphen. Schemes are case-insensitive but we're being + # picky here and allowing only lowercase for autolinks. + # + # See http://en.wikipedia.org/wiki/URI_scheme + # + # The negative lookbehind ensures that users can paste a URL followed by a + # period or comma for punctuation without those characters being included + # in the generated link. + SCHEME_PATTERN = %r{([a-z][a-z0-9_\+\.\-]+:\/\/[^\s]+)(?See #{link}" + expect(filter(act).to_html).to eq exp + end + end + end + + context 'other schemes' do + let(:link) { 'foo://bar.baz/' } + + it 'autolinks smb' do + link = 'smb:///Volumes/shared/foo.pdf' + doc = filter("See #{link}") + + expect(doc.at_css('a').text).to eq link + expect(doc.at_css('a')['href']).to eq link + end + + it 'autolinks irc' do + link = 'irc://irc.freenode.net/git' + doc = filter("See #{link}") + + expect(doc.at_css('a').text).to eq link + expect(doc.at_css('a')['href']).to eq link + end + + it 'does not include trailing punctuation' do + doc = filter("See #{link}.") + expect(doc.at_css('a').text).to eq link + + doc = filter("See #{link}, ok?") + expect(doc.at_css('a').text).to eq link + end + + it 'accepts link_attr options' do + doc = filter("See #{link}", link_attr: {class: 'custom'}) + expect(doc.at_css('a')['class']).to eq 'custom' + end + + described_class::IGNORE_PARENTS.each do |elem| + it "ignores valid links contained inside '#{elem}' element" do + exp = act = "<#{elem}>See #{link}" + expect(filter(act).to_html).to eq exp + end + end + end + end +end From e46d1cdd8bd4cc12e8c8e8fdce10b3114a17d95e Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Mon, 27 Apr 2015 18:56:37 -0400 Subject: [PATCH 63/97] Add Gitlab::Markdown::SanitizationFilter This just extends the HTML::Pipeline::SanitizationFilter with our custom whitelist. --- app/helpers/gitlab_markdown_helper.rb | 2 +- lib/gitlab/markdown.rb | 34 +------- lib/gitlab/markdown/sanitization_filter.rb | 38 +++++++++ spec/helpers/gitlab_markdown_helper_spec.rb | 33 -------- .../markdown/sanitization_filter_spec.rb | 81 +++++++++++++++++++ 5 files changed, 123 insertions(+), 65 deletions(-) create mode 100644 lib/gitlab/markdown/sanitization_filter.rb create mode 100644 spec/lib/gitlab/markdown/sanitization_filter_spec.rb diff --git a/app/helpers/gitlab_markdown_helper.rb b/app/helpers/gitlab_markdown_helper.rb index 7dbffaae5f..24263a0f61 100644 --- a/app/helpers/gitlab_markdown_helper.rb +++ b/app/helpers/gitlab_markdown_helper.rb @@ -34,7 +34,7 @@ module GitlabMarkdownHelper # see https://github.com/vmg/redcarpet#darling-i-packed-you-a-couple-renderers-for-lunch rend = Redcarpet::Render::GitlabHTML.new(self, user_color_scheme_class, { - # Handled further down the line by HTML::Pipeline::SanitizationFilter + # Handled further down the line by Gitlab::Markdown::SanitizationFilter escape_html: false }.merge(options)) diff --git a/lib/gitlab/markdown.rb b/lib/gitlab/markdown.rb index beb97bbdf4..e7ddaab5c2 100644 --- a/lib/gitlab/markdown.rb +++ b/lib/gitlab/markdown.rb @@ -38,6 +38,7 @@ module Gitlab autoload :IssueReferenceFilter, 'gitlab/markdown/issue_reference_filter' autoload :LabelReferenceFilter, 'gitlab/markdown/label_reference_filter' autoload :MergeRequestReferenceFilter, 'gitlab/markdown/merge_request_reference_filter' + autoload :SanitizationFilter, 'gitlab/markdown/sanitization_filter' autoload :SnippetReferenceFilter, 'gitlab/markdown/snippet_reference_filter' autoload :TableOfContentsFilter, 'gitlab/markdown/table_of_contents_filter' autoload :UserReferenceFilter, 'gitlab/markdown/user_reference_filter' @@ -76,9 +77,6 @@ module Gitlab pipeline = HTML::Pipeline.new(filters) context = { - # SanitizationFilter - whitelist: sanitization_whitelist, - # EmojiFilter asset_root: Gitlab.config.gitlab.url, asset_host: Gitlab::Application.config.asset_host, @@ -116,10 +114,10 @@ module Gitlab # SanitizationFilter should come first so that all generated reference HTML # goes through untouched. # - # See https://gitlab.com/gitlab-org/html-pipeline-gitlab for more filters + # See https://github.com/jch/html-pipeline#filters for more filters. def filters [ - HTML::Pipeline::SanitizationFilter, + Gitlab::Markdown::SanitizationFilter, Gitlab::Markdown::EmojiFilter, Gitlab::Markdown::TableOfContentsFilter, @@ -136,32 +134,6 @@ module Gitlab ] end - # Customize the SanitizationFilter whitelist - # - # - Allow `class` and `id` attributes on all elements - # - Allow `span` elements - # - Remove `rel` attributes from `a` elements - # - Remove `a` nodes with `javascript:` in the `href` attribute - def sanitization_whitelist - whitelist = HTML::Pipeline::SanitizationFilter::WHITELIST - whitelist[:attributes][:all].push('class', 'id') - whitelist[:elements].push('span') - - fix_anchors = lambda do |env| - name, node = env[:node_name], env[:node] - if name == 'a' - node.remove_attribute('rel') - if node['href'] && node['href'].match('javascript:') - node.remove_attribute('href') - end - end - end - - whitelist[:transformers].push(fix_anchors) - - whitelist - end - # Turn list items that start with "[ ]" into HTML checkbox inputs. def parse_tasks(text) li_tag = '
  • ' diff --git a/lib/gitlab/markdown/sanitization_filter.rb b/lib/gitlab/markdown/sanitization_filter.rb new file mode 100644 index 0000000000..9a154e0b2f --- /dev/null +++ b/lib/gitlab/markdown/sanitization_filter.rb @@ -0,0 +1,38 @@ +require 'html/pipeline/filter' +require 'html/pipeline/sanitization_filter' + +module Gitlab + module Markdown + # Sanitize HTML + # + # Extends HTML::Pipeline::SanitizationFilter with a custom whitelist. + class SanitizationFilter < HTML::Pipeline::SanitizationFilter + def whitelist + whitelist = HTML::Pipeline::SanitizationFilter::WHITELIST + + # Allow `class` and `id` on all elements + whitelist[:attributes][:all].push('class', 'id') + + # Allow table alignment + whitelist[:attributes]['th'] = %w(style) + whitelist[:attributes]['td'] = %w(style) + + # Allow span elements + whitelist[:elements].push('span') + + # Remove `rel` attribute from `a` elements + whitelist[:transformers].push(remove_rel) + + whitelist + end + + def remove_rel + lambda do |env| + if env[:node_name] == 'a' + env[:node].remove_attribute('rel') + end + end + end + end + end +end diff --git a/spec/helpers/gitlab_markdown_helper_spec.rb b/spec/helpers/gitlab_markdown_helper_spec.rb index bd2240c599..ff0f049ce6 100644 --- a/spec/helpers/gitlab_markdown_helper_spec.rb +++ b/spec/helpers/gitlab_markdown_helper_spec.rb @@ -316,11 +316,6 @@ describe GitlabMarkdownHelper do expected = "" expect(markdown(actual)).to match(expected) end - - it 'should allow whitelisted HTML tags from the user' do - actual = '
    Term
    Definition
    ' - expect(markdown(actual)).to match(actual) - end end context 'with an empty repository' do @@ -336,34 +331,6 @@ describe GitlabMarkdownHelper do end end end - - # SANITIZATION ------------------------------------------------------------ - # TODO (rspeicher): These are testing SanitizationFilter, not `markdown` - - it 'should sanitize tags that are not whitelisted' do - actual = ' no blinks' - expected = 'no inputs allowed no blinks' - expect(markdown(actual)).to match(expected) - expect(markdown(actual)).not_to match('<.textarea>') - expect(markdown(actual)).not_to match('<.blink>') - end - - it 'should allow whitelisted tag attributes from the user' do - actual = 'link text' - expect(markdown(actual)).to match(actual) - end - - it 'should sanitize tag attributes that are not whitelisted' do - actual = 'link text' - expected = 'link text' - expect(markdown(actual)).to match(expected) - end - - it 'should sanitize javascript in attributes' do - actual = %q(link text) - expected = 'link text' - expect(markdown(actual)).to match(expected) - end end describe '#render_wiki_content' do diff --git a/spec/lib/gitlab/markdown/sanitization_filter_spec.rb b/spec/lib/gitlab/markdown/sanitization_filter_spec.rb new file mode 100644 index 0000000000..ab909a6863 --- /dev/null +++ b/spec/lib/gitlab/markdown/sanitization_filter_spec.rb @@ -0,0 +1,81 @@ +require 'spec_helper' + +module Gitlab::Markdown + describe SanitizationFilter do + def filter(html, options = {}) + described_class.call(html, options) + end + + describe 'default whitelist' do + it 'sanitizes tags that are not whitelisted' do + act = %q{ and no blinks} + exp = 'no inputs and no blinks' + expect(filter(act).to_html).to eq exp + end + + it 'sanitizes tag attributes' do + act = %q{Text} + exp = %q{Text} + expect(filter(act).to_html).to eq exp + end + + it 'sanitizes javascript in attributes' do + act = %q(Text) + exp = 'Text' + expect(filter(act).to_html).to eq exp + end + + it 'allows whitelisted HTML tags from the user' do + exp = act = "
    \n
    Term
    \n
    Definition
    \n
    " + expect(filter(act).to_html).to eq exp + end + end + + describe 'custom whitelist' do + it 'allows `class` attribute on any element' do + exp = act = %q{Strong} + expect(filter(act).to_html).to eq exp + end + + it 'allows `id` attribute on any element' do + exp = act = %q{Emphasis} + expect(filter(act).to_html).to eq exp + end + + it 'allows `style` attribute on table elements' do + html = <<-HTML.strip_heredoc + + + +
    Head
    Body
    + HTML + + doc = filter(html) + + expect(doc.at_css('th')['style']).to eq 'text-align: center' + expect(doc.at_css('td')['style']).to eq 'text-align: right' + end + + it 'allows `span` elements' do + exp = act = %q{Hello} + expect(filter(act).to_html).to eq exp + end + + it 'removes `rel` attribute from `a` elements' do + doc = filter(%q{Link}) + + expect(doc.css('a').size).to eq 1 + expect(doc.at_css('a')['href']).to eq '#' + expect(doc.at_css('a')['rel']).to be_nil + end + + it 'removes script-like `href` attribute from `a` elements' do + html = %q{Hi} + doc = filter(html) + + expect(doc.css('a').size).to eq 1 + expect(doc.at_css('a')['href']).to be_nil + end + end + end +end From 588267b5e27238cdf406f248db7cc83b9b0881c8 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Mon, 27 Apr 2015 22:01:46 -0400 Subject: [PATCH 64/97] Update the Gitlab::Markdown docs --- lib/gitlab/markdown.rb | 26 +------------------------- 1 file changed, 1 insertion(+), 25 deletions(-) diff --git a/lib/gitlab/markdown.rb b/lib/gitlab/markdown.rb index e7ddaab5c2..8348e28d0f 100644 --- a/lib/gitlab/markdown.rb +++ b/lib/gitlab/markdown.rb @@ -3,31 +3,7 @@ require 'html/pipeline' module Gitlab # Custom parser for GitLab-flavored Markdown # - # It replaces references in the text with links to the appropriate items in - # GitLab. - # - # Supported reference formats are: - # * @foo for team members - # * #123 for issues - # * JIRA-123 for Jira issues - # * !123 for merge requests - # * $123 for snippets - # * 1c002d for specific commit - # * 1c002d...35cfb2 for commit ranges (comparisons) - # - # It also parses Emoji codes to insert images. See - # http://www.emoji-cheat-sheet.com/ for a list of the supported icons. - # - # Examples - # - # >> gfm("Hey @david, can you fix this?") - # => "Hey @david, can you fix this?" - # - # >> gfm("Commit 35d5f7c closes #1234") - # => "Commit 35d5f7c closes #1234" - # - # >> gfm(":trollface:") - # => "\":trollface:\" + # See the files in `lib/gitlab/markdown/` for specific processing information. module Markdown # Provide autoload paths for filters to prevent a circular dependency error autoload :AutolinkFilter, 'gitlab/markdown/autolink_filter' From 421edd35454103e3ed927de72d23a38bee1f97d3 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Mon, 27 Apr 2015 22:09:00 -0400 Subject: [PATCH 65/97] Escape normal text in our Redcarpet renderer --- lib/redcarpet/render/gitlab_html.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/redcarpet/render/gitlab_html.rb b/lib/redcarpet/render/gitlab_html.rb index 321be9202c..5a87b23057 100644 --- a/lib/redcarpet/render/gitlab_html.rb +++ b/lib/redcarpet/render/gitlab_html.rb @@ -1,5 +1,6 @@ -class Redcarpet::Render::GitlabHTML < Redcarpet::Render::HTML +require 'active_support/core_ext/string/output_safety' +class Redcarpet::Render::GitlabHTML < Redcarpet::Render::HTML attr_reader :template alias_method :h, :template @@ -21,6 +22,7 @@ class Redcarpet::Render::GitlabHTML < Redcarpet::Render::HTML def normal_text(text) return text unless text.present? + text = ERB::Util.html_escape_once(text) text.gsub("'", "’") end From fad015764cb2d550af0210e2158ecdead4b4bdeb Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Mon, 27 Apr 2015 22:09:29 -0400 Subject: [PATCH 66/97] More gitlab_markdown_helper_spec cleanup --- spec/helpers/gitlab_markdown_helper_spec.rb | 57 +-------------------- 1 file changed, 1 insertion(+), 56 deletions(-) diff --git a/spec/helpers/gitlab_markdown_helper_spec.rb b/spec/helpers/gitlab_markdown_helper_spec.rb index ff0f049ce6..b6be82e410 100644 --- a/spec/helpers/gitlab_markdown_helper_spec.rb +++ b/spec/helpers/gitlab_markdown_helper_spec.rb @@ -107,8 +107,7 @@ describe GitlabMarkdownHelper do end it 'should not be confused by whitespace before bullets' do - rendered_text_asterisk = markdown(@source_text_asterisk, - parse_tasks: true) + rendered_text_asterisk = markdown(@source_text_asterisk, parse_tasks: true) rendered_text_dash = markdown(@source_text_dash, parse_tasks: true) expect(rendered_text_asterisk).to match( @@ -207,61 +206,7 @@ describe GitlabMarkdownHelper do end describe "#markdown" do - # REFERENCES (PART TWO: THE REVENGE) --------------------------------------- - - it "should handle references in headers" do - actual = "\n# Working around ##{issue.iid}\n## Apply !#{merge_request.iid}" - - expect(markdown(actual, no_header_anchors: true)). - to match(%r{Working around ##{issue.iid}}) - expect(markdown(actual, no_header_anchors: true)). - to match(%r{Apply !#{merge_request.iid}}) - end - - it "should handle references in " do - actual = "Apply _!#{merge_request.iid}_ ASAP" - - expect(markdown(actual)). - to match(%r{Apply !#{merge_request.iid}}) - end - - # CODE BLOCKS ------------------------------------------------------------- - - it "should leave code blocks untouched" do - allow(helper).to receive(:current_user).and_return(user) - allow(helper).to receive(:user_color_scheme_class).and_return(:white) - - target_html = "
    some code from $#{snippet.id}\nhere too\n
    \n" - - expect(markdown("\n some code from $#{snippet.id}\n here too\n")). - to eq(target_html) - expect(markdown("\n```\nsome code from $#{snippet.id}\nhere too\n```\n")). - to eq(target_html) - end - - it "should leave inline code untouched" do - expect(markdown("Don't use `$#{snippet.id}` here.")). - to eq "

    Don't use $#{snippet.id} here.

    \n" - end - - # REF-LIKE AUTOLINKS? ----------------------------------------------------- - # Basically: Don't parse references inside `` tags. - - it "should leave ref-like autolinks untouched" do - expect(markdown("look at http://example.tld/#!#{merge_request.iid}")).to eq("

    look at http://example.tld/#!#{merge_request.iid}

    \n") - end - - it "should leave ref-like href of 'manual' links untouched" do - expect(markdown("why not [inspect !#{merge_request.iid}](http://example.tld/#!#{merge_request.iid})")).to eq("

    why not inspect !#{merge_request.iid}

    \n") - end - - it "should leave ref-like src of images untouched" do - expect(markdown("screen shot: ![some image](http://example.tld/#!#{merge_request.iid})")).to eq("

    screen shot: \"some

    \n") - end - - # RELATIVE URLS ----------------------------------------------------------- # TODO (rspeicher): These belong in a relative link filter spec - context 'relative links' do context 'with a valid repository' do before do From a3fbf344693957ed0f39171400efa706b3a8709c Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Tue, 28 Apr 2015 15:37:04 -0400 Subject: [PATCH 67/97] Fix header_should_have_correct_id_and_link for features --- features/steps/shared/markdown.rb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/features/steps/shared/markdown.rb b/features/steps/shared/markdown.rb index e71700880c..a7231c47d1 100644 --- a/features/steps/shared/markdown.rb +++ b/features/steps/shared/markdown.rb @@ -2,8 +2,12 @@ module SharedMarkdown include Spinach::DSL def header_should_have_correct_id_and_link(level, text, id, parent = ".wiki") - find(:css, "#{parent} h#{level}##{id}").text.should == text - find(:css, "#{parent} h#{level}##{id} > :last-child")[:href].should =~ /##{id}$/ + node = find("#{parent} h#{level} a##{id}") + node[:href].should == "##{id}" + + # Work around a weird Capybara behavior where calling `parent` on a node + # returns the whole document, not the node's actual parent element + find(:xpath, "#{node.path}/..").text.should == text end def create_taskable(type, title) From 9ec8a5f75d05a9911a1d479a8817b2c348ad91c6 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Tue, 28 Apr 2015 15:42:03 -0400 Subject: [PATCH 68/97] Doc typo --- lib/gitlab/theme.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/gitlab/theme.rb b/lib/gitlab/theme.rb index f0e61aa2e8..e5a1f1b44d 100644 --- a/lib/gitlab/theme.rb +++ b/lib/gitlab/theme.rb @@ -40,7 +40,7 @@ module Gitlab end # Convenience method to get a space-separated String of all the theme - # classes that mighty be applied to the `body` element + # classes that might be applied to the `body` element # # Returns a String def self.body_classes From 50f707e27ade6952b87aef86714f056dea2a1da3 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Wed, 29 Apr 2015 14:17:29 -0400 Subject: [PATCH 69/97] Update Autolink SCHEME_PATTERN --- lib/gitlab/markdown/autolink_filter.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/gitlab/markdown/autolink_filter.rb b/lib/gitlab/markdown/autolink_filter.rb index 97cfc1893a..9889d6643a 100644 --- a/lib/gitlab/markdown/autolink_filter.rb +++ b/lib/gitlab/markdown/autolink_filter.rb @@ -25,7 +25,9 @@ module Gitlab # The negative lookbehind ensures that users can paste a URL followed by a # period or comma for punctuation without those characters being included # in the generated link. - SCHEME_PATTERN = %r{([a-z][a-z0-9_\+\.\-]+:\/\/[^\s]+)(? Date: Wed, 29 Apr 2015 14:28:24 -0400 Subject: [PATCH 70/97] Add jira_project project factory --- spec/factories/projects.rb | 20 +++++++++++++++++-- .../external_issue_reference_filter_spec.rb | 19 +----------------- 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb index 57fa079d75..102678a1d7 100644 --- a/spec/factories/projects.rb +++ b/spec/factories/projects.rb @@ -94,10 +94,26 @@ FactoryGirl.define do 'new_issue_url' => 'http://redmine/projects/project_name_in_redmine/issues/new' } ) - end - after :create do |project| + project.issues_tracker = 'redmine' project.issues_tracker_id = 'project_name_in_redmine' end end + + factory :jira_project, parent: :project do + after :create do |project| + project.create_jira_service( + active: true, + properties: { + 'title' => 'JIRA tracker', + 'project_url' => 'http://jira.example/issues/?jql=project=A', + 'issues_url' => 'http://jira.example/browse/:id', + 'new_issue_url' => 'http://jira.example/secure/CreateIssue.jspa' + } + ) + + project.issues_tracker = 'jira' + project.issues_tracker_id = 'project_name_in_jira' + end + end end diff --git a/spec/lib/gitlab/markdown/external_issue_reference_filter_spec.rb b/spec/lib/gitlab/markdown/external_issue_reference_filter_spec.rb index 27e930ef7d..b19bc125b9 100644 --- a/spec/lib/gitlab/markdown/external_issue_reference_filter_spec.rb +++ b/spec/lib/gitlab/markdown/external_issue_reference_filter_spec.rb @@ -8,29 +8,12 @@ module Gitlab::Markdown IssuesHelper end - let(:project) { create(:empty_project) } + let(:project) { create(:jira_project) } let(:issue) { double('issue', iid: 123) } context 'JIRA issue references' do let(:reference) { "JIRA-#{issue.iid}" } - before do - jira = project.create_jira_service - - props = { - 'title' => 'JIRA tracker', - 'project_url' => 'http://jira.example/issues/?jql=project=A', - 'issues_url' => 'http://jira.example/browse/:id', - 'new_issue_url' => 'http://jira.example/secure/CreateIssue.jspa' - } - - jira.update_attributes(properties: props, active: true) - end - - after do - project.jira_service.destroy - end - it 'requires project context' do expect { described_class.call('Issue JIRA-123', {}) }. to raise_error(ArgumentError, /:project/) From cd3c24a8f3441c249fb73b0a7d7bf412485438de Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Wed, 29 Apr 2015 18:45:29 -0400 Subject: [PATCH 71/97] Autolink short URLs --- lib/gitlab/markdown/autolink_filter.rb | 5 ++++- spec/features/markdown_spec.rb | 4 +--- spec/lib/gitlab/markdown/autolink_filter_spec.rb | 8 ++++++++ 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/lib/gitlab/markdown/autolink_filter.rb b/lib/gitlab/markdown/autolink_filter.rb index 9889d6643a..f0b68bab82 100644 --- a/lib/gitlab/markdown/autolink_filter.rb +++ b/lib/gitlab/markdown/autolink_filter.rb @@ -52,7 +52,10 @@ module Gitlab # NOTE: We don't parse email links because it will erroneously match # external Commit and CommitRange references. - rinku = Rinku.auto_link(html, :urls, options, IGNORE_PARENTS.to_a) + # + # The final argument tells Rinku to link short URLs that don't include a + # period (e.g., http://localhost:3000/) + rinku = Rinku.auto_link(html, :urls, options, IGNORE_PARENTS.to_a, 1) # Rinku returns a String, so parse it back to a Nokogiri::XML::Document # for further processing. diff --git a/spec/features/markdown_spec.rb b/spec/features/markdown_spec.rb index 9db1a0a241..3528200e12 100644 --- a/spec/features/markdown_spec.rb +++ b/spec/features/markdown_spec.rb @@ -207,11 +207,9 @@ describe 'GitLab Markdown' do expect(item(5).children.first['href']).to eq 'irc://irc.freenode.net/git' end - # TODO (rspeicher): Do we really want this? it 'autolinks short, invalid URLs' do - skip 'rspeicher: Pending decision' expect(item(6).children.first.name).to eq 'a' - expect(item(6).children.first['href']).to eq 'http://foo' + expect(item(6).children.first['href']).to eq 'http://localhost:3000' end %w(code a kbd).each do |elem| diff --git a/spec/lib/gitlab/markdown/autolink_filter_spec.rb b/spec/lib/gitlab/markdown/autolink_filter_spec.rb index 83fee12333..0bbdc11a97 100644 --- a/spec/lib/gitlab/markdown/autolink_filter_spec.rb +++ b/spec/lib/gitlab/markdown/autolink_filter_spec.rb @@ -41,6 +41,14 @@ module Gitlab::Markdown expect(doc.at_css('a')['href']).to eq link end + it 'autolinks short URLs' do + link = 'http://localhost:3000/' + doc = filter("See #{link}") + + expect(doc.at_css('a').text).to eq link + expect(doc.at_css('a')['href']).to eq link + end + it 'accepts link_attr options' do doc = filter("See #{link}", link_attr: {class: 'custom'}) From 466bec7caa4708f3d0c671b9fab135ed2c3dcdc1 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Wed, 29 Apr 2015 18:45:38 -0400 Subject: [PATCH 72/97] Rename SCHEME_PATTERN to LINK_PATTERN --- lib/gitlab/markdown/autolink_filter.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/gitlab/markdown/autolink_filter.rb b/lib/gitlab/markdown/autolink_filter.rb index f0b68bab82..4e14a048cf 100644 --- a/lib/gitlab/markdown/autolink_filter.rb +++ b/lib/gitlab/markdown/autolink_filter.rb @@ -27,9 +27,9 @@ module Gitlab # in the generated link. # # Rubular: http://rubular.com/r/cxjPyZc7Sb - SCHEME_PATTERN = %r{([a-z][a-z0-9\+\.-]+://\S+)(? Date: Thu, 30 Apr 2015 16:10:39 -0400 Subject: [PATCH 73/97] Add Project#get_issue --- app/models/project.rb | 16 ++++++++-------- lib/gitlab/markdown/issue_reference_filter.rb | 13 ++++++------- .../markdown/issue_reference_filter_spec.rb | 8 ++++---- 3 files changed, 18 insertions(+), 19 deletions(-) diff --git a/app/models/project.rb b/app/models/project.rb index 397232e98d..e8a0b2f115 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -329,14 +329,18 @@ class Project < ActiveRecord::Base self.id end - def issue_exists?(issue_id) + def get_issue(issue_id) if default_issues_tracker? - self.issues.where(iid: issue_id).first.present? + issues.find_by(iid: issue_id) else - true + ExternalIssue.new(issue_id, self) end end + def issue_exists?(issue_id) + get_issue(issue_id).present? + end + def default_issue_tracker gitlab_issue_tracker_service || create_gitlab_issue_tracker_service end @@ -350,11 +354,7 @@ class Project < ActiveRecord::Base end def default_issues_tracker? - if external_issue_tracker - false - else - true - end + external_issue_tracker.blank? end def external_issues_trackers diff --git a/lib/gitlab/markdown/issue_reference_filter.rb b/lib/gitlab/markdown/issue_reference_filter.rb index 4b360369d3..6812b933fe 100644 --- a/lib/gitlab/markdown/issue_reference_filter.rb +++ b/lib/gitlab/markdown/issue_reference_filter.rb @@ -44,21 +44,20 @@ module Gitlab # Returns a String with `#123` references replaced with links. All links # have `gfm` and `gfm-issue` class names attached for styling. def issue_link_filter(text) - self.class.references_in(text) do |match, issue, project_ref| + self.class.references_in(text) do |match, id, project_ref| project = self.project_from_ref(project_ref) - if project && project.issue_exists?(issue) - # FIXME (rspeicher): Law of Demeter - push_result(:issue, project.issues.where(iid: issue).first) + if project && issue = project.get_issue(id) + push_result(:issue, issue) - url = url_for_issue(issue, project, only_path: context[:only_path]) + url = url_for_issue(id, project, only_path: context[:only_path]) - title = escape_once("Issue: #{title_for_issue(issue, project)}") + title = escape_once("Issue: #{title_for_issue(id, project)}") klass = reference_class(:issue) %(#{project_ref}##{issue}) + class="#{klass}">#{project_ref}##{id}) else match end diff --git a/spec/lib/gitlab/markdown/issue_reference_filter_spec.rb b/spec/lib/gitlab/markdown/issue_reference_filter_spec.rb index 393bf32e19..08382b3e7e 100644 --- a/spec/lib/gitlab/markdown/issue_reference_filter_spec.rb +++ b/spec/lib/gitlab/markdown/issue_reference_filter_spec.rb @@ -27,7 +27,7 @@ module Gitlab::Markdown let(:reference) { "##{issue.iid}" } it 'ignores valid references when using non-default tracker' do - expect(project).to receive(:issue_exists?).with(issue.iid).and_return(false) + expect(project).to receive(:get_issue).with(issue.iid).and_return(nil) exp = act = "Issue ##{issue.iid}" expect(filter(act).to_html).to eq exp @@ -48,7 +48,7 @@ module Gitlab::Markdown it 'ignores invalid issue IDs' do exp = act = "Fixed ##{issue.iid + 1}" - expect(project).to receive(:issue_exists?).with(issue.iid + 1) + expect(project).to receive(:get_issue).with(issue.iid + 1).and_return(nil) expect(filter(act).to_html).to eq exp end @@ -98,8 +98,8 @@ module Gitlab::Markdown before { allow_cross_reference! } it 'ignores valid references when cross-reference project uses external tracker' do - expect_any_instance_of(Project).to receive(:issue_exists?). - with(issue.iid).and_return(false) + expect_any_instance_of(Project).to receive(:get_issue). + with(issue.iid).and_return(nil) exp = act = "Issue ##{issue.iid}" expect(filter(act).to_html).to eq exp From 242bebc13483c281af8bd2e0e9f6d7346997481e Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Thu, 30 Apr 2015 16:13:33 -0400 Subject: [PATCH 74/97] Remove special handling for the `'` problem While `escape_once` will create this HTML entity, Nokogiri always translates it back before it gets to IssueReferenceFilter, so there should be no danger of erroneous issue links. --- .../markdown/merge_request_reference_filter.rb | 1 - lib/redcarpet/render/gitlab_html.rb | 13 +------------ spec/fixtures/markdown.md.erb | 1 - 3 files changed, 1 insertion(+), 14 deletions(-) diff --git a/lib/gitlab/markdown/merge_request_reference_filter.rb b/lib/gitlab/markdown/merge_request_reference_filter.rb index 7c28fe112e..740d72abb3 100644 --- a/lib/gitlab/markdown/merge_request_reference_filter.rb +++ b/lib/gitlab/markdown/merge_request_reference_filter.rb @@ -64,7 +64,6 @@ module Gitlab end end - # TODO (rspeicher): Cleanup def url_for_merge_request(mr, project) h = Rails.application.routes.url_helpers h.namespace_project_merge_request_url(project.namespace, project, mr, diff --git a/lib/redcarpet/render/gitlab_html.rb b/lib/redcarpet/render/gitlab_html.rb index 5a87b23057..bea66e6cdc 100644 --- a/lib/redcarpet/render/gitlab_html.rb +++ b/lib/redcarpet/render/gitlab_html.rb @@ -13,17 +13,8 @@ class Redcarpet::Render::GitlabHTML < Redcarpet::Render::HTML super(options) end - # If project has issue number 39, apostrophe will be linked in - # regular text to the issue as Redcarpet will convert apostrophe to - # #39; - # We replace apostrophe with right single quote before Redcarpet - # does the processing and put the apostrophe back in postprocessing. - # This only influences regular text, code blocks are untouched. def normal_text(text) - return text unless text.present? - - text = ERB::Util.html_escape_once(text) - text.gsub("'", "’") + ERB::Util.html_escape_once(text) end # Stolen from Rugments::Plugins::Redcarpet as this module is not required @@ -45,8 +36,6 @@ class Redcarpet::Render::GitlabHTML < Redcarpet::Render::HTML end def postprocess(full_document) - full_document.gsub!("’", "'") - unless @template.instance_variable_get("@project_wiki") || @project.nil? full_document = h.create_relative_links(full_document) end diff --git a/spec/fixtures/markdown.md.erb b/spec/fixtures/markdown.md.erb index b00fc099b4..0c14075855 100644 --- a/spec/fixtures/markdown.md.erb +++ b/spec/fixtures/markdown.md.erb @@ -138,7 +138,6 @@ References should be parseable even inside _!<%= merge_request.iid %>_ emphasis. - Issue: #<%= issue.iid %> - Issue in another project: <%= xref %>#<%= xissue.iid %> -- Ignores HTML entities: TODO:' - Ignored in code: `#<%= issue.iid %>` - Ignored in links: [Link to #<%= issue.iid %>](#issue-link) From 84a7675ea69b8bbd3e95a94fbcfad716daa77b36 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Thu, 30 Apr 2015 17:27:33 -0400 Subject: [PATCH 75/97] Remove title_for_issue helper --- app/helpers/issues_helper.rb | 13 +------------ app/models/external_issue.rb | 4 ++++ lib/gitlab/markdown/issue_reference_filter.rb | 6 +----- spec/helpers/issues_helper_spec.rb | 18 ------------------ 4 files changed, 6 insertions(+), 35 deletions(-) diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb index c3b4731dff..36d3f371c1 100644 --- a/app/helpers/issues_helper.rb +++ b/app/helpers/issues_helper.rb @@ -43,17 +43,6 @@ module IssuesHelper end end - def title_for_issue(issue_iid, project = @project) - return '' if project.nil? - - if project.default_issues_tracker? - issue = project.issues.where(iid: issue_iid).first - return issue.title if issue - end - - '' - end - def issue_timestamp(issue) # Shows the created at time and the updated at time if different ts = "#{time_ago_with_tooltip(issue.created_at, 'bottom', 'note_created_ago')}" @@ -110,5 +99,5 @@ module IssuesHelper end # Required for Gitlab::Markdown::IssueReferenceFilter - module_function :url_for_issue, :title_for_issue + module_function :url_for_issue end diff --git a/app/models/external_issue.rb b/app/models/external_issue.rb index 50efcb32f1..85fdb12bfd 100644 --- a/app/models/external_issue.rb +++ b/app/models/external_issue.rb @@ -15,6 +15,10 @@ class ExternalIssue @issue_identifier.to_s end + def title + "External Issue #{self}" + end + def ==(other) other.is_a?(self.class) && (to_s == other.to_s) end diff --git a/lib/gitlab/markdown/issue_reference_filter.rb b/lib/gitlab/markdown/issue_reference_filter.rb index 6812b933fe..1e88561516 100644 --- a/lib/gitlab/markdown/issue_reference_filter.rb +++ b/lib/gitlab/markdown/issue_reference_filter.rb @@ -52,7 +52,7 @@ module Gitlab url = url_for_issue(id, project, only_path: context[:only_path]) - title = escape_once("Issue: #{title_for_issue(id, project)}") + title = escape_once("Issue: #{issue.title}") klass = reference_class(:issue) %( Date: Thu, 30 Apr 2015 17:27:51 -0400 Subject: [PATCH 76/97] Change `external_issue_tracker.blank?` to `!external_issue_tracker` --- app/models/project.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/project.rb b/app/models/project.rb index e8a0b2f115..c940021d57 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -354,7 +354,7 @@ class Project < ActiveRecord::Base end def default_issues_tracker? - external_issue_tracker.blank? + !external_issue_tracker end def external_issues_trackers From 8d17e79d1dfc8fb415b3fe4dbabd11659fa6c42e Mon Sep 17 00:00:00 2001 From: Dominik Sander Date: Thu, 30 Apr 2015 23:36:42 +0200 Subject: [PATCH 77/97] Removed unused ApplicationController#set_filter_values method The instance variables assigned in `set_filter_values` are not used by anything anymore. --- app/controllers/application_controller.rb | 25 ----------------------- 1 file changed, 25 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 69fd790183..f56f88b58f 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -286,40 +286,15 @@ class ApplicationController < ActionController::Base @filter_params end - def set_filter_values(collection) - assignee_id = @filter_params[:assignee_id] - author_id = @filter_params[:author_id] - milestone_id = @filter_params[:milestone_id] - - @sort = @filter_params[:sort] - @assignees = User.where(id: collection.pluck(:assignee_id)) - @authors = User.where(id: collection.pluck(:author_id)) - @milestones = Milestone.where(id: collection.pluck(:milestone_id)) - - if assignee_id.present? && !assignee_id.to_i.zero? - @assignee = @assignees.find_by(id: assignee_id) - end - - if author_id.present? && !author_id.to_i.zero? - @author = @authors.find_by(id: author_id) - end - - if milestone_id.present? && !milestone_id.to_i.zero? - @milestone = @milestones.find_by(id: milestone_id) - end - end - def get_issues_collection set_filters_params issues = IssuesFinder.new.execute(current_user, @filter_params) - set_filter_values(issues) issues end def get_merge_requests_collection set_filters_params merge_requests = MergeRequestsFinder.new.execute(current_user, @filter_params) - set_filter_values(merge_requests) merge_requests end From e6ee8d0ebebc217e247558507eac619931a47121 Mon Sep 17 00:00:00 2001 From: Dominik Sander Date: Thu, 30 Apr 2015 23:29:00 +0200 Subject: [PATCH 78/97] Group milestones by title in the dashboard and all other issue views This groups milestones by title for issue views like it has been done for the milestone dashboard/project overview. Before milestones with the same title would show up multiple times in the filter dropdown and one could only filter per project and milestone. Now the milestone filter is based on the title of the milestone, i.e. all issues marked with the same milestone title are shown. --- CHANGELOG | 1 + app/finders/issuable_finder.rb | 5 +++-- app/helpers/milestones_helper.rb | 3 ++- app/views/shared/_issuable_filter.html.haml | 4 ++-- spec/features/issues_spec.rb | 4 ++-- spec/finders/issues_finder_spec.rb | 2 +- 6 files changed, 11 insertions(+), 8 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 3af83ddc25..902ca7a507 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -20,6 +20,7 @@ v 7.11.0 (unreleased) - Don't crash when an MR from a fork has a cross-reference comment from the target project on of its commits. - Include commit comments in MR from a forked project. - Fix adding new group members from admin area + - Group milestones by title in the dashboard and all other issue views. - Add default project and snippet visibility settings to the admin web UI. - - Fix bug where commit data would not appear in some subdirectories (Stan Hu) diff --git a/app/finders/issuable_finder.rb b/app/finders/issuable_finder.rb index 2c0702073d..b8f367c633 100644 --- a/app/finders/issuable_finder.rb +++ b/app/finders/issuable_finder.rb @@ -113,8 +113,9 @@ class IssuableFinder end def by_milestone(items) - if params[:milestone_id].present? - items = items.where(milestone_id: (params[:milestone_id] == NONE ? nil : params[:milestone_id])) + if params[:milestone_title].present? + milestone_ids = (params[:milestone_title] == NONE ? nil : Milestone.where(title: params[:milestone_title]).pluck(:id)) + items = items.where(milestone_id: milestone_ids) end items diff --git a/app/helpers/milestones_helper.rb b/app/helpers/milestones_helper.rb index 282bdf744d..93e33ebefd 100644 --- a/app/helpers/milestones_helper.rb +++ b/app/helpers/milestones_helper.rb @@ -28,6 +28,7 @@ module MilestonesHelper Milestone.where(project_id: @projects) end.active - options_from_collection_for_select(milestones, 'id', 'title', params[:milestone_id]) + grouped_milestones = Milestones::GroupService.new(milestones).execute + options_from_collection_for_select(grouped_milestones, 'title', 'title', params[:milestone_title]) end end diff --git a/app/views/shared/_issuable_filter.html.haml b/app/views/shared/_issuable_filter.html.haml index f9eb2dcfa2..fa8b4eae31 100644 --- a/app/views/shared/_issuable_filter.html.haml +++ b/app/views/shared/_issuable_filter.html.haml @@ -15,7 +15,7 @@ #{state_filters_text_for(:all, @project)} .issues-details-filters - = form_tag page_filter_path(without: [:assignee_id, :author_id, :milestone_id, :label_name]), method: :get, class: 'filter-form' do + = form_tag page_filter_path(without: [:assignee_id, :author_id, :milestone_title, :label_name]), method: :get, class: 'filter-form' do - if controller.controller_name == 'issues' .check-all-holder = check_box_tag "check_all_issues", nil, false, @@ -31,7 +31,7 @@ placeholder: 'Author', class: 'trigger-submit', any_user: true, first_user: true) .filter-item.inline.milestone-filter - = select_tag('milestone_id', projects_milestones_options, class: "select2 trigger-submit", prompt: 'Milestone') + = select_tag('milestone_title', projects_milestones_options, class: "select2 trigger-submit", prompt: 'Milestone') - if @project .filter-item.inline.labels-filter diff --git a/spec/features/issues_spec.rb b/spec/features/issues_spec.rb index e217f0739d..66d73b2505 100644 --- a/spec/features/issues_spec.rb +++ b/spec/features/issues_spec.rb @@ -95,7 +95,7 @@ describe 'Issues', feature: true do let(:issue) { @issue } it 'should allow filtering by issues with no specified milestone' do - visit namespace_project_issues_path(project.namespace, project, milestone_id: IssuableFinder::NONE) + visit namespace_project_issues_path(project.namespace, project, milestone_title: IssuableFinder::NONE) expect(page).not_to have_content 'foobar' expect(page).to have_content 'barbaz' @@ -103,7 +103,7 @@ describe 'Issues', feature: true do end it 'should allow filtering by a specified milestone' do - visit namespace_project_issues_path(project.namespace, project, milestone_id: issue.milestone.id) + visit namespace_project_issues_path(project.namespace, project, milestone_title: issue.milestone.title) expect(page).to have_content 'foobar' expect(page).not_to have_content 'barbaz' diff --git a/spec/finders/issues_finder_spec.rb b/spec/finders/issues_finder_spec.rb index 479fa95038..69bac387d2 100644 --- a/spec/finders/issues_finder_spec.rb +++ b/spec/finders/issues_finder_spec.rb @@ -43,7 +43,7 @@ describe IssuesFinder do end it 'should filter by milestone id' do - params = { scope: "all", milestone_id: milestone.id, state: 'opened' } + params = { scope: "all", milestone_title: milestone.title, state: 'opened' } issues = IssuesFinder.new.execute(user, params) expect(issues).to eq([issue1]) end From 92fd3ccee05acdfd5e498734ed287458a8dd21a3 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Fri, 1 May 2015 10:39:11 +0200 Subject: [PATCH 79/97] Add helpers for header title and sidebar, and move setting those from controllers to layouts. --- app/assets/javascripts/dispatcher.js.coffee | 1 - .../admin/application_controller.rb | 8 +----- app/controllers/application_controller.rb | 1 + .../dashboard/application_controller.rb | 10 +------ .../explore/application_controller.rb | 10 +------ .../groups/application_controller.rb | 8 +----- app/controllers/groups_controller.rb | 8 +++--- app/controllers/help_controller.rb | 7 +---- .../oauth/applications_controller.rb | 11 +++----- .../oauth/authorizations_controller.rb | 9 ++----- .../authorized_applications_controller.rb | 12 +++------ .../profiles/application_controller.rb | 10 +------ .../profiles/passwords_controller.rb | 9 ++++--- app/controllers/projects_controller.rb | 5 ---- app/controllers/search_controller.rb | 9 +------ app/controllers/snippets_controller.rb | 9 +------ app/helpers/application_helper.rb | 8 ------ app/helpers/page_layout_helper.rb | 26 +++++++++++++++++++ app/views/groups/new.html.haml | 2 ++ app/views/layouts/admin.html.haml | 5 ++++ app/views/layouts/application.html.haml | 11 +++----- app/views/layouts/dashboard.html.haml | 5 ++++ app/views/layouts/explore.html.haml | 5 ++++ app/views/layouts/group.html.haml | 5 ++++ app/views/layouts/help.html.haml | 4 +++ app/views/layouts/profile.html.haml | 5 ++++ app/views/layouts/project.html.haml | 20 +++++--------- app/views/layouts/project_settings.html.haml | 4 ++- app/views/layouts/search.html.haml | 4 +++ app/views/layouts/snippets.html.haml | 5 ++++ app/views/profiles/passwords/new.html.haml | 2 ++ app/views/projects/edit.html.haml | 1 - app/views/projects/new.html.haml | 2 ++ 33 files changed, 112 insertions(+), 129 deletions(-) create mode 100644 app/helpers/page_layout_helper.rb create mode 100644 app/views/layouts/admin.html.haml create mode 100644 app/views/layouts/dashboard.html.haml create mode 100644 app/views/layouts/explore.html.haml create mode 100644 app/views/layouts/group.html.haml create mode 100644 app/views/layouts/help.html.haml create mode 100644 app/views/layouts/profile.html.haml create mode 100644 app/views/layouts/search.html.haml create mode 100644 app/views/layouts/snippets.html.haml diff --git a/app/assets/javascripts/dispatcher.js.coffee b/app/assets/javascripts/dispatcher.js.coffee index 9aee3b281f..06787ddf87 100644 --- a/app/assets/javascripts/dispatcher.js.coffee +++ b/app/assets/javascripts/dispatcher.js.coffee @@ -8,7 +8,6 @@ class Dispatcher initPageScripts: -> page = $('body').attr('data-page') - project_id = $('body').attr('data-project-id') unless page return false diff --git a/app/controllers/admin/application_controller.rb b/app/controllers/admin/application_controller.rb index cfbeb035c0..56e2438646 100644 --- a/app/controllers/admin/application_controller.rb +++ b/app/controllers/admin/application_controller.rb @@ -3,15 +3,9 @@ # Automatically sets the layout and ensures an administrator is logged in class Admin::ApplicationController < ApplicationController before_action :authenticate_admin! - before_action :set_title + layout 'admin' def authenticate_admin! return render_404 unless current_user.is_admin? end - - def set_title - @title = "Admin area" - @title_url = admin_root_path - @sidebar = "admin" - end end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 69fd790183..c9b34eac4b 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -3,6 +3,7 @@ require 'gon' class ApplicationController < ActionController::Base include Gitlab::CurrentSettings include GitlabRoutingHelper + include PageLayoutHelper PER_PAGE = 20 diff --git a/app/controllers/dashboard/application_controller.rb b/app/controllers/dashboard/application_controller.rb index 0a0af3d4ce..962ea38d6c 100644 --- a/app/controllers/dashboard/application_controller.rb +++ b/app/controllers/dashboard/application_controller.rb @@ -1,11 +1,3 @@ class Dashboard::ApplicationController < ApplicationController - before_action :set_title - - private - - def set_title - @title = "Dashboard" - @title_url = root_path - @sidebar = "dashboard" - end + layout 'dashboard' end diff --git a/app/controllers/explore/application_controller.rb b/app/controllers/explore/application_controller.rb index 8d94fd238a..4b275033d2 100644 --- a/app/controllers/explore/application_controller.rb +++ b/app/controllers/explore/application_controller.rb @@ -1,11 +1,3 @@ class Explore::ApplicationController < ApplicationController - before_action :set_title - - private - - def set_title - @title = "Explore GitLab" - @title_url = explore_root_path - @sidebar = "explore" - end + layout 'explore' end diff --git a/app/controllers/groups/application_controller.rb b/app/controllers/groups/application_controller.rb index e0fd4befae..4df9d1b753 100644 --- a/app/controllers/groups/application_controller.rb +++ b/app/controllers/groups/application_controller.rb @@ -1,5 +1,5 @@ class Groups::ApplicationController < ApplicationController - before_action :set_title + layout 'group' private @@ -18,10 +18,4 @@ class Groups::ApplicationController < ApplicationController return render_404 end end - - def set_title - @title = group.name - @title_url = group_path(group) - @sidebar = "group" - end end diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index 66e92abff8..34f0b257db 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -12,6 +12,8 @@ class GroupsController < Groups::ApplicationController before_action :load_projects, except: [:new, :create, :projects, :edit, :update] before_action :event_filter, only: :show + layout :determine_layout + def new @group = Group.new end @@ -116,11 +118,11 @@ class GroupsController < Groups::ApplicationController end end - def set_title + def determine_layout if [:new, :create].include?(action_name.to_sym) - @title = 'New Group' + 'application' else - super + 'group' end end diff --git a/app/controllers/help_controller.rb b/app/controllers/help_controller.rb index 2842151e3b..8a45dc8860 100644 --- a/app/controllers/help_controller.rb +++ b/app/controllers/help_controller.rb @@ -1,5 +1,5 @@ class HelpController < ApplicationController - before_action :set_title + layout 'help' def index end @@ -46,11 +46,6 @@ class HelpController < ApplicationController private - def set_title - @title = "Help" - @title_url = help_path - end - def path_params params.require(:category) params.require(:file) diff --git a/app/controllers/oauth/applications_controller.rb b/app/controllers/oauth/applications_controller.rb index f30a85564d..507b8290a2 100644 --- a/app/controllers/oauth/applications_controller.rb +++ b/app/controllers/oauth/applications_controller.rb @@ -1,6 +1,9 @@ class Oauth::ApplicationsController < Doorkeeper::ApplicationsController + include PageLayoutHelper + before_action :authenticate_user! - before_action :set_title + + layout 'profile' def index head :forbidden and return @@ -36,10 +39,4 @@ class Oauth::ApplicationsController < Doorkeeper::ApplicationsController rescue_from ActiveRecord::RecordNotFound do |exception| render "errors/not_found", layout: "errors", status: 404 end - - def set_title - @title = "Profile" - @title_url = profile_path - @sidebar = "profile" - end end diff --git a/app/controllers/oauth/authorizations_controller.rb b/app/controllers/oauth/authorizations_controller.rb index c62890ba85..24025d8c72 100644 --- a/app/controllers/oauth/authorizations_controller.rb +++ b/app/controllers/oauth/authorizations_controller.rb @@ -1,6 +1,7 @@ class Oauth::AuthorizationsController < Doorkeeper::AuthorizationsController before_action :authenticate_resource_owner! - before_action :set_title + + layout 'profile' def new if pre_auth.authorizable? @@ -54,10 +55,4 @@ class Oauth::AuthorizationsController < Doorkeeper::AuthorizationsController def strategy @strategy ||= server.authorization_request(pre_auth.response_type) end - - def set_title - @title = "Profile" - @title_url = profile_path - @sidebar = "profile" - end end diff --git a/app/controllers/oauth/authorized_applications_controller.rb b/app/controllers/oauth/authorized_applications_controller.rb index 63c634f376..3ab6def511 100644 --- a/app/controllers/oauth/authorized_applications_controller.rb +++ b/app/controllers/oauth/authorized_applications_controller.rb @@ -1,16 +1,10 @@ class Oauth::AuthorizedApplicationsController < Doorkeeper::AuthorizedApplicationsController - before_action :set_title + include PageLayoutHelper + + layout 'profile' def destroy Doorkeeper::AccessToken.revoke_all_for(params[:id], current_resource_owner) redirect_to applications_profile_url, notice: I18n.t(:notice, scope: [:doorkeeper, :flash, :authorized_applications, :destroy]) end - - private - - def set_title - @title = "Profile" - @title_url = profile_path - @sidebar = "profile" - end end diff --git a/app/controllers/profiles/application_controller.rb b/app/controllers/profiles/application_controller.rb index 8373ff7a75..c8be288b9a 100644 --- a/app/controllers/profiles/application_controller.rb +++ b/app/controllers/profiles/application_controller.rb @@ -1,11 +1,3 @@ class Profiles::ApplicationController < ApplicationController - before_action :set_title - - private - - def set_title - @title = "Profile" - @title_url = profile_path - @sidebar = "profile" - end + layout 'profile' end diff --git a/app/controllers/profiles/passwords_controller.rb b/app/controllers/profiles/passwords_controller.rb index 86976ae39e..c780e0983f 100644 --- a/app/controllers/profiles/passwords_controller.rb +++ b/app/controllers/profiles/passwords_controller.rb @@ -2,9 +2,10 @@ class Profiles::PasswordsController < Profiles::ApplicationController skip_before_action :check_password_expiration, only: [:new, :create] before_action :set_user - before_action :set_title before_action :authorize_change_password! + layout :determine_layout + def new end @@ -64,11 +65,11 @@ class Profiles::PasswordsController < Profiles::ApplicationController @user = current_user end - def set_title + def determine_layout if [:new, :create].include?(action_name.to_sym) - @title = "New password" + 'application' else - super + 'profile' end end diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index da6b0c3c91..dc43035155 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -6,7 +6,6 @@ class ProjectsController < ApplicationController # Authorize before_action :authorize_admin_project!, only: [:edit, :update, :destroy, :transfer, :archive, :unarchive] - before_action :set_title, only: [:new, :create] before_action :event_filter, only: :show layout :determine_layout @@ -160,10 +159,6 @@ class ProjectsController < ApplicationController private - def set_title - @title = 'New Project' - end - def determine_layout if [:new, :create].include?(action_name.to_sym) 'application' diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb index ba6f2a41fd..4e2ea6c571 100644 --- a/app/controllers/search_controller.rb +++ b/app/controllers/search_controller.rb @@ -1,7 +1,7 @@ class SearchController < ApplicationController include SearchHelper - before_action :set_title + layout 'search' def show return if params[:search].nil? || params[:search].blank? @@ -57,11 +57,4 @@ class SearchController < ApplicationController render json: search_autocomplete_opts(term).to_json end - - private - - def set_title - @title = "Search" - @title_url = search_path - end end diff --git a/app/controllers/snippets_controller.rb b/app/controllers/snippets_controller.rb index c960724b47..cf672c5c09 100644 --- a/app/controllers/snippets_controller.rb +++ b/app/controllers/snippets_controller.rb @@ -7,10 +7,9 @@ class SnippetsController < ApplicationController # Allow destroy snippet before_action :authorize_admin_snippet!, only: [:destroy] - before_action :set_title - skip_before_action :authenticate_user!, only: [:index, :user_index, :show, :raw] + layout 'snippets' respond_to :html def index @@ -96,12 +95,6 @@ class SnippetsController < ApplicationController return render_404 unless can?(current_user, :admin_personal_snippet, @snippet) end - def set_title - @title = 'Snippets' - @title_url = snippets_path - @sidebar = "snippets" - end - def snippet_params params.require(:personal_snippet).permit(:title, :content, :file_name, :private, :visibility_level) end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 399e49e352..6e86400a4f 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -332,12 +332,4 @@ module ApplicationHelper end "#{entity_title}#{count}" end - - def page_title(*titles) - @page_title ||= [] - - @page_title.push(*titles.compact) if titles.any? - - @page_title.join(" | ") - end end diff --git a/app/helpers/page_layout_helper.rb b/app/helpers/page_layout_helper.rb new file mode 100644 index 0000000000..01b6a63552 --- /dev/null +++ b/app/helpers/page_layout_helper.rb @@ -0,0 +1,26 @@ +module PageLayoutHelper + def page_title(*titles) + @page_title ||= [] + + @page_title.push(*titles.compact) if titles.any? + + @page_title.join(" | ") + end + + def header_title(title = nil, title_url = nil) + if title + @header_title = title + @header_title_url = title_url + else + @header_title_url ? link_to(@header_title, @header_title_url) : @header_title + end + end + + def sidebar(name = nil) + if name + @sidebar = name + else + @sidebar + end + end +end diff --git a/app/views/groups/new.html.haml b/app/views/groups/new.html.haml index 6e17cdaef6..edb882bea1 100644 --- a/app/views/groups/new.html.haml +++ b/app/views/groups/new.html.haml @@ -1,3 +1,5 @@ +- page_title 'New Group' +- header_title 'New Group' = form_for @group, html: { class: 'group-form form-horizontal' } do |f| - if @group.errors.any? .alert.alert-danger diff --git a/app/views/layouts/admin.html.haml b/app/views/layouts/admin.html.haml new file mode 100644 index 0000000000..1c738719bd --- /dev/null +++ b/app/views/layouts/admin.html.haml @@ -0,0 +1,5 @@ +- page_title "Admin area" +- header_title "Admin area", admin_root_path +- sidebar "admin" + += render template: "layouts/application" diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index e0829d40bc..a97feeb1ec 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -1,13 +1,10 @@ -- page_title @title !!! 5 %html{ lang: "en"} = render "layouts/head" - %body{class: "#{app_theme} application", :'data-page' => body_data_page} - - title = defined?(@title_url) ? link_to(@title, @title_url) : @title - + %body{class: "#{app_theme}", :'data-page' => body_data_page} - if current_user - = render "layouts/head_panel", title: title + = render "layouts/head_panel", title: header_title - else - = render "layouts/public_head_panel", title: title + = render "layouts/public_head_panel", title: header_title - = render 'layouts/page', sidebar: @sidebar + = render 'layouts/page', sidebar: sidebar diff --git a/app/views/layouts/dashboard.html.haml b/app/views/layouts/dashboard.html.haml new file mode 100644 index 0000000000..c72eca10bf --- /dev/null +++ b/app/views/layouts/dashboard.html.haml @@ -0,0 +1,5 @@ +- page_title "Dashboard" +- header_title "Dashboard", root_path +- sidebar "dashboard" + += render template: "layouts/application" diff --git a/app/views/layouts/explore.html.haml b/app/views/layouts/explore.html.haml new file mode 100644 index 0000000000..56bb92a536 --- /dev/null +++ b/app/views/layouts/explore.html.haml @@ -0,0 +1,5 @@ +- page_title "Explore" +- header_title "Explore GitLab", explore_root_path +- sidebar "explore" + += render template: "layouts/application" diff --git a/app/views/layouts/group.html.haml b/app/views/layouts/group.html.haml new file mode 100644 index 0000000000..5edc03129d --- /dev/null +++ b/app/views/layouts/group.html.haml @@ -0,0 +1,5 @@ +- page_title @group.name +- header_title @group.name, group_path(@group) +- sidebar "group" + += render template: "layouts/application" diff --git a/app/views/layouts/help.html.haml b/app/views/layouts/help.html.haml new file mode 100644 index 0000000000..224b24befb --- /dev/null +++ b/app/views/layouts/help.html.haml @@ -0,0 +1,4 @@ +- page_title "Help" +- header_title "Help", help_path + += render template: "layouts/application" diff --git a/app/views/layouts/profile.html.haml b/app/views/layouts/profile.html.haml new file mode 100644 index 0000000000..9799b4cc4d --- /dev/null +++ b/app/views/layouts/profile.html.haml @@ -0,0 +1,5 @@ +- page_title "Profile" +- header_title "Profile", profile_path +- sidebar "profile" + += render template: "layouts/application" diff --git a/app/views/layouts/project.html.haml b/app/views/layouts/project.html.haml index 62a6f5ddf4..4aeb9d397d 100644 --- a/app/views/layouts/project.html.haml +++ b/app/views/layouts/project.html.haml @@ -1,14 +1,8 @@ -- page_title @project.name_with_namespace -!!! 5 -%html{ lang: "en"} - = render "layouts/head" - %body{class: "#{app_theme} project", :'data-page' => body_data_page, :'data-project-id' => @project.id } - - title = project_title(@project) +- page_title @project.name_with_namespace +- header_title project_title(@project) +- sidebar "project" unless sidebar - - if current_user - = render "layouts/head_panel", title: project_title(@project) - = render "layouts/init_auto_complete" - - else - = render "layouts/public_head_panel", title: project_title(@project) - - = render 'layouts/page', sidebar: @sidebar || 'project' +- content_for :embedded_scripts do + = render "layouts/init_auto_complete" if current_user + += render template: "layouts/application" diff --git a/app/views/layouts/project_settings.html.haml b/app/views/layouts/project_settings.html.haml index d12d07273f..4340166833 100644 --- a/app/views/layouts/project_settings.html.haml +++ b/app/views/layouts/project_settings.html.haml @@ -1,2 +1,4 @@ -- @sidebar = "project_settings" +- page_title "Settings" +- sidebar "project_settings" + = render template: "layouts/project" diff --git a/app/views/layouts/search.html.haml b/app/views/layouts/search.html.haml new file mode 100644 index 0000000000..fd4c7ad21a --- /dev/null +++ b/app/views/layouts/search.html.haml @@ -0,0 +1,4 @@ +- page_title "Search" +- header_title "Search", search_path + += render template: "layouts/application" diff --git a/app/views/layouts/snippets.html.haml b/app/views/layouts/snippets.html.haml new file mode 100644 index 0000000000..9b0f40073a --- /dev/null +++ b/app/views/layouts/snippets.html.haml @@ -0,0 +1,5 @@ +- page_title 'Snippets' +- header_title 'Snippets', snippets_path +- sidebar "snippets" + += render template: "layouts/application" diff --git a/app/views/profiles/passwords/new.html.haml b/app/views/profiles/passwords/new.html.haml index 8bed6e0dbe..9c6204963e 100644 --- a/app/views/profiles/passwords/new.html.haml +++ b/app/views/profiles/passwords/new.html.haml @@ -1,3 +1,5 @@ +- page_title "New Password" +- header_title "New Password" %h3.page-title Setup new password %hr = form_for @user, url: profile_password_path, method: :post, html: { class: 'form-horizontal '} do |f| diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml index 1fe6a24e89..c09d794ef7 100644 --- a/app/views/projects/edit.html.haml +++ b/app/views/projects/edit.html.haml @@ -1,4 +1,3 @@ -- page_title "Settings" .project-edit-container .project-edit-errors .project-edit-content diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml index 47c69f89a9..e56d861513 100644 --- a/app/views/projects/new.html.haml +++ b/app/views/projects/new.html.haml @@ -1,3 +1,5 @@ +- page_title 'New Project' +- header_title 'New Project' .project-edit-container .project-edit-errors = render 'projects/errors' From a2eee3181c6b0fc3ef8b95f3187704a2b12774e4 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Fri, 1 May 2015 11:33:54 +0200 Subject: [PATCH 80/97] Fix title on user page. --- app/controllers/users_controller.rb | 3 --- app/views/users/show.html.haml | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 7285098435..2bb5c338cf 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -12,9 +12,6 @@ class UsersController < ApplicationController # Collect only groups common for both users @groups = @user.groups & GroupsFinder.new.execute(current_user) - @title = @user.name - @title_url = user_path(@user) - respond_to do |format| format.html diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml index 0576c6a11b..6ed45fedfa 100644 --- a/app/views/users/show.html.haml +++ b/app/views/users/show.html.haml @@ -1,3 +1,6 @@ +- page_title @user.name +- header_title @user.name, user_path(@user) + = content_for :meta_tags do = auto_discovery_link_tag(:atom, user_url(@user, format: :atom), title: "#{@user.name} activity") From 99fcf2e6feaa5ec72a2608162251903c1b1a4c07 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Fri, 1 May 2015 13:29:36 -0400 Subject: [PATCH 81/97] Improve/add specs for `Project#get_issue` and `#issue_exists?` --- app/models/project.rb | 2 +- spec/models/project_spec.rb | 61 +++++++++++++++++++++++++------------ 2 files changed, 43 insertions(+), 20 deletions(-) diff --git a/app/models/project.rb b/app/models/project.rb index c940021d57..e866681aab 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -338,7 +338,7 @@ class Project < ActiveRecord::Base end def issue_exists?(issue_id) - get_issue(issue_id).present? + get_issue(issue_id) end def default_issue_tracker diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 879a63dd9f..37e21a9081 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -129,6 +129,48 @@ describe Project do end end + describe '#get_issue' do + let(:project) { create(:empty_project) } + let(:issue) { create(:issue, project: project) } + + context 'with default issues tracker' do + it 'returns an issue' do + expect(project.get_issue(issue.iid)).to eq issue + end + + it 'returns nil when no issue found' do + expect(project.get_issue(999)).to be_nil + end + end + + context 'with external issues tracker' do + before do + allow(project).to receive(:default_issues_tracker?).and_return(false) + end + + it 'returns an ExternalIssue' do + issue = project.get_issue('FOO-1234') + expect(issue).to be_kind_of(ExternalIssue) + expect(issue.iid).to eq 'FOO-1234' + expect(issue.project).to eq project + end + end + end + + describe '#issue_exists?' do + let(:project) { create(:empty_project) } + + it 'is truthy when issue exists' do + expect(project).to receive(:get_issue).and_return(double) + expect(project.issue_exists?(1)).to be_truthy + end + + it 'is falsey when issue does not exist' do + expect(project).to receive(:get_issue).and_return(nil) + expect(project.issue_exists?(1)).to be_falsey + end + end + describe :update_merge_requests do let(:project) { create(:project) } let(:merge_request) { create(:merge_request, source_project: project, target_project: project) } @@ -180,25 +222,6 @@ describe Project do end end - describe :issue_exists? do - let(:project) { create(:project) } - let(:existed_issue) { create(:issue, project: project) } - let(:not_existed_issue) { create(:issue) } - let(:ext_project) { create(:redmine_project) } - - it 'should be true or if used internal tracker and issue exists' do - expect(project.issue_exists?(existed_issue.iid)).to be_truthy - end - - it 'should be false or if used internal tracker and issue not exists' do - expect(project.issue_exists?(not_existed_issue.iid)).to be_falsey - end - - it 'should always be true if used other tracker' do - expect(ext_project.issue_exists?(rand(100))).to be_truthy - end - end - describe :default_issues_tracker? do let(:project) { create(:project) } let(:ext_project) { create(:redmine_project) } From 4dda17a5bfe93e06f416fd4e33d487daee41731e Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Fri, 1 May 2015 17:12:54 -0700 Subject: [PATCH 82/97] Make Reply-To config apply to change e-mail confirmation and other notifications sent through Devise Fix test case that was passing due to a broken `around` statement. Closes #1556 --- CHANGELOG | 1 + app/mailers/devise_mailer.rb | 4 ++++ config/initializers/devise.rb | 7 +------ spec/mailers/notify_spec.rb | 3 +-- 4 files changed, 7 insertions(+), 8 deletions(-) create mode 100644 app/mailers/devise_mailer.rb diff --git a/CHANGELOG b/CHANGELOG index 2364cf5d7f..218c62e3b9 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ Please view this file on the master branch, on stable branches it's out of date. v 7.11.0 (unreleased) + - Make Reply-To config apply to change e-mail confirmation and other Devise notifications (Stan Hu) - Don't allow a merge request to be merged when its title starts with "WIP". - Get Gitorious importer to work again. - Fix clone URL field and X11 Primary selection (Dmitry Medvinsky) diff --git a/app/mailers/devise_mailer.rb b/app/mailers/devise_mailer.rb new file mode 100644 index 0000000000..5395fe1641 --- /dev/null +++ b/app/mailers/devise_mailer.rb @@ -0,0 +1,4 @@ +class DeviseMailer < Devise::Mailer + default from: "GitLab <#{Gitlab.config.gitlab.email_from}>" + default reply_to: Gitlab.config.gitlab.email_reply_to +end diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index 9dce495106..8f8c416974 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -2,13 +2,8 @@ # four configuration values can also be set straight in your models. Devise.setup do |config| # ==> Mailer Configuration - # Configure the e-mail address which will be shown in Devise::Mailer, - # note that it will be overwritten if you use your own mailer class with default "from" parameter. - config.mailer_sender = "GitLab <#{Gitlab.config.gitlab.email_from}>" - - # Configure the class responsible to send e-mails. - # config.mailer = "Devise::Mailer" + config.mailer = "DeviseMailer" # ==> ORM configuration # Load and configure the ORM. Supports :active_record (default) and diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb index d28b476854..dbcf7286e4 100644 --- a/spec/mailers/notify_spec.rb +++ b/spec/mailers/notify_spec.rb @@ -11,9 +11,8 @@ describe Notify do let(:recipient) { create(:user, email: 'recipient@example.com') } let(:project) { create(:project) } - around(:each) { ActionMailer::Base.deliveries.clear } - before(:each) do + ActionMailer::Base.deliveries.clear email = recipient.emails.create(email: "notifications@example.com") recipient.update_attribute(:notification_email, email.email) end From 2c544d43c832e816614a9bef35e1899f34b4a53d Mon Sep 17 00:00:00 2001 From: jubianchi Date: Sat, 17 Jan 2015 23:45:39 +0100 Subject: [PATCH 83/97] Query issues, merge requests and milestones with their IID through API --- CHANGELOG | 1 + doc/api/issues.md | 2 ++ doc/api/merge_requests.md | 4 +++- doc/api/milestones.md | 2 ++ lib/api/helpers.rb | 4 ++++ lib/api/issues.rb | 3 +++ lib/api/merge_requests.rb | 16 +++++++++++----- spec/requests/api/issues_spec.rb | 8 ++++++++ spec/requests/api/merge_requests_spec.rb | 8 ++++++++ spec/requests/api/milestones_spec.rb | 7 +++++++ 10 files changed, 49 insertions(+), 6 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 3af83ddc25..b5bacedc48 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -20,6 +20,7 @@ v 7.11.0 (unreleased) - Don't crash when an MR from a fork has a cross-reference comment from the target project on of its commits. - Include commit comments in MR from a forked project. - Fix adding new group members from admin area + - Query issues, merge requests and milestones with their IID through API (Julien Bianchi) - Add default project and snippet visibility settings to the admin web UI. - - Fix bug where commit data would not appear in some subdirectories (Stan Hu) diff --git a/doc/api/issues.md b/doc/api/issues.md index a7dd8b74c3..d407bc35d7 100644 --- a/doc/api/issues.md +++ b/doc/api/issues.md @@ -99,11 +99,13 @@ GET /projects/:id/issues?labels=foo,bar GET /projects/:id/issues?labels=foo,bar&state=opened GET /projects/:id/issues?milestone=1.0.0 GET /projects/:id/issues?milestone=1.0.0&state=opened +GET /projects/:id/issues?iid=42 ``` Parameters: - `id` (required) - The ID of a project +- `iid` (optional) - Return the issue having the given `iid` - `state` (optional) - Return `all` issues or just those that are `opened` or `closed` - `labels` (optional) - Comma-separated list of label names - `milestone` (optional) - Milestone title diff --git a/doc/api/merge_requests.md b/doc/api/merge_requests.md index 6a272539e4..c1d82ad957 100644 --- a/doc/api/merge_requests.md +++ b/doc/api/merge_requests.md @@ -10,11 +10,13 @@ The pagination parameters `page` and `per_page` can be used to restrict the list GET /projects/:id/merge_requests GET /projects/:id/merge_requests?state=opened GET /projects/:id/merge_requests?state=all +GET /projects/:id/merge_requests?iid=42 ``` Parameters: - `id` (required) - The ID of a project +- `iid` (optional) - Return the request having the given `iid` - `state` (optional) - Return `all` requests or just those that are `merged`, `opened` or `closed` - `order_by` (optional) - Return requests ordered by `created_at` or `updated_at` fields. Default is `created_at` - `sort` (optional) - Return requests sorted in `asc` or `desc` order. Default is `desc` @@ -388,6 +390,6 @@ Parameters: ] ``` -## Comments on issues +## Comments on merge requets Comments are done via the notes resource. diff --git a/doc/api/milestones.md b/doc/api/milestones.md index d48b3bcce8..a682872826 100644 --- a/doc/api/milestones.md +++ b/doc/api/milestones.md @@ -6,6 +6,7 @@ Returns a list of project milestones. ``` GET /projects/:id/milestones +GET /projects/:id/milestones?iid=42 ``` ```json @@ -27,6 +28,7 @@ GET /projects/:id/milestones Parameters: - `id` (required) - The ID of a project +- `iid` (optional) - Return the milestone having the given `iid` ## Get single milestone diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb index be133a2920..85e9081680 100644 --- a/lib/api/helpers.rb +++ b/lib/api/helpers.rb @@ -173,6 +173,10 @@ module API end end + def filter_by_iid(items, iid) + items.where(iid: iid) + end + # error helpers def forbidden!(reason = nil) diff --git a/lib/api/issues.rb b/lib/api/issues.rb index ff062be604..c8db93eb77 100644 --- a/lib/api/issues.rb +++ b/lib/api/issues.rb @@ -51,6 +51,7 @@ module API # # Parameters: # id (required) - The ID of a project + # iid (optional) - Return the project issue having the given `iid` # state (optional) - Return "opened" or "closed" issues # labels (optional) - Comma-separated list of label names # milestone (optional) - Milestone title @@ -66,10 +67,12 @@ module API # GET /projects/:id/issues?labels=foo,bar&state=opened # GET /projects/:id/issues?milestone=1.0.0 # GET /projects/:id/issues?milestone=1.0.0&state=closed + # GET /issues?iid=42 get ":id/issues" do issues = user_project.issues issues = filter_issues_state(issues, params[:state]) unless params[:state].nil? issues = filter_issues_labels(issues, params[:labels]) unless params[:labels].nil? + issues = filter_by_iid(issues, params[:iid]) unless params[:iid].nil? unless params[:milestone].nil? issues = filter_issues_milestone(issues, params[:milestone]) diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb index b252c57fae..2216a12a87 100644 --- a/lib/api/merge_requests.rb +++ b/lib/api/merge_requests.rb @@ -24,6 +24,7 @@ module API # # Parameters: # id (required) - The ID of a project + # iid (optional) - Return the project MR having the given `iid` # state (optional) - Return requests "merged", "opened" or "closed" # order_by (optional) - Return requests ordered by `created_at` or `updated_at` fields. Default is `created_at` # sort (optional) - Return requests sorted in `asc` or `desc` order. Default is `desc` @@ -36,11 +37,16 @@ module API # GET /projects/:id/merge_requests?order_by=updated_at # GET /projects/:id/merge_requests?sort=desc # GET /projects/:id/merge_requests?sort=asc + # GET /projects/:id/merge_requests?iid=42 # get ":id/merge_requests" do authorize! :read_merge_request, user_project merge_requests = user_project.merge_requests + unless params[:iid].nil? + merge_requests = filter_by_iid(merge_requests, params[:iid]) + end + merge_requests = case params["state"] when "opened" then merge_requests.opened @@ -169,8 +175,8 @@ module API # Merge MR # # Parameters: - # id (required) - The ID of a project - # merge_request_id (required) - ID of MR + # id (required) - The ID of a project + # merge_request_id (required) - ID of MR # merge_commit_message (optional) - Custom merge commit message # Example: # PUT /projects/:id/merge_request/:merge_request_id/merge @@ -209,7 +215,7 @@ module API # Get a merge request's comments # # Parameters: - # id (required) - The ID of a project + # id (required) - The ID of a project # merge_request_id (required) - ID of MR # Examples: # GET /projects/:id/merge_request/:merge_request_id/comments @@ -225,9 +231,9 @@ module API # Post comment to merge request # # Parameters: - # id (required) - The ID of a project + # id (required) - The ID of a project # merge_request_id (required) - ID of MR - # note (required) - Text of comment + # note (required) - Text of comment # Examples: # POST /projects/:id/merge_request/:merge_request_id/comments # diff --git a/spec/requests/api/issues_spec.rb b/spec/requests/api/issues_spec.rb index b6b0427deb..8770786f49 100644 --- a/spec/requests/api/issues_spec.rb +++ b/spec/requests/api/issues_spec.rb @@ -194,6 +194,14 @@ describe API::API, api: true do expect(json_response['iid']).to eq(issue.iid) end + it 'should return a project issue by iid' do + get api("/projects/#{project.id}/issues?iid=#{issue.iid}", user) + response.status.should == 200 + json_response.first['title'].should == issue.title + json_response.first['id'].should == issue.id + json_response.first['iid'].should == issue.iid + end + it "should return 404 if issue id not found" do get api("/projects/#{project.id}/issues/54321", user) expect(response.status).to eq(404) diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb index 5fca831f9b..dcd50f7332 100644 --- a/spec/requests/api/merge_requests_spec.rb +++ b/spec/requests/api/merge_requests_spec.rb @@ -115,6 +115,14 @@ describe API::API, api: true do expect(json_response['iid']).to eq(merge_request.iid) end + it 'should return merge_request by iid' do + url = "/projects/#{project.id}/merge_requests?iid=#{merge_request.iid}" + get api(url, user) + response.status.should == 200 + json_response.first['title'].should == merge_request.title + json_response.first['id'].should == merge_request.id + end + it "should return a 404 error if merge_request_id not found" do get api("/projects/#{project.id}/merge_request/999", user) expect(response.status).to eq(404) diff --git a/spec/requests/api/milestones_spec.rb b/spec/requests/api/milestones_spec.rb index effb072347..6890dd1f3a 100644 --- a/spec/requests/api/milestones_spec.rb +++ b/spec/requests/api/milestones_spec.rb @@ -30,6 +30,13 @@ describe API::API, api: true do expect(json_response['iid']).to eq(milestone.iid) end + it 'should return a project milestone by iid' do + get api("/projects/#{project.id}/milestones?iid=#{milestone.iid}", user) + response.status.should == 200 + json_response.first['title'].should == milestone.title + json_response.first['id'].should == milestone.id + end + it 'should return 401 error if user not authenticated' do get api("/projects/#{project.id}/milestones/#{milestone.id}") expect(response.status).to eq(401) From fc79f7382ce08bf3ad0daa70be6ea0603304f2af Mon Sep 17 00:00:00 2001 From: win32 Date: Sat, 2 May 2015 11:04:07 +0000 Subject: [PATCH 84/97] Update config.yml.example --- config/gitlab.yml.example | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example index ba40671b16..e9d962b190 100644 --- a/config/gitlab.yml.example +++ b/config/gitlab.yml.example @@ -12,6 +12,9 @@ # 2. Update gitlab -> host with your fully qualified domain name # 3. Update gitlab -> email_from # 4. If you installed Git from source, change git -> bin_path to /usr/local/bin/git + IMPORTANT: If Git was installed in a different location use that instead. + You can check with `which git`. If a wrong path of Git is specified, it will + result in various issues such as failures of GitLab CI builds. # 5. Review this configuration file for other settings you may want to adjust production: &base @@ -334,4 +337,4 @@ test: sync_ssh_keys: false staging: - <<: *base + <<: *base \ No newline at end of file From eb4f1eb5f55fe3630c9191db1b9da2dc92437391 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Sat, 2 May 2015 06:53:32 -0700 Subject: [PATCH 85/97] Add application setting to restrict user signups to e-mail domains This feature was requested long ago: http://feedback.gitlab.com/forums/176466-general/suggestions/4118466-ability-to-register-only-from-ceratain-domains This MR is based off !253 but changed to use application settings and use wildcard strings to give more flexibility in pattern matching. Regexps seemed overkill and easy to get wrong. Only restrict e-mail addresses upon creation --- CHANGELOG | 1 + .../admin/application_settings_controller.rb | 3 +- app/models/application_setting.rb | 24 +++++++++- app/models/user.rb | 24 ++++++++++ .../application_settings/_form.html.haml | 5 ++ config/initializers/1_settings.rb | 1 + ..._signup_domains_to_application_settings.rb | 5 ++ db/schema.rb | 3 +- spec/models/application_setting_spec.rb | 24 ++++++++++ spec/models/user_spec.rb | 47 +++++++++++++++++++ 10 files changed, 133 insertions(+), 4 deletions(-) create mode 100644 db/migrate/20150502064022_add_restricted_signup_domains_to_application_settings.rb diff --git a/CHANGELOG b/CHANGELOG index 2c5c9c76cc..dc3a670922 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ Please view this file on the master branch, on stable branches it's out of date. v 7.11.0 (unreleased) + - Add application setting to restrict user signups to e-mail domains (Stan Hu) - Don't allow a merge request to be merged when its title starts with "WIP". - Add a page title to every page. - Get Gitorious importer to work again. diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb index 8f6a766635..3975e30835 100644 --- a/app/controllers/admin/application_settings_controller.rb +++ b/app/controllers/admin/application_settings_controller.rb @@ -41,7 +41,8 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController :max_attachment_size, :default_project_visibility, :default_snippet_visibility, - restricted_visibility_levels: [] + :restricted_signup_domains_raw, + restricted_visibility_levels: [], ) end end diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb index 9406fb9193..f2cebde970 100644 --- a/app/models/application_setting.rb +++ b/app/models/application_setting.rb @@ -18,11 +18,13 @@ # restricted_visibility_levels :text # max_attachment_size :integer default(10) # default_project_visibility :integer -# default_snippet_visibility :integer +# restricted_signup_domains :text # class ApplicationSetting < ActiveRecord::Base serialize :restricted_visibility_levels + serialize :restricted_signup_domains, Array + attr_accessor :restricted_signup_domains_raw validates :home_page_url, allow_blank: true, @@ -55,11 +57,29 @@ class ApplicationSetting < ActiveRecord::Base restricted_visibility_levels: Settings.gitlab['restricted_visibility_levels'], max_attachment_size: Settings.gitlab['max_attachment_size'], default_project_visibility: Settings.gitlab.default_projects_features['visibility_level'], - default_snippet_visibility: Settings.gitlab.default_projects_features['visibility_level'] + default_snippet_visibility: Settings.gitlab.default_projects_features['visibility_level'], + restricted_signup_domains: Settings.gitlab['restricted_signup_domains'] ) end def home_page_url_column_exist ActiveRecord::Base.connection.column_exists?(:application_settings, :home_page_url) end + + def restricted_signup_domains_raw + self.restricted_signup_domains.join("\n") unless self.restricted_signup_domains.nil? + end + + def restricted_signup_domains_raw=(values) + self.restricted_signup_domains = [] + self.restricted_signup_domains = values.split( + /\s*[,;]\s* # comma or semicolon, optionally surrounded by whitespace + | # or + \s # any whitespace character + | # or + [\r\n] # any number of newline characters + /x) + self.restricted_signup_domains.reject! { |d| d.empty? } + end + end diff --git a/app/models/user.rb b/app/models/user.rb index d6b93afe73..f22fdc2843 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -142,6 +142,7 @@ class User < ActiveRecord::Base validates :avatar, file_size: { maximum: 200.kilobytes.to_i } before_validation :generate_password, on: :create + before_validation :restricted_signup_domains, on: :create before_validation :sanitize_attrs before_validation :set_notification_email, if: ->(user) { user.email_changed? } before_validation :set_public_email, if: ->(user) { user.public_email_changed? } @@ -611,4 +612,27 @@ class User < ActiveRecord::Base select(:project_id). uniq.map(&:project_id) end + + def restricted_signup_domains + email_domains = current_application_settings.restricted_signup_domains + + unless email_domains.blank? + match_found = email_domains.any? do |domain| + escaped = Regexp.escape(domain).gsub('\*','.*?') + regexp = Regexp.new "^#{escaped}$", Regexp::IGNORECASE + email_domain = Mail::Address.new(self.email).domain + email_domain =~ regexp + end + + unless match_found + self.errors.add :email, + 'is not whitelisted. ' + + 'Email domains valid for registration are: ' + + email_domains.join(', ') + return false + end + end + + true + end end diff --git a/app/views/admin/application_settings/_form.html.haml b/app/views/admin/application_settings/_form.html.haml index 87e7c9634e..f6eb00ea0b 100644 --- a/app/views/admin/application_settings/_form.html.haml +++ b/app/views/admin/application_settings/_form.html.haml @@ -72,6 +72,11 @@ = f.label :max_attachment_size, 'Maximum attachment size (MB)', class: 'control-label col-sm-2' .col-sm-10 = f.number_field :max_attachment_size, class: 'form-control' + .form-group + = f.label :restricted_signup_domains, 'Restricted domains for sign-ups', class: 'control-label col-sm-2' + .col-sm-10 + = f.text_area :restricted_signup_domains_raw, placeholder: 'domain.com', class: 'form-control' + .help-block Ex: domain.com, *.domain.com. Wildcards allowed. Use separate lines for multiple entries. .form-actions = f.submit 'Save', class: 'btn btn-primary' diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb index 0abd34fc3e..e5ac66a232 100644 --- a/config/initializers/1_settings.rb +++ b/config/initializers/1_settings.rb @@ -132,6 +132,7 @@ Settings.gitlab.default_projects_features['wiki'] = true if Settings.g Settings.gitlab.default_projects_features['snippets'] = false if Settings.gitlab.default_projects_features['snippets'].nil? Settings.gitlab.default_projects_features['visibility_level'] = Settings.send(:verify_constant, Gitlab::VisibilityLevel, Settings.gitlab.default_projects_features['visibility_level'], Gitlab::VisibilityLevel::PRIVATE) Settings.gitlab['repository_downloads_path'] = File.absolute_path(Settings.gitlab['repository_downloads_path'] || 'tmp/repositories', Rails.root) +Settings.gitlab['restricted_signup_domains'] ||= [] # # Gravatar diff --git a/db/migrate/20150502064022_add_restricted_signup_domains_to_application_settings.rb b/db/migrate/20150502064022_add_restricted_signup_domains_to_application_settings.rb new file mode 100644 index 0000000000..184e265361 --- /dev/null +++ b/db/migrate/20150502064022_add_restricted_signup_domains_to_application_settings.rb @@ -0,0 +1,5 @@ +class AddRestrictedSignupDomainsToApplicationSettings < ActiveRecord::Migration + def change + add_column :application_settings, :restricted_signup_domains, :text + end +end diff --git a/db/schema.rb b/db/schema.rb index 02882186fc..f0cccb8b74 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: 20150429002313) do +ActiveRecord::Schema.define(version: 20150502064022) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -31,6 +31,7 @@ ActiveRecord::Schema.define(version: 20150429002313) do t.integer "max_attachment_size", default: 10, null: false t.integer "default_project_visibility" t.integer "default_snippet_visibility" + t.text "restricted_signup_domains" end create_table "broadcast_messages", force: true do |t| diff --git a/spec/models/application_setting_spec.rb b/spec/models/application_setting_spec.rb index b4f0b2c201..876502d03c 100644 --- a/spec/models/application_setting_spec.rb +++ b/spec/models/application_setting_spec.rb @@ -21,4 +21,28 @@ require 'spec_helper' describe ApplicationSetting, models: true do it { expect(ApplicationSetting.create_from_defaults).to be_valid } + + context 'restricted signup domains' do + let(:setting) { ApplicationSetting.create_from_defaults } + + it 'set single domain' do + setting.restricted_signup_domains_raw = 'example.com' + expect(setting.restricted_signup_domains).to eq(['example.com']) + end + + it 'set multiple domains with spaces' do + setting.restricted_signup_domains_raw = 'example.com *.example.com' + expect(setting.restricted_signup_domains).to eq(['example.com', '*.example.com']) + end + + it 'set multiple domains with newlines and a space' do + setting.restricted_signup_domains_raw = "example.com\n *.example.com" + expect(setting.restricted_signup_domains).to eq(['example.com', '*.example.com']) + end + + it 'set multiple domains with commas' do + setting.restricted_signup_domains_raw = "example.com, *.example.com" + expect(setting.restricted_signup_domains).to eq(['example.com', '*.example.com']) + end + end end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 24384e8bf2..441aa79313 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -54,6 +54,8 @@ require 'spec_helper' describe User do + include Gitlab::CurrentSettings + describe "Associations" do it { is_expected.to have_one(:namespace) } it { is_expected.to have_many(:snippets).class_name('Snippet').dependent(:destroy) } @@ -112,6 +114,51 @@ describe User do user = build(:user, email: "lol!'+=?><#$%^&*()@gmail.com") expect(user).to be_invalid end + + context 'when no signup domains listed' do + before { allow(current_application_settings).to receive(:restricted_signup_domains).and_return([]) } + it 'accepts any email' do + user = build(:user, email: "info@example.com") + expect(user).to be_valid + end + end + + context 'when a signup domain is listed and subdomains are allowed' do + before { allow(current_application_settings).to receive(:restricted_signup_domains).and_return(['example.com', '*.example.com']) } + it 'accepts info@example.com' do + user = build(:user, email: "info@example.com") + expect(user).to be_valid + end + + it 'accepts info@test.example.com' do + user = build(:user, email: "info@test.example.com") + expect(user).to be_valid + end + + it 'rejects example@test.com' do + user = build(:user, email: "example@test.com") + expect(user).to be_invalid + end + end + + context 'when a signup domain is listed and subdomains are not allowed' do + before { allow(current_application_settings).to receive(:restricted_signup_domains).and_return(['example.com']) } + + it 'accepts info@example.com' do + user = build(:user, email: "info@example.com") + expect(user).to be_valid + end + + it 'rejects info@test.example.com' do + user = build(:user, email: "info@test.example.com") + expect(user).to be_invalid + end + + it 'rejects example@test.com' do + user = build(:user, email: "example@test.com") + expect(user).to be_invalid + end + end end end From 1c49809bf89e6e0ebe869476044e9e6dda4a0545 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Sat, 2 May 2015 16:01:33 -0400 Subject: [PATCH 86/97] Don't delete gitlab-test-fork folder after every test run --- spec/support/test_env.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spec/support/test_env.rb b/spec/support/test_env.rb index d1844bd2b8..6d4a806791 100644 --- a/spec/support/test_env.rb +++ b/spec/support/test_env.rb @@ -35,6 +35,7 @@ module TestEnv # Create repository for FactoryGirl.create(:project) setup_factory_repo + # Create repository for FactoryGirl.create(:forked_project_with_submodules) setup_forked_repo end @@ -54,7 +55,7 @@ module TestEnv tmp_test_path = Rails.root.join('tmp', 'tests', '**') Dir[tmp_test_path].each do |entry| - unless File.basename(entry) =~ /\Agitlab-(shell|test)\z/ + unless File.basename(entry) =~ /\Agitlab-(shell|test|test-fork)\z/ FileUtils.rm_rf(entry) end end From 0ae574007d2118fc6e291591121ceca2da6fc22e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Onur=20K=C3=BC=C3=A7=C3=BCk?= Date: Sun, 3 May 2015 00:43:46 +0300 Subject: [PATCH 87/97] add common method to force utf8 and force oauth properties to be utf8 --- CHANGELOG | 1 + lib/gitlab/o_auth/auth_hash.rb | 19 ++-- lib/gitlab/utils.rb | 4 + spec/lib/gitlab/o_auth/auth_hash_spec.rb | 111 +++++++++++++++++------ 4 files changed, 100 insertions(+), 35 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 3af83ddc25..a58a5cca96 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -27,6 +27,7 @@ v 7.11.0 (unreleased) - Move snippets UI to fluid layout - Improve UI for sidebar. Increase separation between navigation and content - Improve new project command options (Ben Bodenmiller) + - Add common method to force UTF-8 and use it to properly handle non-ascii OAuth user properties (Onur Küçük) - Prevent sending empty messages to HipChat (Chulki Lee) - Improve UI for mobile phones on dashboard and project pages - Add room notification and message color option for HipChat diff --git a/lib/gitlab/o_auth/auth_hash.rb b/lib/gitlab/o_auth/auth_hash.rb index ce52beec78..0f16c92590 100644 --- a/lib/gitlab/o_auth/auth_hash.rb +++ b/lib/gitlab/o_auth/auth_hash.rb @@ -9,11 +9,11 @@ module Gitlab end def uid - auth_hash.uid.to_s + Gitlab::Utils.force_utf8(auth_hash.uid.to_s) end def provider - auth_hash.provider + Gitlab::Utils.force_utf8(auth_hash.provider.to_s) end def info @@ -21,23 +21,28 @@ module Gitlab end def name - (info.try(:name) || full_name).to_s.force_encoding('utf-8') + Gitlab::Utils.force_utf8((info.try(:name) || full_name).to_s) end def full_name - "#{info.first_name} #{info.last_name}" + Gitlab::Utils.force_utf8("#{info.first_name} #{info.last_name}") end def username - (info.try(:nickname) || generate_username).to_s.force_encoding('utf-8') + Gitlab::Utils.force_utf8( + (info.try(:nickname) || generate_username).to_s + ) end def email - (info.try(:email) || generate_temporarily_email).downcase + Gitlab::Utils.force_utf8( + (info.try(:email) || generate_temporarily_email).downcase + ) end def password - @password ||= Devise.friendly_token[0, 8].downcase + devise_friendly_token = Devise.friendly_token[0, 8].downcase + @password ||= Gitlab::Utils.force_utf8(devise_friendly_token) end # Get the first part of the email address (before @) diff --git a/lib/gitlab/utils.rb b/lib/gitlab/utils.rb index bd184c2718..d13fe0ef8a 100644 --- a/lib/gitlab/utils.rb +++ b/lib/gitlab/utils.rb @@ -9,5 +9,9 @@ module Gitlab def system_silent(cmd) Popen::popen(cmd).last.zero? end + + def force_utf8(str) + str.force_encoding(Encoding::UTF_8) + end end end diff --git a/spec/lib/gitlab/o_auth/auth_hash_spec.rb b/spec/lib/gitlab/o_auth/auth_hash_spec.rb index 5eb77b492b..678086ffa1 100644 --- a/spec/lib/gitlab/o_auth/auth_hash_spec.rb +++ b/spec/lib/gitlab/o_auth/auth_hash_spec.rb @@ -2,54 +2,109 @@ require 'spec_helper' describe Gitlab::OAuth::AuthHash do let(:auth_hash) do - Gitlab::OAuth::AuthHash.new(double({ - provider: 'twitter', - uid: uid, - info: double(info_hash) - })) + Gitlab::OAuth::AuthHash.new( + double({ + provider: provider_ascii, + uid: uid_ascii, + info: double(info_hash) + }) + ) end - let(:uid) { 'my-uid' } - let(:email) { 'my-email@example.com' } - let(:nickname) { 'my-nickname' } + + let(:uid_raw) { + "CN=Onur K\xC3\xBC\xC3\xA7\xC3\xBCk,OU=Test,DC=example,DC=net" + } + let(:email_raw) { "onur.k\xC3\xBC\xC3\xA7\xC3\xBCk@example.net" } + let(:nickname_raw) { "ok\xC3\xBC\xC3\xA7\xC3\xBCk" } + let(:first_name_raw) { 'Onur' } + let(:last_name_raw) { "K\xC3\xBC\xC3\xA7\xC3\xBCk" } + let(:name_raw) { "Onur K\xC3\xBC\xC3\xA7\xC3\xBCk" } + + let(:provider_ascii) { 'ldap'.force_encoding(Encoding::ASCII_8BIT) } + let(:uid_ascii) { uid_raw.force_encoding(Encoding::ASCII_8BIT) } + let(:email_ascii) { email_raw.force_encoding(Encoding::ASCII_8BIT) } + let(:nickname_ascii) { nickname_raw.force_encoding(Encoding::ASCII_8BIT) } + let(:first_name_ascii) { first_name_raw.force_encoding(Encoding::ASCII_8BIT) } + let(:last_name_ascii) { last_name_raw.force_encoding(Encoding::ASCII_8BIT) } + let(:name_ascii) { name_raw.force_encoding(Encoding::ASCII_8BIT) } + + let(:provider_utf8) { provider_ascii.force_encoding(Encoding::UTF_8) } + let(:uid_utf8) { uid_ascii.force_encoding(Encoding::UTF_8) } + let(:email_utf8) { email_ascii.force_encoding(Encoding::UTF_8) } + let(:nickname_utf8) { nickname_ascii.force_encoding(Encoding::UTF_8) } + let(:name_utf8) { name_ascii.force_encoding(Encoding::UTF_8) } + let(:info_hash) { { - email: email, - nickname: nickname, - name: 'John', - first_name: "John", - last_name: "Who" + email: email_ascii, + first_name: first_name_ascii, + last_name: last_name_ascii, + name: name_ascii, + nickname: nickname_ascii, + uid: uid_ascii } } - context "defaults" do - it { expect(auth_hash.provider).to eql 'twitter' } - it { expect(auth_hash.uid).to eql uid } - it { expect(auth_hash.email).to eql email } - it { expect(auth_hash.username).to eql nickname } - it { expect(auth_hash.name).to eql "John" } + context 'defaults' do + it { expect(auth_hash.provider).to eql provider_utf8 } + it { expect(auth_hash.uid).to eql uid_utf8 } + it { expect(auth_hash.email).to eql email_utf8 } + it { expect(auth_hash.username).to eql nickname_utf8 } + it { expect(auth_hash.name).to eql name_utf8 } it { expect(auth_hash.password).to_not be_empty } end - context "email not provided" do + context 'email not provided' do before { info_hash.delete(:email) } - it "generates a temp email" do + + it 'generates a temp email' do expect( auth_hash.email).to start_with('temp-email-for-oauth') end end - context "username not provided" do + context 'username not provided' do before { info_hash.delete(:nickname) } - it "takes the first part of the email as username" do - expect( auth_hash.username ).to eql "my-email" + it 'takes the first part of the email as username' do + expect(auth_hash.username).to eql 'onur-kucuk' end end - context "name not provided" do + context 'name not provided' do before { info_hash.delete(:name) } - it "concats first and lastname as the name" do - expect( auth_hash.name ).to eql "John Who" + it 'concats first and lastname as the name' do + expect(auth_hash.name).to eql name_utf8 end end -end \ No newline at end of file + + context 'auth_hash constructed with ASCII-8BIT encoding' do + it 'forces utf8 encoding on uid' do + auth_hash.uid.encoding.should eql Encoding::UTF_8 + end + + it 'forces utf8 encoding on provider' do + auth_hash.provider.encoding.should eql Encoding::UTF_8 + end + + it 'forces utf8 encoding on name' do + auth_hash.name.encoding.should eql Encoding::UTF_8 + end + + it 'forces utf8 encoding on full_name' do + auth_hash.full_name.encoding.should eql Encoding::UTF_8 + end + + it 'forces utf8 encoding on username' do + auth_hash.username.encoding.should eql Encoding::UTF_8 + end + + it 'forces utf8 encoding on email' do + auth_hash.email.encoding.should eql Encoding::UTF_8 + end + + it 'forces utf8 encoding on password' do + auth_hash.password.encoding.should eql Encoding::UTF_8 + end + end +end From 297efc4ed78c9e7676de5fe9dabdf5f5331e3a61 Mon Sep 17 00:00:00 2001 From: Ben Bodenmiller Date: Sun, 3 May 2015 03:18:29 -0700 Subject: [PATCH 88/97] add missing word to changelog --- CHANGELOG | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 104d3869f9..36f1986a27 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -21,7 +21,7 @@ v 7.11.0 (unreleased) - - Show Atom feed buttons everywhere where applicable. - Add project activity atom feed. - - Don't crash when an MR from a fork has a cross-reference comment from the target project on of its commits. + - Don't crash when an MR from a fork has a cross-reference comment from the target project on one of its commits. - Include commit comments in MR from a forked project. - Fix adding new group members from admin area - Add default project and snippet visibility settings to the admin web UI. From 78aadc933627c1e990fb00666ade07d18d4caf11 Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Sun, 3 May 2015 14:56:00 +0200 Subject: [PATCH 89/97] Add snippet visibilty as parameter to API doc, closes #1562 --- doc/api/project_snippets.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/doc/api/project_snippets.md b/doc/api/project_snippets.md index 50e134847c..a7acf37b5b 100644 --- a/doc/api/project_snippets.md +++ b/doc/api/project_snippets.md @@ -1,5 +1,18 @@ # Project snippets +### Snippet visibility level + +Snippets in GitLab can be either private, internal or public. +You can set it with the `visibility_level` field in the snippet. + +Constants for snippet visibility levels are: + +| Visibility | visibility_level | Description | +| ---------- | ---------------- | ----------- | +| Private | `0` | The snippet is visible only the snippet creator | +| Internal | `10` | The snippet is visible for any logged in user | +| Public | `20` | The snippet can be accessed without any authentication | + ## List snippets Get a list of project snippets. @@ -58,6 +71,7 @@ Parameters: - `title` (required) - The title of a snippet - `file_name` (required) - The name of a snippet file - `code` (required) - The content of a snippet +- `visibility_level` (required) - The snippet's visibility ## Update snippet @@ -74,6 +88,7 @@ Parameters: - `title` (optional) - The title of a snippet - `file_name` (optional) - The name of a snippet file - `code` (optional) - The content of a snippet +- `visibility_level` (optional) - The snippet's visibility ## Delete snippet From 5f3eef6e56ac4908c3fc67ca238340a3caf5a9b8 Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Sun, 3 May 2015 15:00:46 +0200 Subject: [PATCH 90/97] Add period at snippet visibilty description --- app/helpers/visibility_level_helper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/helpers/visibility_level_helper.rb b/app/helpers/visibility_level_helper.rb index 66a1383d61..00d4c7f105 100644 --- a/app/helpers/visibility_level_helper.rb +++ b/app/helpers/visibility_level_helper.rb @@ -47,7 +47,7 @@ module VisibilityLevelHelper haml_tag :span do case level when Gitlab::VisibilityLevel::PRIVATE - haml_concat "The snippet is visible only for me" + haml_concat "The snippet is visible only for me." when Gitlab::VisibilityLevel::INTERNAL haml_concat "The snippet is visible for any logged in user." when Gitlab::VisibilityLevel::PUBLIC From dc2b380da6b36bd9a8b80c9fb94a226ddee2e5b2 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Sun, 3 May 2015 08:58:52 -0700 Subject: [PATCH 91/97] Fix config template from parse errors --- config/gitlab.yml.example | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example index 93e75b4685..bd2081688d 100644 --- a/config/gitlab.yml.example +++ b/config/gitlab.yml.example @@ -12,9 +12,9 @@ # 2. Update gitlab -> host with your fully qualified domain name # 3. Update gitlab -> email_from # 4. If you installed Git from source, change git -> bin_path to /usr/local/bin/git - IMPORTANT: If Git was installed in a different location use that instead. - You can check with `which git`. If a wrong path of Git is specified, it will - result in various issues such as failures of GitLab CI builds. +# IMPORTANT: If Git was installed in a different location use that instead. +# You can check with `which git`. If a wrong path of Git is specified, it will +# result in various issues such as failures of GitLab CI builds. # 5. Review this configuration file for other settings you may want to adjust production: &base From a3157626f1970158573c71066982fac6a9ffe7ce Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Sun, 3 May 2015 09:05:38 -0700 Subject: [PATCH 92/97] Re-annotate models --- app/models/application_setting.rb | 7 +++--- app/models/deploy_key.rb | 2 +- app/models/key.rb | 1 + app/models/member.rb | 6 ++--- app/models/members/group_member.rb | 6 ++++- app/models/members/project_member.rb | 6 ++++- app/models/project_import_data.rb | 8 +++---- app/models/project_services/ci_service.rb | 1 + .../custom_issue_tracker_service.rb | 1 + .../emails_on_push_service.rb | 1 + .../project_services/external_wiki_service.rb | 22 ++++++++++++------- .../project_services/flowdock_service.rb | 1 + .../project_services/gemnasium_service.rb | 1 + .../project_services/gitlab_ci_service.rb | 1 + .../project_services/hipchat_service.rb | 1 + app/models/project_services/irker_service.rb | 1 + app/models/service.rb | 1 + app/models/user.rb | 1 + spec/models/application_setting_spec.rb | 5 ++++- spec/models/deploy_key_spec.rb | 1 + spec/models/external_wiki_service_spec.rb | 20 +++++++++++++++++ spec/models/key_spec.rb | 1 + spec/models/member_spec.rb | 19 ++++++++++++++++ spec/models/members/group_member_spec.rb | 6 ++++- spec/models/members/project_member_spec.rb | 6 ++++- .../project_services/asana_service_spec.rb | 1 + .../project_services/assembla_service_spec.rb | 1 + .../buildkite_service_spec.rb | 1 + .../project_services/flowdock_service_spec.rb | 1 + .../gemnasium_service_spec.rb | 1 + .../gitlab_ci_service_spec.rb | 1 + .../gitlab_issue_tracker_service_spec.rb | 1 + .../project_services/hipchat_service_spec.rb | 4 +++- .../project_services/irker_service_spec.rb | 1 + .../project_services/jira_service_spec.rb | 1 + .../project_services/pushover_service_spec.rb | 1 + .../project_services/slack_service_spec.rb | 1 + spec/models/service_spec.rb | 1 + spec/models/user_spec.rb | 2 ++ 39 files changed, 118 insertions(+), 26 deletions(-) diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb index f2cebde970..d5123249c5 100644 --- a/app/models/application_setting.rb +++ b/app/models/application_setting.rb @@ -2,13 +2,11 @@ # # Table name: application_settings # -# id :integer not null, primary key +# id :integer not null, primary key # default_projects_limit :integer -# default_branch_protection :integer # signup_enabled :boolean # signin_enabled :boolean # gravatar_enabled :boolean -# twitter_sharing_enabled :boolean # sign_in_text :text # created_at :datetime # updated_at :datetime @@ -16,8 +14,9 @@ # default_branch_protection :integer default(2) # twitter_sharing_enabled :boolean default(TRUE) # restricted_visibility_levels :text -# max_attachment_size :integer default(10) +# max_attachment_size :integer default(10), not null # default_project_visibility :integer +# default_snippet_visibility :integer # restricted_signup_domains :text # diff --git a/app/models/deploy_key.rb b/app/models/deploy_key.rb index 85d52d558c..9ab663c04a 100644 --- a/app/models/deploy_key.rb +++ b/app/models/deploy_key.rb @@ -7,10 +7,10 @@ # created_at :datetime # updated_at :datetime # key :text -# public :boolean default(FALSE) # title :string(255) # type :string(255) # fingerprint :string(255) +# public :boolean default(FALSE), not null # class DeployKey < Key diff --git a/app/models/key.rb b/app/models/key.rb index 016eee8699..bbc2867817 100644 --- a/app/models/key.rb +++ b/app/models/key.rb @@ -10,6 +10,7 @@ # title :string(255) # type :string(255) # fingerprint :string(255) +# public :boolean default(FALSE), not null # require 'digest/md5' diff --git a/app/models/member.rb b/app/models/member.rb index d151c7b239..cae8caa23f 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -6,14 +6,14 @@ # access_level :integer not null # source_id :integer not null # source_type :string(255) not null -# user_id :integer not null +# user_id :integer # notification_level :integer not null # type :string(255) # created_at :datetime # updated_at :datetime # created_by_id :integer -# invite_email :string -# invite_token :string +# invite_email :string(255) +# invite_token :string(255) # invite_accepted_at :datetime # diff --git a/app/models/members/group_member.rb b/app/models/members/group_member.rb index 84c91372b3..65d2ea0057 100644 --- a/app/models/members/group_member.rb +++ b/app/models/members/group_member.rb @@ -6,11 +6,15 @@ # access_level :integer not null # source_id :integer not null # source_type :string(255) not null -# user_id :integer not null +# user_id :integer # notification_level :integer not null # type :string(255) # created_at :datetime # updated_at :datetime +# created_by_id :integer +# invite_email :string(255) +# invite_token :string(255) +# invite_accepted_at :datetime # class GroupMember < Member diff --git a/app/models/members/project_member.rb b/app/models/members/project_member.rb index 0a3b4d2182..1b0c76917a 100644 --- a/app/models/members/project_member.rb +++ b/app/models/members/project_member.rb @@ -6,11 +6,15 @@ # access_level :integer not null # source_id :integer not null # source_type :string(255) not null -# user_id :integer not null +# user_id :integer # notification_level :integer not null # type :string(255) # created_at :datetime # updated_at :datetime +# created_by_id :integer +# invite_email :string(255) +# invite_token :string(255) +# invite_accepted_at :datetime # class ProjectMember < Member diff --git a/app/models/project_import_data.rb b/app/models/project_import_data.rb index 6a8a8a56eb..cd3319f077 100644 --- a/app/models/project_import_data.rb +++ b/app/models/project_import_data.rb @@ -1,10 +1,10 @@ # == Schema Information # -# Table name: project_import_datas +# Table name: project_import_data # -# id :integer not null, primary key -# project_id :integer -# data :text +# id :integer not null, primary key +# project_id :integer +# data :text # require 'carrierwave/orm/activerecord' diff --git a/app/models/project_services/ci_service.rb b/app/models/project_services/ci_service.rb index 1a36e43924..77d48d4af5 100644 --- a/app/models/project_services/ci_service.rb +++ b/app/models/project_services/ci_service.rb @@ -15,6 +15,7 @@ # issues_events :boolean default(TRUE) # merge_requests_events :boolean default(TRUE) # tag_push_events :boolean default(TRUE) +# note_events :boolean default(TRUE), not null # # Base class for CI services diff --git a/app/models/project_services/custom_issue_tracker_service.rb b/app/models/project_services/custom_issue_tracker_service.rb index 8d25f62787..7c2027c18e 100644 --- a/app/models/project_services/custom_issue_tracker_service.rb +++ b/app/models/project_services/custom_issue_tracker_service.rb @@ -15,6 +15,7 @@ # issues_events :boolean default(TRUE) # merge_requests_events :boolean default(TRUE) # tag_push_events :boolean default(TRUE) +# note_events :boolean default(TRUE), not null # class CustomIssueTrackerService < IssueTrackerService diff --git a/app/models/project_services/emails_on_push_service.rb b/app/models/project_services/emails_on_push_service.rb index 6f6e5950aa..8f5d8b086e 100644 --- a/app/models/project_services/emails_on_push_service.rb +++ b/app/models/project_services/emails_on_push_service.rb @@ -15,6 +15,7 @@ # issues_events :boolean default(TRUE) # merge_requests_events :boolean default(TRUE) # tag_push_events :boolean default(TRUE) +# note_events :boolean default(TRUE), not null # class EmailsOnPushService < Service diff --git a/app/models/project_services/external_wiki_service.rb b/app/models/project_services/external_wiki_service.rb index a199d0e86f..9c46af7e72 100644 --- a/app/models/project_services/external_wiki_service.rb +++ b/app/models/project_services/external_wiki_service.rb @@ -2,14 +2,20 @@ # # Table name: services # -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer not null -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text +# id :integer not null, primary key +# type :string(255) +# title :string(255) +# project_id :integer +# created_at :datetime +# updated_at :datetime +# active :boolean default(FALSE), not null +# properties :text +# template :boolean default(FALSE) +# push_events :boolean default(TRUE) +# issues_events :boolean default(TRUE) +# merge_requests_events :boolean default(TRUE) +# tag_push_events :boolean default(TRUE) +# note_events :boolean default(TRUE), not null # class ExternalWikiService < Service diff --git a/app/models/project_services/flowdock_service.rb b/app/models/project_services/flowdock_service.rb index 99e361dd6e..bf801ba61a 100644 --- a/app/models/project_services/flowdock_service.rb +++ b/app/models/project_services/flowdock_service.rb @@ -15,6 +15,7 @@ # issues_events :boolean default(TRUE) # merge_requests_events :boolean default(TRUE) # tag_push_events :boolean default(TRUE) +# note_events :boolean default(TRUE), not null # require "flowdock-git-hook" diff --git a/app/models/project_services/gemnasium_service.rb b/app/models/project_services/gemnasium_service.rb index 4e75bdfc95..91ef267ad7 100644 --- a/app/models/project_services/gemnasium_service.rb +++ b/app/models/project_services/gemnasium_service.rb @@ -15,6 +15,7 @@ # issues_events :boolean default(TRUE) # merge_requests_events :boolean default(TRUE) # tag_push_events :boolean default(TRUE) +# note_events :boolean default(TRUE), not null # require "gemnasium/gitlab_service" diff --git a/app/models/project_services/gitlab_ci_service.rb b/app/models/project_services/gitlab_ci_service.rb index 0f9838a575..f95bd79dfd 100644 --- a/app/models/project_services/gitlab_ci_service.rb +++ b/app/models/project_services/gitlab_ci_service.rb @@ -15,6 +15,7 @@ # issues_events :boolean default(TRUE) # merge_requests_events :boolean default(TRUE) # tag_push_events :boolean default(TRUE) +# note_events :boolean default(TRUE), not null # class GitlabCiService < CiService diff --git a/app/models/project_services/hipchat_service.rb b/app/models/project_services/hipchat_service.rb index 3a15b2207e..38cb64f8c4 100644 --- a/app/models/project_services/hipchat_service.rb +++ b/app/models/project_services/hipchat_service.rb @@ -15,6 +15,7 @@ # issues_events :boolean default(TRUE) # merge_requests_events :boolean default(TRUE) # tag_push_events :boolean default(TRUE) +# note_events :boolean default(TRUE), not null # class HipchatService < Service diff --git a/app/models/project_services/irker_service.rb b/app/models/project_services/irker_service.rb index e9e1e276e7..89f312e8c9 100644 --- a/app/models/project_services/irker_service.rb +++ b/app/models/project_services/irker_service.rb @@ -15,6 +15,7 @@ # issues_events :boolean default(TRUE) # merge_requests_events :boolean default(TRUE) # tag_push_events :boolean default(TRUE) +# note_events :boolean default(TRUE), not null # require 'uri' diff --git a/app/models/service.rb b/app/models/service.rb index 393cf55a69..818a6808db 100644 --- a/app/models/service.rb +++ b/app/models/service.rb @@ -15,6 +15,7 @@ # issues_events :boolean default(TRUE) # merge_requests_events :boolean default(TRUE) # tag_push_events :boolean default(TRUE) +# note_events :boolean default(TRUE), not null # # To add new service you should build a class inherited from Service diff --git a/app/models/user.rb b/app/models/user.rb index 9f19836812..1cf7cfea97 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -49,6 +49,7 @@ # password_automatically_set :boolean default(FALSE) # bitbucket_access_token :string(255) # bitbucket_access_token_secret :string(255) +# location :string(255) # public_email :string(255) default(""), not null # diff --git a/spec/models/application_setting_spec.rb b/spec/models/application_setting_spec.rb index 876502d03c..116c318121 100644 --- a/spec/models/application_setting_spec.rb +++ b/spec/models/application_setting_spec.rb @@ -4,7 +4,6 @@ # # id :integer not null, primary key # default_projects_limit :integer -# default_branch_protection :integer # signup_enabled :boolean # signin_enabled :boolean # gravatar_enabled :boolean @@ -15,6 +14,10 @@ # default_branch_protection :integer default(2) # twitter_sharing_enabled :boolean default(TRUE) # restricted_visibility_levels :text +# max_attachment_size :integer default(10), not null +# default_project_visibility :integer +# default_snippet_visibility :integer +# restricted_signup_domains :text # require 'spec_helper' diff --git a/spec/models/deploy_key_spec.rb b/spec/models/deploy_key_spec.rb index b32be8d7a7..9572993245 100644 --- a/spec/models/deploy_key_spec.rb +++ b/spec/models/deploy_key_spec.rb @@ -10,6 +10,7 @@ # title :string(255) # type :string(255) # fingerprint :string(255) +# public :boolean default(FALSE), not null # require 'spec_helper' diff --git a/spec/models/external_wiki_service_spec.rb b/spec/models/external_wiki_service_spec.rb index 78ef687d29..f2e77fc88c 100644 --- a/spec/models/external_wiki_service_spec.rb +++ b/spec/models/external_wiki_service_spec.rb @@ -1,3 +1,23 @@ +# == Schema Information +# +# Table name: services +# +# id :integer not null, primary key +# type :string(255) +# title :string(255) +# project_id :integer +# created_at :datetime +# updated_at :datetime +# active :boolean default(FALSE), not null +# properties :text +# template :boolean default(FALSE) +# push_events :boolean default(TRUE) +# issues_events :boolean default(TRUE) +# merge_requests_events :boolean default(TRUE) +# tag_push_events :boolean default(TRUE) +# note_events :boolean default(TRUE), not null +# + require 'spec_helper' describe ExternalWikiService do diff --git a/spec/models/key_spec.rb b/spec/models/key_spec.rb index 2fb651bef1..6eb1208a7f 100644 --- a/spec/models/key_spec.rb +++ b/spec/models/key_spec.rb @@ -10,6 +10,7 @@ # title :string(255) # type :string(255) # fingerprint :string(255) +# public :boolean default(FALSE), not null # require 'spec_helper' diff --git a/spec/models/member_spec.rb b/spec/models/member_spec.rb index 56d030a03b..57f840c1e9 100644 --- a/spec/models/member_spec.rb +++ b/spec/models/member_spec.rb @@ -1,3 +1,22 @@ +# == Schema Information +# +# Table name: members +# +# id :integer not null, primary key +# access_level :integer not null +# source_id :integer not null +# source_type :string(255) not null +# user_id :integer +# notification_level :integer not null +# type :string(255) +# created_at :datetime +# updated_at :datetime +# created_by_id :integer +# invite_email :string(255) +# invite_token :string(255) +# invite_accepted_at :datetime +# + require 'spec_helper' describe Member do diff --git a/spec/models/members/group_member_spec.rb b/spec/models/members/group_member_spec.rb index e206c11f33..7c10c9f0f4 100644 --- a/spec/models/members/group_member_spec.rb +++ b/spec/models/members/group_member_spec.rb @@ -6,11 +6,15 @@ # access_level :integer not null # source_id :integer not null # source_type :string(255) not null -# user_id :integer not null +# user_id :integer # notification_level :integer not null # type :string(255) # created_at :datetime # updated_at :datetime +# created_by_id :integer +# invite_email :string(255) +# invite_token :string(255) +# invite_accepted_at :datetime # require 'spec_helper' diff --git a/spec/models/members/project_member_spec.rb b/spec/models/members/project_member_spec.rb index 521721f357..5c72cfe1d6 100644 --- a/spec/models/members/project_member_spec.rb +++ b/spec/models/members/project_member_spec.rb @@ -6,11 +6,15 @@ # access_level :integer not null # source_id :integer not null # source_type :string(255) not null -# user_id :integer not null +# user_id :integer # notification_level :integer not null # type :string(255) # created_at :datetime # updated_at :datetime +# created_by_id :integer +# invite_email :string(255) +# invite_token :string(255) +# invite_accepted_at :datetime # require 'spec_helper' diff --git a/spec/models/project_services/asana_service_spec.rb b/spec/models/project_services/asana_service_spec.rb index 13c8d54a2a..cc1f99e0c7 100644 --- a/spec/models/project_services/asana_service_spec.rb +++ b/spec/models/project_services/asana_service_spec.rb @@ -15,6 +15,7 @@ # issues_events :boolean default(TRUE) # merge_requests_events :boolean default(TRUE) # tag_push_events :boolean default(TRUE) +# note_events :boolean default(TRUE), not null # require 'spec_helper' diff --git a/spec/models/project_services/assembla_service_spec.rb b/spec/models/project_services/assembla_service_spec.rb index 91730da1ee..9aee754dd6 100644 --- a/spec/models/project_services/assembla_service_spec.rb +++ b/spec/models/project_services/assembla_service_spec.rb @@ -15,6 +15,7 @@ # issues_events :boolean default(TRUE) # merge_requests_events :boolean default(TRUE) # tag_push_events :boolean default(TRUE) +# note_events :boolean default(TRUE), not null # require 'spec_helper' diff --git a/spec/models/project_services/buildkite_service_spec.rb b/spec/models/project_services/buildkite_service_spec.rb index e987241f3c..6db54243ea 100644 --- a/spec/models/project_services/buildkite_service_spec.rb +++ b/spec/models/project_services/buildkite_service_spec.rb @@ -15,6 +15,7 @@ # issues_events :boolean default(TRUE) # merge_requests_events :boolean default(TRUE) # tag_push_events :boolean default(TRUE) +# note_events :boolean default(TRUE), not null # require 'spec_helper' diff --git a/spec/models/project_services/flowdock_service_spec.rb b/spec/models/project_services/flowdock_service_spec.rb index 73f68301a3..e6e8fbba6a 100644 --- a/spec/models/project_services/flowdock_service_spec.rb +++ b/spec/models/project_services/flowdock_service_spec.rb @@ -15,6 +15,7 @@ # issues_events :boolean default(TRUE) # merge_requests_events :boolean default(TRUE) # tag_push_events :boolean default(TRUE) +# note_events :boolean default(TRUE), not null # require 'spec_helper' diff --git a/spec/models/project_services/gemnasium_service_spec.rb b/spec/models/project_services/gemnasium_service_spec.rb index d44064bbe6..1a7765e5c2 100644 --- a/spec/models/project_services/gemnasium_service_spec.rb +++ b/spec/models/project_services/gemnasium_service_spec.rb @@ -15,6 +15,7 @@ # issues_events :boolean default(TRUE) # merge_requests_events :boolean default(TRUE) # tag_push_events :boolean default(TRUE) +# note_events :boolean default(TRUE), not null # require 'spec_helper' diff --git a/spec/models/project_services/gitlab_ci_service_spec.rb b/spec/models/project_services/gitlab_ci_service_spec.rb index 6a557d839c..afacd4afaf 100644 --- a/spec/models/project_services/gitlab_ci_service_spec.rb +++ b/spec/models/project_services/gitlab_ci_service_spec.rb @@ -15,6 +15,7 @@ # issues_events :boolean default(TRUE) # merge_requests_events :boolean default(TRUE) # tag_push_events :boolean default(TRUE) +# note_events :boolean default(TRUE), not null # require 'spec_helper' diff --git a/spec/models/project_services/gitlab_issue_tracker_service_spec.rb b/spec/models/project_services/gitlab_issue_tracker_service_spec.rb index f94bef5c36..e34ca09bff 100644 --- a/spec/models/project_services/gitlab_issue_tracker_service_spec.rb +++ b/spec/models/project_services/gitlab_issue_tracker_service_spec.rb @@ -15,6 +15,7 @@ # issues_events :boolean default(TRUE) # merge_requests_events :boolean default(TRUE) # tag_push_events :boolean default(TRUE) +# note_events :boolean default(TRUE), not null # require 'spec_helper' diff --git a/spec/models/project_services/hipchat_service_spec.rb b/spec/models/project_services/hipchat_service_spec.rb index 348f83c56a..bbaf54488b 100644 --- a/spec/models/project_services/hipchat_service_spec.rb +++ b/spec/models/project_services/hipchat_service_spec.rb @@ -5,15 +5,17 @@ # id :integer not null, primary key # type :string(255) # title :string(255) -# project_id :integer not null +# project_id :integer # created_at :datetime # updated_at :datetime # active :boolean default(FALSE), not null # properties :text +# template :boolean default(FALSE) # push_events :boolean default(TRUE) # issues_events :boolean default(TRUE) # merge_requests_events :boolean default(TRUE) # tag_push_events :boolean default(TRUE) +# note_events :boolean default(TRUE), not null # require 'spec_helper' diff --git a/spec/models/project_services/irker_service_spec.rb b/spec/models/project_services/irker_service_spec.rb index d55399bc36..49face26bb 100644 --- a/spec/models/project_services/irker_service_spec.rb +++ b/spec/models/project_services/irker_service_spec.rb @@ -15,6 +15,7 @@ # issues_events :boolean default(TRUE) # merge_requests_events :boolean default(TRUE) # tag_push_events :boolean default(TRUE) +# note_events :boolean default(TRUE), not null # require 'spec_helper' diff --git a/spec/models/project_services/jira_service_spec.rb b/spec/models/project_services/jira_service_spec.rb index 355911e637..ddd2cce212 100644 --- a/spec/models/project_services/jira_service_spec.rb +++ b/spec/models/project_services/jira_service_spec.rb @@ -15,6 +15,7 @@ # issues_events :boolean default(TRUE) # merge_requests_events :boolean default(TRUE) # tag_push_events :boolean default(TRUE) +# note_events :boolean default(TRUE), not null # require 'spec_helper' diff --git a/spec/models/project_services/pushover_service_spec.rb b/spec/models/project_services/pushover_service_spec.rb index 5a18fd09bf..5f93703b50 100644 --- a/spec/models/project_services/pushover_service_spec.rb +++ b/spec/models/project_services/pushover_service_spec.rb @@ -15,6 +15,7 @@ # issues_events :boolean default(TRUE) # merge_requests_events :boolean default(TRUE) # tag_push_events :boolean default(TRUE) +# note_events :boolean default(TRUE), not null # require 'spec_helper' diff --git a/spec/models/project_services/slack_service_spec.rb b/spec/models/project_services/slack_service_spec.rb index c36506644b..e9105677d2 100644 --- a/spec/models/project_services/slack_service_spec.rb +++ b/spec/models/project_services/slack_service_spec.rb @@ -15,6 +15,7 @@ # issues_events :boolean default(TRUE) # merge_requests_events :boolean default(TRUE) # tag_push_events :boolean default(TRUE) +# note_events :boolean default(TRUE), not null # require 'spec_helper' diff --git a/spec/models/service_spec.rb b/spec/models/service_spec.rb index 735652aea7..5d4827ce92 100644 --- a/spec/models/service_spec.rb +++ b/spec/models/service_spec.rb @@ -15,6 +15,7 @@ # issues_events :boolean default(TRUE) # merge_requests_events :boolean default(TRUE) # tag_push_events :boolean default(TRUE) +# note_events :boolean default(TRUE), not null # require 'spec_helper' diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 441aa79313..771709c127 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -49,6 +49,8 @@ # password_automatically_set :boolean default(FALSE) # bitbucket_access_token :string(255) # bitbucket_access_token_secret :string(255) +# location :string(255) +# public_email :string(255) default(""), not null # require 'spec_helper' From 361284fec23eebc09c4bba418306a36805504dc7 Mon Sep 17 00:00:00 2001 From: Sven Selberg Date: Mon, 9 Feb 2015 13:52:42 +0100 Subject: [PATCH 93/97] Add current_sign_in_at to api User --- CHANGELOG | 1 + doc/api/users.md | 6 ++++-- lib/api/entities.rb | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 8456975639..1667e9dd77 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -40,6 +40,7 @@ v 7.11.0 (unreleased) - Add room notification and message color option for HipChat - Allow to use non-ASCII letters and dashes in project and namespace name. (Jakub Jirutka) - Add footnotes support to Markdown (Guillaume Delbergue) + - Add current_sign_in_at to UserFull REST api. v 7.10.0 - Ignore submodules that are defined in .gitmodules but are checked in as directories. diff --git a/doc/api/users.md b/doc/api/users.md index a8b7685b50..cd141daadc 100644 --- a/doc/api/users.md +++ b/doc/api/users.md @@ -57,7 +57,8 @@ GET /users "color_scheme_id": 2, "is_admin": false, "avatar_url": "http://localhost:3000/uploads/user/avatar/1/cd8.jpeg", - "can_create_group": true + "can_create_group": true, + "current_sign_in_at": "2014-03-19T13:12:15Z" }, { "id": 2, @@ -79,7 +80,8 @@ GET /users "avatar_url": "http://localhost:3000/uploads/user/avatar/1/cd8.jpeg", "can_create_group": true, "can_create_project": true, - "projects_limit": 100 + "projects_limit": 100, + "current_sign_in_at": "2014-03-19T17:54:13Z" } ] ``` diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 79b4afa40b..b23eff3661 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -20,7 +20,7 @@ module API class UserFull < User expose :email - expose :theme_id, :color_scheme_id, :projects_limit + expose :theme_id, :color_scheme_id, :projects_limit, :current_sign_in_at expose :identities, using: Entities::Identity expose :can_create_group?, as: :can_create_group expose :can_create_project?, as: :can_create_project From 2530141aceaaf4452cc2308648846fd52c48aa8c Mon Sep 17 00:00:00 2001 From: Job van der Voort Date: Mon, 4 May 2015 11:13:07 +0200 Subject: [PATCH 94/97] update doc by removing unnecessary parts --- doc/raketasks/user_management.md | 32 +++----------------------------- 1 file changed, 3 insertions(+), 29 deletions(-) diff --git a/doc/raketasks/user_management.md b/doc/raketasks/user_management.md index 04a8126c16..4fbd20762d 100644 --- a/doc/raketasks/user_management.md +++ b/doc/raketasks/user_management.md @@ -50,35 +50,9 @@ bundle exec rake gitlab:import:all_users_to_all_groups RAILS_ENV=production ## Maintain tight control over the number of active users on your GitLab installation -- Enable this setting to keep new users blocked until they have been cleared by the admin +- Enable this setting to keep new users blocked until they have been cleared by the admin (default: false). -```bash -(default: false). -block_auto_created_users: false -Base where we can search for users - -Ex. ou=People,dc=gitlab,dc=example - -base: '' - -Filter LDAP users - -Format: RFC 4515 http://tools.ietf.org/search/rfc4515 -Ex. (employeeType=developer) - -Note: GitLab does not support omniauth-ldap's custom filter syntax. - -user_filter: '' ``` - -- GitLab EE only: add more LDAP servers - -```bash -Choose an ID made of a-z and 0-9 . This ID will be stored in the database -so that GitLab can remember which LDAP server a user belongs to. -uswest2: -label: -host: -.... -``` \ No newline at end of file +block_auto_created_users: false +``` From b7decf1de76d3ae3f96d18555ffe144e0a2a0a7a Mon Sep 17 00:00:00 2001 From: Jakob Englisch Date: Mon, 4 May 2015 10:50:52 +0000 Subject: [PATCH 95/97] Docker: update omnibus package --- docker/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 69e34955b7..df828a2a34 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -11,7 +11,7 @@ RUN apt-get update -q \ # If the Omnibus package version below is outdated please contribute a merge request to update it. # If you run GitLab Enterprise Edition point it to a location where you have downloaded it. RUN TMP_FILE=$(mktemp); \ - wget -q -O $TMP_FILE https://downloads-packages.s3.amazonaws.com/ubuntu-14.04/gitlab-ce_7.10.0~omnibus.2-1_amd64.deb \ + wget -q -O $TMP_FILE https://downloads-packages.s3.amazonaws.com/ubuntu-14.04/gitlab-ce_7.10.1~omnibus.2-1_amd64.deb \ && dpkg -i $TMP_FILE \ && rm -f $TMP_FILE @@ -30,4 +30,4 @@ EXPOSE 80 22 COPY assets/wrapper /usr/local/bin/ # Wrapper to handle signal, trigger runit and reconfigure GitLab -CMD ["/usr/local/bin/wrapper"] +CMD ["/usr/local/bin/wrapper"] \ No newline at end of file From b953796ac83630321ecfb89edbc8a8b8ed19bc02 Mon Sep 17 00:00:00 2001 From: quodos Date: Mon, 4 May 2015 14:09:03 +0200 Subject: [PATCH 96/97] Update authentication.rb correct spelling --- lib/gitlab/ldap/authentication.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/gitlab/ldap/authentication.rb b/lib/gitlab/ldap/authentication.rb index 649cf3194b..bad683c651 100644 --- a/lib/gitlab/ldap/authentication.rb +++ b/lib/gitlab/ldap/authentication.rb @@ -1,4 +1,4 @@ -# This calls helps to authenticate to LDAP by providing username and password +# These calls help to authenticate to LDAP by providing username and password # # Since multiple LDAP servers are supported, it will loop through all of them # until a valid bind is found From 07dc51701785d78cd4ebbf7afd762a1d95b5e62b Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Sun, 26 Apr 2015 16:44:22 -0700 Subject: [PATCH 97/97] Improve documentation of configuring external issue trackers Closes #1514 --- doc/integration/external-issue-tracker.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/integration/external-issue-tracker.md b/doc/integration/external-issue-tracker.md index 96755707de..3e660cfba1 100644 --- a/doc/integration/external-issue-tracker.md +++ b/doc/integration/external-issue-tracker.md @@ -36,4 +36,9 @@ In GitLab Admin section, navigate to `Service Templates` and choose the service After the template is created, the template details will be pre-filled on the project service page. +NOTE: For each project, you will still need to configure the issue tracking URLs by replacing `:issues_tracker_id` in the above screenshot +with the ID used by your external issue tracker. Prior to GitLab v7.8, this ID was configured in the project settings, and GitLab would automatically +update the URL configured in `gitlab.yml`. This behavior is now depecated, and all issue tracker URLs must be configured directly +within the project's Services settings. + Support to add your commits to the Jira ticket automatically is [available in GitLab EE](http://doc.gitlab.com/ee/integration/jira.html).