From 35b93f9d223e132a66501920ba84d5ece1013aab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20Trzci=C5=84ski?= Date: Mon, 2 Nov 2015 15:14:34 +0000 Subject: Add notice about offline migrations --- doc/development/migration_style_guide.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/doc/development/migration_style_guide.md b/doc/development/migration_style_guide.md index 4fa1961fde9..4e108c17871 100644 --- a/doc/development/migration_style_guide.md +++ b/doc/development/migration_style_guide.md @@ -8,6 +8,8 @@ In addition, having to take a server offline for a an upgrade small or big is a big burden for most organizations. For this reason it is important that your migrations are written carefully, can be applied online and adhere to the style guide below. +It's advised to have offline migrations only in major GitLab releases. + When writing your migrations, also consider that databases might have stale data or inconsistencies and guard for that. Try to make as little assumptions as possible about the state of the database. @@ -33,6 +35,8 @@ It is always preferable to have a migration run online. If you expect the migrat to take particularly long (for instance, if it loops through all notes), this is valuable information to add. +If you don't provide the information it means that a migration is safe to run online. + ### Reversibility Your migration should be reversible. This is very important, as it should @@ -85,4 +89,4 @@ select_all("SELECT name, COUNT(id) as cnt FROM tags GROUP BY name HAVING COUNT(i execute("UPDATE taggings SET tag_id = #{origin_tag_id} WHERE tag_id IN(#{duplicate_ids.join(",")})") execute("DELETE FROM tags WHERE id IN(#{duplicate_ids.join(",")})") end -``` +``` \ No newline at end of file -- cgit v1.2.1 From 6e6a99061dbec4bb45a398a03e8a13a084e44035 Mon Sep 17 00:00:00 2001 From: Ted Hogan Date: Mon, 23 Nov 2015 11:36:47 -0700 Subject: No space required after WIP identifier Modified changelog --- CHANGELOG | 1 + app/models/merge_request.rb | 2 +- spec/models/merge_request_spec.rb | 15 +++++++++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index fc7b6e75b1d..2453b35ead3 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 8.3.0 (unreleased) - Fix: Assignee selector is empty when 'Unassigned' is selected (Jose Corcuera) + - WIP identifier on merge requests no longer requires trailing space v 8.2.0 - Improved performance of finding projects and groups in various places diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 1b3d6079d2c..2b336ca8927 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -239,7 +239,7 @@ class MergeRequest < ActiveRecord::Base end def work_in_progress? - !!(title =~ /\A\[?WIP\]?:? /i) + !!(title =~ /\A\[?WIP(\]|:| )/i) end def mergeable? diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index 567c911425c..edf211c85c1 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -162,6 +162,21 @@ describe MergeRequest do 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 "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 -- cgit v1.2.1 From f0c2f7481febf1e1149cb3dba87780c462759d14 Mon Sep 17 00:00:00 2001 From: Ted Hogan Date: Wed, 6 Jan 2016 10:48:08 -0700 Subject: Removed redundent and incorrect tests on WIP --- spec/models/merge_request_spec.rb | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index 0d3901f4d00..ecfbbb0cfc9 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -193,16 +193,6 @@ describe MergeRequest, models: true do 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 "detects the '[WIP]' prefix" do subject.title = "[WIP]#{subject.title}" expect(subject).to be_work_in_progress -- cgit v1.2.1 From 67a6fee5b124a768279b0681b52be19f138530dc Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Fri, 15 Jan 2016 18:12:36 +0100 Subject: Prototype of Git blobs via workhorse --- app/controllers/projects/raw_controller.rb | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/app/controllers/projects/raw_controller.rb b/app/controllers/projects/raw_controller.rb index be7d5c187fe..e55cdea94ae 100644 --- a/app/controllers/projects/raw_controller.rb +++ b/app/controllers/projects/raw_controller.rb @@ -1,3 +1,5 @@ +require 'base64' + # Controller for viewing a file's raw class Projects::RawController < Projects::ApplicationController include ExtractsPath @@ -15,7 +17,10 @@ class Projects::RawController < Projects::ApplicationController if @blob.lfs_pointer? send_lfs_object else - stream_data + headers['Gitlab-Workhorse-Repo-Path'] = @repository.path_to_repo + headers['Gitlab-Workhorse-Send-Blob'] = Base64.urlsafe_encode64(@commit.id + ':' + @path) + headers['Content-Disposition'] = 'inline' + render nothing: true, content_type: get_blob_type end else render_404 @@ -34,16 +39,6 @@ class Projects::RawController < Projects::ApplicationController end end - def stream_data - type = get_blob_type - - send_data( - @blob.data, - type: type, - disposition: 'inline' - ) - end - def send_lfs_object lfs_object = find_lfs_object -- cgit v1.2.1 From 609baf6f34fd3aee89aab3b2b8e038d331e632b6 Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Mon, 18 Jan 2016 09:27:35 +0100 Subject: Refactor deploy_key_multiple_projects API documentation [ci skip] --- doc/api/deploy_key_multiple_projects.md | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/doc/api/deploy_key_multiple_projects.md b/doc/api/deploy_key_multiple_projects.md index 1a5a458905e..3ad836f51b5 100644 --- a/doc/api/deploy_key_multiple_projects.md +++ b/doc/api/deploy_key_multiple_projects.md @@ -1,25 +1,29 @@ # Adding deploy keys to multiple projects -If you want to easily add the same deploy key to multiple projects in the same group, this can be achieved quite easily with the API. +If you want to easily add the same deploy key to multiple projects in the same +group, this can be achieved quite easily with the API. -First, find the ID of the projects you're interested in, by either listing all projects: +First, find the ID of the projects you're interested in, by either listing all +projects: ``` -curl --header 'PRIVATE-TOKEN: abcdef' https://gitlab.com/api/v3/projects +curl -H 'PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK' https://gitlab.example.com/api/v3/projects ``` -Or finding the id of a group and then listing all projects in that group: +Or finding the ID of a group and then listing all projects in that group: ``` -curl --header 'PRIVATE-TOKEN: abcdef' https://gitlab.com/api/v3/groups +curl -H 'PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK' https://gitlab.example.com/api/v3/groups # For group 1234: -curl --header 'PRIVATE-TOKEN: abcdef' https://gitlab.com/api/v3/groups/1234 +curl -H 'PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK' https://gitlab.example.com/api/v3/groups/1234 ``` With those IDs, add the same deploy key to all: + ``` for project_id in 321 456 987; do - curl -X POST --data '{"title": "my key", "key": "ssh-rsa AAAA..."}' --header 'PRIVATE-TOKEN: abcdef' https://gitlab.com/api/v3/projects/${project_id}/keys + curl -X POST -H "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" -H "Content-Type: application/json" \ + --data '{"title": "my key", "key": "ssh-rsa AAAA..."}' https://gitlab.example.com/api/v3/projects/${project_id}/keys done ``` -- cgit v1.2.1 From bef01c48bd3702e996c55484ed777db095ce480a Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Mon, 18 Jan 2016 09:43:46 +0100 Subject: Refactor session API documentation [ci skip] --- doc/api/session.md | 42 +++++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/doc/api/session.md b/doc/api/session.md index 47c1c8a7a49..71e93d0bb0a 100644 --- a/doc/api/session.md +++ b/doc/api/session.md @@ -1,39 +1,47 @@ # Session -Login to get private token +You can login with both GitLab and LDAP credentials in order to obtain the +private token. ``` POST /session ``` -Parameters: +| Attribute | Type | Required | Description | +| ---------- | ------- | -------- | -------- | +| `login` | string | yes | The username of the user| +| `email` | string | yes if login is not provided | The email of the user | +| `password` | string | yes | The password of the user | -- `login` (required) - The login of user -- `email` (required if login missing) - The email of user -- `password` (required) - Valid password - -**You can login with both GitLab and LDAP credentials now** +```bash +curl -X POST "https://gitlab.example.com/api/v3/session?login=john_smith&password=strongpassw0rd" +``` +Example response: ```json { - "id": 1, - "username": "john_smith", - "email": "john@example.com", "name": "John Smith", - "private_token": "dd34asd13as", - "blocked": false, - "created_at": "2012-05-23T08:00:58Z", + "username": "john_smith", + "id": 32, + "state": "active", + "avatar_url": null, + "created_at": "2015-01-29T21:07:19.440Z", + "is_admin": true, "bio": null, "skype": "", "linkedin": "", "twitter": "", "website_url": "", - "dark_scheme": false, + "email": "john@example.com", "theme_id": 1, - "is_admin": false, + "color_scheme_id": 1, + "projects_limit": 10, + "current_sign_in_at": "2015-07-07T07:10:58.392Z", + "identities": [], "can_create_group": true, - "can_create_team": true, - "can_create_project": true + "can_create_project": true, + "two_factor_enabled": false, + "private_token": "9koXpg98eAheJpvBs5tK" } ``` -- cgit v1.2.1 From 53ddb8f2ccaa95a19d530827e3fc7500d02ccfff Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Wed, 20 Jan 2016 13:44:39 +0100 Subject: Use a /raw/ request to show an image --- app/views/projects/blob/_image.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/projects/blob/_image.html.haml b/app/views/projects/blob/_image.html.haml index c090f690d1d..51fa91b08e4 100644 --- a/app/views/projects/blob/_image.html.haml +++ b/app/views/projects/blob/_image.html.haml @@ -1,2 +1,2 @@ .file-content.image_file - %img{ src: "data:#{blob.mime_type};base64,#{Base64.encode64(blob.data)}"} + %img{ src: namespace_project_raw_path(@project.namespace, @project, @id)} -- cgit v1.2.1 From d781eee575ffd5e05500e9e2e18c1a2a245a2339 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Louis=20Roch=C3=A9?= Date: Fri, 22 Jan 2016 14:33:25 +0000 Subject: Fix typo indentation in CI projects' API --- doc/ci/api/projects.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ci/api/projects.md b/doc/ci/api/projects.md index 74a4c64d000..fe6b1c01352 100644 --- a/doc/ci/api/projects.md +++ b/doc/ci/api/projects.md @@ -18,7 +18,7 @@ GET /ci/projects Returns: ```json - [ +[ { "id" : 271, "name" : "gitlabhq", -- cgit v1.2.1 From 4d2da5fd2585fead823c4450e54613dadf882c0d Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 22 Jan 2016 17:55:12 +0100 Subject: WIP - spec failure on .atom project URL --- spec/controllers/projects_controller_spec.rb | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb index 665526fde93..ad143c14c43 100644 --- a/spec/controllers/projects_controller_spec.rb +++ b/spec/controllers/projects_controller_spec.rb @@ -86,6 +86,17 @@ describe ProjectsController do end end end + + context "when the url contains .atom" do + let(:public_project_with_dot) { create(:project, :public, name: 'my.atom', path: 'my.atom') } + + it 'loads a project' do + get :show, namespace_id: public_project_with_dot.namespace.path, id: public_project_with_dot.path + + expect(assigns(:project)).to eq(public_project_with_dot) + expect(response.status).to eq(200) + end + end end describe "#destroy" do -- cgit v1.2.1 From acfc526828923db381ab01d872ecd1b82618ddc3 Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Mon, 25 Jan 2016 06:34:30 +0000 Subject: update OAuth doc --- doc/integration/oauth_provider.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/integration/oauth_provider.md b/doc/integration/oauth_provider.md index dbe5a175c82..f0c2a45b6ae 100644 --- a/doc/integration/oauth_provider.md +++ b/doc/integration/oauth_provider.md @@ -26,7 +26,7 @@ Every application you authorized will be shown in your "Authorized application" ![authorized_application](img/oauth_provider_authorized_application.png) -At any time you can revoke access just clicking button "Revoke" +As you can see we use default scope "api" here which is only scope we have so far. At any time you can revoke access just clicking button "Revoke". ### OAuth applications in admin area -- cgit v1.2.1 From 5287da7412e01ac1508bd15bec5bae7c3a0afa1b Mon Sep 17 00:00:00 2001 From: fbretel Date: Mon, 25 Jan 2016 13:19:27 +0000 Subject: Consistent rails_socket use. --- lib/support/init.d/gitlab | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/support/init.d/gitlab b/lib/support/init.d/gitlab index 1633891c8a0..9e90a99f15b 100755 --- a/lib/support/init.d/gitlab +++ b/lib/support/init.d/gitlab @@ -219,7 +219,7 @@ start_gitlab() { echo "The Unicorn web server already running with pid $wpid, not restarting." else # Remove old socket if it exists - rm -f "$socket_path"/gitlab.socket 2>/dev/null + rm -f "$rails_socket" 2>/dev/null # Start the web server RAILS_ENV=$RAILS_ENV bin/web start fi -- cgit v1.2.1 From e32eb5715141101a95e97c4f51a2f96976822c9a Mon Sep 17 00:00:00 2001 From: Mike Chelen Date: Wed, 27 Jan 2016 02:10:03 +0000 Subject: explicitly call script with bash for consistency --- doc/ci/languages/php.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/ci/languages/php.md b/doc/ci/languages/php.md index 77f9fae5bb6..aeadd6a448e 100644 --- a/doc/ci/languages/php.md +++ b/doc/ci/languages/php.md @@ -97,7 +97,7 @@ image: php:5.6 before_script: # Install dependencies -- ci/docker_install.sh > /dev/null +- bash ci/docker_install.sh > /dev/null test:app: script: @@ -112,7 +112,7 @@ with a different docker image version and the runner will do the rest: ```yaml before_script: # Install dependencies -- ci/docker_install.sh > /dev/null +- bash ci/docker_install.sh > /dev/null # We test PHP5.6 test:5.6: -- cgit v1.2.1 From 087abdf7fd47cfc1ec597fc18b5fa910b945bbd1 Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Wed, 27 Jan 2016 17:38:19 -0500 Subject: New right side gutter design. [WIP] --- app/assets/javascripts/issuable_context.js.coffee | 12 -- app/assets/stylesheets/framework/sidebar.scss | 13 +- app/assets/stylesheets/framework/variables.scss | 2 + app/assets/stylesheets/pages/issuable.scss | 13 ++ app/helpers/application_helper.rb | 30 ++++ app/helpers/nav_helper.rb | 6 + app/views/layouts/_page.html.haml | 2 +- app/views/projects/issues/show.html.haml | 8 +- app/views/projects/merge_requests/_show.html.haml | 6 +- app/views/shared/issuable/_sidebar.html.haml | 160 ++++++++++++---------- 10 files changed, 155 insertions(+), 97 deletions(-) diff --git a/app/assets/javascripts/issuable_context.js.coffee b/app/assets/javascripts/issuable_context.js.coffee index 02232698bc2..c2144aea25e 100644 --- a/app/assets/javascripts/issuable_context.js.coffee +++ b/app/assets/javascripts/issuable_context.js.coffee @@ -10,18 +10,6 @@ class @IssuableContext $(".issuable-sidebar .inline-update").on "change", ".js-assignee", -> $(this).submit() - $('.issuable-details').waitForImages -> - $('.issuable-affix').on 'affix.bs.affix', -> - $(@).width($(@).outerWidth()) - .on 'affixed-top.bs.affix affixed-bottom.bs.affix', -> - $(@).width('') - - $('.issuable-affix').affix offset: - top: -> - @top = ($('.issuable-affix').offset().top - 70) - bottom: -> - @bottom = $('.footer').outerHeight(true) - $(".edit-link").click (e) -> block = $(@).parents('.block') block.find('.selectbox').show() diff --git a/app/assets/stylesheets/framework/sidebar.scss b/app/assets/stylesheets/framework/sidebar.scss index 540d0b03163..e0fc969ff0e 100644 --- a/app/assets/stylesheets/framework/sidebar.scss +++ b/app/assets/stylesheets/framework/sidebar.scss @@ -200,6 +200,10 @@ } } +@mixin expanded-gutter { + padding-right: $gutter_width; +} + @mixin collapsed-sidebar { padding-left: $sidebar_collapsed_width; @@ -266,6 +270,7 @@ background: #f2f6f7; } +// page is small enough @media (max-width: $screen-md-max) { .page-sidebar-collapsed { @include collapsed-sidebar; @@ -280,7 +285,13 @@ } } +// page is large enough @media(min-width: $screen-md-max) { + + .page-gutter { + @include expanded-gutter; + } + .page-sidebar-collapsed { @include collapsed-sidebar; } @@ -288,4 +299,4 @@ .page-sidebar-expanded { @include expanded-sidebar; } -} +} \ No newline at end of file diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss index 3ec48da9a41..7af6688963f 100644 --- a/app/assets/stylesheets/framework/variables.scss +++ b/app/assets/stylesheets/framework/variables.scss @@ -12,6 +12,8 @@ $gl-font-size: 15px; $list-font-size: 15px; $sidebar_collapsed_width: 62px; $sidebar_width: 230px; +$gutter_collapsed_width: 62px; +$gutter_width: 320px; $avatar_radius: 50%; $code_font_size: 13px; $code_line_height: 1.5; diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss index 977ada0ff38..d1f2175bfb7 100644 --- a/app/assets/stylesheets/pages/issuable.scss +++ b/app/assets/stylesheets/pages/issuable.scss @@ -133,3 +133,16 @@ margin-right: 2px; } } + + +.right-sidebar { + position: fixed; + top: 58px; + right: 0; + height: 100%; + transition-duration: .3s; + background: $gray-light; + overflow: scroll; + width: $gutter_width; + padding: 10px 20px; +} \ No newline at end of file diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index a2458ad3be0..57a9ce8294a 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -293,6 +293,36 @@ module ApplicationHelper end end + def issuable_count(entity, project) + if project.nil? + 0 + elsif current_controller?(:issues) + project.issues.send(entity).count + elsif current_controller?(:merge_requests) + project.merge_requests.send(entity).count + end + end + + def next_issuable_for(project) + if project.nil? + nil + elsif current_controller?(:issues) + project.issues.where("id > ?", id).first + elsif current_controller?(:merge_requests) + project.merge_requests.where("id > ?", id).first + end + end + + def prev_issuable_for(project) + if project.nil? + nil + elsif current_controller?(:issues) + project.issues.where("id < ?", id).last + elsif current_controller?(:merge_requests) + project.merge_requests.where("id > ?", id).last + end + end + def state_filters_text_for(entity, project) titles = { opened: "Open" diff --git a/app/helpers/nav_helper.rb b/app/helpers/nav_helper.rb index e6fb8670e57..20b89cc9db3 100644 --- a/app/helpers/nav_helper.rb +++ b/app/helpers/nav_helper.rb @@ -19,6 +19,12 @@ module NavHelper end end + def page_gutter_class + if current_path?('merge_requests#show') || current_path?('issues#show') + "page-gutter" + end + end + def nav_header_class if nav_menu_collapsed? "header-collapsed" diff --git a/app/views/layouts/_page.html.haml b/app/views/layouts/_page.html.haml index 26159989777..0c1b5eec95a 100644 --- a/app/views/layouts/_page.html.haml +++ b/app/views/layouts/_page.html.haml @@ -1,4 +1,4 @@ -.page-with-sidebar{ class: page_sidebar_class } +.page-with-sidebar{ class: "#{page_sidebar_class} #{page_gutter_class}" } = render "layouts/broadcast" .sidebar-wrapper.nicescroll{ class: nav_sidebar_class } .header-logo diff --git a/app/views/projects/issues/show.html.haml b/app/views/projects/issues/show.html.haml index 51dcca7a1ab..a567c22c823 100644 --- a/app/views/projects/issues/show.html.haml +++ b/app/views/projects/issues/show.html.haml @@ -54,11 +54,9 @@ = render 'votes/votes_block', votable: @issue .row - %section.col-md-9 + %section.col-md-12 .issuable-discussion = render 'projects/issues/discussion' - - %aside.col-md-3 - = render 'shared/issuable/sidebar', issuable: @issue - = render 'shared/show_aside' + += render 'shared/issuable/sidebar', issuable: @issue \ No newline at end of file diff --git a/app/views/projects/merge_requests/_show.html.haml b/app/views/projects/merge_requests/_show.html.haml index 8641c3d8b4b..c2ecb48b094 100644 --- a/app/views/projects/merge_requests/_show.html.haml +++ b/app/views/projects/merge_requests/_show.html.haml @@ -70,11 +70,9 @@ = render 'votes/votes_block', votable: @merge_request .row - %section.col-md-9 + %section.col-md-12 .issuable-discussion = render "projects/merge_requests/discussion" - %aside.col-md-3 - = render 'shared/issuable/sidebar', issuable: @merge_request = render 'shared/show_aside' #commits.commits.tab-pane @@ -87,6 +85,8 @@ .mr-loading-status = spinner += render 'shared/issuable/sidebar', issuable: @merge_request + :javascript var merge_request; diff --git a/app/views/shared/issuable/_sidebar.html.haml b/app/views/shared/issuable/_sidebar.html.haml index 3092ff54242..2aa6dc840eb 100644 --- a/app/views/shared/issuable/_sidebar.html.haml +++ b/app/views/shared/issuable/_sidebar.html.haml @@ -1,88 +1,98 @@ -.issuable-sidebar.issuable-affix - = form_for [@project.namespace.becomes(Namespace), @project, issuable], remote: true, html: {class: 'issuable-context-form inline-update js-issuable-update'} do |f| - .block.assignee - .title - %label - Assignee - - if can?(current_user, :"admin_#{issuable.to_ability_name}", @project) - .pull-right - = link_to 'Edit', '#', class: 'edit-link' - .value - - if issuable.assignee - %strong= link_to_member(@project, issuable.assignee, size: 24) - - if issuable.instance_of?(MergeRequest) && !issuable.can_be_merged_by?(issuable.assignee) - %a.pull-right.cannot-be-merged{href: '#', data: {toggle: 'tooltip'}, title: 'Not allowed to merge'} - = icon('exclamation-triangle') - - else - .light None - - .selectbox - = users_select_tag("#{issuable.class.table_name.singularize}[assignee_id]", placeholder: 'Select assignee', class: 'custom-form-control js-select2 js-assignee', selected: issuable.assignee_id, project: @target_project, null_user: true, current_user: true, first_user: true) +%aside.right-sidebar + .issuable-sidebar + .block + = issuable.iid + of + = issuable_count(:all, @project) + .issuable-nav.pull-right.btn-group{role: 'group', "aria-label" => '...'} + %a.btn.btn-default{href: '#'} + Prev + %a.btn.btn-default{href: '#'} + Next + = form_for [@project.namespace.becomes(Namespace), @project, issuable], remote: true, html: {class: 'issuable-context-form inline-update js-issuable-update'} do |f| + .block.assignee + .title + %label + Assignee + - if can?(current_user, :"admin_#{issuable.to_ability_name}", @project) + .pull-right + = link_to 'Edit', '#', class: 'edit-link' + .value + - if issuable.assignee + %strong= link_to_member(@project, issuable.assignee, size: 24) + - if issuable.instance_of?(MergeRequest) && !issuable.can_be_merged_by?(issuable.assignee) + %a.pull-right.cannot-be-merged{href: '#', data: {toggle: 'tooltip'}, title: 'Not allowed to merge'} + = icon('exclamation-triangle') + - else + .light None - .block.milestone - .title - %label - Milestone - - if can?(current_user, :"admin_#{issuable.to_ability_name}", @project) - .pull-right - = link_to 'Edit', '#', class: 'edit-link' - .value - - if issuable.milestone - %span.back-to-milestone - = link_to namespace_project_milestone_path(@project.namespace, @project, issuable.milestone) do - %strong - = icon('clock-o') - = issuable.milestone.title - - else - .light None - .selectbox - = f.select(:milestone_id, milestone_options(issuable), { include_blank: true }, { class: 'select2 select2-compact js-select2 js-milestone', data: { placeholder: 'Select milestone' }}) - = hidden_field_tag :issuable_context - = f.submit class: 'btn hide' + .selectbox + = users_select_tag("#{issuable.class.table_name.singularize}[assignee_id]", placeholder: 'Select assignee', class: 'custom-form-control js-select2 js-assignee', selected: issuable.assignee_id, project: @target_project, null_user: true, current_user: true, first_user: true) - - if issuable.project.labels.any? - .block + .block.milestone .title - %label Labels + %label + Milestone - if can?(current_user, :"admin_#{issuable.to_ability_name}", @project) .pull-right = link_to 'Edit', '#', class: 'edit-link' - .value.issuable-show-labels - - if issuable.labels.any? - - issuable.labels.each do |label| - = link_to_label(label) + .value + - if issuable.milestone + %span.back-to-milestone + = link_to namespace_project_milestone_path(@project.namespace, @project, issuable.milestone) do + %strong + = icon('clock-o') + = issuable.milestone.title - else .light None .selectbox - = f.collection_select :label_ids, issuable.project.labels.all, :id, :name, - { selected: issuable.label_ids }, multiple: true, class: 'select2 js-select2', data: { placeholder: "Select labels" } + = f.select(:milestone_id, milestone_options(issuable), { include_blank: true }, { class: 'select2 select2-compact js-select2 js-milestone', data: { placeholder: 'Select milestone' }}) + = hidden_field_tag :issuable_context + = f.submit class: 'btn hide' - = render "shared/issuable/participants", participants: issuable.participants(current_user) + - if issuable.project.labels.any? + .block + .title + %label Labels + - if can?(current_user, :"admin_#{issuable.to_ability_name}", @project) + .pull-right + = link_to 'Edit', '#', class: 'edit-link' + .value.issuable-show-labels + - if issuable.labels.any? + - issuable.labels.each do |label| + = link_to_label(label) + - else + .light None + .selectbox + = f.collection_select :label_ids, issuable.project.labels.all, :id, :name, + { selected: issuable.label_ids }, multiple: true, class: 'select2 js-select2', data: { placeholder: "Select labels" } - - if current_user - - subscribed = issuable.subscribed?(current_user) - .block.light - .title - %label.light Notifications - - subscribtion_status = subscribed ? 'subscribed' : 'unsubscribed' - %button.btn.btn-block.btn-gray.subscribe-button{:type => 'button'} - %span= subscribed ? 'Unsubscribe' : 'Subscribe' - .subscription-status{data: {status: subscribtion_status}} - .unsubscribed{class: ( 'hidden' if subscribed )} - You're not receiving notifications from this thread. - .subscribed{class: ( 'hidden' unless subscribed )} - You're receiving notifications because you're subscribed to this thread. + = render "shared/issuable/participants", participants: issuable.participants(current_user) - - project_ref = cross_project_reference(@project, issuable) - .block - .title - .cross-project-reference - %span - Reference: - %cite{title: project_ref} - = project_ref - = clipboard_button(clipboard_text: project_ref) + - if current_user + - subscribed = issuable.subscribed?(current_user) + .block.light + .title + %label.light Notifications + - subscribtion_status = subscribed ? 'subscribed' : 'unsubscribed' + %button.btn.btn-block.btn-gray.subscribe-button{:type => 'button'} + %span= subscribed ? 'Unsubscribe' : 'Subscribe' + .subscription-status{data: {status: subscribtion_status}} + .unsubscribed{class: ( 'hidden' if subscribed )} + You're not receiving notifications from this thread. + .subscribed{class: ( 'hidden' unless subscribed )} + You're receiving notifications because you're subscribed to this thread. + + - project_ref = cross_project_reference(@project, issuable) + .block + .title + .cross-project-reference + %span + Reference: + %cite{title: project_ref} + = project_ref + = clipboard_button(clipboard_text: project_ref) - :javascript - new Subscription("#{toggle_subscription_path(issuable)}"); - new IssuableContext(); \ No newline at end of file + :javascript + new Subscription("#{toggle_subscription_path(issuable)}"); + new IssuableContext(); \ No newline at end of file -- cgit v1.2.1 From ee89e9c8d13c9fd58bb8e36c5ca2d6b35891a1f8 Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Wed, 27 Jan 2016 22:50:18 -0500 Subject: Adds prev/next buttons to top area --- app/assets/stylesheets/framework/variables.scss | 3 ++- app/assets/stylesheets/pages/issuable.scss | 24 ++++++++++++++++++++++++ app/views/shared/issuable/_sidebar.html.haml | 10 +++++++--- 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss index 7af6688963f..f8b6e0e5e6f 100644 --- a/app/assets/stylesheets/framework/variables.scss +++ b/app/assets/stylesheets/framework/variables.scss @@ -13,7 +13,7 @@ $list-font-size: 15px; $sidebar_collapsed_width: 62px; $sidebar_width: 230px; $gutter_collapsed_width: 62px; -$gutter_width: 320px; +$gutter_width: 250px; $avatar_radius: 50%; $code_font_size: 13px; $code_line_height: 1.5; @@ -41,6 +41,7 @@ $white-dark: #ededed; $gray-light: #f7f7f7; $gray-normal: #ededed; $gray-dark: #ededed; +$gray-darkest: #c9c9c9; $green-light: #31AF64; $green-normal: #2FAA60; diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss index d1f2175bfb7..c229d689e3c 100644 --- a/app/assets/stylesheets/pages/issuable.scss +++ b/app/assets/stylesheets/pages/issuable.scss @@ -75,9 +75,28 @@ padding: $gl-padding 0; border-bottom: 1px solid #F0F0F0; + &:first-child { + padding-top: 5px; + } + &:last-child { border: none; } + + span { + margin-top: 7px; + display: inline-block; + } + + .issuable-count { + + } + + .gutter-collapse { + margin-left: 10px; + border-left: 1px solid #F0F0F0; + padding-left: 10px; + } } .title { @@ -145,4 +164,9 @@ overflow: scroll; width: $gutter_width; padding: 10px 20px; + + .btn { + background: $gray-normal; + border: 1px solid $gray-darkest; + } } \ No newline at end of file diff --git a/app/views/shared/issuable/_sidebar.html.haml b/app/views/shared/issuable/_sidebar.html.haml index 2aa6dc840eb..76947ca114d 100644 --- a/app/views/shared/issuable/_sidebar.html.haml +++ b/app/views/shared/issuable/_sidebar.html.haml @@ -1,14 +1,18 @@ %aside.right-sidebar .issuable-sidebar .block - = issuable.iid - of - = issuable_count(:all, @project) + %span.issuable-count.pull-left + = issuable.iid + of + = issuable_count(:all, @project) + %span.gutter-collapse.pull-right + = icon('angle-double-right') .issuable-nav.pull-right.btn-group{role: 'group', "aria-label" => '...'} %a.btn.btn-default{href: '#'} Prev %a.btn.btn-default{href: '#'} Next + = form_for [@project.namespace.becomes(Namespace), @project, issuable], remote: true, html: {class: 'issuable-context-form inline-update js-issuable-update'} do |f| .block.assignee .title -- cgit v1.2.1 From f64e35069eb26959a201c25d548c68d00987d30d Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Wed, 27 Jan 2016 23:47:37 -0500 Subject: Add js to expand and contract side menu --- app/assets/javascripts/application.js.coffee | 21 +++++++++++++++++++++ app/assets/stylesheets/pages/issuable.scss | 13 +++++++++---- app/helpers/application_helper.rb | 6 +++--- app/views/shared/issuable/_sidebar.html.haml | 13 ++++++------- 4 files changed, 39 insertions(+), 14 deletions(-) diff --git a/app/assets/javascripts/application.js.coffee b/app/assets/javascripts/application.js.coffee index 48c9890cfb5..040317ed73a 100644 --- a/app/assets/javascripts/application.js.coffee +++ b/app/assets/javascripts/application.js.coffee @@ -212,4 +212,25 @@ $ -> $this = $(this) $this.attr 'value', $this.val() + $('.right-sidebar').on 'click', '.gutter-toggle', (e) -> + e.preventDefault() + $this = $(this) + $thisIcon = $this.find 'i' + if $thisIcon.hasClass('fa-angle-double-right') + $thisIcon.removeClass('fa-angle-double-right') + .addClass('fa-angle-double-left') + $this + .closest('aside') + .removeClass('right-sidebar-expanded') + .addClass('right-sidebar-collapsed') + else + $thisIcon.removeClass('fa-angle-double-left') + .addClass('fa-angle-double-right') + $this + .closest('aside') + .removeClass('right-sidebar-collapsed') + .addClass('right-sidebar-expanded') + + console.log('collapse') + new Aside() diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss index c229d689e3c..02ac1b2da0c 100644 --- a/app/assets/stylesheets/pages/issuable.scss +++ b/app/assets/stylesheets/pages/issuable.scss @@ -42,8 +42,6 @@ .issuable-details { section { - border-right: 1px solid $border-white-light; - .issuable-discussion { margin-right: 1px; } @@ -92,7 +90,7 @@ } - .gutter-collapse { + .gutter-toggle { margin-left: 10px; border-left: 1px solid #F0F0F0; padding-left: 10px; @@ -162,9 +160,16 @@ transition-duration: .3s; background: $gray-light; overflow: scroll; - width: $gutter_width; padding: 10px 20px; + &.right-sidebar-expanded { + width: $gutter_width; + } + + &.right-sidebar-collapsed { + width: $sidebar_collapsed_width; + } + .btn { background: $gray-normal; border: 1px solid $gray-darkest; diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 57a9ce8294a..b0cd984024f 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -303,7 +303,7 @@ module ApplicationHelper end end - def next_issuable_for(project) + def next_issuable_for(project, id) if project.nil? nil elsif current_controller?(:issues) @@ -313,13 +313,13 @@ module ApplicationHelper end end - def prev_issuable_for(project) + def prev_issuable_for(project, id) if project.nil? nil elsif current_controller?(:issues) project.issues.where("id < ?", id).last elsif current_controller?(:merge_requests) - project.merge_requests.where("id > ?", id).last + project.merge_requests.where("id < ?", id).last end end diff --git a/app/views/shared/issuable/_sidebar.html.haml b/app/views/shared/issuable/_sidebar.html.haml index 76947ca114d..e50c4879848 100644 --- a/app/views/shared/issuable/_sidebar.html.haml +++ b/app/views/shared/issuable/_sidebar.html.haml @@ -1,17 +1,16 @@ -%aside.right-sidebar +%aside.right-sidebar.right-sidebar-expanded .issuable-sidebar .block %span.issuable-count.pull-left = issuable.iid of = issuable_count(:all, @project) - %span.gutter-collapse.pull-right - = icon('angle-double-right') + %span.pull-right + %a.gutter-toggle{href: '#'} + = icon('angle-double-right') .issuable-nav.pull-right.btn-group{role: 'group', "aria-label" => '...'} - %a.btn.btn-default{href: '#'} - Prev - %a.btn.btn-default{href: '#'} - Next + = link_to 'Prev', namespace_project_issue_path(namespace_id: @project, id: prev_issuable_for(@project, issuable.id)), class: 'btn btn-default' + = link_to 'Next', namespace_project_issue_path(namespace_id: @project, id: next_issuable_for(@project, issuable.id)), class: 'btn btn-default' = form_for [@project.namespace.becomes(Namespace), @project, issuable], remote: true, html: {class: 'issuable-context-form inline-update js-issuable-update'} do |f| .block.assignee -- cgit v1.2.1 From 0b030e00a15f849a5cbb2778a6b88c57a2e43d4b Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Thu, 28 Jan 2016 00:06:36 -0500 Subject: Add icon when collapsed. Hide and show icons in collapse and expanded mode. --- app/assets/stylesheets/pages/issuable.scss | 22 ++++++++++++++++++++++ app/views/shared/issuable/_sidebar.html.haml | 6 ++++-- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss index 02ac1b2da0c..6be1163a8a6 100644 --- a/app/assets/stylesheets/pages/issuable.scss +++ b/app/assets/stylesheets/pages/issuable.scss @@ -174,4 +174,26 @@ background: $gray-normal; border: 1px solid $gray-darkest; } + + &.right-sidebar-collapsed { + .issuable-count, + .issuable-nav, + .assignee .title, + .assignee .selectbox, + .assignee .value .author, + .milestone, + .labels, + .participants, + .light, + .project-reference { + display: none; + } + + } + + &.right-sidebar-expanded { + .sidebar-collapsed-icon { + display: none; + } + } } \ No newline at end of file diff --git a/app/views/shared/issuable/_sidebar.html.haml b/app/views/shared/issuable/_sidebar.html.haml index e50c4879848..486c1c922d5 100644 --- a/app/views/shared/issuable/_sidebar.html.haml +++ b/app/views/shared/issuable/_sidebar.html.haml @@ -33,6 +33,8 @@ = users_select_tag("#{issuable.class.table_name.singularize}[assignee_id]", placeholder: 'Select assignee', class: 'custom-form-control js-select2 js-assignee', selected: issuable.assignee_id, project: @target_project, null_user: true, current_user: true, first_user: true) .block.milestone + .sidebar-collapsed-icon + = icon('balance-scale') .title %label Milestone @@ -54,7 +56,7 @@ = f.submit class: 'btn hide' - if issuable.project.labels.any? - .block + .block.labels .title %label Labels - if can?(current_user, :"admin_#{issuable.to_ability_name}", @project) @@ -87,7 +89,7 @@ You're receiving notifications because you're subscribed to this thread. - project_ref = cross_project_reference(@project, issuable) - .block + .block.project-reference .title .cross-project-reference %span -- cgit v1.2.1 From 9109619ee6fe85ee7e8ebfa51c6587319b523930 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Thu, 28 Jan 2016 15:02:44 +0100 Subject: Use less memory while counting lines --- app/views/shared/_file_highlight.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/shared/_file_highlight.html.haml b/app/views/shared/_file_highlight.html.haml index 2bc98983d67..331bad3ccf7 100644 --- a/app/views/shared/_file_highlight.html.haml +++ b/app/views/shared/_file_highlight.html.haml @@ -1,7 +1,7 @@ .file-content.code.js-syntax-highlight{ class: user_color_scheme } .line-numbers - if blob.data.present? - - blob.data.lines.each_index do |index| + - blob.data.each_line.each_with_index do |_, index| - offset = defined?(first_line_number) ? first_line_number : 1 - i = index + offset -# We're not using `link_to` because it is too slow once we get to thousands of lines. -- cgit v1.2.1 From 26d97ac5e19c242594b59d224a77d41d0f1de6e1 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Thu, 28 Jan 2016 18:04:46 +0100 Subject: Send more raw blob data with workhorse --- app/controllers/projects/avatars_controller.rb | 13 ++++++------- app/controllers/projects/raw_controller.rb | 2 +- lib/api/repositories.rb | 6 ++++-- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/app/controllers/projects/avatars_controller.rb b/app/controllers/projects/avatars_controller.rb index 548f1b9ebfe..0cd65ad5b16 100644 --- a/app/controllers/projects/avatars_controller.rb +++ b/app/controllers/projects/avatars_controller.rb @@ -2,15 +2,14 @@ class Projects::AvatarsController < Projects::ApplicationController before_action :project def show - @blob = @project.repository.blob_at_branch('master', @project.avatar_in_git) + repository = @project.repository + @blob = repository.blob_at_branch('master', @project.avatar_in_git) if @blob headers['X-Content-Type-Options'] = 'nosniff' - send_data( - @blob.data, - type: @blob.mime_type, - disposition: 'inline', - filename: @blob.name - ) + headers['Gitlab-Workhorse-Repo-Path'] = repository.path_to_repo + headers['Gitlab-Workhorse-Send-Blob'] = @blob.id + headers['Content-Disposition'] = 'inline' + render nothing: true, content_type: @blob.content_type else render_404 end diff --git a/app/controllers/projects/raw_controller.rb b/app/controllers/projects/raw_controller.rb index e55cdea94ae..b3c846bc3c3 100644 --- a/app/controllers/projects/raw_controller.rb +++ b/app/controllers/projects/raw_controller.rb @@ -18,7 +18,7 @@ class Projects::RawController < Projects::ApplicationController send_lfs_object else headers['Gitlab-Workhorse-Repo-Path'] = @repository.path_to_repo - headers['Gitlab-Workhorse-Send-Blob'] = Base64.urlsafe_encode64(@commit.id + ':' + @path) + headers['Gitlab-Workhorse-Send-Blob'] = @blob.id headers['Content-Disposition'] = 'inline' render nothing: true, content_type: get_blob_type end diff --git a/lib/api/repositories.rb b/lib/api/repositories.rb index d7c48639eba..0f4cd2443b0 100644 --- a/lib/api/repositories.rb +++ b/lib/api/repositories.rb @@ -57,7 +57,8 @@ module API not_found! "File" unless blob content_type 'text/plain' - present blob.data + header 'Gitlab-Workhorse-Repo-Path', repo.path_to_repo + header 'Gitlab-Workhorse-Send-Blob', blob.id end # Get a raw blob contents by blob sha @@ -83,7 +84,8 @@ module API env['api.format'] = :txt content_type blob.mime_type - present blob.data + header 'Gitlab-Workhorse-Repo-Path', repo.path_to_repo + header 'Gitlab-Workhorse-Send-Blob', blob.id end # Get a an archive of the repository -- cgit v1.2.1 From 368b855d88597a48637145838f61113af9c0e98e Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Thu, 28 Jan 2016 18:08:37 +0100 Subject: No need for base64 anymore --- app/controllers/projects/raw_controller.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/controllers/projects/raw_controller.rb b/app/controllers/projects/raw_controller.rb index b3c846bc3c3..b8b90489027 100644 --- a/app/controllers/projects/raw_controller.rb +++ b/app/controllers/projects/raw_controller.rb @@ -1,5 +1,3 @@ -require 'base64' - # Controller for viewing a file's raw class Projects::RawController < Projects::ApplicationController include ExtractsPath -- cgit v1.2.1 From 0197549d57bd32ee933ee775c625ed6fc5f5eec8 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Thu, 28 Jan 2016 18:09:52 +0100 Subject: Cannot see a raw blob without workhorse --- features/steps/project/source/browse_files.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/steps/project/source/browse_files.rb b/features/steps/project/source/browse_files.rb index d08935aa101..71db552f7b4 100644 --- a/features/steps/project/source/browse_files.rb +++ b/features/steps/project/source/browse_files.rb @@ -52,7 +52,7 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps end step 'I should see raw file content' do - expect(source).to eq sample_blob.data + expect(source).to eq '' # Body is filled in by gitlab-workhorse end step 'I click button "Edit"' do -- cgit v1.2.1 From 9c2bd8b70eedc9969f5ba4c7fc1a7d96369e1438 Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Thu, 28 Jan 2016 18:26:47 -0500 Subject: Sidebar collapse and expand work with whole page. --- app/assets/javascripts/application.js.coffee | 11 +++++++-- app/assets/stylesheets/framework/sidebar.scss | 11 ++++++++- app/assets/stylesheets/pages/issuable.scss | 27 ++++++++++++++++++---- app/helpers/application_helper.rb | 28 +++++++++++++++++++---- app/helpers/nav_helper.rb | 19 ++++++++++++++- app/views/shared/issuable/_participants.html.haml | 2 ++ app/views/shared/issuable/_sidebar.html.haml | 27 ++++++++++++++++++---- 7 files changed, 108 insertions(+), 17 deletions(-) diff --git a/app/assets/javascripts/application.js.coffee b/app/assets/javascripts/application.js.coffee index 040317ed73a..02b0a32539a 100644 --- a/app/assets/javascripts/application.js.coffee +++ b/app/assets/javascripts/application.js.coffee @@ -223,6 +223,9 @@ $ -> .closest('aside') .removeClass('right-sidebar-expanded') .addClass('right-sidebar-collapsed') + $('.page-with-sidebar') + .removeClass('right-sidebar-expanded') + .addClass('right-sidebar-collapsed') else $thisIcon.removeClass('fa-angle-double-left') .addClass('fa-angle-double-right') @@ -230,7 +233,11 @@ $ -> .closest('aside') .removeClass('right-sidebar-collapsed') .addClass('right-sidebar-expanded') - - console.log('collapse') + $('.page-with-sidebar') + .removeClass('right-sidebar-collapsed') + .addClass('right-sidebar-expanded') + $.cookie("collapsed_gutter", + $('.right-sidebar') + .hasClass('right-sidebar-collapsed'), { path: '/' }) new Aside() diff --git a/app/assets/stylesheets/framework/sidebar.scss b/app/assets/stylesheets/framework/sidebar.scss index e0fc969ff0e..1616c140c0d 100644 --- a/app/assets/stylesheets/framework/sidebar.scss +++ b/app/assets/stylesheets/framework/sidebar.scss @@ -204,6 +204,10 @@ padding-right: $gutter_width; } +@mixin collapsed-gutter { + padding-right: $sidebar_collapsed_width; +} + @mixin collapsed-sidebar { padding-left: $sidebar_collapsed_width; @@ -289,7 +293,12 @@ @media(min-width: $screen-md-max) { .page-gutter { - @include expanded-gutter; + &.right-sidebar-collapsed { + @include collapsed-gutter; + } + &.right-sidebar-expanded { + @include expanded-gutter; + } } .page-sidebar-collapsed { diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss index 6be1163a8a6..9bceb06ae4b 100644 --- a/app/assets/stylesheets/pages/issuable.scss +++ b/app/assets/stylesheets/pages/issuable.scss @@ -72,6 +72,11 @@ @include clearfix; padding: $gl-padding 0; border-bottom: 1px solid #F0F0F0; + // This prevents the mess when resizing the sidebar + // of elements repositioning themselves.. + width: 210px; + overflow-x: hidden; + // -- &:first-child { padding-top: 5px; @@ -181,14 +186,26 @@ .assignee .title, .assignee .selectbox, .assignee .value .author, - .milestone, - .labels, - .participants, - .light, - .project-reference { + .milestone > *, + .labels > *, + .participants > *, + .light > *, + .project-reference > * { display: none; } + .assignee { + margin-left: -7px; + } + + .gutter-toggle { + margin-left: -207px; + } + + .sidebar-collapsed-icon { + display: block; + } + } &.right-sidebar-expanded { diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index b0cd984024f..00f38932861 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -307,9 +307,19 @@ module ApplicationHelper if project.nil? nil elsif current_controller?(:issues) - project.issues.where("id > ?", id).first + project.issues.where("id > ?", id).last elsif current_controller?(:merge_requests) - project.merge_requests.where("id > ?", id).first + project.merge_requests.where("id > ?", id).last + end + end + + def has_next_issuable?(project, id) + if project.nil? + nil + elsif current_controller?(:issues) + project.issues.where("id > ?", id).last + elsif current_controller?(:merge_requests) + project.merge_requests.where("id > ?", id).last end end @@ -317,9 +327,19 @@ module ApplicationHelper if project.nil? nil elsif current_controller?(:issues) - project.issues.where("id < ?", id).last + project.issues.where("id < ?", id).first + elsif current_controller?(:merge_requests) + project.merge_requests.where("id < ?", id).first + end + end + + def has_prev_issuable?(project, id) + if project.nil? + nil + elsif current_controller?(:issues) + project.issues.where("id < ?", id).first elsif current_controller?(:merge_requests) - project.merge_requests.where("id < ?", id).last + project.merge_requests.where("id < ?", id).first end end diff --git a/app/helpers/nav_helper.rb b/app/helpers/nav_helper.rb index 20b89cc9db3..2c299d1d794 100644 --- a/app/helpers/nav_helper.rb +++ b/app/helpers/nav_helper.rb @@ -3,6 +3,18 @@ module NavHelper cookies[:collapsed_nav] == 'true' end + def sidebar_gutter_collapsed_class + if cookies[:collapsed_gutter] == 'true' + "right-sidebar-collapsed" + else + "right-sidebar-expanded" + end + end + + def sidebar_gutter_collapsed? + cookies[:collapsed_gutter] == 'true' + end + def nav_sidebar_class if nav_menu_collapsed? "sidebar-collapsed" @@ -20,8 +32,13 @@ module NavHelper end def page_gutter_class + if current_path?('merge_requests#show') || current_path?('issues#show') - "page-gutter" + if cookies[:collapsed_gutter] == 'true' + "page-gutter right-sidebar-collapsed" + else + "page-gutter right-sidebar-expanded" + end end end diff --git a/app/views/shared/issuable/_participants.html.haml b/app/views/shared/issuable/_participants.html.haml index da6bacbb74a..ed34b6d0aef 100644 --- a/app/views/shared/issuable/_participants.html.haml +++ b/app/views/shared/issuable/_participants.html.haml @@ -1,4 +1,6 @@ .block.participants + .sidebar-collapsed-icon + = icon('users') .title = pluralize participants.count, "participant" - participants.each do |participant| diff --git a/app/views/shared/issuable/_sidebar.html.haml b/app/views/shared/issuable/_sidebar.html.haml index 486c1c922d5..123eba5f1cf 100644 --- a/app/views/shared/issuable/_sidebar.html.haml +++ b/app/views/shared/issuable/_sidebar.html.haml @@ -1,4 +1,4 @@ -%aside.right-sidebar.right-sidebar-expanded +%aside.right-sidebar{ class: sidebar_gutter_collapsed_class } .issuable-sidebar .block %span.issuable-count.pull-left @@ -7,13 +7,26 @@ = issuable_count(:all, @project) %span.pull-right %a.gutter-toggle{href: '#'} - = icon('angle-double-right') + - if sidebar_gutter_collapsed? + = icon('angle-double-left') + - else + = icon('angle-double-right') .issuable-nav.pull-right.btn-group{role: 'group', "aria-label" => '...'} - = link_to 'Prev', namespace_project_issue_path(namespace_id: @project, id: prev_issuable_for(@project, issuable.id)), class: 'btn btn-default' - = link_to 'Next', namespace_project_issue_path(namespace_id: @project, id: next_issuable_for(@project, issuable.id)), class: 'btn btn-default' + - if has_prev_issuable?(@project, issuable.id) + = link_to 'Prev', namespace_project_issue_path(@project.namespace, @project, prev_issuable_for(@project, issuable.id).try(:iid)), class: 'btn btn-default' + - else + %a.btn.btn-default.disabled{href: '#'} + Prev + - if has_next_issuable?(@project, issuable.id) + = link_to 'Next', namespace_project_issue_path(@project.namespace, @project, next_issuable_for(@project, issuable.id).try(:iid)), class: 'btn btn-default' + - else + %a.btn.btn-default.disabled{href: '#'} + Next = form_for [@project.namespace.becomes(Namespace), @project, issuable], remote: true, html: {class: 'issuable-context-form inline-update js-issuable-update'} do |f| .block.assignee + .sidebar-collapsed-icon + = icon('user') .title %label Assignee @@ -57,6 +70,8 @@ - if issuable.project.labels.any? .block.labels + .sidebar-collapsed-icon + = icon('tags') .title %label Labels - if can?(current_user, :"admin_#{issuable.to_ability_name}", @project) @@ -77,6 +92,8 @@ - if current_user - subscribed = issuable.subscribed?(current_user) .block.light + .sidebar-collapsed-icon + = icon('rss') .title %label.light Notifications - subscribtion_status = subscribed ? 'subscribed' : 'unsubscribed' @@ -90,6 +107,8 @@ - project_ref = cross_project_reference(@project, issuable) .block.project-reference + .sidebar-collapsed-icon + = icon('clipboard') .title .cross-project-reference %span -- cgit v1.2.1 From 1bba15589a6c8b349bf235058c13120618d516b6 Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Thu, 28 Jan 2016 19:27:42 -0500 Subject: Fix icon centering on collapsed view --- app/assets/stylesheets/pages/issuable.scss | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss index 9bceb06ae4b..5d1a488d377 100644 --- a/app/assets/stylesheets/pages/issuable.scss +++ b/app/assets/stylesheets/pages/issuable.scss @@ -183,9 +183,7 @@ &.right-sidebar-collapsed { .issuable-count, .issuable-nav, - .assignee .title, - .assignee .selectbox, - .assignee .value .author, + .assignee > *, .milestone > *, .labels > *, .participants > *, @@ -194,16 +192,17 @@ display: none; } - .assignee { - margin-left: -7px; - } - .gutter-toggle { margin-left: -207px; } .sidebar-collapsed-icon { display: block; + float: left; + width: 62px; + text-align: center; + margin-left: -19px; +} } } -- cgit v1.2.1 From 541fcc37bf0c8979cc1495b63ac71912cc28f825 Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Thu, 28 Jan 2016 20:36:48 -0500 Subject: Add detail to collapsed icons --- app/assets/stylesheets/pages/issuable.scss | 25 ++++++++++++++++++++++- app/helpers/projects_helper.rb | 6 ++++++ app/views/shared/issuable/_participants.html.haml | 2 ++ app/views/shared/issuable/_sidebar.html.haml | 14 +++++++++++-- 4 files changed, 44 insertions(+), 3 deletions(-) diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss index 5d1a488d377..16429e01e0a 100644 --- a/app/assets/stylesheets/pages/issuable.scss +++ b/app/assets/stylesheets/pages/issuable.scss @@ -169,10 +169,28 @@ &.right-sidebar-expanded { width: $gutter_width; + + hr { + display: none; + } } &.right-sidebar-collapsed { width: $sidebar_collapsed_width; + padding-top: 0; + + hr { + margin: 0; + color: $gray-normal; + border-color: $gray-normal; + width: 62px; + margin-left: -20px + } + + .block { + border-bottom: none; + padding: 15px 0 0 0; + } } .btn { @@ -202,7 +220,12 @@ width: 62px; text-align: center; margin-left: -19px; -} + padding-bottom: 10px; + + span { + display: block; + margin-top: 0; + } } } diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 77ba612548a..9215f29209c 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -20,6 +20,12 @@ module ProjectsHelper end end + def link_to_member_avatar(author, opts = {}) + default_opts = { avatar: true, name: true, size: 16, author_class: 'author', title: ":name" } + opts = default_opts.merge(opts) + image_tag(avatar_icon(author, opts[:size]), width: opts[:size], class: "avatar avatar-inline #{"s#{opts[:size]}" if opts[:size]}", alt:'') if opts[:avatar] + end + def link_to_member(project, author, opts = {}) default_opts = { avatar: true, name: true, size: 16, author_class: 'author', title: ":name" } opts = default_opts.merge(opts) diff --git a/app/views/shared/issuable/_participants.html.haml b/app/views/shared/issuable/_participants.html.haml index ed34b6d0aef..ea61935487c 100644 --- a/app/views/shared/issuable/_participants.html.haml +++ b/app/views/shared/issuable/_participants.html.haml @@ -1,6 +1,8 @@ .block.participants .sidebar-collapsed-icon = icon('users') + %span + = participants.count .title = pluralize participants.count, "participant" - participants.each do |participant| diff --git a/app/views/shared/issuable/_sidebar.html.haml b/app/views/shared/issuable/_sidebar.html.haml index 123eba5f1cf..f4f04a42196 100644 --- a/app/views/shared/issuable/_sidebar.html.haml +++ b/app/views/shared/issuable/_sidebar.html.haml @@ -26,7 +26,10 @@ = form_for [@project.namespace.becomes(Namespace), @project, issuable], remote: true, html: {class: 'issuable-context-form inline-update js-issuable-update'} do |f| .block.assignee .sidebar-collapsed-icon - = icon('user') + - if issuable.assignee + = link_to_member_avatar(issuable.assignee, size: 24) + - else + = icon('user') .title %label Assignee @@ -48,6 +51,11 @@ .block.milestone .sidebar-collapsed-icon = icon('balance-scale') + %span + - if issuable.milestone + = issuable.milestone.title + - else + No .title %label Milestone @@ -72,6 +80,8 @@ .block.labels .sidebar-collapsed-icon = icon('tags') + %span + = issuable.labels.count .title %label Labels - if can?(current_user, :"admin_#{issuable.to_ability_name}", @project) @@ -88,7 +98,7 @@ { selected: issuable.label_ids }, multiple: true, class: 'select2 js-select2', data: { placeholder: "Select labels" } = render "shared/issuable/participants", participants: issuable.participants(current_user) - + %hr - if current_user - subscribed = issuable.subscribed?(current_user) .block.light -- cgit v1.2.1 From fc334e72f40ab5394c70f5cd29829dc3c0b0d485 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 29 Jan 2016 10:28:05 +0000 Subject: Adds the markdown link at the cursor poisition When writing a comment and then dropping an image it will correctly add the image markdown link at the cursor position Fixes #12822 --- app/assets/javascripts/dropzone_input.js.coffee | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/assets/javascripts/dropzone_input.js.coffee b/app/assets/javascripts/dropzone_input.js.coffee index c714c0fa939..32a5594a5b1 100644 --- a/app/assets/javascripts/dropzone_input.js.coffee +++ b/app/assets/javascripts/dropzone_input.js.coffee @@ -65,8 +65,13 @@ class @DropzoneInput return success: (header, response) -> + link_markdown = response.link.markdown child = $(dropzone[0]).children("textarea") - $(child).val $(child).val() + response.link.markdown + "\n" + cursor_pos = child.prop "selectionStart" + value = $(child).val() + new_text = "#{value.substring(0, cursor_pos)}#{link_markdown}#{value.substring(cursor_pos, value.length)}" + + $(child).val new_text + "\n" return error: (temp, errorMessage) -> -- cgit v1.2.1 From eb51a4ac1b7702873ecb9de7ddafdb989370437c Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 29 Jan 2016 15:35:21 +0100 Subject: refactor previous test and add validation to project model --- lib/gitlab/regex.rb | 4 ++-- spec/controllers/projects_controller_spec.rb | 9 +++------ 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/lib/gitlab/regex.rb b/lib/gitlab/regex.rb index 53ab2686b43..3331bd123b2 100644 --- a/lib/gitlab/regex.rb +++ b/lib/gitlab/regex.rb @@ -34,12 +34,12 @@ module Gitlab def project_path_regex - @project_path_regex ||= /\A[a-zA-Z0-9_.][a-zA-Z0-9_\-\.]*(? Date: Fri, 29 Jan 2016 15:55:31 +0000 Subject: Keeps cursor at the correct place after changing text in dropzone --- app/assets/javascripts/dropzone_input.js.coffee | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/app/assets/javascripts/dropzone_input.js.coffee b/app/assets/javascripts/dropzone_input.js.coffee index 32a5594a5b1..b502131a99d 100644 --- a/app/assets/javascripts/dropzone_input.js.coffee +++ b/app/assets/javascripts/dropzone_input.js.coffee @@ -65,13 +65,7 @@ class @DropzoneInput return success: (header, response) -> - link_markdown = response.link.markdown - child = $(dropzone[0]).children("textarea") - cursor_pos = child.prop "selectionStart" - value = $(child).val() - new_text = "#{value.substring(0, cursor_pos)}#{link_markdown}#{value.substring(cursor_pos, value.length)}" - - $(child).val new_text + "\n" + pasteText response.link.markdown return error: (temp, errorMessage) -> @@ -133,6 +127,7 @@ class @DropzoneInput beforeSelection = $(child).val().substring 0, caretStart afterSelection = $(child).val().substring caretEnd, textEnd $(child).val beforeSelection + text + afterSelection + child.get(0).setSelectionRange caretStart + text.length, caretEnd + text.length form_textarea.trigger "input" getFilename = (e) -> -- cgit v1.2.1 From 7dffec2c43116fa339f967b1005f23442752ce0d Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 29 Jan 2016 18:52:49 +0100 Subject: WIP - add migration --- ...5155_remove_dot_atom_path_ending_of_projects.rb | 54 ++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 db/migrate/20160129135155_remove_dot_atom_path_ending_of_projects.rb diff --git a/db/migrate/20160129135155_remove_dot_atom_path_ending_of_projects.rb b/db/migrate/20160129135155_remove_dot_atom_path_ending_of_projects.rb new file mode 100644 index 00000000000..c7b986aca91 --- /dev/null +++ b/db/migrate/20160129135155_remove_dot_atom_path_ending_of_projects.rb @@ -0,0 +1,54 @@ +class RemoveDotAtomPathEndingOfProjects < ActiveRecord::Migration + + class ProjectPath + def initilize(old_path) + @old_path = old_path + end + + def clean_path + @_clean_path ||= PathCleaner.clean(@old_path) + end + end + + module PathCleaner + def initialize(path) + @path = path + end + + def self.clean(*args) + new(*args).clean + end + + def clean + path = cleaned_path + count = 0 + while path_exists?(path) + path = "#{cleaned_path}#{count}" + count += 1 + end + path + end + + def cleaned_path + @_cleaned_path ||= path.gsub(/\.atom\z/, '-atom') + end + + def path_exists?(path) + Project.find_by_path(path) + end + end + + def up + projects_with_dot_atom.each do |project| + remove_dot(project) + end + end + + private + + def remove_dot(project) + #TODO + end + + +end -- cgit v1.2.1 From e2b6e9c3c531649535e47de0814dd4cb651411fa Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Sat, 30 Jan 2016 00:30:25 -0500 Subject: Add ajax calls to return JSON Fix subtitles on minimize. Fix styles for show. --- app/assets/stylesheets/framework/mobile.scss | 2 +- app/assets/stylesheets/framework/sidebar.scss | 9 +++++++++ app/controllers/projects/issues_controller.rb | 4 +++- app/views/projects/issues/show.html.haml | 1 - app/views/projects/merge_requests/_show.html.haml | 1 - app/views/shared/issuable/_sidebar.html.haml | 2 +- 6 files changed, 14 insertions(+), 5 deletions(-) diff --git a/app/assets/stylesheets/framework/mobile.scss b/app/assets/stylesheets/framework/mobile.scss index 0997dfc287c..3bfac2ad9b5 100644 --- a/app/assets/stylesheets/framework/mobile.scss +++ b/app/assets/stylesheets/framework/mobile.scss @@ -116,7 +116,7 @@ display: none; } - aside { + aside:not(.right-sidebar){ display: none; } diff --git a/app/assets/stylesheets/framework/sidebar.scss b/app/assets/stylesheets/framework/sidebar.scss index 1616c140c0d..b7f532c0771 100644 --- a/app/assets/stylesheets/framework/sidebar.scss +++ b/app/assets/stylesheets/framework/sidebar.scss @@ -284,6 +284,15 @@ @include collapsed-sidebar; } + .page-gutter { + &.right-sidebar-collapsed { + @include collapsed-gutter; + } + &.right-sidebar-expanded { + @include expanded-gutter; + } + } + .collapse-nav { display: none; } diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb index 68244883803..1b6ea280ad4 100644 --- a/app/controllers/projects/issues_controller.rb +++ b/app/controllers/projects/issues_controller.rb @@ -98,7 +98,9 @@ class Projects::IssuesController < Projects::ApplicationController format.json do render json: { saved: @issue.valid?, - assignee_avatar_url: @issue.assignee.try(:avatar_url) + assignee_avatar_url: @issue.assignee.try(:avatar_url), + milestone: @issue.milestone.title, + labels: @issue.labels.pluck(:id,:title,:color) } end end diff --git a/app/views/projects/issues/show.html.haml b/app/views/projects/issues/show.html.haml index a567c22c823..030f4a2e644 100644 --- a/app/views/projects/issues/show.html.haml +++ b/app/views/projects/issues/show.html.haml @@ -57,6 +57,5 @@ %section.col-md-12 .issuable-discussion = render 'projects/issues/discussion' - = render 'shared/show_aside' = render 'shared/issuable/sidebar', issuable: @issue \ No newline at end of file diff --git a/app/views/projects/merge_requests/_show.html.haml b/app/views/projects/merge_requests/_show.html.haml index c2ecb48b094..da67645bc2b 100644 --- a/app/views/projects/merge_requests/_show.html.haml +++ b/app/views/projects/merge_requests/_show.html.haml @@ -73,7 +73,6 @@ %section.col-md-12 .issuable-discussion = render "projects/merge_requests/discussion" - = render 'shared/show_aside' #commits.commits.tab-pane - # This tab is always loaded via AJAX diff --git a/app/views/shared/issuable/_sidebar.html.haml b/app/views/shared/issuable/_sidebar.html.haml index f4f04a42196..0ed2c9c710d 100644 --- a/app/views/shared/issuable/_sidebar.html.haml +++ b/app/views/shared/issuable/_sidebar.html.haml @@ -23,7 +23,7 @@ %a.btn.btn-default.disabled{href: '#'} Next - = form_for [@project.namespace.becomes(Namespace), @project, issuable], remote: true, html: {class: 'issuable-context-form inline-update js-issuable-update'} do |f| + = form_for [@project.namespace.becomes(Namespace), @project, issuable], remote: true, html: {class: 'issuable-context-form inline-update js-issuable-update', 'data-type' => 'json'} do |f| .block.assignee .sidebar-collapsed-icon - if issuable.assignee -- cgit v1.2.1 From a1e1e72375c6b8f511c779c74b3dd1073afff6c1 Mon Sep 17 00:00:00 2001 From: Warren Guy Date: Sat, 30 Jan 2016 18:30:51 +0800 Subject: Generate valid Message-ID in email rejection mailer Use a Message-ID that is RFC 2111 compliant. This fix is consistent with how the Message-ID is generated in the 'notify' mailer. --- app/mailers/email_rejection_mailer.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/mailers/email_rejection_mailer.rb b/app/mailers/email_rejection_mailer.rb index 883f1c73ad4..76db31a4c45 100644 --- a/app/mailers/email_rejection_mailer.rb +++ b/app/mailers/email_rejection_mailer.rb @@ -10,7 +10,7 @@ class EmailRejectionMailer < BaseMailer subject: "[Rejected] #{@original_message.subject}" } - headers['Message-ID'] = SecureRandom.hex + headers['Message-ID'] = "<#{SecureRandom.hex}@#{Gitlab.config.gitlab.host}>" headers['In-Reply-To'] = @original_message.message_id headers['References'] = @original_message.message_id -- cgit v1.2.1 From 026c31dafc80059ec429b484dc28e03e91df2238 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Sat, 23 Jan 2016 14:59:22 -0800 Subject: Bump New Relic gem version to avoid warnings in Web page --- CHANGELOG | 1 + Gemfile | 2 +- Gemfile.lock | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 0a21462ebdb..a8cbcdfe26d 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 8.5.0 (unreleased) - Ensure rake tasks that don't need a DB connection can be run without one + - Update New Relic gem to 3.14.1.311 (Stan Hu) - Add "visibility" flag to GET /projects api endpoint - Ignore binary files in code search to prevent Error 500 (Stan Hu) - Upgrade gitlab_git to 7.2.23 to fix commit message mentions in first branch push diff --git a/Gemfile b/Gemfile index a09d44f8bfd..a1a9c776ae7 100644 --- a/Gemfile +++ b/Gemfile @@ -299,7 +299,7 @@ group :production do gem "gitlab_meta", '7.0' end -gem "newrelic_rpm", '~> 3.9.4.245' +gem "newrelic_rpm", '~> 3.14' gem 'newrelic-grape' gem 'octokit', '~> 3.8.0' diff --git a/Gemfile.lock b/Gemfile.lock index ec92964df25..4ca79ccd49f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -481,7 +481,7 @@ GEM newrelic-grape (2.1.0) grape newrelic_rpm - newrelic_rpm (3.9.4.245) + newrelic_rpm (3.14.1.311) nokogiri (1.6.7.2) mini_portile2 (~> 2.0.0.rc2) nprogress-rails (0.1.6.7) @@ -961,7 +961,7 @@ DEPENDENCIES nested_form (~> 0.3.2) net-ssh (~> 3.0.1) newrelic-grape - newrelic_rpm (~> 3.9.4.245) + newrelic_rpm (~> 3.14) nokogiri (= 1.6.7.2) nprogress-rails (~> 0.1.6.7) oauth2 (~> 1.0.0) -- cgit v1.2.1 From 2828274b418cccc8171692495dd2856209dbfa49 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Mon, 25 Jan 2016 21:17:38 -0800 Subject: Remove newrelic_grape gem since the New Relic gem now provides native support: https://docs.newrelic.com/docs/agents/ruby-agent/frameworks/grape-instrumentation --- Gemfile | 1 - Gemfile.lock | 4 ---- 2 files changed, 5 deletions(-) diff --git a/Gemfile b/Gemfile index a1a9c776ae7..0420043e869 100644 --- a/Gemfile +++ b/Gemfile @@ -300,7 +300,6 @@ group :production do end gem "newrelic_rpm", '~> 3.14' -gem 'newrelic-grape' gem 'octokit', '~> 3.8.0' diff --git a/Gemfile.lock b/Gemfile.lock index 4ca79ccd49f..981607bdd6b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -478,9 +478,6 @@ GEM net-ldap (0.12.1) net-ssh (3.0.1) netrc (0.11.0) - newrelic-grape (2.1.0) - grape - newrelic_rpm newrelic_rpm (3.14.1.311) nokogiri (1.6.7.2) mini_portile2 (~> 2.0.0.rc2) @@ -960,7 +957,6 @@ DEPENDENCIES mysql2 (~> 0.3.16) nested_form (~> 0.3.2) net-ssh (~> 3.0.1) - newrelic-grape newrelic_rpm (~> 3.14) nokogiri (= 1.6.7.2) nprogress-rails (~> 0.1.6.7) -- cgit v1.2.1 From 9040010481e6ab9b1d9ee2d0699dc99d1109f2f2 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Thu, 14 Jan 2016 19:16:50 +0000 Subject: Added dropdown to list all projects on project header When clicking the current project name, it shows a dropdown menu with a list of all projects for that group or user --- app/assets/stylesheets/framework/header.scss | 22 ++++++++++++++++++++- app/helpers/projects_helper.rb | 29 ++++++++++++++++++++++++---- 2 files changed, 46 insertions(+), 5 deletions(-) diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss index f875b1460e7..0789d8133f9 100644 --- a/app/assets/stylesheets/framework/header.scss +++ b/app/assets/stylesheets/framework/header.scss @@ -73,7 +73,6 @@ header { .title { margin: 0; - overflow: hidden; font-size: 19px; line-height: $header-height; font-weight: normal; @@ -88,6 +87,27 @@ header { text-decoration: underline; } } + + .dropdown { + display: inline-block; + } + + .dropdown-toggle-caret { + margin-left: 5px; + } + + .dropdown-item { + &.active { + .dropdown-link { + color: #fff; + } + } + + .dropdown-link:hover { + color: #fff; + text-decoration: none; + } + } } .navbar-collapse { diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 8c8b355028c..5afbdb332cc 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -45,6 +45,7 @@ module ProjectsHelper end def project_title(project, name = nil, url = nil) + project_id = project.id namespace_link = if project.group link_to(simple_sanitize(project.group.name), group_path(project.group)) @@ -53,14 +54,34 @@ module ProjectsHelper link_to(simple_sanitize(owner.name), user_path(owner)) end - project_link = link_to(simple_sanitize(project.name), project_path(project)) + all_projects = + if project.group + project.group.projects + else + PersonalProjectsFinder.new(project.namespace.owner).execute(current_user) + end + + project_link = content_tag :div, {class: "dropdown"} do + output = content_tag :a, {class: "dropdown-toggle", href: "#", data: {toggle: "dropdown"}} do + btnOutput = simple_sanitize(project.name) + btnOutput += content_tag :span, nil, {class: "caret dropdown-toggle-caret"} + end + + list = all_projects.map do |project| + content_tag :li, {class: "dropdown-item #{"active" if project_id == project.id}"} do + link_to(simple_sanitize(project.name), project_path(project), {class: "dropdown-link"}) + end + end + + output += content_tag :ul, {class: "dropdown-menu"} do + list.join.html_safe + end + end full_title = namespace_link + ' / ' + project_link full_title += ' · '.html_safe + link_to(simple_sanitize(name), url) if name - content_tag :span do - full_title - end + full_title end def remove_project_message(project) -- cgit v1.2.1 From 14394e8bad388dcb331f16353af46755740b216a Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 15 Jan 2016 07:30:36 +0000 Subject: pulls in all user projects --- app/assets/stylesheets/framework/header.scss | 8 ++++++++ app/helpers/projects_helper.rb | 13 +++++-------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss index 0789d8133f9..c71c1cbae34 100644 --- a/app/assets/stylesheets/framework/header.scss +++ b/app/assets/stylesheets/framework/header.scss @@ -92,8 +92,16 @@ header { display: inline-block; } + .dropdown-menu { + max-height: 300px; + overflow: auto; + } + .dropdown-toggle-caret { + position: relative; + top: -2px; margin-left: 5px; + font-size: 10px; } .dropdown-item { diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 5afbdb332cc..238bbbbe0a5 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -54,22 +54,19 @@ module ProjectsHelper link_to(simple_sanitize(owner.name), user_path(owner)) end - all_projects = - if project.group - project.group.projects - else - PersonalProjectsFinder.new(project.namespace.owner).execute(current_user) - end + all_projects = current_user.authorized_projects.sorted_by_activity.non_archived project_link = content_tag :div, {class: "dropdown"} do output = content_tag :a, {class: "dropdown-toggle", href: "#", data: {toggle: "dropdown"}} do btnOutput = simple_sanitize(project.name) - btnOutput += content_tag :span, nil, {class: "caret dropdown-toggle-caret"} + btnOutput += content_tag :span, nil, {class: "fa fa-chevron-down dropdown-toggle-caret"} end list = all_projects.map do |project| content_tag :li, {class: "dropdown-item #{"active" if project_id == project.id}"} do - link_to(simple_sanitize(project.name), project_path(project), {class: "dropdown-link"}) + link_to project_path(project), {class: "dropdown-link"} do + project.owner.name + ' / ' + simple_sanitize(project.name) + end end end -- cgit v1.2.1 From 81e7086fec60c368dcd54ff7195f37f6cb8f481c Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 15 Jan 2016 09:13:12 +0000 Subject: uses AJAX to select the projects --- app/assets/javascripts/project.js.coffee | 10 ++++++++++ app/assets/stylesheets/framework/common.scss | 4 ++-- app/assets/stylesheets/framework/header.scss | 22 ---------------------- app/helpers/projects_helper.rb | 20 ++++---------------- .../shared/_new_project_item_select.html.haml | 8 ++++---- 5 files changed, 20 insertions(+), 44 deletions(-) diff --git a/app/assets/javascripts/project.js.coffee b/app/assets/javascripts/project.js.coffee index d7a658f8faa..9e313436804 100644 --- a/app/assets/javascripts/project.js.coffee +++ b/app/assets/javascripts/project.js.coffee @@ -50,3 +50,13 @@ class @Project $('#notifications-button').empty().append("" + label + "") $(@).parents('ul').find('li.active').removeClass 'active' $(@).parent().addClass 'active' + + @._projectSelectDropdown() + + _projectSelectDropdown: -> + new ProjectSelect() + + $('.js-projects-dropdown-toggle').on 'click', (e) -> + e.preventDefault() + + $('.js-projects-dropdown').select2 'open' diff --git a/app/assets/stylesheets/framework/common.scss b/app/assets/stylesheets/framework/common.scss index 6ea2219073c..ea56d9e12a0 100644 --- a/app/assets/stylesheets/framework/common.scss +++ b/app/assets/stylesheets/framework/common.scss @@ -376,11 +376,11 @@ table { margin-bottom: $gl-padding; } -.new-project-item-select-holder { +.project-item-select-holder { display: inline-block; position: relative; - .new-project-item-select { + .project-item-select { position: absolute; top: 0; right: 0; diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss index c71c1cbae34..7871a33b6c5 100644 --- a/app/assets/stylesheets/framework/header.scss +++ b/app/assets/stylesheets/framework/header.scss @@ -88,34 +88,12 @@ header { } } - .dropdown { - display: inline-block; - } - - .dropdown-menu { - max-height: 300px; - overflow: auto; - } - .dropdown-toggle-caret { position: relative; top: -2px; margin-left: 5px; font-size: 10px; } - - .dropdown-item { - &.active { - .dropdown-link { - color: #fff; - } - } - - .dropdown-link:hover { - color: #fff; - text-decoration: none; - } - } } .navbar-collapse { diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 238bbbbe0a5..c175de94361 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -56,23 +56,11 @@ module ProjectsHelper all_projects = current_user.authorized_projects.sorted_by_activity.non_archived - project_link = content_tag :div, {class: "dropdown"} do - output = content_tag :a, {class: "dropdown-toggle", href: "#", data: {toggle: "dropdown"}} do - btnOutput = simple_sanitize(project.name) - btnOutput += content_tag :span, nil, {class: "fa fa-chevron-down dropdown-toggle-caret"} - end - - list = all_projects.map do |project| - content_tag :li, {class: "dropdown-item #{"active" if project_id == project.id}"} do - link_to project_path(project), {class: "dropdown-link"} do - project.owner.name + ' / ' + simple_sanitize(project.name) - end - end - end + project_link = link_to project_path(project), {class: "project-item-select-holder js-projects-dropdown-toggle"} do + link_output = simple_sanitize(project.name) + link_output += content_tag :span, nil, {class: "fa fa-chevron-down dropdown-toggle-caret"} - output += content_tag :ul, {class: "dropdown-menu"} do - list.join.html_safe - end + link_output += project_select_tag :project_path, class: "project-item-select js-projects-dropdown", data: { include_groups: false } end full_title = namespace_link + ' / ' + project_link diff --git a/app/views/shared/_new_project_item_select.html.haml b/app/views/shared/_new_project_item_select.html.haml index c4431d66927..46095912821 100644 --- a/app/views/shared/_new_project_item_select.html.haml +++ b/app/views/shared/_new_project_item_select.html.haml @@ -1,6 +1,6 @@ - if @projects.any? - .prepend-left-10.new-project-item-select-holder - = project_select_tag :project_path, class: "new-project-item-select", data: { include_groups: local_assigns[:include_groups] } + .prepend-left-10.project-item-select-holder + = project_select_tag :project_path, class: "project-item-select", data: { include_groups: local_assigns[:include_groups] } %a.btn.btn-new.new-project-item-select-button = icon('plus') = local_assigns[:label] @@ -8,12 +8,12 @@ :javascript $('.new-project-item-select-button').on('click', function() { - $('.new-project-item-select').select2('open'); + $('.project-item-select').select2('open'); }); var relativePath = '#{local_assigns[:path]}'; - $('.new-project-item-select').on('click', function() { + $('.project-item-select').on('click', function() { window.location = $(this).val() + '/' + relativePath; }); -- cgit v1.2.1 From a5267d0fbdc3e67d7d7cf3445fd1470676accc7a Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 15 Jan 2016 09:17:09 +0000 Subject: selecting project in dropdown takes user to the correct project --- app/assets/javascripts/project.js.coffee | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/assets/javascripts/project.js.coffee b/app/assets/javascripts/project.js.coffee index 9e313436804..fd7844baac4 100644 --- a/app/assets/javascripts/project.js.coffee +++ b/app/assets/javascripts/project.js.coffee @@ -56,6 +56,9 @@ class @Project _projectSelectDropdown: -> new ProjectSelect() + $('.project-item-select').on 'click', -> + window.location = $(this).val() + $('.js-projects-dropdown-toggle').on 'click', (e) -> e.preventDefault() -- cgit v1.2.1 From 60139345403fe2ddeed27a49582800b365606e2c Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 15 Jan 2016 11:08:12 +0000 Subject: fixes issue when user is not logged in but viewing public project --- app/helpers/projects_helper.rb | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index c175de94361..6c66d0f7251 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -54,13 +54,15 @@ module ProjectsHelper link_to(simple_sanitize(owner.name), user_path(owner)) end - all_projects = current_user.authorized_projects.sorted_by_activity.non_archived + all_projects = current_user.authorized_projects.sorted_by_activity.non_archived if current_user - project_link = link_to project_path(project), {class: "project-item-select-holder js-projects-dropdown-toggle"} do + project_link = link_to project_path(project), {class: "project-item-select-holder #{"js-projects-dropdown-toggle" if current_user}"} do link_output = simple_sanitize(project.name) - link_output += content_tag :span, nil, {class: "fa fa-chevron-down dropdown-toggle-caret"} + link_output += content_tag :span, nil, {class: "fa fa-chevron-down dropdown-toggle-caret"} if current_user - link_output += project_select_tag :project_path, class: "project-item-select js-projects-dropdown", data: { include_groups: false } + link_output += project_select_tag :project_path, class: "project-item-select js-projects-dropdown", data: { include_groups: false } if current_user + + link_output end full_title = namespace_link + ' / ' + project_link -- cgit v1.2.1 From e79b5ff9d65b5a872bfc69649441d6262ac76b4d Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 15 Jan 2016 11:10:27 +0000 Subject: removed un-used variable --- app/helpers/projects_helper.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 6c66d0f7251..705d1e786f4 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -54,8 +54,6 @@ module ProjectsHelper link_to(simple_sanitize(owner.name), user_path(owner)) end - all_projects = current_user.authorized_projects.sorted_by_activity.non_archived if current_user - project_link = link_to project_path(project), {class: "project-item-select-holder #{"js-projects-dropdown-toggle" if current_user}"} do link_output = simple_sanitize(project.name) link_output += content_tag :span, nil, {class: "fa fa-chevron-down dropdown-toggle-caret"} if current_user -- cgit v1.2.1 From 09dc9bd5686501b2c9847896fee9713cf7cf4aea Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 15 Jan 2016 11:43:49 +0000 Subject: rubocop fixes --- app/helpers/projects_helper.rb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 705d1e786f4..e7e472cbb5b 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -45,7 +45,6 @@ module ProjectsHelper end def project_title(project, name = nil, url = nil) - project_id = project.id namespace_link = if project.group link_to(simple_sanitize(project.group.name), group_path(project.group)) @@ -54,9 +53,9 @@ module ProjectsHelper link_to(simple_sanitize(owner.name), user_path(owner)) end - project_link = link_to project_path(project), {class: "project-item-select-holder #{"js-projects-dropdown-toggle" if current_user}"} do + project_link = link_to project_path(project), { class: "project-item-select-holder #{"js-projects-dropdown-toggle" if current_user}" } do link_output = simple_sanitize(project.name) - link_output += content_tag :span, nil, {class: "fa fa-chevron-down dropdown-toggle-caret"} if current_user + link_output += content_tag :span, nil, { class: "fa fa-chevron-down dropdown-toggle-caret" } if current_user link_output += project_select_tag :project_path, class: "project-item-select js-projects-dropdown", data: { include_groups: false } if current_user -- cgit v1.2.1 From d34928ca580b9a605f1fb4f0bc0077b99d694d9b Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 15 Jan 2016 13:04:37 +0000 Subject: remove period from function call --- app/assets/javascripts/project.js.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/javascripts/project.js.coffee b/app/assets/javascripts/project.js.coffee index fd7844baac4..15c5bfa47e9 100644 --- a/app/assets/javascripts/project.js.coffee +++ b/app/assets/javascripts/project.js.coffee @@ -51,7 +51,7 @@ class @Project $(@).parents('ul').find('li.active').removeClass 'active' $(@).parent().addClass 'active' - @._projectSelectDropdown() + @_projectSelectDropdown() _projectSelectDropdown: -> new ProjectSelect() -- cgit v1.2.1 From ad7ec74458523caad5c10108bde620de9a52fe12 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Sun, 17 Jan 2016 14:54:28 +0000 Subject: removed private method naming --- app/assets/javascripts/project.js.coffee | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/project.js.coffee b/app/assets/javascripts/project.js.coffee index 15c5bfa47e9..bf987f115ae 100644 --- a/app/assets/javascripts/project.js.coffee +++ b/app/assets/javascripts/project.js.coffee @@ -51,9 +51,9 @@ class @Project $(@).parents('ul').find('li.active').removeClass 'active' $(@).parent().addClass 'active' - @_projectSelectDropdown() + @projectSelectDropdown() - _projectSelectDropdown: -> + projectSelectDropdown: -> new ProjectSelect() $('.project-item-select').on 'click', -> -- cgit v1.2.1 From 56b0c46bf6da069be4ea935de4bad35a50e7f3c9 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Sun, 17 Jan 2016 17:19:50 +0000 Subject: added tests --- app/assets/javascripts/project.js.coffee | 9 +++-- spec/javascripts/fixtures/project_title.html.haml | 7 ++++ spec/javascripts/fixtures/projects.json | 1 + spec/javascripts/project_title_spec.js.coffee | 46 +++++++++++++++++++++++ 4 files changed, 60 insertions(+), 3 deletions(-) create mode 100644 spec/javascripts/fixtures/project_title.html.haml create mode 100644 spec/javascripts/fixtures/projects.json create mode 100644 spec/javascripts/project_title_spec.js.coffee diff --git a/app/assets/javascripts/project.js.coffee b/app/assets/javascripts/project.js.coffee index bf987f115ae..76bc4ff42a2 100644 --- a/app/assets/javascripts/project.js.coffee +++ b/app/assets/javascripts/project.js.coffee @@ -56,10 +56,13 @@ class @Project projectSelectDropdown: -> new ProjectSelect() - $('.project-item-select').on 'click', -> - window.location = $(this).val() + $('.project-item-select').on 'click', (e) => + @changeProject $(e.currentTarget).val() $('.js-projects-dropdown-toggle').on 'click', (e) -> e.preventDefault() - $('.js-projects-dropdown').select2 'open' + $('.js-projects-dropdown').select2('open') + + changeProject: (url) -> + window.location = url diff --git a/spec/javascripts/fixtures/project_title.html.haml b/spec/javascripts/fixtures/project_title.html.haml new file mode 100644 index 00000000000..4286d1be669 --- /dev/null +++ b/spec/javascripts/fixtures/project_title.html.haml @@ -0,0 +1,7 @@ +%h1.title + %a + GitLab Org + %a.project-item-select-holder.js-projects-dropdown-toggle{href: "/gitlab-org/gitlab-test"} + GitLab Test + %span.fa.fa-chevron-down.dropdown-toggle-caret + %input#project_path.project-item-select.js-projects-dropdown.ajax-project-select{type: "hidden", name: "project_path", "data-include-groups" => "false"} diff --git a/spec/javascripts/fixtures/projects.json b/spec/javascripts/fixtures/projects.json new file mode 100644 index 00000000000..84e8d0ba1e4 --- /dev/null +++ b/spec/javascripts/fixtures/projects.json @@ -0,0 +1 @@ +[{"id":9,"description":"","default_branch":null,"tag_list":[],"public":true,"archived":false,"visibility_level":20,"ssh_url_to_repo":"phil@localhost:root/test.git","http_url_to_repo":"http://localhost:3000/root/test.git","web_url":"http://localhost:3000/root/test","owner":{"name":"Administrator","username":"root","id":1,"state":"active","avatar_url":"http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon","web_url":"http://localhost:3000/u/root"},"name":"test","name_with_namespace":"Administrator / test","path":"test","path_with_namespace":"root/test","issues_enabled":true,"merge_requests_enabled":true,"wiki_enabled":true,"builds_enabled":true,"snippets_enabled":false,"created_at":"2016-01-14T19:08:05.364Z","last_activity_at":"2016-01-14T19:08:07.418Z","shared_runners_enabled":true,"creator_id":1,"namespace":{"id":1,"name":"root","path":"root","owner_id":1,"created_at":"2016-01-13T20:19:44.439Z","updated_at":"2016-01-13T20:19:44.439Z","description":"","avatar":null},"avatar_url":null,"star_count":0,"forks_count":0,"open_issues_count":0,"permissions":{"project_access":null,"group_access":null}},{"id":8,"description":"Voluptatem quae nulla eius numquam ullam voluptatibus quia modi.","default_branch":"master","tag_list":[],"public":false,"archived":false,"visibility_level":0,"ssh_url_to_repo":"phil@localhost:h5bp/html5-boilerplate.git","http_url_to_repo":"http://localhost:3000/h5bp/html5-boilerplate.git","web_url":"http://localhost:3000/h5bp/html5-boilerplate","name":"Html5 Boilerplate","name_with_namespace":"H5bp / Html5 Boilerplate","path":"html5-boilerplate","path_with_namespace":"h5bp/html5-boilerplate","issues_enabled":true,"merge_requests_enabled":true,"wiki_enabled":true,"builds_enabled":true,"snippets_enabled":false,"created_at":"2016-01-13T20:19:57.525Z","last_activity_at":"2016-01-13T20:27:57.280Z","shared_runners_enabled":true,"creator_id":1,"namespace":{"id":5,"name":"H5bp","path":"h5bp","owner_id":null,"created_at":"2016-01-13T20:19:57.239Z","updated_at":"2016-01-13T20:19:57.239Z","description":"Tempore accusantium possimus aut libero.","avatar":{"url":null}},"avatar_url":null,"star_count":0,"forks_count":0,"open_issues_count":5,"permissions":{"project_access":{"access_level":10,"notification_level":3},"group_access":{"access_level":50,"notification_level":3}}},{"id":7,"description":"Modi odio mollitia dolorem qui.","default_branch":"master","tag_list":[],"public":false,"archived":false,"visibility_level":0,"ssh_url_to_repo":"phil@localhost:twitter/typeahead-js.git","http_url_to_repo":"http://localhost:3000/twitter/typeahead-js.git","web_url":"http://localhost:3000/twitter/typeahead-js","name":"Typeahead.Js","name_with_namespace":"Twitter / Typeahead.Js","path":"typeahead-js","path_with_namespace":"twitter/typeahead-js","issues_enabled":true,"merge_requests_enabled":true,"wiki_enabled":true,"builds_enabled":true,"snippets_enabled":false,"created_at":"2016-01-13T20:19:56.212Z","last_activity_at":"2016-01-13T20:27:51.496Z","shared_runners_enabled":true,"creator_id":1,"namespace":{"id":4,"name":"Twitter","path":"twitter","owner_id":null,"created_at":"2016-01-13T20:19:54.480Z","updated_at":"2016-01-13T20:19:54.480Z","description":"Id voluptatem ipsa maiores omnis repudiandae et et.","avatar":{"url":null}},"avatar_url":null,"star_count":0,"forks_count":0,"open_issues_count":4,"permissions":{"project_access":null,"group_access":{"access_level":10,"notification_level":3}}},{"id":6,"description":"Omnis asperiores ipsa et beatae quidem necessitatibus quia.","default_branch":"master","tag_list":[],"public":true,"archived":false,"visibility_level":20,"ssh_url_to_repo":"phil@localhost:twitter/flight.git","http_url_to_repo":"http://localhost:3000/twitter/flight.git","web_url":"http://localhost:3000/twitter/flight","name":"Flight","name_with_namespace":"Twitter / Flight","path":"flight","path_with_namespace":"twitter/flight","issues_enabled":true,"merge_requests_enabled":true,"wiki_enabled":true,"builds_enabled":true,"snippets_enabled":false,"created_at":"2016-01-13T20:19:54.754Z","last_activity_at":"2016-01-13T20:27:50.502Z","shared_runners_enabled":true,"creator_id":1,"namespace":{"id":4,"name":"Twitter","path":"twitter","owner_id":null,"created_at":"2016-01-13T20:19:54.480Z","updated_at":"2016-01-13T20:19:54.480Z","description":"Id voluptatem ipsa maiores omnis repudiandae et et.","avatar":{"url":null}},"avatar_url":null,"star_count":0,"forks_count":0,"open_issues_count":4,"permissions":{"project_access":null,"group_access":{"access_level":10,"notification_level":3}}},{"id":5,"description":"Voluptatem commodi voluptate placeat architecto beatae illum dolores fugiat.","default_branch":"master","tag_list":[],"public":false,"archived":false,"visibility_level":0,"ssh_url_to_repo":"phil@localhost:gitlab-org/gitlab-test.git","http_url_to_repo":"http://localhost:3000/gitlab-org/gitlab-test.git","web_url":"http://localhost:3000/gitlab-org/gitlab-test","name":"Gitlab Test","name_with_namespace":"Gitlab Org / Gitlab Test","path":"gitlab-test","path_with_namespace":"gitlab-org/gitlab-test","issues_enabled":true,"merge_requests_enabled":true,"wiki_enabled":true,"builds_enabled":true,"snippets_enabled":false,"created_at":"2016-01-13T20:19:53.202Z","last_activity_at":"2016-01-13T20:27:41.626Z","shared_runners_enabled":true,"creator_id":1,"namespace":{"id":3,"name":"Gitlab Org","path":"gitlab-org","owner_id":null,"created_at":"2016-01-13T20:19:48.851Z","updated_at":"2016-01-13T20:19:48.851Z","description":"Magni mollitia quod quidem soluta nesciunt impedit.","avatar":{"url":null}},"avatar_url":null,"star_count":0,"forks_count":0,"open_issues_count":5,"permissions":{"project_access":null,"group_access":{"access_level":50,"notification_level":3}}},{"id":4,"description":"Aut molestias quas est ut aperiam officia quod libero.","default_branch":"master","tag_list":[],"public":true,"archived":false,"visibility_level":20,"ssh_url_to_repo":"phil@localhost:gitlab-org/gitlab-shell.git","http_url_to_repo":"http://localhost:3000/gitlab-org/gitlab-shell.git","web_url":"http://localhost:3000/gitlab-org/gitlab-shell","name":"Gitlab Shell","name_with_namespace":"Gitlab Org / Gitlab Shell","path":"gitlab-shell","path_with_namespace":"gitlab-org/gitlab-shell","issues_enabled":true,"merge_requests_enabled":true,"wiki_enabled":true,"builds_enabled":true,"snippets_enabled":false,"created_at":"2016-01-13T20:19:51.882Z","last_activity_at":"2016-01-13T20:27:35.678Z","shared_runners_enabled":true,"creator_id":1,"namespace":{"id":3,"name":"Gitlab Org","path":"gitlab-org","owner_id":null,"created_at":"2016-01-13T20:19:48.851Z","updated_at":"2016-01-13T20:19:48.851Z","description":"Magni mollitia quod quidem soluta nesciunt impedit.","avatar":{"url":null}},"avatar_url":null,"star_count":0,"forks_count":0,"open_issues_count":5,"permissions":{"project_access":{"access_level":20,"notification_level":3},"group_access":{"access_level":50,"notification_level":3}}},{"id":3,"description":"Excepturi molestiae quia repellendus omnis est illo illum eligendi.","default_branch":"master","tag_list":[],"public":true,"archived":false,"visibility_level":20,"ssh_url_to_repo":"phil@localhost:gitlab-org/gitlab-ci.git","http_url_to_repo":"http://localhost:3000/gitlab-org/gitlab-ci.git","web_url":"http://localhost:3000/gitlab-org/gitlab-ci","name":"Gitlab Ci","name_with_namespace":"Gitlab Org / Gitlab Ci","path":"gitlab-ci","path_with_namespace":"gitlab-org/gitlab-ci","issues_enabled":true,"merge_requests_enabled":true,"wiki_enabled":true,"builds_enabled":true,"snippets_enabled":false,"created_at":"2016-01-13T20:19:50.346Z","last_activity_at":"2016-01-13T20:27:30.115Z","shared_runners_enabled":true,"creator_id":1,"namespace":{"id":3,"name":"Gitlab Org","path":"gitlab-org","owner_id":null,"created_at":"2016-01-13T20:19:48.851Z","updated_at":"2016-01-13T20:19:48.851Z","description":"Magni mollitia quod quidem soluta nesciunt impedit.","avatar":{"url":null}},"avatar_url":null,"star_count":0,"forks_count":0,"open_issues_count":3,"permissions":{"project_access":null,"group_access":{"access_level":50,"notification_level":3}}},{"id":2,"description":"Adipisci quaerat dignissimos enim sed ipsam dolorem quia.","default_branch":"master","tag_list":[],"public":false,"archived":false,"visibility_level":10,"ssh_url_to_repo":"phil@localhost:gitlab-org/gitlab-ce.git","http_url_to_repo":"http://localhost:3000/gitlab-org/gitlab-ce.git","web_url":"http://localhost:3000/gitlab-org/gitlab-ce","name":"Gitlab Ce","name_with_namespace":"Gitlab Org / Gitlab Ce","path":"gitlab-ce","path_with_namespace":"gitlab-org/gitlab-ce","issues_enabled":true,"merge_requests_enabled":true,"wiki_enabled":true,"builds_enabled":true,"snippets_enabled":false,"created_at":"2016-01-13T20:19:49.065Z","last_activity_at":"2016-01-13T20:26:58.454Z","shared_runners_enabled":true,"creator_id":1,"namespace":{"id":3,"name":"Gitlab Org","path":"gitlab-org","owner_id":null,"created_at":"2016-01-13T20:19:48.851Z","updated_at":"2016-01-13T20:19:48.851Z","description":"Magni mollitia quod quidem soluta nesciunt impedit.","avatar":{"url":null}},"avatar_url":null,"star_count":0,"forks_count":0,"open_issues_count":5,"permissions":{"project_access":{"access_level":30,"notification_level":3},"group_access":{"access_level":50,"notification_level":3}}},{"id":1,"description":"Vel voluptatem maxime saepe ex quia.","default_branch":"master","tag_list":[],"public":false,"archived":false,"visibility_level":0,"ssh_url_to_repo":"phil@localhost:documentcloud/underscore.git","http_url_to_repo":"http://localhost:3000/documentcloud/underscore.git","web_url":"http://localhost:3000/documentcloud/underscore","name":"Underscore","name_with_namespace":"Documentcloud / Underscore","path":"underscore","path_with_namespace":"documentcloud/underscore","issues_enabled":true,"merge_requests_enabled":true,"wiki_enabled":true,"builds_enabled":true,"snippets_enabled":false,"created_at":"2016-01-13T20:19:45.862Z","last_activity_at":"2016-01-13T20:25:03.106Z","shared_runners_enabled":true,"creator_id":1,"namespace":{"id":2,"name":"Documentcloud","path":"documentcloud","owner_id":null,"created_at":"2016-01-13T20:19:44.464Z","updated_at":"2016-01-13T20:19:44.464Z","description":"Aut impedit perferendis fuga et ipsa repellat cupiditate et.","avatar":{"url":null}},"avatar_url":null,"star_count":0,"forks_count":0,"open_issues_count":5,"permissions":{"project_access":null,"group_access":{"access_level":50,"notification_level":3}}}] diff --git a/spec/javascripts/project_title_spec.js.coffee b/spec/javascripts/project_title_spec.js.coffee new file mode 100644 index 00000000000..47c7b7febe3 --- /dev/null +++ b/spec/javascripts/project_title_spec.js.coffee @@ -0,0 +1,46 @@ +#= require select2 +#= require api +#= require project_select +#= require project + +window.gon = {} +window.gon.api_version = 'v3' + +describe 'Project Title', -> + fixture.preload('project_title.html') + fixture.preload('projects.json') + + beforeEach -> + fixture.load('project_title.html') + @project = new Project() + + spyOn(@project, 'changeProject').and.callFake (url) -> + window.current_project_url = url + + describe 'project list', -> + beforeEach => + @projects_data = fixture.load('projects.json')[0] + + spyOn(jQuery, 'ajax').and.callFake (req) => + expect(req.url).toBe('/api/v3/projects.json') + d = $.Deferred() + d.resolve @projects_data + d.promise() + + it 'to show on toggle click', => + $('.js-projects-dropdown-toggle').click() + + expect($('.title .select2-container').hasClass('select2-dropdown-open')).toBe(true) + expect($('.ajax-project-dropdown li').length).toBe(@projects_data.length) + + it 'hide dropdown', -> + $("#select2-drop-mask").click() + + expect($('.title .select2-container').hasClass('select2-dropdown-open')).toBe(false) + + it 'change project when clicking item', -> + $('.js-projects-dropdown-toggle').click() + $('.ajax-project-dropdown li:nth-child(2)').trigger('mouseup') + + expect($('.title .select2-container').hasClass('select2-dropdown-open')).toBe(false) + expect(window.current_project_url).toBe('http://localhost:3000/h5bp/html5-boilerplate') -- cgit v1.2.1 From 15bc1a01ab31b4288a3dea429cb7d77d272afbe5 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Sun, 17 Jan 2016 18:12:05 +0000 Subject: added feature test --- spec/features/projects_spec.rb | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/spec/features/projects_spec.rb b/spec/features/projects_spec.rb index 9a01c89ae2a..ed97b6cb577 100644 --- a/spec/features/projects_spec.rb +++ b/spec/features/projects_spec.rb @@ -82,7 +82,26 @@ feature 'Project', feature: true do it 'click project-settings and find leave project' do find('#project-settings-button').click - expect(page).to have_link('Leave Project') + expect(page).to have_link('Leave Project') + end + end + + describe 'project title' do + include WaitForAjax + + let(:user) { create(:user) } + let(:project) { create(:project, namespace: user.namespace) } + + before do + login_with(user) + project.team.add_user(user, Gitlab::Access::MASTER) + visit namespace_project_path(project.namespace, project) + end + + it 'click toggle and show dropdown', js: true do + find('.js-projects-dropdown-toggle').click + wait_for_ajax + expect(page).to have_css('.select2-results li', count: 1) end end -- cgit v1.2.1 From 797bcdf43e19f159492b80ddc635f4bbcf6b41a1 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Sun, 31 Jan 2016 15:56:27 -0500 Subject: Add notes about the regression issues to CONTRIBUTING.md [ci skip] --- CONTRIBUTING.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1bd91f0bdce..a6c85e2a6bb 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -177,6 +177,26 @@ is probably 1, adding a new Git Hook maybe 4 or 5, big features 7-9. issues or chunks. You can simply not set the weight of a parent issue and set weights to children issues. +### Regression issues + +Every monthly release has a corresponding issue on the CE issue tracker to keep +track of functionality broken by that release and any fixes that need to be +included in a patch release (see [8.3 Regressions] as an example). + +As outlined in the issue description, the intended workflow is to post one note +with a reference to an issue describing the regression, and then to update that +note with a reference to the merge request that fixes it as it becomes available. + +If you're a contributor who doesn't have the required permissions to update +other users' notes, please post a new note with a reference to both the issue +and the merge request. + +The release manager will [update the notes] in the regression issue as fixes are +addressed. + +[8.3 Regressions]: https://gitlab.com/gitlab-org/gitlab-ce/issues/4127 +[update the notes]: https://gitlab.com/gitlab-org/release-tools/blob/master/doc/pro-tips.md#update-the-regression-issue + ## Merge requests We welcome merge requests with fixes and improvements to GitLab code, tests, -- cgit v1.2.1 From 64c8ee47c96d9245081abdf1b9d4ec39cdfc5883 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Mon, 1 Feb 2016 10:41:52 +0100 Subject: WIP lazy blobs --- app/controllers/projects/blob_controller.rb | 3 +++ app/models/ci/commit.rb | 6 +++++- app/models/tree.rb | 2 ++ app/views/projects/blob/_blob.html.haml | 1 + lib/api/files.rb | 6 ++++-- 5 files changed, 15 insertions(+), 3 deletions(-) diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb index c56a3497bb2..9045e668735 100644 --- a/app/controllers/projects/blob_controller.rb +++ b/app/controllers/projects/blob_controller.rb @@ -33,6 +33,7 @@ class Projects::BlobController < Projects::ApplicationController def edit @last_commit = Gitlab::Git::Commit.last_for_path(@repository, @ref, @path).sha + blob.load_all_data!(@repository) end def update @@ -51,6 +52,7 @@ class Projects::BlobController < Projects::ApplicationController def preview @content = params[:content] + @blob.load_all_data!(@repository) diffy = Diffy::Diff.new(@blob.data, @content, diff: '-U 3', include_diff_info: true) @diff_lines = Gitlab::Diff::Parser.new.parse(diffy.diff.scan(/.*\n/)) @@ -65,6 +67,7 @@ class Projects::BlobController < Projects::ApplicationController end def diff + @blob.load_all_data!(@repository) @form = UnfoldForm.new(params) @lines = @blob.data.lines[@form.since - 1..@form.to - 1] diff --git a/app/models/ci/commit.rb b/app/models/ci/commit.rb index d2a29236942..96786ac4573 100644 --- a/app/models/ci/commit.rb +++ b/app/models/ci/commit.rb @@ -205,7 +205,11 @@ module Ci end def ci_yaml_file - @ci_yaml_file ||= project.repository.blob_at(sha, '.gitlab-ci.yml').data + return @ci_yaml_file if defined?(@ci_yaml_file) + + blob = project.repository.blob_at(sha, '.gitlab-ci.yml') + blob.load_all_data!(project.repository) + @ci_yaml_file = blob.data rescue nil end diff --git a/app/models/tree.rb b/app/models/tree.rb index e0e04d8859f..ecee54c3e0a 100644 --- a/app/models/tree.rb +++ b/app/models/tree.rb @@ -31,6 +31,8 @@ class Tree git_repo = repository.raw_repository @readme = Gitlab::Git::Blob.find(git_repo, sha, readme_path) + @readme.load_all_data!(git_repo) + @readme end def trees diff --git a/app/views/projects/blob/_blob.html.haml b/app/views/projects/blob/_blob.html.haml index 3d8d88834e2..50aea968980 100644 --- a/app/views/projects/blob/_blob.html.haml +++ b/app/views/projects/blob/_blob.html.haml @@ -35,6 +35,7 @@ - if blob.lfs_pointer? = render "download", blob: blob - elsif blob.text? + - blob.load_all_data!(@repository) = render "text", blob: blob - elsif blob.image? = render "image", blob: blob diff --git a/lib/api/files.rb b/lib/api/files.rb index 8ad2c1883c7..c1d86f313b0 100644 --- a/lib/api/files.rb +++ b/lib/api/files.rb @@ -58,9 +58,11 @@ module API commit = user_project.commit(ref) not_found! 'Commit' unless commit - blob = user_project.repository.blob_at(commit.sha, file_path) + repo = user_project.repository + blob = repo.blob_at(commit.sha, file_path) if blob + blob.load_all_data!(repo) status(200) { @@ -72,7 +74,7 @@ module API ref: ref, blob_id: blob.id, commit_id: commit.id, - last_commit_id: user_project.repository.last_commit_for_path(commit.sha, file_path).id + last_commit_id: repo.last_commit_for_path(commit.sha, file_path).id } else not_found! 'File' -- cgit v1.2.1 From 02afa6793cca042f8563b0e26472606c743d76f5 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Mon, 1 Feb 2016 11:33:22 +0100 Subject: Use only one header to send git blobs --- app/controllers/projects/avatars_controller.rb | 3 +-- app/controllers/projects/raw_controller.rb | 3 +-- lib/api/repositories.rb | 6 ++---- lib/gitlab/workhorse.rb | 21 +++++++++++++++++++++ 4 files changed, 25 insertions(+), 8 deletions(-) create mode 100644 lib/gitlab/workhorse.rb diff --git a/app/controllers/projects/avatars_controller.rb b/app/controllers/projects/avatars_controller.rb index 0cd65ad5b16..eb501c3964c 100644 --- a/app/controllers/projects/avatars_controller.rb +++ b/app/controllers/projects/avatars_controller.rb @@ -6,8 +6,7 @@ class Projects::AvatarsController < Projects::ApplicationController @blob = repository.blob_at_branch('master', @project.avatar_in_git) if @blob headers['X-Content-Type-Options'] = 'nosniff' - headers['Gitlab-Workhorse-Repo-Path'] = repository.path_to_repo - headers['Gitlab-Workhorse-Send-Blob'] = @blob.id + headers.store(*Gitlab::Workhorse.send_git_blob(repository, @blob)) headers['Content-Disposition'] = 'inline' render nothing: true, content_type: @blob.content_type else diff --git a/app/controllers/projects/raw_controller.rb b/app/controllers/projects/raw_controller.rb index b8b90489027..2ab8a6b83bb 100644 --- a/app/controllers/projects/raw_controller.rb +++ b/app/controllers/projects/raw_controller.rb @@ -15,8 +15,7 @@ class Projects::RawController < Projects::ApplicationController if @blob.lfs_pointer? send_lfs_object else - headers['Gitlab-Workhorse-Repo-Path'] = @repository.path_to_repo - headers['Gitlab-Workhorse-Send-Blob'] = @blob.id + headers.store(*Gitlab::Workhorse.send_git_blob(@repository, @blob)) headers['Content-Disposition'] = 'inline' render nothing: true, content_type: get_blob_type end diff --git a/lib/api/repositories.rb b/lib/api/repositories.rb index 0f4cd2443b0..c95d2d2001d 100644 --- a/lib/api/repositories.rb +++ b/lib/api/repositories.rb @@ -57,8 +57,7 @@ module API not_found! "File" unless blob content_type 'text/plain' - header 'Gitlab-Workhorse-Repo-Path', repo.path_to_repo - header 'Gitlab-Workhorse-Send-Blob', blob.id + header *Gitlab::Workhorse.send_git_blob(repo, blob) end # Get a raw blob contents by blob sha @@ -84,8 +83,7 @@ module API env['api.format'] = :txt content_type blob.mime_type - header 'Gitlab-Workhorse-Repo-Path', repo.path_to_repo - header 'Gitlab-Workhorse-Send-Blob', blob.id + header *Gitlab::Workhorse.send_git_blob(repo, blob) end # Get a an archive of the repository diff --git a/lib/gitlab/workhorse.rb b/lib/gitlab/workhorse.rb new file mode 100644 index 00000000000..ff6fbf0b5c1 --- /dev/null +++ b/lib/gitlab/workhorse.rb @@ -0,0 +1,21 @@ +require 'base64' +require 'json' + +module Gitlab + class Workhorse + class << self + def send_git_blob(repository, blob) + params_hash = { + 'RepoPath' => repository.path_to_repo, + 'BlobId' => blob.id, + } + params = Base64.urlsafe_encode64(JSON.dump(params_hash)) + + [ + 'Gitlab-Workhorse-Send-Data', + "git-blob:#{params}", + ] + end + end + end +end \ No newline at end of file -- cgit v1.2.1 From b2a634c352ab23ed1180b7678b5c83db0137c0f7 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Mon, 1 Feb 2016 12:01:13 +0100 Subject: Avoid trailing 'charset=' garbage --- app/controllers/projects/avatars_controller.rb | 3 ++- app/controllers/projects/raw_controller.rb | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/app/controllers/projects/avatars_controller.rb b/app/controllers/projects/avatars_controller.rb index eb501c3964c..bc40e601030 100644 --- a/app/controllers/projects/avatars_controller.rb +++ b/app/controllers/projects/avatars_controller.rb @@ -8,7 +8,8 @@ class Projects::AvatarsController < Projects::ApplicationController headers['X-Content-Type-Options'] = 'nosniff' headers.store(*Gitlab::Workhorse.send_git_blob(repository, @blob)) headers['Content-Disposition'] = 'inline' - render nothing: true, content_type: @blob.content_type + headers['Content-Type'] = @blob.content_type + head :ok # 'render nothing: true' messes up the Content-Type else render_404 end diff --git a/app/controllers/projects/raw_controller.rb b/app/controllers/projects/raw_controller.rb index 2ab8a6b83bb..87b4d08da0e 100644 --- a/app/controllers/projects/raw_controller.rb +++ b/app/controllers/projects/raw_controller.rb @@ -17,7 +17,8 @@ class Projects::RawController < Projects::ApplicationController else headers.store(*Gitlab::Workhorse.send_git_blob(@repository, @blob)) headers['Content-Disposition'] = 'inline' - render nothing: true, content_type: get_blob_type + headers['Content-Type'] = get_blob_type + head :ok # 'render nothing: true' messes up the Content-Type end else render_404 -- cgit v1.2.1 From b1f22aa35aa62d72f514b3f9beee0a190b6599cc Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Mon, 1 Feb 2016 12:27:35 +0100 Subject: Gotta have newlines --- lib/gitlab/workhorse.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/gitlab/workhorse.rb b/lib/gitlab/workhorse.rb index ff6fbf0b5c1..a23120a4176 100644 --- a/lib/gitlab/workhorse.rb +++ b/lib/gitlab/workhorse.rb @@ -18,4 +18,4 @@ module Gitlab end end end -end \ No newline at end of file +end -- cgit v1.2.1 From d11d425acc6b6aeaf85113dc9b2aca89b36dfe78 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Mon, 1 Feb 2016 14:00:28 +0100 Subject: Develop with a custom gitlab_git branch --- Gemfile | 2 +- Gemfile.lock | 18 ++++++++++++------ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/Gemfile b/Gemfile index a09d44f8bfd..88236146a14 100644 --- a/Gemfile +++ b/Gemfile @@ -49,7 +49,7 @@ gem "browser", '~> 1.0.0' # Extracting information from a git repository # Provide access to Gitlab::Git library -gem "gitlab_git", '~> 7.2.23' +gem "gitlab_git", git: 'https://gitlab.com/gitlab-org/gitlab_git.git', branch: 'lazy-blob' # LDAP Auth # GitLab fork with several improvements to original library. For full list of changes diff --git a/Gemfile.lock b/Gemfile.lock index ec92964df25..d6a5fe9dd0e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,3 +1,14 @@ +GIT + remote: https://gitlab.com/gitlab-org/gitlab_git.git + revision: dbf224a5d0404ab094e53144b5e01a88b5e9dbaa + branch: lazy-blob + specs: + gitlab_git (7.2.24) + activesupport (~> 4.0) + charlock_holmes (~> 0.7.3) + github-linguist (~> 4.7.0) + rugged (~> 0.23.3) + GEM remote: https://rubygems.org/ specs: @@ -356,11 +367,6 @@ GEM posix-spawn (~> 0.3) gitlab_emoji (0.2.0) gemojione (~> 2.1) - gitlab_git (7.2.24) - activesupport (~> 4.0) - charlock_holmes (~> 0.7.3) - github-linguist (~> 4.7.0) - rugged (~> 0.23.3) gitlab_meta (7.0) gitlab_omniauth-ldap (1.2.1) net-ldap (~> 0.9) @@ -934,7 +940,7 @@ DEPENDENCIES github-markup (~> 1.3.1) gitlab-flowdock-git-hook (~> 1.0.1) gitlab_emoji (~> 0.2.0) - gitlab_git (~> 7.2.23) + gitlab_git! gitlab_meta (= 7.0) gitlab_omniauth-ldap (~> 1.2.1) gollum-lib (~> 4.1.0) -- cgit v1.2.1 From 29d376025dbca5512a3d8204b262bfb576384b6c Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Mon, 1 Feb 2016 14:34:22 +0100 Subject: Update gitlab_git (lazy-blob branch) --- Gemfile.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index d6a5fe9dd0e..2c63cca6111 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,6 +1,6 @@ GIT remote: https://gitlab.com/gitlab-org/gitlab_git.git - revision: dbf224a5d0404ab094e53144b5e01a88b5e9dbaa + revision: 170a36889aebfd43e3e1e20b6b7661c896816b41 branch: lazy-blob specs: gitlab_git (7.2.24) @@ -350,7 +350,7 @@ GEM json get_process_mem (0.2.0) gherkin-ruby (0.3.2) - github-linguist (4.7.3) + github-linguist (4.7.4) charlock_holmes (~> 0.7.3) escape_utils (~> 1.1.0) mime-types (>= 1.19) -- cgit v1.2.1 From b1a7cb57cd695f1348e38710007f1676e95cce8c Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Mon, 1 Feb 2016 14:41:35 +0100 Subject: Update gitlab_git@lazy-blob again --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 2c63cca6111..9473e918632 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,6 +1,6 @@ GIT remote: https://gitlab.com/gitlab-org/gitlab_git.git - revision: 170a36889aebfd43e3e1e20b6b7661c896816b41 + revision: 69f2185b8bfc8c54b70a1ce4c8c81d9b9a977ce6 branch: lazy-blob specs: gitlab_git (7.2.24) -- cgit v1.2.1 From b4e6ee7adc5ad4cb4ab42c5b691684885e2562f1 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Mon, 1 Feb 2016 15:19:55 +0100 Subject: Update development version of gitlab_git --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 9473e918632..9aacbced998 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,6 +1,6 @@ GIT remote: https://gitlab.com/gitlab-org/gitlab_git.git - revision: 69f2185b8bfc8c54b70a1ce4c8c81d9b9a977ce6 + revision: 57160e1cbcf4c03e68aa881dfa8e2f55c37a3ee6 branch: lazy-blob specs: gitlab_git (7.2.24) -- cgit v1.2.1 From 927ab48101d44976e174b13323d085aa5f846155 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Mon, 1 Feb 2016 15:47:11 +0100 Subject: WIP - refactored migration --- CHANGELOG | 1 + ...5155_remove_dot_atom_path_ending_of_projects.rb | 49 ++++++++++++++++++---- 2 files changed, 43 insertions(+), 7 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index fe0504ec996..2e6e65e7ae2 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -17,6 +17,7 @@ v 8.5.0 (unreleased) - Update the ExternalIssue regex pattern (Blake Hitchcock) - Deprecate API "merge_request/:merge_request_id/comments". Use "merge_requests/:merge_request_id/notes" instead - Deprecate API "merge_request/:merge_request_id/...". Use "merge_requests/:merge_request_id/..." instead + - Prevent parse error when name of project ends with .atom and prevent path issues v 8.4.2 - Bump required gitlab-workhorse version to bring in a fix for missing diff --git a/db/migrate/20160129135155_remove_dot_atom_path_ending_of_projects.rb b/db/migrate/20160129135155_remove_dot_atom_path_ending_of_projects.rb index c7b986aca91..622b0f5db08 100644 --- a/db/migrate/20160129135155_remove_dot_atom_path_ending_of_projects.rb +++ b/db/migrate/20160129135155_remove_dot_atom_path_ending_of_projects.rb @@ -1,8 +1,12 @@ class RemoveDotAtomPathEndingOfProjects < ActiveRecord::Migration + include Gitlab::ShellAdapter class ProjectPath - def initilize(old_path) + attr_reader :old_path, :id + + def initialize(old_path, id) @old_path = old_path + @id = id end def clean_path @@ -10,7 +14,7 @@ class RemoveDotAtomPathEndingOfProjects < ActiveRecord::Migration end end - module PathCleaner + class PathCleaner def initialize(path) @path = path end @@ -30,7 +34,7 @@ class RemoveDotAtomPathEndingOfProjects < ActiveRecord::Migration end def cleaned_path - @_cleaned_path ||= path.gsub(/\.atom\z/, '-atom') + @_cleaned_path ||= @path.gsub(/\.atom\z/, '-atom') end def path_exists?(path) @@ -38,17 +42,48 @@ class RemoveDotAtomPathEndingOfProjects < ActiveRecord::Migration end end + def projects_with_dot_atom + select_all("SELECT id, path FROM projects WHERE lower(path) LIKE '%.atom'") + end + def up projects_with_dot_atom.each do |project| - remove_dot(project) + binding.pry + project_path = ProjectPath.new(project['path'], project['id']) + clean_path(project_path) if move_path(project_path) end end private - def remove_dot(project) - #TODO + def clean_path(project_path) + execute "UPDATE projects SET path = '#{project_path.clean_path}' WHERE id = #{project.id}" end - + def move_path(project_path) + # Based on RemovePeriodsAtEndsOfUsernames + # Don't attempt to move if original path only contains periods. + return if project_path.clean_path =~ /\A\.+\z/ + if gitlab_shell.mv_namespace(project_path.old_path, project_path.clean_path) + # If repositories moved successfully we need to remove old satellites + # and send update instructions to users. + # However we cannot allow rollback since we moved namespace dir + # So we basically we mute exceptions in next actions + begin + gitlab_shell.rm_satellites(project_path.old_path) + # We cannot send update instructions since models and mailers + # can't safely be used from migrations as they may be written for + # later versions of the database. + # send_update_instructions + rescue + # Returning false does not rollback after_* transaction but gives + # us information about failing some of tasks + false + end + else + # if we cannot move namespace directory we should avoid + # db changes in order to prevent out of sync between db and fs + false + end + end end -- cgit v1.2.1 From 94b27f9d795c05134a777f754adbea2ab3accd33 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Mon, 1 Feb 2016 15:49:52 +0100 Subject: added TODO to not working method --- db/migrate/20160129135155_remove_dot_atom_path_ending_of_projects.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/db/migrate/20160129135155_remove_dot_atom_path_ending_of_projects.rb b/db/migrate/20160129135155_remove_dot_atom_path_ending_of_projects.rb index 622b0f5db08..0bc23f5627f 100644 --- a/db/migrate/20160129135155_remove_dot_atom_path_ending_of_projects.rb +++ b/db/migrate/20160129135155_remove_dot_atom_path_ending_of_projects.rb @@ -60,6 +60,7 @@ class RemoveDotAtomPathEndingOfProjects < ActiveRecord::Migration execute "UPDATE projects SET path = '#{project_path.clean_path}' WHERE id = #{project.id}" end + #TODO: Fix this def move_path(project_path) # Based on RemovePeriodsAtEndsOfUsernames # Don't attempt to move if original path only contains periods. -- cgit v1.2.1 From 72bd004b3114fad43feaa7d21e0c2cde4b5b6a0d Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Mon, 1 Feb 2016 16:20:49 +0100 Subject: Allow "@" in file names and path --- lib/gitlab/regex.rb | 8 ++++---- spec/lib/gitlab/regex_spec.rb | 8 ++++++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/lib/gitlab/regex.rb b/lib/gitlab/regex.rb index 53ab2686b43..5c35c5b1450 100644 --- a/lib/gitlab/regex.rb +++ b/lib/gitlab/regex.rb @@ -44,19 +44,19 @@ module Gitlab def file_name_regex - @file_name_regex ||= /\A[a-zA-Z0-9_\-\.]*\z/.freeze + @file_name_regex ||= /\A[a-zA-Z0-9_\-\.\@]*\z/.freeze end def file_name_regex_message - "can contain only letters, digits, '_', '-' and '.'. " + "can contain only letters, digits, '_', '-', '@' and '.'. " end def file_path_regex - @file_path_regex ||= /\A[a-zA-Z0-9_\-\.\/]*\z/.freeze + @file_path_regex ||= /\A[a-zA-Z0-9_\-\.\/\@]*\z/.freeze end def file_path_regex_message - "can contain only letters, digits, '_', '-' and '.'. Separate directories with a '/'. " + "can contain only letters, digits, '_', '-', '@' and '.'. Separate directories with a '/'. " end diff --git a/spec/lib/gitlab/regex_spec.rb b/spec/lib/gitlab/regex_spec.rb index d67ee423b9b..c51b10bdc69 100644 --- a/spec/lib/gitlab/regex_spec.rb +++ b/spec/lib/gitlab/regex_spec.rb @@ -21,4 +21,12 @@ describe Gitlab::Regex, lib: true do it { expect('Dash – is this').to match(Gitlab::Regex.project_name_regex) } it { expect('?gitlab').not_to match(Gitlab::Regex.project_name_regex) } end + + describe 'file name regex' do + it { expect('foo@bar').to match(Gitlab::Regex.file_name_regex) } + end + + describe 'file path regex' do + it { expect('foo@/bar').to match(Gitlab::Regex.file_path_regex) } + end end -- cgit v1.2.1 From e6cb010088c92a4c26fd2ac201944327369e7803 Mon Sep 17 00:00:00 2001 From: Aral Balkan Date: Sat, 25 Jul 2015 10:39:49 +0000 Subject: Added note: working copy changes (e.g., deleted vendor folder) should be stashed before beginning the update process. We should probably include this notice on all update guides. [ci skip] --- doc/update/6.x-or-7.x-to-7.14.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/doc/update/6.x-or-7.x-to-7.14.md b/doc/update/6.x-or-7.x-to-7.14.md index 4516a102084..c45fc9340ea 100644 --- a/doc/update/6.x-or-7.x-to-7.14.md +++ b/doc/update/6.x-or-7.x-to-7.14.md @@ -14,6 +14,12 @@ possible to edit the label text and color. The characters `?`, `&` and `,` are no longer allowed however so those will be removed from your tags during the database migrations for GitLab 7.2. +## Stash changes + +If you [deleted the vendors folder during your original installation](https://github.com/gitlabhq/gitlabhq/issues/4883#issuecomment-31108431), [you will get an error](https://gitlab.com/gitlab-org/gitlab-ce/issues/1494) when you attempt to rebuild the assets in step 7. To avoid this, stash the changes in your GitLab working copy before starting: + + git stash + ## 0. Stop server sudo service gitlab stop -- cgit v1.2.1 From 06c0025f16480fce831362317ed6427d51ab3c64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Mon, 1 Feb 2016 19:10:25 +0100 Subject: Improving the "Environment variables" administration doc --- config/database.yml.env | 12 +++++- doc/administration/environment_variables.md | 60 ++++++++++++++--------------- 2 files changed, 40 insertions(+), 32 deletions(-) diff --git a/config/database.yml.env b/config/database.yml.env index b2ff23cb5ab..1e35651c9a6 100644 --- a/config/database.yml.env +++ b/config/database.yml.env @@ -1,9 +1,17 @@ <%= ENV['RAILS_ENV'] %>: + ## Connection information + # Please be aware that the DATABASE_URL environment variable will take + # precedence over the following 6 parameters. For more information, see + # doc/administration/environment_variables.md adapter: <%= ENV['GITLAB_DATABASE_ADAPTER'] || 'postgresql' %> - encoding: <%= ENV['GITLAB_DATABASE_ENCODING'] || 'unicode' %> database: <%= ENV['GITLAB_DATABASE_DATABASE'] || "gitlab_#{ENV['RAILS_ENV']}" %> - pool: <%= ENV['GITLAB_DATABASE_POOL'] || '10' %> username: <%= ENV['GITLAB_DATABASE_USERNAME'] || 'root' %> password: <%= ENV['GITLAB_DATABASE_PASSWORD'] || '' %> host: <%= ENV['GITLAB_DATABASE_HOST'] || 'localhost' %> port: <%= ENV['GITLAB_DATABASE_PORT'] || '5432' %> + + ## Behavior information + # The following parameters will be used even if you're using the DATABASE_URL + # environment variable. + encoding: <%= ENV['GITLAB_DATABASE_ENCODING'] || 'unicode' %> + pool: <%= ENV['GITLAB_DATABASE_POOL'] || '10' %> diff --git a/doc/administration/environment_variables.md b/doc/administration/environment_variables.md index 0faef526d43..b0aa420e055 100644 --- a/doc/administration/environment_variables.md +++ b/doc/administration/environment_variables.md @@ -2,7 +2,7 @@ ## Introduction -Commonly people configure GitLab via the gitlab.rb configuration file in the Omnibus package. +Commonly people configure GitLab via the `gitlab.rb` configuration file in the Omnibus package. But if you prefer to use environment variables we allow that too. @@ -10,45 +10,45 @@ But if you prefer to use environment variables we allow that too. Variable | Type | Explanation -------- | ---- | ----------- -GITLAB_ROOT_PASSWORD | string | sets the password for the `root` user on installation -GITLAB_HOST | url | hostname of the GitLab server includes http or https -RAILS_ENV | production / development / staging / test | Rails environment -DATABASE_URL | url | For example: postgresql://localhost/blog_development?pool=5 -GITLAB_EMAIL_FROM | email | Email address used in the "From" field in mails sent by GitLab -GITLAB_EMAIL_DISPLAY_NAME | string | Name used in the "From" field in mails sent by GitLab -GITLAB_EMAIL_REPLY_TO | email | Email address used in the "Reply-To" field in mails sent by GitLab -GITLAB_UNICORN_MEMORY_MIN | integer | The minimum memory threshold (in bytes) for the Unicorn worker killer -GITLAB_UNICORN_MEMORY_MAX | integer | The maximum memory threshold (in bytes) for the Unicorn worker killer +`GITLAB_ROOT_PASSWORD` | string | Sets the password for the `root` user on installation +`GITLAB_HOST` | url | Hostname of the GitLab server includes http or https +`RAILS_ENV` | production / development / staging / test | Rails environment +`DATABASE_URL` | url | For example: postgresql://localhost/blog_development +`GITLAB_EMAIL_FROM` | email | Email address used in the "From" field in mails sent by GitLab +`GITLAB_EMAIL_DISPLAY_NAME` | string | Name used in the "From" field in mails sent by GitLab +`GITLAB_EMAIL_REPLY_TO` | email | Email address used in the "Reply-To" field in mails sent by GitLab +`GITLAB_UNICORN_MEMORY_MIN` | integer | The minimum memory threshold (in bytes) for the Unicorn worker killer +`GITLAB_UNICORN_MEMORY_MAX` | integer | The maximum memory threshold (in bytes) for the Unicorn worker killer ## Complete database variables -As explained in the [Heroku documentation](https://devcenter.heroku.com/articles/rails-database-connection-behavior) the DATABASE_URL doesn't let you set: +The recommended way of specifying your database connection information is to set +the `DATABASE_URL` environment variable. This variable only holds connection +information (adapter, database, username, password, host and port), but not +behavior information (encoding, pool). If you don't want to use `DATABASE_URL` +and/or want to set database behavior information, you will have to: -- adapter -- database -- username -- password -- host -- port +- copy our template `config/database.yml` file: `cp config/database.yml.env config/database.yml` +- set a value for some `GITLAB_DATABASE_XXX` variables -To do so please `cp config/database.yml.env config/database.yml` and use the following variables: +The list of `GITLAB_DATABASE_XXX` variables that you can set is as follow: -Variable | Default ---- | --- -GITLAB_DATABASE_ADAPTER | postgresql -GITLAB_DATABASE_ENCODING | unicode -GITLAB_DATABASE_DATABASE | gitlab_#{ENV['RAILS_ENV'] -GITLAB_DATABASE_POOL | 10 -GITLAB_DATABASE_USERNAME | root -GITLAB_DATABASE_PASSWORD | -GITLAB_DATABASE_HOST | localhost -GITLAB_DATABASE_PORT | 5432 +Variable | Default value | Overridden by `DATABASE_URL`? +--- | --- | --- +`GITLAB_DATABASE_ADAPTER` | `postgresql` | Yes +`GITLAB_DATABASE_DATABASE` | `gitlab_#{ENV['RAILS_ENV']` | Yes +`GITLAB_DATABASE_USERNAME` | `root` | Yes +`GITLAB_DATABASE_PASSWORD` | None | Yes +`GITLAB_DATABASE_HOST` | `localhost` | Yes +`GITLAB_DATABASE_PORT` | `5432` | Yes +`GITLAB_DATABASE_ENCODING` | `unicode` | No +`GITLAB_DATABASE_POOL` | `10` | No ## Adding more variables We welcome merge requests to make more settings configurable via variables. -Please make changes in the file config/initializers/1_settings.rb -Please stick to the naming scheme "GITLAB_#{name 1_settings.rb in upper case}". +Please make changes in the `config/initializers/1_settings.rb` file. +Please stick to the naming scheme `GITLAB_#{name in 1_settings.rb in upper case}`. ## Omnibus configuration -- cgit v1.2.1 From 055afab5c7d33d061d339c270bd258ed847450f3 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Mon, 1 Feb 2016 23:58:04 +0100 Subject: Make the CI permission model simpler This MR simplifies CI permission model: - read_build: allows to read a list of builds, artifacts and trace - update_build: allows to cancel and retry builds - create_build: allows to create builds from gitlab-ci.yml (not yet implemented) - admin_build: allows to manage triggers, runners and variables - read_commit_status: allows to read a list of commit statuses (including the overall of builds) - create_commit_status: allows to create a new commit status using API Remove all extra methods to manage permission. Made all controllers to use explicitly the new permissions. --- app/controllers/ci/application_controller.rb | 2 +- app/controllers/projects/artifacts_controller.rb | 12 +------- app/controllers/projects/builds_controller.rb | 9 ++---- app/controllers/projects/commit_controller.rb | 12 ++------ .../projects/runner_projects_controller.rb | 2 +- app/controllers/projects/runners_controller.rb | 2 +- app/controllers/projects/triggers_controller.rb | 2 +- app/controllers/projects/variables_controller.rb | 2 +- app/helpers/projects_helper.rb | 2 +- app/models/ability.rb | 34 +++++++++++++++++----- app/views/admin/builds/_build.html.haml | 6 ++-- app/views/projects/builds/index.html.haml | 2 +- app/views/projects/builds/show.html.haml | 5 ++-- app/views/projects/commit/_builds.html.haml | 2 +- .../commit_statuses/_commit_status.html.haml | 6 ++-- lib/api/builds.rb | 29 ++++++++++++------ lib/api/commit_statuses.rb | 2 +- lib/api/triggers.rb | 8 ++--- lib/api/variables.rb | 2 +- spec/requests/api/builds_spec.rb | 8 ++--- 20 files changed, 78 insertions(+), 71 deletions(-) diff --git a/app/controllers/ci/application_controller.rb b/app/controllers/ci/application_controller.rb index c420b59c3a2..59c77653509 100644 --- a/app/controllers/ci/application_controller.rb +++ b/app/controllers/ci/application_controller.rb @@ -13,7 +13,7 @@ module Ci end def authorize_manage_builds! - unless can?(current_user, :manage_builds, project) + unless can?(current_user, :update_build, project) return page_404 end end diff --git a/app/controllers/projects/artifacts_controller.rb b/app/controllers/projects/artifacts_controller.rb index f159a6d6dc6..cfea1266516 100644 --- a/app/controllers/projects/artifacts_controller.rb +++ b/app/controllers/projects/artifacts_controller.rb @@ -1,6 +1,6 @@ class Projects::ArtifactsController < Projects::ApplicationController layout 'project' - before_action :authorize_read_build_artifacts! + before_action :authorize_read_build! def download unless artifacts_file.file_storage? @@ -43,14 +43,4 @@ class Projects::ArtifactsController < Projects::ApplicationController def artifacts_file @artifacts_file ||= build.artifacts_file end - - def authorize_read_build_artifacts! - unless can?(current_user, :read_build_artifacts, @project) - if current_user.nil? - return authenticate_user! - else - return render_404 - end - end - end end diff --git a/app/controllers/projects/builds_controller.rb b/app/controllers/projects/builds_controller.rb index 92d9699fe84..9e89296e71d 100644 --- a/app/controllers/projects/builds_controller.rb +++ b/app/controllers/projects/builds_controller.rb @@ -1,7 +1,8 @@ class Projects::BuildsController < Projects::ApplicationController before_action :build, except: [:index, :cancel_all] - before_action :authorize_manage_builds!, except: [:index, :show, :status] + before_action :authorize_read_build!, except: [:cancel, :cancel_all, :retry] + before_action :authorize_update_build!, except: [:index, :show, :status] layout "project" @@ -69,10 +70,4 @@ class Projects::BuildsController < Projects::ApplicationController def build_path(build) namespace_project_build_path(build.project.namespace, build.project, build) end - - def authorize_manage_builds! - unless can?(current_user, :manage_builds, project) - return render_404 - end - end end diff --git a/app/controllers/projects/commit_controller.rb b/app/controllers/projects/commit_controller.rb index f5a169e5aa9..2bf367d2a25 100644 --- a/app/controllers/projects/commit_controller.rb +++ b/app/controllers/projects/commit_controller.rb @@ -4,10 +4,10 @@ class Projects::CommitController < Projects::ApplicationController # Authorize before_action :require_non_empty_project - before_action :authorize_download_code!, except: [:cancel_builds] - before_action :authorize_manage_builds!, only: [:cancel_builds] + before_action :authorize_download_code!, except: [:cancel_builds, :retry_builds] + before_action :authorize_update_build!, only: [:cancel_builds, :retry_builds] + before_action :authorize_read_commit_status!, only: [:builds] before_action :commit - before_action :authorize_manage_builds!, only: [:cancel_builds, :retry_builds] before_action :define_show_vars, only: [:show, :builds] def show @@ -77,10 +77,4 @@ class Projects::CommitController < Projects::ApplicationController @statuses = ci_commit.statuses if ci_commit end - - def authorize_manage_builds! - unless can?(current_user, :manage_builds, project) - return render_404 - end - end end diff --git a/app/controllers/projects/runner_projects_controller.rb b/app/controllers/projects/runner_projects_controller.rb index e2785caa2fb..bedeb4a295c 100644 --- a/app/controllers/projects/runner_projects_controller.rb +++ b/app/controllers/projects/runner_projects_controller.rb @@ -1,5 +1,5 @@ class Projects::RunnerProjectsController < Projects::ApplicationController - before_action :authorize_admin_project! + before_action :authorize_admin_build! layout 'project_settings' diff --git a/app/controllers/projects/runners_controller.rb b/app/controllers/projects/runners_controller.rb index 4993b2648a5..0dd2d6a99be 100644 --- a/app/controllers/projects/runners_controller.rb +++ b/app/controllers/projects/runners_controller.rb @@ -1,6 +1,6 @@ class Projects::RunnersController < Projects::ApplicationController + before_action :authorize_admin_build! before_action :set_runner, only: [:edit, :update, :destroy, :pause, :resume, :show] - before_action :authorize_admin_project! layout 'project_settings' diff --git a/app/controllers/projects/triggers_controller.rb b/app/controllers/projects/triggers_controller.rb index 30adfad1daa..92359745cec 100644 --- a/app/controllers/projects/triggers_controller.rb +++ b/app/controllers/projects/triggers_controller.rb @@ -1,5 +1,5 @@ class Projects::TriggersController < Projects::ApplicationController - before_action :authorize_admin_project! + before_action :authorize_admin_build! layout 'project_settings' diff --git a/app/controllers/projects/variables_controller.rb b/app/controllers/projects/variables_controller.rb index 10efafea9db..00234654578 100644 --- a/app/controllers/projects/variables_controller.rb +++ b/app/controllers/projects/variables_controller.rb @@ -1,5 +1,5 @@ class Projects::VariablesController < Projects::ApplicationController - before_action :authorize_admin_project! + before_action :authorize_admin_build! layout 'project_settings' diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 8c8b355028c..4543eff0d63 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -126,7 +126,7 @@ module ProjectsHelper nav_tabs << :merge_requests end - if project.builds_enabled? && can?(current_user, :read_build, project) + if can?(current_user, :read_build, project) nav_tabs << :builds end diff --git a/app/models/ability.rb b/app/models/ability.rb index ab59a3506a2..e58e7a40273 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -52,10 +52,15 @@ class Ability :read_project_member, :read_merge_request, :read_note, + :read_commit_status, :read_build, :download_code ] + if project.restrict_builds? + rules -= :read_build + end + rules - project_disabled_features_rules(project) else [] @@ -113,6 +118,10 @@ class Ability if project.public? || project.internal? rules.push(*public_project_rules) + + if team.guest?(user) && project.restrict_builds? + rules -= named_abilities('build') + end end if project.owner == user || user.admin? @@ -134,7 +143,9 @@ class Ability def public_project_rules @public_project_rules ||= project_guest_rules + [ :download_code, - :fork_project + :fork_project, + :read_commit_status, + :read_build, ] end @@ -149,7 +160,7 @@ class Ability :read_project_member, :read_merge_request, :read_note, - :read_build, + :read_commit_status, :create_project, :create_issue, :create_note @@ -158,24 +169,25 @@ class Ability def project_report_rules @project_report_rules ||= project_guest_rules + [ - :create_commit_status, - :read_commit_statuses, - :read_build_artifacts, :download_code, :fork_project, :create_project_snippet, :update_issue, :admin_issue, - :admin_label + :admin_label, + :read_build, ] end def project_dev_rules @project_dev_rules ||= project_report_rules + [ :admin_merge_request, + :create_commit_status, + :update_commit_status, + :create_build, + :update_build, :create_merge_request, :create_wiki, - :manage_builds, :push_code ] end @@ -201,7 +213,9 @@ class Ability :admin_merge_request, :admin_note, :admin_wiki, - :admin_project + :admin_project, + :admin_commit_status, + :admin_build ] end @@ -240,6 +254,10 @@ class Ability rules += named_abilities('wiki') end + unless project.builds_enabled + rules += named_abilities('build') + end + rules end diff --git a/app/views/admin/builds/_build.html.haml b/app/views/admin/builds/_build.html.haml index c395bd908c3..bd7fb0b36f4 100644 --- a/app/views/admin/builds/_build.html.haml +++ b/app/views/admin/builds/_build.html.haml @@ -4,7 +4,7 @@ = ci_status_with_icon(build.status) %td.build-link - - if build.target_url + - if can?(current_user, :read_build, project) && build.target_url = link_to build.target_url do %strong Build ##{build.id} - else @@ -60,10 +60,10 @@ %td .pull-right - - if current_user && can?(current_user, :read_build_artifacts, project) && build.artifacts? + - if can?(current_user, :read_build, project) && build.artifacts? = link_to build.artifacts_download_url, title: 'Download artifacts' do %i.fa.fa-download - - if current_user && can?(current_user, :manage_builds, build.project) + - if current_user && can?(current_user, :update_build, build.project) - if build.active? - if build.cancel_url = link_to build.cancel_url, method: :post, title: 'Cancel' do diff --git a/app/views/projects/builds/index.html.haml b/app/views/projects/builds/index.html.haml index bbb6944a65a..2a2a4745bed 100644 --- a/app/views/projects/builds/index.html.haml +++ b/app/views/projects/builds/index.html.haml @@ -3,7 +3,7 @@ .project-issuable-filter .controls - - if can?(current_user, :manage_builds, @project) + - if can?(current_user, :update_build, @project) .pull-left.hidden-xs - if @all_builds.running_or_pending.any? = link_to 'Cancel running', cancel_all_namespace_project_builds_path(@project.namespace, @project), diff --git a/app/views/projects/builds/show.html.haml b/app/views/projects/builds/show.html.haml index ba1fdc6f0e7..c43d6c3b427 100644 --- a/app/views/projects/builds/show.html.haml +++ b/app/views/projects/builds/show.html.haml @@ -89,8 +89,7 @@ Test coverage %h1 #{@build.coverage}% - - if current_user && can?(current_user, :read_build_artifacts, @project) && @build.artifacts? - + - if can?(current_user, :read_build, @project) && @build.artifacts? .build-widget.artifacts %h4.title Build artifacts .center @@ -102,7 +101,7 @@ .build-widget %h4.title Build ##{@build.id} - - if current_user && can?(current_user, :manage_builds, @project) + - if current_user && can?(current_user, :update_build, @project) .pull-right - if @build.cancel_url = link_to "Cancel", @build.cancel_url, class: 'btn btn-sm btn-danger', method: :post diff --git a/app/views/projects/commit/_builds.html.haml b/app/views/projects/commit/_builds.html.haml index 329aaa0bb8b..befad27666c 100644 --- a/app/views/projects/commit/_builds.html.haml +++ b/app/views/projects/commit/_builds.html.haml @@ -1,6 +1,6 @@ .gray-content-block.middle-block .pull-right - - if can?(current_user, :manage_builds, @ci_commit.project) + - if can?(current_user, :update_build, @ci_commit.project) - if @ci_commit.builds.latest.failed.any?(&:retryable?) = link_to "Retry failed", retry_builds_namespace_project_commit_path(@ci_commit.project.namespace, @ci_commit.project, @ci_commit.sha), class: 'btn btn-grouped btn-primary', method: :post diff --git a/app/views/projects/commit_statuses/_commit_status.html.haml b/app/views/projects/commit_statuses/_commit_status.html.haml index 2e3c956ddc4..fba4405cb7d 100644 --- a/app/views/projects/commit_statuses/_commit_status.html.haml +++ b/app/views/projects/commit_statuses/_commit_status.html.haml @@ -8,7 +8,7 @@ = ci_status_with_icon(commit_status.status) %td.commit_status-link - - if commit_status.target_url + - if can?(current_user, :read_build, commit_status.project) && commit_status.target_url = link_to commit_status.target_url do %strong ##{commit_status.id} - else @@ -66,10 +66,10 @@ %td .pull-right - - if current_user && can?(current_user, :read_build_artifacts, commit_status.project) && commit_status.artifacts_download_url + - if can?(current_user, :read_build, commit_status.project) && commit_status.artifacts_download_url = link_to commit_status.artifacts_download_url, title: 'Download artifacts' do %i.fa.fa-download - - if current_user && can?(current_user, :manage_builds, commit_status.project) + - if can?(current_user, :update_build, commit_status.project) - if commit_status.active? - if commit_status.cancel_url = link_to commit_status.cancel_url, method: :post, title: 'Cancel' do diff --git a/lib/api/builds.rb b/lib/api/builds.rb index d293f988165..a8bd3842ce4 100644 --- a/lib/api/builds.rb +++ b/lib/api/builds.rb @@ -13,11 +13,12 @@ module API # Example Request: # GET /projects/:id/builds get ':id/builds' do + builds = user_project.builds.order('id DESC') builds = filter_builds(builds, params[:scope]) present paginate(builds), with: Entities::Build, - user_can_download_artifacts: can?(current_user, :download_build_artifacts, user_project) + user_can_download_artifacts: can?(current_user, :read_build, user_project) end # Get builds for a specific commit of a project @@ -30,6 +31,8 @@ module API # Example Request: # GET /projects/:id/repository/commits/:sha/builds get ':id/repository/commits/:sha/builds' do + authorize_read_builds! + commit = user_project.ci_commits.find_by_sha(params[:sha]) return not_found! unless commit @@ -37,7 +40,7 @@ module API builds = filter_builds(builds, params[:scope]) present paginate(builds), with: Entities::Build, - user_can_download_artifacts: can?(current_user, :download_build_artifacts, user_project) + user_can_download_artifacts: can?(current_user, :read_build, user_project) end # Get a specific build of a project @@ -48,11 +51,13 @@ module API # Example Request: # GET /projects/:id/builds/:build_id get ':id/builds/:build_id' do + authorize_read_builds! + build = get_build(params[:build_id]) return not_found!(build) unless build present build, with: Entities::Build, - user_can_download_artifacts: can?(current_user, :download_build_artifacts, user_project) + user_can_download_artifacts: can?(current_user, :read_build, user_project) end # Get a trace of a specific build of a project @@ -67,6 +72,8 @@ module API # is saved in the DB instead of file). But before that, we need to consider how to replace the value of # `runners_token` with some mask (like `xxxxxx`) when sending trace file directly by workhorse. get ':id/builds/:build_id/trace' do + authorize_read_builds! + build = get_build(params[:build_id]) return not_found!(build) unless build @@ -86,7 +93,7 @@ module API # example request: # post /projects/:id/build/:build_id/cancel post ':id/builds/:build_id/cancel' do - authorize_manage_builds! + authorize_update_builds! build = get_build(params[:build_id]) return not_found!(build) unless build @@ -94,7 +101,7 @@ module API build.cancel present build, with: Entities::Build, - user_can_download_artifacts: can?(current_user, :download_build_artifacts, user_project) + user_can_download_artifacts: can?(current_user, :read_build, user_project) end # Retry a specific build of a project @@ -105,7 +112,7 @@ module API # example request: # post /projects/:id/build/:build_id/retry post ':id/builds/:build_id/retry' do - authorize_manage_builds! + authorize_update_builds! build = get_build(params[:build_id]) return forbidden!('Build is not retryable') unless build && build.retryable? @@ -113,7 +120,7 @@ module API build = Ci::Build.retry(build) present build, with: Entities::Build, - user_can_download_artifacts: can?(current_user, :download_build_artifacts, user_project) + user_can_download_artifacts: can?(current_user, :read_build, user_project) end end @@ -141,8 +148,12 @@ module API builds.where(status: available_statuses && scope) end - def authorize_manage_builds! - authorize! :manage_builds, user_project + def authorize_read_builds! + authorize! :read_build, user_project + end + + def authorize_update_builds! + authorize! :update_build, user_project end end end diff --git a/lib/api/commit_statuses.rb b/lib/api/commit_statuses.rb index 1162271f5fc..9422d438d21 100644 --- a/lib/api/commit_statuses.rb +++ b/lib/api/commit_statuses.rb @@ -18,7 +18,7 @@ module API # Examples: # GET /projects/:id/repository/commits/:sha/statuses get ':id/repository/commits/:sha/statuses' do - authorize! :read_commit_statuses, user_project + authorize! :read_commit_status, user_project sha = params[:sha] ci_commit = user_project.ci_commit(sha) not_found! 'Commit' unless ci_commit diff --git a/lib/api/triggers.rb b/lib/api/triggers.rb index 5e4964f446c..d1d07394e92 100644 --- a/lib/api/triggers.rb +++ b/lib/api/triggers.rb @@ -54,7 +54,7 @@ module API # GET /projects/:id/triggers get ':id/triggers' do authenticate! - authorize_admin_project + authorize! :admin_build, user_project triggers = user_project.triggers.includes(:trigger_requests) triggers = paginate(triggers) @@ -71,7 +71,7 @@ module API # GET /projects/:id/triggers/:token get ':id/triggers/:token' do authenticate! - authorize_admin_project + authorize! :admin_build, user_project trigger = user_project.triggers.find_by(token: params[:token].to_s) return not_found!('Trigger') unless trigger @@ -87,7 +87,7 @@ module API # POST /projects/:id/triggers post ':id/triggers' do authenticate! - authorize_admin_project + authorize! :admin_build, user_project trigger = user_project.triggers.create @@ -103,7 +103,7 @@ module API # DELETE /projects/:id/triggers/:token delete ':id/triggers/:token' do authenticate! - authorize_admin_project + authorize! :admin_build, user_project trigger = user_project.triggers.find_by(token: params[:token].to_s) return not_found!('Trigger') unless trigger diff --git a/lib/api/variables.rb b/lib/api/variables.rb index d9a055f6c92..f6495071a11 100644 --- a/lib/api/variables.rb +++ b/lib/api/variables.rb @@ -2,7 +2,7 @@ module API # Projects variables API class Variables < Grape::API before { authenticate! } - before { authorize_admin_project } + before { authorize! :admin_build, user_project } resource :projects do # Get project variables diff --git a/spec/requests/api/builds_spec.rb b/spec/requests/api/builds_spec.rb index 8c9f5a382b7..6c07802db8b 100644 --- a/spec/requests/api/builds_spec.rb +++ b/spec/requests/api/builds_spec.rb @@ -113,7 +113,7 @@ describe API::API, api: true do describe 'POST /projects/:id/builds/:build_id/cancel' do context 'authorized user' do - context 'user with :manage_builds persmission' do + context 'user with :update_build persmission' do it 'should cancel running or pending build' do post api("/projects/#{project.id}/builds/#{build.id}/cancel", user) @@ -122,7 +122,7 @@ describe API::API, api: true do end end - context 'user without :manage_builds permission' do + context 'user without :update_build permission' do it 'should not cancel build' do post api("/projects/#{project.id}/builds/#{build.id}/cancel", user2) @@ -142,7 +142,7 @@ describe API::API, api: true do describe 'POST /projects/:id/builds/:build_id/retry' do context 'authorized user' do - context 'user with :manage_builds persmission' do + context 'user with :update_build persmission' do it 'should retry non-running build' do post api("/projects/#{project.id}/builds/#{build_canceled.id}/retry", user) @@ -152,7 +152,7 @@ describe API::API, api: true do end end - context 'user without :manage_builds permission' do + context 'user without :update_build permission' do it 'should not retry build' do post api("/projects/#{project.id}/builds/#{build_canceled.id}/retry", user2) -- cgit v1.2.1 From 9dfc4511ff1b8029ce8ad4e6c94bc0f39164b02d Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Thu, 28 Jan 2016 11:49:41 +0100 Subject: Updated contributing guide for stable releases Fixes #12784 --- CONTRIBUTING.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e7659b06c71..4130c57d472 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -257,6 +257,18 @@ Please ensure that your merge request meets the contribution acceptance criteria When having your code reviewed and when reviewing merge requests please take the [thoughtbot code review guidelines](https://github.com/thoughtbot/guides/tree/master/code-review) into account. +## Changes for Stable Releases + +Sometimes certain changes have to be added to an existing stable release. +Two examples are bug fixes and performance improvements. In these cases the +corresponding merge request should be updated to have the following: + +1. A milestone indicating what release the merge request should be merged into. +1. The label "Pick into Stable" + +This makes it easier for release managers to keep track of what still has to be +merged and where changes have to be merged into. + ## Definition of done If you contribute to GitLab please know that changes involve more than just -- cgit v1.2.1 From 7eb961f0816fd8be628162ca58a5377aae7ac165 Mon Sep 17 00:00:00 2001 From: Zeger-Jan van de Weg Date: Tue, 2 Feb 2016 11:17:20 +0100 Subject: Improve tooltips on admin menu --- app/views/layouts/nav/_admin.html.haml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/views/layouts/nav/_admin.html.haml b/app/views/layouts/nav/_admin.html.haml index cffdb52cc23..62e6fba5e34 100644 --- a/app/views/layouts/nav/_admin.html.haml +++ b/app/views/layouts/nav/_admin.html.haml @@ -1,6 +1,6 @@ %ul.nav.nav-sidebar = nav_link(controller: :dashboard, html_options: {class: 'home'}) do - = link_to admin_root_path, title: "Stats" do + = link_to admin_root_path, title: 'Overview' do = icon('dashboard fw') %span Overview @@ -25,13 +25,13 @@ %span Deploy Keys = nav_link path: ['runners#index', 'runners#show'] do - = link_to admin_runners_path do + = link_to admin_runners_path, title: 'Runners' do = icon('cog fw') %span Runners %span.count= number_with_delimiter(Ci::Runner.count(:all)) = nav_link path: 'builds#index' do - = link_to admin_builds_path do + = link_to admin_builds_path, title: 'Builds' do = icon('link fw') %span Builds -- cgit v1.2.1 From 771f14b96e058649ca5db7ce6c99e38108d4abec Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Tue, 2 Feb 2016 14:09:55 +0100 Subject: First version of "git archive" headers --- .../projects/repositories_controller.rb | 4 +++- app/services/archive_repository_service.rb | 23 ------------------ lib/api/repositories.rb | 7 ++---- lib/gitlab/workhorse.rb | 27 ++++++++++++++++++---- .../projects/repositories_controller_spec.rb | 11 +++------ spec/lib/gitlab/workhorse_spec.rb | 18 +++++++++++++++ spec/services/archive_repository_service_spec.rb | 25 -------------------- 7 files changed, 49 insertions(+), 66 deletions(-) delete mode 100644 app/services/archive_repository_service.rb create mode 100644 spec/lib/gitlab/workhorse_spec.rb delete mode 100644 spec/services/archive_repository_service_spec.rb diff --git a/app/controllers/projects/repositories_controller.rb b/app/controllers/projects/repositories_controller.rb index ba9aea1c165..5c7614cfbaf 100644 --- a/app/controllers/projects/repositories_controller.rb +++ b/app/controllers/projects/repositories_controller.rb @@ -11,7 +11,9 @@ class Projects::RepositoriesController < Projects::ApplicationController end def archive - render json: ArchiveRepositoryService.new(@project, params[:ref], params[:format]).execute + RepositoryArchiveCacheWorker.perform_async + headers.store(*Gitlab::Workhorse.send_git_archive(@project, params[:ref], params[:format])) + head :ok rescue => ex logger.error("#{self.class.name}: #{ex}") return git_not_found! diff --git a/app/services/archive_repository_service.rb b/app/services/archive_repository_service.rb deleted file mode 100644 index 2160bf13e6d..00000000000 --- a/app/services/archive_repository_service.rb +++ /dev/null @@ -1,23 +0,0 @@ -class ArchiveRepositoryService - attr_reader :project, :ref, :format - - def initialize(project, ref, format) - format ||= 'tar.gz' - @project, @ref, @format = project, ref, format.downcase - end - - def execute(options = {}) - RepositoryArchiveCacheWorker.perform_async - - metadata = project.repository.archive_metadata(ref, storage_path, format) - raise "Repository or ref not found" if metadata.empty? - - metadata - end - - private - - def storage_path - Gitlab.config.gitlab.repository_downloads_path - end -end diff --git a/lib/api/repositories.rb b/lib/api/repositories.rb index c95d2d2001d..0178289f57f 100644 --- a/lib/api/repositories.rb +++ b/lib/api/repositories.rb @@ -98,11 +98,8 @@ module API authorize! :download_code, user_project begin - ArchiveRepositoryService.new( - user_project, - params[:sha], - params[:format] - ).execute + RepositoryArchiveCacheWorker.perform_async + header *Gitlab::Workhorse.send_git_archive(@project, params[:ref], params[:format]) rescue not_found!('File') end diff --git a/lib/gitlab/workhorse.rb b/lib/gitlab/workhorse.rb index a23120a4176..2f3e57156b6 100644 --- a/lib/gitlab/workhorse.rb +++ b/lib/gitlab/workhorse.rb @@ -4,18 +4,37 @@ require 'json' module Gitlab class Workhorse class << self + SEND_DATA_HEADER = 'Gitlab-Workhorse-Send-Data' + def send_git_blob(repository, blob) - params_hash = { + params = { 'RepoPath' => repository.path_to_repo, 'BlobId' => blob.id, } - params = Base64.urlsafe_encode64(JSON.dump(params_hash)) [ - 'Gitlab-Workhorse-Send-Data', - "git-blob:#{params}", + SEND_DATA_HEADER, + "git-blob:#{encode(params)}", ] end + + def send_git_archive(project, ref, format) + format ||= 'tar.gz' + format.downcase! + params = project.repository.archive_metadata(ref, Gitlab.config.gitlab.repository_downloads_path, format) + raise "Repository or ref not found" if params.empty? + + [ + SEND_DATA_HEADER, + "git-archive:#{encode(params)}", + ] + end + + protected + + def encode(hash) + Base64.urlsafe_encode64(JSON.dump(hash)) + end end end end diff --git a/spec/controllers/projects/repositories_controller_spec.rb b/spec/controllers/projects/repositories_controller_spec.rb index 18a30033ed8..09ec4f18f9d 100644 --- a/spec/controllers/projects/repositories_controller_spec.rb +++ b/spec/controllers/projects/repositories_controller_spec.rb @@ -8,15 +8,10 @@ describe Projects::RepositoriesController do before do sign_in(user) project.team << [user, :developer] - - allow(ArchiveRepositoryService).to receive(:new).and_return(service) end - let(:service) { ArchiveRepositoryService.new(project, "master", "zip") } - - it "executes ArchiveRepositoryService" do - expect(ArchiveRepositoryService).to receive(:new).with(project, "master", "zip") - expect(service).to receive(:execute) + it "uses Gitlab::Workhorse" do + expect(Gitlab::Workhorse).to receive(:send_git_archive).with(project, "master", "zip") get :archive, namespace_id: project.namespace.path, project_id: project.path, ref: "master", format: "zip" end @@ -24,7 +19,7 @@ describe Projects::RepositoriesController do context "when the service raises an error" do before do - allow(service).to receive(:execute).and_raise("Archive failed") + allow(Gitlab::Workhorse).to receive(:send_git_archive).and_raise("Archive failed") end it "renders Not Found" do diff --git a/spec/lib/gitlab/workhorse_spec.rb b/spec/lib/gitlab/workhorse_spec.rb new file mode 100644 index 00000000000..d940bf05061 --- /dev/null +++ b/spec/lib/gitlab/workhorse_spec.rb @@ -0,0 +1,18 @@ +require 'spec_helper' + +describe Gitlab::Workhorse, lib: true do + let(:project) { create(:project) } + let(:subject) { Gitlab::Workhorse } + + describe "#send_git_archive" do + context "when the repository doesn't have an archive file path" do + before do + allow(project.repository).to receive(:archive_metadata).and_return(Hash.new) + end + + it "raises an error" do + expect { subject.send_git_archive(project, "master", "zip") }.to raise_error(RuntimeError) + end + end + end +end diff --git a/spec/services/archive_repository_service_spec.rb b/spec/services/archive_repository_service_spec.rb deleted file mode 100644 index bd871605c66..00000000000 --- a/spec/services/archive_repository_service_spec.rb +++ /dev/null @@ -1,25 +0,0 @@ -require 'spec_helper' - -describe ArchiveRepositoryService, services: true do - let(:project) { create(:project) } - subject { ArchiveRepositoryService.new(project, "master", "zip") } - - describe "#execute" do - it "cleans old archives" do - expect(RepositoryArchiveCacheWorker).to receive(:perform_async) - - subject.execute(timeout: 0.0) - end - - context "when the repository doesn't have an archive file path" do - before do - allow(project.repository).to receive(:archive_metadata).and_return(Hash.new) - end - - it "raises an error" do - expect { subject.execute(timeout: 0.0) }.to raise_error(RuntimeError) - end - end - - end -end -- cgit v1.2.1 From c76e6b982bb171f24592b62264b28eb3fbe1bafc Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Tue, 2 Feb 2016 14:17:08 +0100 Subject: Move load command into _text partial --- app/views/projects/blob/_blob.html.haml | 1 - app/views/projects/blob/_text.html.haml | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/projects/blob/_blob.html.haml b/app/views/projects/blob/_blob.html.haml index 50aea968980..3d8d88834e2 100644 --- a/app/views/projects/blob/_blob.html.haml +++ b/app/views/projects/blob/_blob.html.haml @@ -35,7 +35,6 @@ - if blob.lfs_pointer? = render "download", blob: blob - elsif blob.text? - - blob.load_all_data!(@repository) = render "text", blob: blob - elsif blob.image? = render "image", blob: blob diff --git a/app/views/projects/blob/_text.html.haml b/app/views/projects/blob/_text.html.haml index 906e5ccb360..d09cd73558c 100644 --- a/app/views/projects/blob/_text.html.haml +++ b/app/views/projects/blob/_text.html.haml @@ -1,3 +1,4 @@ +- blob.load_all_data!(@repository) - if markup?(blob.name) .file-content.wiki = render_markup(blob.name, blob.data) -- cgit v1.2.1 From d20e75a8d80c2828336cd22897ea6868d666f8a5 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Sat, 9 Jan 2016 19:30:34 +0000 Subject: Support Akismet spam checking for creation of issues via API Currently any spam detected by Akismet by non-members via API will be logged in a separate table in the admin page. Closes #5612 --- CHANGELOG | 1 + Gemfile | 3 +- Gemfile.lock | 2 + .../admin/application_settings_controller.rb | 2 + app/controllers/admin/spam_logs_controller.rb | 33 +++++++++++++++ app/models/application_setting.rb | 8 +++- app/models/spam_log.rb | 13 ++++++ app/models/spam_report.rb | 5 +++ app/models/user.rb | 1 + app/services/create_spam_log_service.rb | 13 ++++++ .../admin/application_settings/_form.html.haml | 23 ++++++++-- app/views/admin/spam_logs/_spam_log.html.haml | 30 +++++++++++++ app/views/admin/spam_logs/index.html.haml | 21 +++++++++ app/views/layouts/nav/_admin.html.haml | 7 +++ config/routes.rb | 2 + ...31152326_add_akismet_to_application_settings.rb | 8 ++++ db/migrate/20160109054846_create_spam_logs.rb | 16 +++++++ db/schema.rb | 15 +++++++ doc/integration/README.md | 1 + doc/integration/akismet.md | 30 +++++++++++++ doc/integration/img/akismet_settings.png | Bin 0 -> 55837 bytes features/admin/spam_logs.feature | 8 ++++ features/steps/admin/spam_logs.rb | 18 ++++++++ features/steps/shared/paths.rb | 4 ++ lib/api/issues.rb | 22 +++++++++- lib/gitlab/akismet_helper.rb | 39 +++++++++++++++++ lib/gitlab/current_settings.rb | 3 +- .../controllers/admin/spam_logs_controller_spec.rb | 47 +++++++++++++++++++++ spec/factories/spam_logs.rb | 7 +++ spec/lib/gitlab/akismet_helper_spec.rb | 35 +++++++++++++++ spec/requests/api/issues_spec.rb | 22 ++++++++++ 31 files changed, 432 insertions(+), 7 deletions(-) create mode 100644 app/controllers/admin/spam_logs_controller.rb create mode 100644 app/models/spam_log.rb create mode 100644 app/models/spam_report.rb create mode 100644 app/services/create_spam_log_service.rb create mode 100644 app/views/admin/spam_logs/_spam_log.html.haml create mode 100644 app/views/admin/spam_logs/index.html.haml create mode 100644 db/migrate/20151231152326_add_akismet_to_application_settings.rb create mode 100644 db/migrate/20160109054846_create_spam_logs.rb create mode 100644 doc/integration/akismet.md create mode 100644 doc/integration/img/akismet_settings.png create mode 100644 features/admin/spam_logs.feature create mode 100644 features/steps/admin/spam_logs.rb create mode 100644 lib/gitlab/akismet_helper.rb create mode 100644 spec/controllers/admin/spam_logs_controller_spec.rb create mode 100644 spec/factories/spam_logs.rb create mode 100644 spec/lib/gitlab/akismet_helper_spec.rb diff --git a/CHANGELOG b/CHANGELOG index 7a70516173c..1be1f7374df 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -74,6 +74,7 @@ v 8.4.0 - Don't notify users twice if they are both project watchers and subscribers (Stan Hu) - Remove gray background from layout in UI - Fix signup for OAuth providers that don't provide a name + - Support Akismet spam checking for creation of issues via API (Stan Hu) - Implement new UI for group page - Implement search inside emoji picker - Let the CI runner know about builds that this build depends on diff --git a/Gemfile b/Gemfile index c9d428a1798..9f012e1a7e5 100644 --- a/Gemfile +++ b/Gemfile @@ -36,8 +36,9 @@ gem 'omniauth-twitter', '~> 1.2.0' gem 'omniauth_crowd', '~> 2.2.0' gem 'rack-oauth2', '~> 1.2.1' -# reCAPTCHA protection +# Spam and anti-bot protection gem 'recaptcha', require: 'recaptcha/rails' +gem 'akismet', '~> 2.0' # Two-factor authentication gem 'devise-two-factor', '~> 2.0.0' diff --git a/Gemfile.lock b/Gemfile.lock index b4f7587c419..9570d387f68 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -49,6 +49,7 @@ GEM addressable (2.3.8) after_commit_queue (1.3.0) activerecord (>= 3.0) + akismet (2.0.0) allocations (1.0.3) annotate (2.6.10) activerecord (>= 3.2, <= 4.3) @@ -884,6 +885,7 @@ DEPENDENCIES acts-as-taggable-on (~> 3.4) addressable (~> 2.3.8) after_commit_queue + akismet (~> 2.0) allocations (~> 1.0) annotate (~> 2.6.0) asana (~> 0.4.0) diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb index 9943745208e..1515086b16d 100644 --- a/app/controllers/admin/application_settings_controller.rb +++ b/app/controllers/admin/application_settings_controller.rb @@ -79,6 +79,8 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController :recaptcha_private_key, :sentry_enabled, :sentry_dsn, + :akismet_enabled, + :akismet_api_key, restricted_visibility_levels: [], import_sources: [] ) diff --git a/app/controllers/admin/spam_logs_controller.rb b/app/controllers/admin/spam_logs_controller.rb new file mode 100644 index 00000000000..69f94dd3ba8 --- /dev/null +++ b/app/controllers/admin/spam_logs_controller.rb @@ -0,0 +1,33 @@ +class Admin::SpamLogsController < Admin::ApplicationController + before_action :set_spam_log, only: [:destroy] + + def index + @spam_logs = SpamLog.order(created_at: :desc).page(params[:page]) + end + + def destroy + @spam_log.destroy + message = 'Spam log was successfully destroyed.' + + if params[:remove_user] + username = @spam_log.user.username + @spam_log.user.destroy + message = "User #{username} was successfully destroyed." + end + + respond_to do |format| + format.json { render json: '{}' } + format.html { redirect_to admin_spam_logs_path, notice: message } + end + end + + private + + def set_spam_log + @spam_log = SpamLog.find(params[:id]) + end + + def spam_log_params + params[:spam_log] + end +end diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb index 59563b8823c..9cafc78f761 100644 --- a/app/models/application_setting.rb +++ b/app/models/application_setting.rb @@ -88,6 +88,10 @@ class ApplicationSetting < ActiveRecord::Base presence: true, if: :sentry_enabled + validates :akismet_api_key, + presence: true, + if: :akismet_enabled + validates_each :restricted_visibility_levels do |record, attr, value| unless value.nil? value.each do |level| @@ -143,7 +147,9 @@ class ApplicationSetting < ActiveRecord::Base shared_runners_enabled: Settings.gitlab_ci['shared_runners_enabled'], max_artifacts_size: Settings.artifacts['max_size'], require_two_factor_authentication: false, - two_factor_grace_period: 48 + two_factor_grace_period: 48, + recaptcha_enabled: false, + akismet_enabled: false ) end diff --git a/app/models/spam_log.rb b/app/models/spam_log.rb new file mode 100644 index 00000000000..132c5713e0a --- /dev/null +++ b/app/models/spam_log.rb @@ -0,0 +1,13 @@ +class SpamLog < ActiveRecord::Base + belongs_to :user + + validates :user, presence: true + + def truncated_description + if description.present? && description.length > 100 + return description[0..100] + "..." + end + + description + end +end diff --git a/app/models/spam_report.rb b/app/models/spam_report.rb new file mode 100644 index 00000000000..cdc7321b08e --- /dev/null +++ b/app/models/spam_report.rb @@ -0,0 +1,5 @@ +class SpamReport < ActiveRecord::Base + belongs_to :user + + validates :user, presence: true +end diff --git a/app/models/user.rb b/app/models/user.rb index 4214f01f6a4..63c895683f7 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -138,6 +138,7 @@ class User < ActiveRecord::Base has_many :assigned_merge_requests, dependent: :destroy, foreign_key: :assignee_id, class_name: "MergeRequest" has_many :oauth_applications, class_name: 'Doorkeeper::Application', as: :owner, dependent: :destroy has_one :abuse_report, dependent: :destroy + has_many :spam_log, dependent: :destroy has_many :builds, dependent: :nullify, class_name: 'Ci::Build' diff --git a/app/services/create_spam_log_service.rb b/app/services/create_spam_log_service.rb new file mode 100644 index 00000000000..59a66fde47a --- /dev/null +++ b/app/services/create_spam_log_service.rb @@ -0,0 +1,13 @@ +class CreateSpamLogService < BaseService + def initialize(project, user, params) + super(project, user, params) + end + + def execute + spam_params = params.merge({ user_id: @current_user.id, + project_id: @project.id } ) + spam_log = SpamLog.new(spam_params) + spam_log.save + spam_log + end +end diff --git a/app/views/admin/application_settings/_form.html.haml b/app/views/admin/application_settings/_form.html.haml index b0f1a34cbec..b4e3d96d405 100644 --- a/app/views/admin/application_settings/_form.html.haml +++ b/app/views/admin/application_settings/_form.html.haml @@ -218,20 +218,37 @@ = f.label :recaptcha_enabled do = f.check_box :recaptcha_enabled Enable reCAPTCHA - %span.help-block#recaptcha_help_block Helps preventing bots from creating accounts + %span.help-block#recaptcha_help_block Helps prevent bots from creating accounts .form-group = f.label :recaptcha_site_key, 'reCAPTCHA Site Key', class: 'control-label col-sm-2' .col-sm-10 = f.text_field :recaptcha_site_key, class: 'form-control' .help-block - Generate site and private keys here: - %a{ href: 'http://www.google.com/recaptcha', target: '_blank'} http://www.google.com/recaptcha + Generate site and private keys at + %a{ href: 'http://www.google.com/recaptcha', target: 'blank'} http://www.google.com/recaptcha + .form-group = f.label :recaptcha_private_key, 'reCAPTCHA Private Key', class: 'control-label col-sm-2' .col-sm-10 = f.text_field :recaptcha_private_key, class: 'form-control' + .form-group + .col-sm-offset-2.col-sm-10 + .checkbox + = f.label :akismet_enabled do + = f.check_box :akismet_enabled + Enable Akismet + %span.help-block#akismet_help_block Helps prevent bots from creating issues + + .form-group + = f.label :akismet_api_key, 'Akismet API Key', class: 'control-label col-sm-2' + .col-sm-10 + = f.text_field :akismet_api_key, class: 'form-control' + .help-block + Generate API key at + %a{ href: 'http://www.akismet.com', target: 'blank'} http://www.akismet.com + %fieldset %legend Error Reporting and Logging %p diff --git a/app/views/admin/spam_logs/_spam_log.html.haml b/app/views/admin/spam_logs/_spam_log.html.haml new file mode 100644 index 00000000000..1c793bbf738 --- /dev/null +++ b/app/views/admin/spam_logs/_spam_log.html.haml @@ -0,0 +1,30 @@ +- user = spam_log.user +%tr + %td + = spam_log.created_at.to_s(:short) + %td + - if user + = link_to user.name, user + - else + (removed) + %td + = spam_log.source_ip + %td + = spam_log.via_api ? 'Y' : 'N' + %td + = spam_log.noteable_type + %td + = spam_log.title + %td + = spam_log.truncated_description + %td + - if user + = link_to 'Remove user', admin_spam_log_path(spam_log, remove_user: true), + data: { confirm: "USER #{user.name} WILL BE REMOVED! Are you sure?" }, method: :delete, class: "btn btn-xs btn-remove" + %td + - if user && !user.blocked? + = link_to 'Block user', block_admin_user_path(user), data: {confirm: 'USER WILL BE BLOCKED! Are you sure?'}, method: :put, class: "btn btn-xs" + - else + .btn.btn-xs.disabled + Already Blocked + = link_to 'Remove log', [:admin, spam_log, format: :json], remote: true, method: :delete, class: "btn btn-xs btn-close js-remove-tr" diff --git a/app/views/admin/spam_logs/index.html.haml b/app/views/admin/spam_logs/index.html.haml new file mode 100644 index 00000000000..439468e572b --- /dev/null +++ b/app/views/admin/spam_logs/index.html.haml @@ -0,0 +1,21 @@ +- page_title "Spam Logs" +%h3.page-title Spam Logs +%hr +- if @spam_logs.present? + .table-holder + %table.table + %thead + %tr + %th Date + %th User + %th Source IP + %th Via API? + %th Type + %th Title + %th Description + %th Primary Action + %th + = render @spam_logs + = paginate @spam_logs +- else + %h4 There are no Spam Logs diff --git a/app/views/layouts/nav/_admin.html.haml b/app/views/layouts/nav/_admin.html.haml index cffdb52cc23..8dc20587421 100644 --- a/app/views/layouts/nav/_admin.html.haml +++ b/app/views/layouts/nav/_admin.html.haml @@ -82,6 +82,13 @@ Abuse Reports %span.count= number_with_delimiter(AbuseReport.count(:all)) + = nav_link(controller: :spam_logs) do + = link_to admin_spam_logs_path, title: "Spam Logs" do + = icon('exclamation-triangle fw') + %span + Spam Logs + %span.count= number_with_delimiter(SpamLog.count(:all)) + = nav_link(controller: :application_settings, html_options: { class: 'separate-item'}) do = link_to admin_application_settings_path, title: 'Settings' do = icon('cogs fw') diff --git a/config/routes.rb b/config/routes.rb index 54cc338b605..034bfaf1bcd 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -211,6 +211,8 @@ Rails.application.routes.draw do end resources :abuse_reports, only: [:index, :destroy] + resources :spam_logs, only: [:index, :destroy] + resources :applications resources :groups, constraints: { id: /[^\/]+/ } do diff --git a/db/migrate/20151231152326_add_akismet_to_application_settings.rb b/db/migrate/20151231152326_add_akismet_to_application_settings.rb new file mode 100644 index 00000000000..3f52c758f9a --- /dev/null +++ b/db/migrate/20151231152326_add_akismet_to_application_settings.rb @@ -0,0 +1,8 @@ +class AddAkismetToApplicationSettings < ActiveRecord::Migration + def change + change_table :application_settings do |t| + t.boolean :akismet_enabled, default: false + t.string :akismet_api_key + end + end +end diff --git a/db/migrate/20160109054846_create_spam_logs.rb b/db/migrate/20160109054846_create_spam_logs.rb new file mode 100644 index 00000000000..f12fe9f8f78 --- /dev/null +++ b/db/migrate/20160109054846_create_spam_logs.rb @@ -0,0 +1,16 @@ +class CreateSpamLogs < ActiveRecord::Migration + def change + create_table :spam_logs do |t| + t.integer :user_id + t.string :source_ip + t.string :user_agent + t.boolean :via_api + t.integer :project_id + t.string :noteable_type + t.string :title + t.text :description + + t.timestamps null: false + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 2ad2c23fba5..d546e06cd8a 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -64,6 +64,8 @@ ActiveRecord::Schema.define(version: 20160128233227) do t.integer "metrics_sample_interval", default: 15 t.boolean "sentry_enabled", default: false t.string "sentry_dsn" + t.boolean "akismet_enabled", default: false + t.string "akismet_api_key" end create_table "audit_events", force: :cascade do |t| @@ -770,6 +772,19 @@ ActiveRecord::Schema.define(version: 20160128233227) do add_index "snippets", ["project_id"], name: "index_snippets_on_project_id", using: :btree add_index "snippets", ["visibility_level"], name: "index_snippets_on_visibility_level", using: :btree + create_table "spam_logs", force: :cascade do |t| + t.integer "user_id" + t.string "source_ip" + t.string "user_agent" + t.boolean "via_api" + t.integer "project_id" + t.string "noteable_type" + t.string "title" + t.text "description" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + create_table "subscriptions", force: :cascade do |t| t.integer "user_id" t.integer "subscribable_id" diff --git a/doc/integration/README.md b/doc/integration/README.md index 83116bc8370..281eea8363d 100644 --- a/doc/integration/README.md +++ b/doc/integration/README.md @@ -15,6 +15,7 @@ See the documentation below for details on how to configure these services. - [OAuth2 provider](oauth_provider.md) OAuth2 application creation - [Gmail actions buttons](gmail_action_buttons_for_gitlab.md) Adds GitLab actions to messages - [reCAPTCHA](recaptcha.md) Configure GitLab to use Google reCAPTCHA for new users +- [Akismet](akismet.md) Configure Akismet to stop spam GitLab Enterprise Edition contains [advanced Jenkins support][jenkins]. diff --git a/doc/integration/akismet.md b/doc/integration/akismet.md new file mode 100644 index 00000000000..5cc09bd536d --- /dev/null +++ b/doc/integration/akismet.md @@ -0,0 +1,30 @@ +# Akismet + +GitLab leverages [Akismet](http://akismet.com) to protect against spam. Currently +GitLab uses Akismet to prevent users who are not members of a project from +creating spam via the GitLab API. Detected spam will be rejected, and +an entry in the "Spam Log" section in the Admin page will be created. + +Privacy note: GitLab submits the user's IP and user agent to Akismet. Note that +adding a user to a project will disable the Akismet check and prevent this +from happening. + +## Configuration + +To use Akismet: + +1. Go to the URL: https://akismet.com/account/ + +2. Sign-in or create a new account. + +3. Click on "Show" to reveal the API key. + +4. Go to Applications Settings on Admin Area (`admin/application_settings`) + +5. Check the `Enable Akismet` checkbox + +6. Fill in the API key from step 3. + +7. Save the configuration. + +![Screenshot of Akismet settings](img/akismet_settings.png) diff --git a/doc/integration/img/akismet_settings.png b/doc/integration/img/akismet_settings.png new file mode 100644 index 00000000000..ccdd3adb1c5 Binary files /dev/null and b/doc/integration/img/akismet_settings.png differ diff --git a/features/admin/spam_logs.feature b/features/admin/spam_logs.feature new file mode 100644 index 00000000000..92a5389e3a4 --- /dev/null +++ b/features/admin/spam_logs.feature @@ -0,0 +1,8 @@ +Feature: Admin spam logs + Background: + Given I sign in as an admin + And spam logs exist + + Scenario: Browse spam logs + When I visit spam logs page + Then I should see list of spam logs diff --git a/features/steps/admin/spam_logs.rb b/features/steps/admin/spam_logs.rb new file mode 100644 index 00000000000..79d18b036b0 --- /dev/null +++ b/features/steps/admin/spam_logs.rb @@ -0,0 +1,18 @@ +class Spinach::Features::AdminSpamLogs < Spinach::FeatureSteps + include SharedAuthentication + include SharedPaths + include SharedAdmin + + step 'I should see list of spam logs' do + page.should have_content("Spam Logs") + spam_log = SpamLog.first + page.should have_content spam_log.title + page.should have_content spam_log.description + page.should have_link("Remove user") + page.should have_link("Block user") + end + + step 'spam logs exist' do + create(:spam_log) + end +end diff --git a/features/steps/shared/paths.rb b/features/steps/shared/paths.rb index 4264c9c6f1a..2c854ac7bf9 100644 --- a/features/steps/shared/paths.rb +++ b/features/steps/shared/paths.rb @@ -191,6 +191,10 @@ module SharedPaths visit admin_application_settings_path end + step 'I visit spam logs page' do + visit admin_spam_logs_path + end + step 'I visit applications page' do visit admin_applications_path end diff --git a/lib/api/issues.rb b/lib/api/issues.rb index 6e7a7672070..cdadd13c13a 100644 --- a/lib/api/issues.rb +++ b/lib/api/issues.rb @@ -3,6 +3,8 @@ module API class Issues < Grape::API before { authenticate! } + helpers ::Gitlab::AkismetHelper + helpers do def filter_issues_state(issues, state) case state @@ -19,6 +21,15 @@ module API def filter_issues_milestone(issues, milestone) issues.includes(:milestone).where('milestones.title' => milestone) end + + def create_spam_log(project, current_user, attrs) + params = attrs.dup + params[:source_ip] = env['REMOTE_ADDR'] + params[:user_agent] = env['HTTP_USER_AGENT'] + params[:noteable_type] = 'Issue' + params[:via_api] = true + ::CreateSpamLogService.new(project, current_user, params).execute + end end resource :issues do @@ -114,7 +125,16 @@ module API render_api_error!({ labels: errors }, 400) end - issue = ::Issues::CreateService.new(user_project, current_user, attrs).execute + project = user_project + text = attrs[:title] + text += "\n#{attrs[:description]}" if attrs[:description].present? + + if check_for_spam?(project, current_user) && is_spam?(env, current_user, text) + create_spam_log(project, current_user, attrs) + render_api_error!({ error: 'Spam detected' }, 400) + end + + issue = ::Issues::CreateService.new(project, current_user, attrs).execute if issue.valid? # Find or create labels and attach to issue. Labels are valid because diff --git a/lib/gitlab/akismet_helper.rb b/lib/gitlab/akismet_helper.rb new file mode 100644 index 00000000000..71f525309fe --- /dev/null +++ b/lib/gitlab/akismet_helper.rb @@ -0,0 +1,39 @@ +module Gitlab + module AkismetHelper + def akismet_enabled? + current_application_settings.akismet_enabled + end + + def akismet_client + ::Akismet::Client.new(current_application_settings.akismet_api_key, + Gitlab.config.gitlab.url) + end + + def check_for_spam?(project, user) + akismet_enabled? && !project.team.member?(user) + end + + def is_spam?(environment, user, text) + client = akismet_client + ip_address = environment['REMOTE_ADDR'] + user_agent = environment['HTTP_USER_AGENT'] + + params = { + type: 'comment', + text: text, + created_at: DateTime.now, + author: user.name, + author_email: user.email, + referrer: environment['HTTP_REFERER'], + } + + begin + is_spam, is_blatant = client.check(ip_address, user_agent, params) + is_spam || is_blatant + rescue => e + Rails.logger.error("Unable to connect to Akismet: #{e}, skipping check") + false + end + end + end +end diff --git a/lib/gitlab/current_settings.rb b/lib/gitlab/current_settings.rb index a6b2f14521c..8531c7e87e1 100644 --- a/lib/gitlab/current_settings.rb +++ b/lib/gitlab/current_settings.rb @@ -34,7 +34,8 @@ module Gitlab shared_runners_enabled: Settings.gitlab_ci['shared_runners_enabled'], max_artifacts_size: Settings.artifacts['max_size'], require_two_factor_authentication: false, - two_factor_grace_period: 48 + two_factor_grace_period: 48, + akismet_enabled: false ) end diff --git a/spec/controllers/admin/spam_logs_controller_spec.rb b/spec/controllers/admin/spam_logs_controller_spec.rb new file mode 100644 index 00000000000..2486298fc78 --- /dev/null +++ b/spec/controllers/admin/spam_logs_controller_spec.rb @@ -0,0 +1,47 @@ +require 'spec_helper' + +describe Admin::SpamLogsController do + let(:admin) { create(:admin) } + let(:spam_log) { create(:spam_log, user: admin) } + + before do + sign_in(admin) + end + + describe '#index' do + it 'lists all spam logs' do + get :index + expect(response.status).to eq(200) + end + end + + describe '#destroy' do + it 'destroys just spam log' do + user = spam_log.user + delete :destroy, id: spam_log.id + + expect(SpamLog.all.count).to eq(0) + expect(User.find(user.id)).to be_truthy + expect(response.status).to eq(302) + end + + it 'destroys user and his spam logs' do + user = spam_log.user + delete :destroy, id: spam_log.id, remove_user: true + + expect(SpamLog.all.count).to eq(0) + expect { User.find(user.id) }.to raise_error(ActiveRecord::RecordNotFound) + expect(response.status).to eq(302) + end + + it 'destroys user and his spam logs with JSON format' do + user = spam_log.user + delete :destroy, id: spam_log.id, remove_user: true, format: :json + + expect(SpamLog.all.count).to eq(0) + expect { User.find(user.id) }.to raise_error(ActiveRecord::RecordNotFound) + expect(JSON.parse(response.body)).to eq({}) + expect(response.status).to eq(200) + end + end +end diff --git a/spec/factories/spam_logs.rb b/spec/factories/spam_logs.rb new file mode 100644 index 00000000000..9e8686d73c2 --- /dev/null +++ b/spec/factories/spam_logs.rb @@ -0,0 +1,7 @@ +# Read about factories at https://github.com/thoughtbot/factory_girl + +FactoryGirl.define do + factory :spam_log do + user + end +end diff --git a/spec/lib/gitlab/akismet_helper_spec.rb b/spec/lib/gitlab/akismet_helper_spec.rb new file mode 100644 index 00000000000..9858935180a --- /dev/null +++ b/spec/lib/gitlab/akismet_helper_spec.rb @@ -0,0 +1,35 @@ +require 'spec_helper' + +describe Gitlab::AkismetHelper, type: :helper do + let(:project) { create(:project) } + let(:user) { create(:user) } + + before do + allow(Gitlab.config.gitlab).to receive(:url).and_return(Settings.send(:build_gitlab_url)) + current_application_settings.akismet_enabled = true + current_application_settings.akismet_api_key = '12345' + end + + describe '#check_for_spam?' do + it 'returns true for non-member' do + expect(helper.check_for_spam?(project, user)).to eq(true) + end + + it 'returns false for member' do + project.team << [user, :guest] + expect(helper.check_for_spam?(project, user)).to eq(false) + end + end + + describe '#is_spam?' do + it 'returns true for spam' do + environment = { + 'REMOTE_ADDR' => '127.0.0.1', + 'HTTP_USER_AGENT' => 'Test User Agent' + } + + allow_any_instance_of(::Akismet::Client).to receive(:check).and_return([true, true]) + expect(helper.is_spam?(environment, user, 'Is this spam?')).to eq(true) + end + end +end diff --git a/spec/requests/api/issues_spec.rb b/spec/requests/api/issues_spec.rb index 5e65ad18c0e..2e50344c149 100644 --- a/spec/requests/api/issues_spec.rb +++ b/spec/requests/api/issues_spec.rb @@ -241,6 +241,28 @@ describe API::API, api: true do end end + describe 'POST /projects/:id/issues with spam filtering' do + before do + Grape::Endpoint.before_each do |endpoint| + allow(endpoint).to receive(:check_for_spam?).and_return(true) + allow(endpoint).to receive(:is_spam?).and_return(true) + end + end + + it "should create a new project issue" do + post api("/projects/#{project.id}/issues", user), + title: 'new issue', labels: 'label, label2' + expect(response.status).to eq(400) + expect(json_response['message']).to eq({ "error" => "Spam detected" }) + spam_logs = SpamLog.all + expect(spam_logs.count).to eq(1) + expect(spam_logs[0].title).to eq('new issue') + expect(spam_logs[0].user).to eq(user) + expect(spam_logs[0].noteable_type).to eq('Issue') + expect(spam_logs[0].project_id).to eq(project.id) + end + end + describe "PUT /projects/:id/issues/:issue_id to update only title" do it "should update a project issue" do put api("/projects/#{project.id}/issues/#{issue.id}", user), -- cgit v1.2.1 From 64c9768bd6916edfc1e43907ca5e976524b8d51b Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Tue, 26 Jan 2016 16:59:23 -0200 Subject: Use truncate helper on spam logs list --- app/models/spam_log.rb | 8 -------- app/views/admin/spam_logs/_spam_log.html.haml | 2 +- features/steps/admin/spam_logs.rb | 22 ++++++++++++++++------ spec/factories/spam_logs.rb | 4 ++++ 4 files changed, 21 insertions(+), 15 deletions(-) diff --git a/app/models/spam_log.rb b/app/models/spam_log.rb index 132c5713e0a..b7b32b478a7 100644 --- a/app/models/spam_log.rb +++ b/app/models/spam_log.rb @@ -2,12 +2,4 @@ class SpamLog < ActiveRecord::Base belongs_to :user validates :user, presence: true - - def truncated_description - if description.present? && description.length > 100 - return description[0..100] + "..." - end - - description - end end diff --git a/app/views/admin/spam_logs/_spam_log.html.haml b/app/views/admin/spam_logs/_spam_log.html.haml index 1c793bbf738..9f9f1d75895 100644 --- a/app/views/admin/spam_logs/_spam_log.html.haml +++ b/app/views/admin/spam_logs/_spam_log.html.haml @@ -16,7 +16,7 @@ %td = spam_log.title %td - = spam_log.truncated_description + = truncate(spam_log.description, length: 100) %td - if user = link_to 'Remove user', admin_spam_log_path(spam_log, remove_user: true), diff --git a/features/steps/admin/spam_logs.rb b/features/steps/admin/spam_logs.rb index 79d18b036b0..ad825fd414c 100644 --- a/features/steps/admin/spam_logs.rb +++ b/features/steps/admin/spam_logs.rb @@ -4,15 +4,25 @@ class Spinach::Features::AdminSpamLogs < Spinach::FeatureSteps include SharedAdmin step 'I should see list of spam logs' do - page.should have_content("Spam Logs") - spam_log = SpamLog.first - page.should have_content spam_log.title - page.should have_content spam_log.description - page.should have_link("Remove user") - page.should have_link("Block user") + expect(page).to have_content('Spam Logs') + expect(page).to have_content spam_log.source_ip + expect(page).to have_content spam_log.noteable_type + expect(page).to have_content 'N' + expect(page).to have_content spam_log.title + expect(page).to have_content truncate(spam_log.description) + expect(page).to have_link('Remove user') + expect(page).to have_link('Block user') end step 'spam logs exist' do create(:spam_log) end + + def spam_log + @spam_log ||= SpamLog.first + end + + def truncate(description) + "#{spam_log.description[0...97]}..." + end end diff --git a/spec/factories/spam_logs.rb b/spec/factories/spam_logs.rb index 9e8686d73c2..d90e5d6bf26 100644 --- a/spec/factories/spam_logs.rb +++ b/spec/factories/spam_logs.rb @@ -3,5 +3,9 @@ FactoryGirl.define do factory :spam_log do user + source_ip { FFaker::Internet.ip_v4_address } + noteable_type 'Issue' + title { FFaker::Lorem.sentence } + description { FFaker::Lorem.paragraph(5) } end end -- cgit v1.2.1 From 80d0a2a6d8dccbb9888f9cd4dc3c3e7e208817e6 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Tue, 26 Jan 2016 17:01:56 -0200 Subject: Add model spec for SpamLog --- spec/models/spam_log_spec.rb | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 spec/models/spam_log_spec.rb diff --git a/spec/models/spam_log_spec.rb b/spec/models/spam_log_spec.rb new file mode 100644 index 00000000000..076f3e44c70 --- /dev/null +++ b/spec/models/spam_log_spec.rb @@ -0,0 +1,11 @@ +require 'spec_helper' + +describe SpamLog, models: true do + describe 'associations' do + it { is_expected.to belong_to(:user) } + end + + describe 'validations' do + it { is_expected.to validate_presence_of(:user) } + end +end -- cgit v1.2.1 From e38a1fc83ee7a9fb04fe370204f0094723890f00 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Tue, 26 Jan 2016 17:55:33 -0200 Subject: Fix typo on User model --- app/models/user.rb | 2 +- spec/models/user_spec.rb | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/models/user.rb b/app/models/user.rb index 63c895683f7..234c1cd89f9 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -138,7 +138,7 @@ class User < ActiveRecord::Base has_many :assigned_merge_requests, dependent: :destroy, foreign_key: :assignee_id, class_name: "MergeRequest" has_many :oauth_applications, class_name: 'Doorkeeper::Application', as: :owner, dependent: :destroy has_one :abuse_report, dependent: :destroy - has_many :spam_log, dependent: :destroy + has_many :spam_logs, dependent: :destroy has_many :builds, dependent: :nullify, class_name: 'Ci::Build' diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 0bef68e2885..cee051f5732 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -91,6 +91,7 @@ describe User, models: true do it { is_expected.to have_many(:assigned_merge_requests).dependent(:destroy) } it { is_expected.to have_many(:identities).dependent(:destroy) } it { is_expected.to have_one(:abuse_report) } + it { is_expected.to have_many(:spam_logs).dependent(:destroy) } end describe 'validations' do -- cgit v1.2.1 From 62cad887ea695d40afee894089f894ee398cf98a Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Tue, 26 Jan 2016 18:03:01 -0200 Subject: Use time_ago_with_tooltip on spam logs list --- app/views/admin/spam_logs/_spam_log.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/admin/spam_logs/_spam_log.html.haml b/app/views/admin/spam_logs/_spam_log.html.haml index 9f9f1d75895..51e94acce22 100644 --- a/app/views/admin/spam_logs/_spam_log.html.haml +++ b/app/views/admin/spam_logs/_spam_log.html.haml @@ -1,7 +1,7 @@ - user = spam_log.user %tr %td - = spam_log.created_at.to_s(:short) + = time_ago_with_tooltip(spam_log.created_at) %td - if user = link_to user.name, user -- cgit v1.2.1 From a2bbf004779db402e67a918db893c166502f5050 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Tue, 26 Jan 2016 18:08:20 -0200 Subject: Refactor spam filtering on issues API --- lib/api/issues.rb | 15 ++++++++------- spec/requests/api/issues_spec.rb | 11 ++++++++--- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/lib/api/issues.rb b/lib/api/issues.rb index cdadd13c13a..252744515da 100644 --- a/lib/api/issues.rb +++ b/lib/api/issues.rb @@ -23,11 +23,13 @@ module API end def create_spam_log(project, current_user, attrs) - params = attrs.dup - params[:source_ip] = env['REMOTE_ADDR'] - params[:user_agent] = env['HTTP_USER_AGENT'] - params[:noteable_type] = 'Issue' - params[:via_api] = true + params = attrs.merge({ + source_ip: env['REMOTE_ADDR'], + user_agent: env['HTTP_USER_AGENT'], + noteable_type: 'Issue', + via_api: true + }) + ::CreateSpamLogService.new(project, current_user, params).execute end end @@ -126,8 +128,7 @@ module API end project = user_project - text = attrs[:title] - text += "\n#{attrs[:description]}" if attrs[:description].present? + text = [attrs[:title], attrs[:description]].reject(&:blank?).join("\n") if check_for_spam?(project, current_user) && is_spam?(env, current_user, text) create_spam_log(project, current_user, attrs) diff --git a/spec/requests/api/issues_spec.rb b/spec/requests/api/issues_spec.rb index 2e50344c149..dcf1b394a3f 100644 --- a/spec/requests/api/issues_spec.rb +++ b/spec/requests/api/issues_spec.rb @@ -249,14 +249,19 @@ describe API::API, api: true do end end - it "should create a new project issue" do - post api("/projects/#{project.id}/issues", user), - title: 'new issue', labels: 'label, label2' + it "should not create a new project issue" do + expect { + post api("/projects/#{project.id}/issues", user), + title: 'new issue', description: 'content here', labels: 'label, label2' + }.not_to change(Issue, :count) + expect(response.status).to eq(400) expect(json_response['message']).to eq({ "error" => "Spam detected" }) + spam_logs = SpamLog.all expect(spam_logs.count).to eq(1) expect(spam_logs[0].title).to eq('new issue') + expect(spam_logs[0].description).to eq('content here') expect(spam_logs[0].user).to eq(user) expect(spam_logs[0].noteable_type).to eq('Issue') expect(spam_logs[0].project_id).to eq(project.id) -- cgit v1.2.1 From 718b1dddfe8d7422e8de8b2fbbd8357fc1c3b5e4 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Tue, 26 Jan 2016 19:20:01 -0200 Subject: Refactor Admin::SpamLogsController to block user before destroying --- app/controllers/admin/spam_logs_controller.rb | 30 +++++-------------- app/models/spam_log.rb | 5 ++++ app/views/admin/spam_logs/_spam_log.html.haml | 8 +++-- app/views/admin/spam_logs/index.html.haml | 2 +- .../controllers/admin/spam_logs_controller_spec.rb | 35 +++++++++------------- spec/models/spam_log_spec.rb | 14 +++++++++ 6 files changed, 46 insertions(+), 48 deletions(-) diff --git a/app/controllers/admin/spam_logs_controller.rb b/app/controllers/admin/spam_logs_controller.rb index 69f94dd3ba8..377e9741e5f 100644 --- a/app/controllers/admin/spam_logs_controller.rb +++ b/app/controllers/admin/spam_logs_controller.rb @@ -1,33 +1,17 @@ class Admin::SpamLogsController < Admin::ApplicationController - before_action :set_spam_log, only: [:destroy] - def index - @spam_logs = SpamLog.order(created_at: :desc).page(params[:page]) + @spam_logs = SpamLog.order(id: :desc).page(params[:page]) end def destroy - @spam_log.destroy - message = 'Spam log was successfully destroyed.' + spam_log = SpamLog.find(params[:id]) if params[:remove_user] - username = @spam_log.user.username - @spam_log.user.destroy - message = "User #{username} was successfully destroyed." - end - - respond_to do |format| - format.json { render json: '{}' } - format.html { redirect_to admin_spam_logs_path, notice: message } + spam_log.remove_user + redirect_to admin_spam_logs_path, notice: "User #{spam_log.user.username} was successfully removed." + else + spam_log.destroy + render nothing: true end end - - private - - def set_spam_log - @spam_log = SpamLog.find(params[:id]) - end - - def spam_log_params - params[:spam_log] - end end diff --git a/app/models/spam_log.rb b/app/models/spam_log.rb index b7b32b478a7..12df68ef83b 100644 --- a/app/models/spam_log.rb +++ b/app/models/spam_log.rb @@ -2,4 +2,9 @@ class SpamLog < ActiveRecord::Base belongs_to :user validates :user, presence: true + + def remove_user + user.block + user.destroy + end end diff --git a/app/views/admin/spam_logs/_spam_log.html.haml b/app/views/admin/spam_logs/_spam_log.html.haml index 51e94acce22..8aea67f4497 100644 --- a/app/views/admin/spam_logs/_spam_log.html.haml +++ b/app/views/admin/spam_logs/_spam_log.html.haml @@ -4,13 +4,15 @@ = time_ago_with_tooltip(spam_log.created_at) %td - if user - = link_to user.name, user + = link_to user.name, [:admin, user] + .light.small + Joined #{time_ago_with_tooltip(user.created_at)} - else (removed) %td = spam_log.source_ip %td - = spam_log.via_api ? 'Y' : 'N' + = spam_log.via_api? ? 'Y' : 'N' %td = spam_log.noteable_type %td @@ -27,4 +29,4 @@ - else .btn.btn-xs.disabled Already Blocked - = link_to 'Remove log', [:admin, spam_log, format: :json], remote: true, method: :delete, class: "btn btn-xs btn-close js-remove-tr" + = link_to 'Remove log', [:admin, spam_log], remote: true, method: :delete, class: "btn btn-xs btn-close js-remove-tr" diff --git a/app/views/admin/spam_logs/index.html.haml b/app/views/admin/spam_logs/index.html.haml index 439468e572b..0fdd5bd9960 100644 --- a/app/views/admin/spam_logs/index.html.haml +++ b/app/views/admin/spam_logs/index.html.haml @@ -9,7 +9,7 @@ %th Date %th User %th Source IP - %th Via API? + %th API? %th Type %th Title %th Description diff --git a/spec/controllers/admin/spam_logs_controller_spec.rb b/spec/controllers/admin/spam_logs_controller_spec.rb index 2486298fc78..6beebc362e9 100644 --- a/spec/controllers/admin/spam_logs_controller_spec.rb +++ b/spec/controllers/admin/spam_logs_controller_spec.rb @@ -1,8 +1,10 @@ require 'spec_helper' describe Admin::SpamLogsController do - let(:admin) { create(:admin) } - let(:spam_log) { create(:spam_log, user: admin) } + let(:admin) { create(:admin) } + let(:user) { create(:user) } + let!(:first_spam) { create(:spam_log, user: user) } + let!(:second_spam) { create(:spam_log, user: user) } before do sign_in(admin) @@ -11,37 +13,28 @@ describe Admin::SpamLogsController do describe '#index' do it 'lists all spam logs' do get :index + expect(response.status).to eq(200) end end describe '#destroy' do - it 'destroys just spam log' do - user = spam_log.user - delete :destroy, id: spam_log.id + it 'removes only the spam log when removing log' do + expect { + delete :destroy, id: first_spam.id + }.to change { SpamLog.count }.by(-1) - expect(SpamLog.all.count).to eq(0) expect(User.find(user.id)).to be_truthy - expect(response.status).to eq(302) + expect(response.status).to eq(200) end - it 'destroys user and his spam logs' do - user = spam_log.user - delete :destroy, id: spam_log.id, remove_user: true + it 'removes user and his spam logs when removing the user' do + delete :destroy, id: first_spam.id, remove_user: true - expect(SpamLog.all.count).to eq(0) - expect { User.find(user.id) }.to raise_error(ActiveRecord::RecordNotFound) + expect(flash[:notice]).to eq "User #{user.username} was successfully removed." expect(response.status).to eq(302) - end - - it 'destroys user and his spam logs with JSON format' do - user = spam_log.user - delete :destroy, id: spam_log.id, remove_user: true, format: :json - - expect(SpamLog.all.count).to eq(0) + expect(SpamLog.count).to eq(0) expect { User.find(user.id) }.to raise_error(ActiveRecord::RecordNotFound) - expect(JSON.parse(response.body)).to eq({}) - expect(response.status).to eq(200) end end end diff --git a/spec/models/spam_log_spec.rb b/spec/models/spam_log_spec.rb index 076f3e44c70..c4ec7625cb0 100644 --- a/spec/models/spam_log_spec.rb +++ b/spec/models/spam_log_spec.rb @@ -8,4 +8,18 @@ describe SpamLog, models: true do describe 'validations' do it { is_expected.to validate_presence_of(:user) } end + + describe '#remove_user' do + it 'blocks the user' do + spam_log = build(:spam_log) + + expect { spam_log.remove_user }.to change { spam_log.user.blocked? }.to(true) + end + + it 'removes the user' do + spam_log = build(:spam_log) + + expect { spam_log.remove_user }.to change { User.count }.by(-1) + end + end end -- cgit v1.2.1 From eefc46e0d5310cce5b5a64c1b982d5348d465f83 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Tue, 26 Jan 2016 19:51:52 -0200 Subject: Fix rubocop offenses --- spec/controllers/admin/spam_logs_controller_spec.rb | 5 +---- spec/requests/api/issues_spec.rb | 14 +++++++++----- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/spec/controllers/admin/spam_logs_controller_spec.rb b/spec/controllers/admin/spam_logs_controller_spec.rb index 6beebc362e9..b51b303a714 100644 --- a/spec/controllers/admin/spam_logs_controller_spec.rb +++ b/spec/controllers/admin/spam_logs_controller_spec.rb @@ -20,10 +20,7 @@ describe Admin::SpamLogsController do describe '#destroy' do it 'removes only the spam log when removing log' do - expect { - delete :destroy, id: first_spam.id - }.to change { SpamLog.count }.by(-1) - + expect { delete :destroy, id: first_spam.id }.to change { SpamLog.count }.by(-1) expect(User.find(user.id)).to be_truthy expect(response.status).to eq(200) end diff --git a/spec/requests/api/issues_spec.rb b/spec/requests/api/issues_spec.rb index dcf1b394a3f..4443036d98f 100644 --- a/spec/requests/api/issues_spec.rb +++ b/spec/requests/api/issues_spec.rb @@ -249,12 +249,16 @@ describe API::API, api: true do end end - it "should not create a new project issue" do - expect { - post api("/projects/#{project.id}/issues", user), - title: 'new issue', description: 'content here', labels: 'label, label2' - }.not_to change(Issue, :count) + let(:params) do + { + title: 'new issue', + description: 'content here', + labels: 'label, label2' + } + end + it "should not create a new project issue" do + expect { post api("/projects/#{project.id}/issues", user), params }.not_to change(Issue, :count) expect(response.status).to eq(400) expect(json_response['message']).to eq({ "error" => "Spam detected" }) -- cgit v1.2.1 From 07384aa00d8a8759cdb29ba51ae32a6032ba2571 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Mon, 1 Feb 2016 22:05:56 -0200 Subject: Memoize Akismet client initialization on AkismetHelper --- lib/gitlab/akismet_helper.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/gitlab/akismet_helper.rb b/lib/gitlab/akismet_helper.rb index 71f525309fe..b366c89889e 100644 --- a/lib/gitlab/akismet_helper.rb +++ b/lib/gitlab/akismet_helper.rb @@ -5,8 +5,8 @@ module Gitlab end def akismet_client - ::Akismet::Client.new(current_application_settings.akismet_api_key, - Gitlab.config.gitlab.url) + @akismet_client ||= ::Akismet::Client.new(current_application_settings.akismet_api_key, + Gitlab.config.gitlab.url) end def check_for_spam?(project, user) -- cgit v1.2.1 From 0ea5d764f2ad8d94adfca36b20ce92e67af81e36 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Mon, 1 Feb 2016 22:25:00 -0200 Subject: Hide the link for spam logs if the Askimet is disabled --- app/helpers/application_settings_helper.rb | 4 ++++ app/views/layouts/nav/_admin.html.haml | 13 +++++++------ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb index 7d6b58ee21a..23693629a4c 100644 --- a/app/helpers/application_settings_helper.rb +++ b/app/helpers/application_settings_helper.rb @@ -23,6 +23,10 @@ module ApplicationSettingsHelper current_application_settings.user_oauth_applications end + def askimet_enabled? + current_application_settings.akismet_enabled? + end + # Return a group of checkboxes that use Bootstrap's button plugin for a # toggle button effect. def restricted_level_checkboxes(help_block_id) diff --git a/app/views/layouts/nav/_admin.html.haml b/app/views/layouts/nav/_admin.html.haml index 8dc20587421..5f8212ea264 100644 --- a/app/views/layouts/nav/_admin.html.haml +++ b/app/views/layouts/nav/_admin.html.haml @@ -82,12 +82,13 @@ Abuse Reports %span.count= number_with_delimiter(AbuseReport.count(:all)) - = nav_link(controller: :spam_logs) do - = link_to admin_spam_logs_path, title: "Spam Logs" do - = icon('exclamation-triangle fw') - %span - Spam Logs - %span.count= number_with_delimiter(SpamLog.count(:all)) + - if askimet_enabled? + = nav_link(controller: :spam_logs) do + = link_to admin_spam_logs_path, title: "Spam Logs" do + = icon('exclamation-triangle fw') + %span + Spam Logs + %span.count= number_with_delimiter(SpamLog.count(:all)) = nav_link(controller: :application_settings, html_options: { class: 'separate-item'}) do = link_to admin_application_settings_path, title: 'Settings' do -- cgit v1.2.1 From dffacbb12c0abd4edf677aed2d9e201b41fd2dae Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Mon, 1 Feb 2016 22:28:33 -0200 Subject: Update CHANGELOG --- CHANGELOG | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 1be1f7374df..187ab000057 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -22,6 +22,7 @@ v 8.5.0 (unreleased) - Deprecate API "merge_request/:merge_request_id/comments". Use "merge_requests/:merge_request_id/notes" instead - Deprecate API "merge_request/:merge_request_id/...". Use "merge_requests/:merge_request_id/..." instead - Mark inline difference between old and new paths when a file is renamed + - Support Akismet spam checking for creation of issues via API (Stan Hu) v 8.4.3 - Increase lfs_objects size column to 8-byte integer to allow files larger @@ -74,7 +75,6 @@ v 8.4.0 - Don't notify users twice if they are both project watchers and subscribers (Stan Hu) - Remove gray background from layout in UI - Fix signup for OAuth providers that don't provide a name - - Support Akismet spam checking for creation of issues via API (Stan Hu) - Implement new UI for group page - Implement search inside emoji picker - Let the CI runner know about builds that this build depends on -- cgit v1.2.1 From 0a4db90d36870211df2dc1e606b01602666706c8 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Tue, 2 Feb 2016 14:35:09 +0100 Subject: Use begin/end instead of defined? --- app/models/ci/commit.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/models/ci/commit.rb b/app/models/ci/commit.rb index 96786ac4573..ecbd2078b1d 100644 --- a/app/models/ci/commit.rb +++ b/app/models/ci/commit.rb @@ -205,11 +205,11 @@ module Ci end def ci_yaml_file - return @ci_yaml_file if defined?(@ci_yaml_file) - - blob = project.repository.blob_at(sha, '.gitlab-ci.yml') - blob.load_all_data!(project.repository) - @ci_yaml_file = blob.data + @ci_yaml_file ||= begin + blob = project.repository.blob_at(sha, '.gitlab-ci.yml') + blob.load_all_data!(project.repository) + blob.data + end rescue nil end -- cgit v1.2.1 From e08aa3df905f09f1c964fb056cba922a1d6eaa85 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Tue, 2 Feb 2016 15:04:50 +0100 Subject: Use gitlab_git 8.0.0 --- Gemfile | 2 +- Gemfile.lock | 20 +++++++------------- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/Gemfile b/Gemfile index 88236146a14..a511b114f9d 100644 --- a/Gemfile +++ b/Gemfile @@ -49,7 +49,7 @@ gem "browser", '~> 1.0.0' # Extracting information from a git repository # Provide access to Gitlab::Git library -gem "gitlab_git", git: 'https://gitlab.com/gitlab-org/gitlab_git.git', branch: 'lazy-blob' +gem "gitlab_git", '~> 8.0.0' # LDAP Auth # GitLab fork with several improvements to original library. For full list of changes diff --git a/Gemfile.lock b/Gemfile.lock index 9aacbced998..211cb9a42ae 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,14 +1,3 @@ -GIT - remote: https://gitlab.com/gitlab-org/gitlab_git.git - revision: 57160e1cbcf4c03e68aa881dfa8e2f55c37a3ee6 - branch: lazy-blob - specs: - gitlab_git (7.2.24) - activesupport (~> 4.0) - charlock_holmes (~> 0.7.3) - github-linguist (~> 4.7.0) - rugged (~> 0.23.3) - GEM remote: https://rubygems.org/ specs: @@ -350,7 +339,7 @@ GEM json get_process_mem (0.2.0) gherkin-ruby (0.3.2) - github-linguist (4.7.4) + github-linguist (4.7.3) charlock_holmes (~> 0.7.3) escape_utils (~> 1.1.0) mime-types (>= 1.19) @@ -367,6 +356,11 @@ GEM posix-spawn (~> 0.3) gitlab_emoji (0.2.0) gemojione (~> 2.1) + gitlab_git (8.0.0) + activesupport (~> 4.0) + charlock_holmes (~> 0.7.3) + github-linguist (~> 4.7.0) + rugged (~> 0.23.3) gitlab_meta (7.0) gitlab_omniauth-ldap (1.2.1) net-ldap (~> 0.9) @@ -940,7 +934,7 @@ DEPENDENCIES github-markup (~> 1.3.1) gitlab-flowdock-git-hook (~> 1.0.1) gitlab_emoji (~> 0.2.0) - gitlab_git! + gitlab_git (~> 8.0.0) gitlab_meta (= 7.0) gitlab_omniauth-ldap (~> 1.2.1) gollum-lib (~> 4.1.0) -- cgit v1.2.1 From b67f8eee0d2810be4a010c5e968e1848b4ca3c88 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Tue, 2 Feb 2016 15:06:14 +0100 Subject: Use @repository --- app/controllers/projects/avatars_controller.rb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/controllers/projects/avatars_controller.rb b/app/controllers/projects/avatars_controller.rb index bc40e601030..f7e6bb34443 100644 --- a/app/controllers/projects/avatars_controller.rb +++ b/app/controllers/projects/avatars_controller.rb @@ -2,11 +2,10 @@ class Projects::AvatarsController < Projects::ApplicationController before_action :project def show - repository = @project.repository - @blob = repository.blob_at_branch('master', @project.avatar_in_git) + @blob = @repository.blob_at_branch('master', @project.avatar_in_git) if @blob headers['X-Content-Type-Options'] = 'nosniff' - headers.store(*Gitlab::Workhorse.send_git_blob(repository, @blob)) + headers.store(*Gitlab::Workhorse.send_git_blob(@repository, @blob)) headers['Content-Disposition'] = 'inline' headers['Content-Type'] = @blob.content_type head :ok # 'render nothing: true' messes up the Content-Type -- cgit v1.2.1 From c41a8be8d266ceefac307939a2acfd103260fb29 Mon Sep 17 00:00:00 2001 From: Michi302 Date: Wed, 6 Jan 2016 20:11:50 +0100 Subject: Fix add_pagination_headers to keep request parameters in Link header --- CHANGELOG | 1 + lib/api/helpers.rb | 20 +++++++++++++++----- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 7a70516173c..f207e0c5316 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -19,6 +19,7 @@ v 8.5.0 (unreleased) - Update the ExternalIssue regex pattern (Blake Hitchcock) - Optimized performance of finding issues to be closed by a merge request - Revert "Add IP check against DNSBLs at account sign-up" + - Fix API to keep request parameters in Link header (Michael Potthoff) - Deprecate API "merge_request/:merge_request_id/comments". Use "merge_requests/:merge_request_id/notes" instead - Deprecate API "merge_request/:merge_request_id/...". Use "merge_requests/:merge_request_id/..." instead - Mark inline difference between old and new paths when a file is renamed diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb index 9dacf7c1e86..a72044e8058 100644 --- a/lib/api/helpers.rb +++ b/lib/api/helpers.rb @@ -30,7 +30,7 @@ module API end def sudo_identifier() - identifier ||= params[SUDO_PARAM] ||= env[SUDO_HEADER] + identifier ||= params[SUDO_PARAM] || env[SUDO_HEADER] # Regex for integers if !!(identifier =~ /^[0-9]+$/) @@ -344,12 +344,22 @@ module API def pagination_links(paginated_data) request_url = request.url.split('?').first + request_params = params.clone + request_params[:per_page] = paginated_data.limit_value links = [] - links << %(<#{request_url}?page=#{paginated_data.current_page - 1}&per_page=#{paginated_data.limit_value}>; rel="prev") unless paginated_data.first_page? - links << %(<#{request_url}?page=#{paginated_data.current_page + 1}&per_page=#{paginated_data.limit_value}>; rel="next") unless paginated_data.last_page? - links << %(<#{request_url}?page=1&per_page=#{paginated_data.limit_value}>; rel="first") - links << %(<#{request_url}?page=#{paginated_data.total_pages}&per_page=#{paginated_data.limit_value}>; rel="last") + + request_params[:page] = paginated_data.current_page - 1 + links << %(<#{request_url}?#{request_params.to_query}>; rel="prev") unless paginated_data.first_page? + + request_params[:page] = paginated_data.current_page + 1 + links << %(<#{request_url}?#{request_params.to_query}>; rel="next") unless paginated_data.last_page? + + request_params[:page] = 1 + links << %(<#{request_url}?#{request_params.to_query}>; rel="first") + + request_params[:page] = paginated_data.total_pages + links << %(<#{request_url}?#{request_params.to_query}>; rel="last") links.join(', ') end -- cgit v1.2.1 From 070a3079fc9115ec564bc48f6b4deec5cabd901d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Tue, 2 Feb 2016 14:34:46 +0100 Subject: Add a spec for the API pagination Link header --- spec/requests/api/issues_spec.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/requests/api/issues_spec.rb b/spec/requests/api/issues_spec.rb index 5e65ad18c0e..410e684ee3b 100644 --- a/spec/requests/api/issues_spec.rb +++ b/spec/requests/api/issues_spec.rb @@ -46,10 +46,10 @@ describe API::API, api: true do expect(json_response.first['title']).to eq(issue.title) end - it "should add pagination headers" do - get api("/issues?per_page=3", user) + it "should add pagination headers and keep query params" do + get api("/issues?state=closed&per_page=3", user) expect(response.headers['Link']).to eq( - '; rel="first", ; rel="last"' + '; rel="first", ; rel="last"' % [user.private_token, user.private_token] ) end -- cgit v1.2.1 From d716905743352de34bca8441706eef776f1cd6ce Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Tue, 2 Feb 2016 16:00:13 +0100 Subject: Use gitlab-workhorse 0.6.3 --- GITLAB_WORKHORSE_VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GITLAB_WORKHORSE_VERSION b/GITLAB_WORKHORSE_VERSION index b6160487433..844f6a91acb 100644 --- a/GITLAB_WORKHORSE_VERSION +++ b/GITLAB_WORKHORSE_VERSION @@ -1 +1 @@ -0.6.2 +0.6.3 -- cgit v1.2.1 From ea41d3607769b2b726a25d50ea23675bc5936227 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Tue, 2 Feb 2016 16:01:20 +0100 Subject: Use gitlab-workhorse 0.6.3 in installation guide --- doc/install/installation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/install/installation.md b/doc/install/installation.md index 2cc2dbef41b..a2c23bd52e5 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -355,7 +355,7 @@ GitLab Shell is an SSH access and repository management software developed speci cd /home/git sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-workhorse.git cd gitlab-workhorse - sudo -u git -H git checkout 0.6.2 + sudo -u git -H git checkout 0.6.3 sudo -u git -H make ### Initialize Database and Activate Advanced Features -- cgit v1.2.1 From ecb174bfeadffbccc5c5cf35b6e94b65f5fbce79 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Tue, 2 Feb 2016 17:28:14 +0100 Subject: fixed move project method in migration --- ...5155_remove_dot_atom_path_ending_of_projects.rb | 46 ++++++---------------- db/schema.rb | 2 +- lib/gitlab/backend/shell.rb | 2 +- 3 files changed, 15 insertions(+), 35 deletions(-) diff --git a/db/migrate/20160129135155_remove_dot_atom_path_ending_of_projects.rb b/db/migrate/20160129135155_remove_dot_atom_path_ending_of_projects.rb index 0bc23f5627f..9ca695d713f 100644 --- a/db/migrate/20160129135155_remove_dot_atom_path_ending_of_projects.rb +++ b/db/migrate/20160129135155_remove_dot_atom_path_ending_of_projects.rb @@ -2,11 +2,12 @@ class RemoveDotAtomPathEndingOfProjects < ActiveRecord::Migration include Gitlab::ShellAdapter class ProjectPath - attr_reader :old_path, :id + attr_reader :old_path, :id, :namespace_path - def initialize(old_path, id) + def initialize(old_path, id, namespace_path) @old_path = old_path @id = id + @namespace_path = namespace_path end def clean_path @@ -43,48 +44,27 @@ class RemoveDotAtomPathEndingOfProjects < ActiveRecord::Migration end def projects_with_dot_atom - select_all("SELECT id, path FROM projects WHERE lower(path) LIKE '%.atom'") + select_all("SELECT p.id, p.path, n.path as namespace_path FROM projects p inner join namespaces n on n.id = p.namespace_id WHERE lower(p.path) LIKE '%.atom'") end def up projects_with_dot_atom.each do |project| - binding.pry - project_path = ProjectPath.new(project['path'], project['id']) - clean_path(project_path) if move_path(project_path) + project_path = ProjectPath.new(project['path'], project['id'], project['namespace_path']) + clean_path(project_path) if rename_project_repo(project_path) end end private def clean_path(project_path) - execute "UPDATE projects SET path = '#{project_path.clean_path}' WHERE id = #{project.id}" + execute "UPDATE projects SET path = '#{project_path.clean_path}' WHERE id = #{project_path.id}" end - #TODO: Fix this - def move_path(project_path) - # Based on RemovePeriodsAtEndsOfUsernames - # Don't attempt to move if original path only contains periods. - return if project_path.clean_path =~ /\A\.+\z/ - if gitlab_shell.mv_namespace(project_path.old_path, project_path.clean_path) - # If repositories moved successfully we need to remove old satellites - # and send update instructions to users. - # However we cannot allow rollback since we moved namespace dir - # So we basically we mute exceptions in next actions - begin - gitlab_shell.rm_satellites(project_path.old_path) - # We cannot send update instructions since models and mailers - # can't safely be used from migrations as they may be written for - # later versions of the database. - # send_update_instructions - rescue - # Returning false does not rollback after_* transaction but gives - # us information about failing some of tasks - false - end - else - # if we cannot move namespace directory we should avoid - # db changes in order to prevent out of sync between db and fs - false - end + def rename_project_repo(project_path) + old_path_with_namespace = File.join(project_path.namespace_path, project_path.old_path) + new_path_with_namespace = File.join(project_path.namespace_path, project_path.clean_path) + + gitlab_shell.mv_repository("#{old_path_with_namespace}.wiki", "#{new_path_with_namespace}.wiki") + gitlab_shell.mv_repository(old_path_with_namespace, new_path_with_namespace) end end diff --git a/db/schema.rb b/db/schema.rb index 2ad2c23fba5..ad9e9e8a5de 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: 20160128233227) do +ActiveRecord::Schema.define(version: 20160129135155) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" diff --git a/lib/gitlab/backend/shell.rb b/lib/gitlab/backend/shell.rb index 4c15d58d680..f751458ac66 100644 --- a/lib/gitlab/backend/shell.rb +++ b/lib/gitlab/backend/shell.rb @@ -47,7 +47,7 @@ module Gitlab # new_path - new project path with namespace # # Ex. - # mv_repository("gitlab/gitlab-ci", "randx/gitlab-ci-new.git") + # mv_repository("gitlab/gitlab-ci", "randx/gitlab-ci-new") # def mv_repository(path, new_path) Gitlab::Utils.system_silent([gitlab_shell_projects_path, 'mv-project', -- cgit v1.2.1 From 627909c2a4a938c6387afa459ef4dc815fe9fb5a Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Tue, 2 Feb 2016 17:59:37 +0100 Subject: Add CI setting: allow_guest_to_access_builds Add the `read_build` ability if user is anonymous or guest and allow_guest_to_access_builds is enabled. --- app/controllers/projects_controller.rb | 1 + app/models/ability.rb | 14 +++++---- app/views/projects/edit.html.haml | 8 +++-- ...642_add_allow_guest_to_access_builds_project.rb | 5 ++++ db/schema.rb | 35 +++++++++++----------- doc/permissions/permissions.md | 9 ++++++ 6 files changed, 47 insertions(+), 25 deletions(-) create mode 100644 db/migrate/20160202164642_add_allow_guest_to_access_builds_project.rb diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 4df5095bd94..153e7caaae3 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -227,6 +227,7 @@ class ProjectsController < ApplicationController :issues_enabled, :merge_requests_enabled, :snippets_enabled, :issues_tracker_id, :default_branch, :wiki_enabled, :visibility_level, :import_url, :last_activity_at, :namespace_id, :avatar, :builds_enabled, :build_allow_git_fetch, :build_timeout_in_minutes, :build_coverage_regex, + :allow_guest_to_access_builds, ) end diff --git a/app/models/ability.rb b/app/models/ability.rb index e58e7a40273..313c6f049b7 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -53,12 +53,11 @@ class Ability :read_merge_request, :read_note, :read_commit_status, - :read_build, :download_code ] - if project.restrict_builds? - rules -= :read_build + if project.allow_guest_to_access_builds? + rules += :read_build end rules - project_disabled_features_rules(project) @@ -114,13 +113,17 @@ class Ability elsif team.guest?(user) rules.push(*project_guest_rules) + + if project.allow_guest_to_access_builds? + rules += :read_build + end end if project.public? || project.internal? rules.push(*public_project_rules) - if team.guest?(user) && project.restrict_builds? - rules -= named_abilities('build') + if project.allow_guest_to_access_builds? + rules += :read_build end end @@ -145,7 +148,6 @@ class Ability :download_code, :fork_project, :read_commit_status, - :read_build, ] end diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml index 8a99aceef7f..e3165caad05 100644 --- a/app/views/projects/edit.html.haml +++ b/app/views/projects/edit.html.haml @@ -157,8 +157,12 @@ %li phpunit --coverage-text --colors=never (PHP) - %code ^\s*Lines:\s*\d+.\d+\% - - + .form-group + .col-sm-offset-2.col-sm-10 + .checkbox + = f.label :allow_guest_to_access_builds do + = f.check_box :allow_guest_to_access_builds + Allow guest to access builds (including build logs and artifacts) %fieldset.features %legend Advanced settings diff --git a/db/migrate/20160202164642_add_allow_guest_to_access_builds_project.rb b/db/migrate/20160202164642_add_allow_guest_to_access_builds_project.rb new file mode 100644 index 00000000000..69ce8d08bba --- /dev/null +++ b/db/migrate/20160202164642_add_allow_guest_to_access_builds_project.rb @@ -0,0 +1,5 @@ +class AddAllowGuestToAccessBuildsProject < ActiveRecord::Migration + def change + add_column :projects, :allow_guest_to_access_builds, :boolean, default: true, null: false + end +end diff --git a/db/schema.rb b/db/schema.rb index 2ad2c23fba5..a04e812ae22 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: 20160128233227) do +ActiveRecord::Schema.define(version: 20160202164642) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -650,34 +650,35 @@ ActiveRecord::Schema.define(version: 20160128233227) do t.datetime "created_at" t.datetime "updated_at" t.integer "creator_id" - t.boolean "issues_enabled", default: true, null: false - t.boolean "wall_enabled", default: true, null: false - t.boolean "merge_requests_enabled", default: true, null: false - t.boolean "wiki_enabled", default: true, null: false + t.boolean "issues_enabled", default: true, null: false + t.boolean "wall_enabled", default: true, null: false + t.boolean "merge_requests_enabled", default: true, null: false + t.boolean "wiki_enabled", default: true, null: false t.integer "namespace_id" - t.string "issues_tracker", default: "gitlab", null: false + t.string "issues_tracker", default: "gitlab", null: false t.string "issues_tracker_id" - t.boolean "snippets_enabled", default: true, null: false + t.boolean "snippets_enabled", default: true, null: false t.datetime "last_activity_at" t.string "import_url" - t.integer "visibility_level", default: 0, null: false - t.boolean "archived", default: false, null: false + t.integer "visibility_level", default: 0, null: false + t.boolean "archived", default: false, null: false t.string "avatar" t.string "import_status" - t.float "repository_size", default: 0.0 - t.integer "star_count", default: 0, null: false + t.float "repository_size", default: 0.0 + t.integer "star_count", default: 0, null: false t.string "import_type" t.string "import_source" - t.integer "commit_count", default: 0 + t.integer "commit_count", default: 0 t.text "import_error" t.integer "ci_id" - t.boolean "builds_enabled", default: true, null: false - t.boolean "shared_runners_enabled", default: true, null: false + t.boolean "builds_enabled", default: true, null: false + t.boolean "shared_runners_enabled", default: true, null: false t.string "runners_token" t.string "build_coverage_regex" - t.boolean "build_allow_git_fetch", default: true, null: false - t.integer "build_timeout", default: 3600, null: false - t.boolean "pending_delete", default: false + t.boolean "build_allow_git_fetch", default: true, null: false + t.integer "build_timeout", default: 3600, null: false + t.boolean "pending_delete", default: false + t.boolean "allow_guest_to_access_builds", default: true, null: false end add_index "projects", ["builds_enabled", "shared_runners_enabled"], name: "index_projects_on_builds_enabled_and_shared_runners_enabled", using: :btree diff --git a/doc/permissions/permissions.md b/doc/permissions/permissions.md index 1be78ac1823..168e7d143ee 100644 --- a/doc/permissions/permissions.md +++ b/doc/permissions/permissions.md @@ -18,6 +18,9 @@ documentation](../workflow/add-user/add-user.md). |---------------------------------------|---------|------------|-------------|----------|--------| | Create new issue | ✓ | ✓ | ✓ | ✓ | ✓ | | Leave comments | ✓ | ✓ | ✓ | ✓ | ✓ | +| See a list of builds | ✓ [^1] | ✓ | ✓ | ✓ | ✓ | +| See a build log | ✓ [^1] | ✓ | ✓ | ✓ | ✓ | +| Download and browse build artifacts | ✓ [^1] | ✓ | ✓ | ✓ | ✓ | | Pull project code | | ✓ | ✓ | ✓ | ✓ | | Download project | | ✓ | ✓ | ✓ | ✓ | | Create code snippets | | ✓ | ✓ | ✓ | ✓ | @@ -31,6 +34,7 @@ documentation](../workflow/add-user/add-user.md). | Remove non-protected branches | | | ✓ | ✓ | ✓ | | Add tags | | | ✓ | ✓ | ✓ | | Write a wiki | | | ✓ | ✓ | ✓ | +| Cancel and retry builds | | | ✓ | ✓ | ✓ | | Create new milestones | | | | ✓ | ✓ | | Add new team members | | | | ✓ | ✓ | | Push to protected branches | | | | ✓ | ✓ | @@ -40,12 +44,17 @@ documentation](../workflow/add-user/add-user.md). | Edit project | | | | ✓ | ✓ | | Add deploy keys to project | | | | ✓ | ✓ | | Configure project hooks | | | | ✓ | ✓ | +| Manage runners | | | | ✓ | ✓ | +| Manage build triggers | | | | ✓ | ✓ | +| Manage variables | | | | ✓ | ✓ | | Switch visibility level | | | | | ✓ | | Transfer project to another namespace | | | | | ✓ | | Remove project | | | | | ✓ | | Force push to protected branches | | | | | | | Remove protected branches | | | | | | +[^1]: If **Allow guest to access builds** is enabled in CI settings + ## Group In order for a group to appear as public and be browsable, it must contain at -- cgit v1.2.1 From d87e317be449274983f5c515edf5285a1bb08c21 Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Tue, 2 Feb 2016 14:27:45 -0500 Subject: Added correct colors and styles from antetype mockup. --- app/assets/stylesheets/framework/buttons.scss | 2 +- app/assets/stylesheets/framework/issue_box.scss | 2 +- app/assets/stylesheets/framework/variables.scss | 15 ++++++++------- app/assets/stylesheets/pages/issuable.scss | 4 ++-- 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/app/assets/stylesheets/framework/buttons.scss b/app/assets/stylesheets/framework/buttons.scss index c99292c3f83..b3d7874d277 100644 --- a/app/assets/stylesheets/framework/buttons.scss +++ b/app/assets/stylesheets/framework/buttons.scss @@ -2,7 +2,7 @@ @include border-radius(3px); font-size: $gl-font-size; font-weight: 500; - padding: $gl-vert-padding $gl-padding; + padding: $gl-vert-padding $gl-btn-padding; &:focus, &:active { diff --git a/app/assets/stylesheets/framework/issue_box.scss b/app/assets/stylesheets/framework/issue_box.scss index e93dbab0c42..08dcb563dce 100644 --- a/app/assets/stylesheets/framework/issue_box.scss +++ b/app/assets/stylesheets/framework/issue_box.scss @@ -9,7 +9,7 @@ display: block; float: left; - padding: 0 $gl-padding; + padding: 0 $gl-btn-padding; font-weight: normal; margin-right: 10px; font-size: $gl-font-size; diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss index f8b6e0e5e6f..5e249059c29 100644 --- a/app/assets/stylesheets/framework/variables.scss +++ b/app/assets/stylesheets/framework/variables.scss @@ -24,6 +24,7 @@ $header-height: 58px; $fixed-layout-width: 1280px; $gl-gray: #5a5a5a; $gl-padding: 16px; +$gl-btn-padding: 10px; $gl-vert-padding: 6px; $gl-padding-top:10px; $gl-avatar-size: 46px; @@ -38,12 +39,12 @@ $white-light: #FFFFFF; $white-normal: #ededed; $white-dark: #ededed; -$gray-light: #f7f7f7; -$gray-normal: #ededed; +$gray-light: #faf9f9; +$gray-normal: #f5f5f5; $gray-dark: #ededed; $gray-darkest: #c9c9c9; -$green-light: #31AF64; +$green-light: #38ae67; $green-normal: #2FAA60; $green-dark: #2CA05B; @@ -55,7 +56,7 @@ $blue-medium-light: #3498CB; $blue-medium: #2F8EBF; $blue-medium-dark: #2D86B4; -$orange-light: #FC6443; +$orange-light: rgba(252, 109, 38, 0.80); $orange-normal: #E75E40; $orange-dark: #CE5237; @@ -67,8 +68,8 @@ $border-white-light: #F1F2F4; $border-white-normal: #D6DAE2; $border-white-dark: #C6CACF; -$border-gray-light: #d1d1d1; -$border-gray-normal: #D6DAE2; +$border-gray-light: rgba(0, 0, 0, 0.06); +$border-gray-normal: rgba(0, 0, 0, 0.10);; $border-gray-dark: #C6CACF; $border-green-light: #2FAA60; @@ -79,7 +80,7 @@ $border-blue-light: #2D9FD8; $border-blue-normal: #2897CE; $border-blue-dark: #258DC1; -$border-orange-light: #ED5C3D; +$border-orange-light: #fc6d26; $border-orange-normal: #CE5237; $border-orange-dark: #C14E35; diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss index 16429e01e0a..2c8fc509f20 100644 --- a/app/assets/stylesheets/pages/issuable.scss +++ b/app/assets/stylesheets/pages/issuable.scss @@ -71,7 +71,7 @@ .block { @include clearfix; padding: $gl-padding 0; - border-bottom: 1px solid #F0F0F0; + border-bottom: 1px solid $border-gray-light; // This prevents the mess when resizing the sidebar // of elements repositioning themselves.. width: 210px; @@ -195,7 +195,7 @@ .btn { background: $gray-normal; - border: 1px solid $gray-darkest; + border: 1px solid $border-gray-normal; } &.right-sidebar-collapsed { -- cgit v1.2.1 From a12ac9c060018071d75c7b1e9d9ee3b90cb4d792 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Tue, 2 Feb 2016 14:50:14 -0500 Subject: Update CHANGELOG [ci skip] --- CHANGELOG | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 7a9b51cf331..3469a1e026b 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -32,6 +32,9 @@ v 8.4.3 - Fix highlighting in blame view - Update sentry-raven gem to prevent "Not a git repository" console output when running certain commands + - Add instrumentation to additional Gitlab::Git and Rugged methods for + performance monitoring + - Allow autosize textareas to also be manually resized v 8.4.2 - Bump required gitlab-workhorse version to bring in a fix for missing -- cgit v1.2.1 From acea6e1c507cf35123a8fe87ca708683719f4820 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Malte=20Bl=C3=A4ttermann?= Date: Tue, 26 Jan 2016 23:53:36 +0000 Subject: Documentation cleanup of artifacts section in Gitlab CI Readme - Added notice about build artifacts not beeing collected on failed builds. - Removed "introduced in 0.7.0" for artifacts section. - Made windows notice more precise --- doc/ci/yaml/README.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md index 4d280297dbb..194c8171bb9 100644 --- a/doc/ci/yaml/README.md +++ b/doc/ci/yaml/README.md @@ -393,8 +393,12 @@ The above script will: ### artifacts -_**Note:** Introduced in GitLab Runner v0.7.0. Also, the Windows shell executor - does not currently support artifact uploads._ +_**Note:** Introduced in GitLab Runner v0.7.0 for non-Windows platforms._ + +_**Note:** Limited Windows support was added in GitLab Runner v.1.0.0. +Currently not all executors are supported._ + +_**Note:** Build artifacts are only collected for successful builds._ `artifacts` is used to specify list of files and directories which should be attached to build after success. Below are some examples. -- cgit v1.2.1 From 4105f292e1c9d9c9416914fcd41f9c982b4a80fb Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Mon, 1 Feb 2016 21:29:37 -0500 Subject: Display database type and version in Administration dashboard Closes #12900 --- CHANGELOG | 1 + app/views/admin/dashboard/index.html.haml | 5 ++++ lib/gitlab/database.rb | 38 ++++++++++++++++++++++++++----- spec/lib/gitlab/database_spec.rb | 20 ++++++++++++++++ 4 files changed, 58 insertions(+), 6 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 3469a1e026b..5ca9777e258 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -15,6 +15,7 @@ v 8.5.0 (unreleased) - Don't vendor minified JS - Display 404 error on group not found - Track project import failure + - Display database type and version in Administration dashboard - Fix visibility level text in admin area (Zeger-Jan van de Weg) - Warn admin during OAuth of granting admin rights (Zeger-Jan van de Weg) - Update the ExternalIssue regex pattern (Blake Hitchcock) diff --git a/app/views/admin/dashboard/index.html.haml b/app/views/admin/dashboard/index.html.haml index cc389c3ae08..3274ba5377b 100644 --- a/app/views/admin/dashboard/index.html.haml +++ b/app/views/admin/dashboard/index.html.haml @@ -92,6 +92,11 @@ Rails %span.pull-right #{Rails::VERSION::STRING} + + %p + = Gitlab::Database.adapter_name + %span.pull-right + = Gitlab::Database.version %hr .row .col-sm-4 diff --git a/lib/gitlab/database.rb b/lib/gitlab/database.rb index de77a6fbff1..6ebb8027553 100644 --- a/lib/gitlab/database.rb +++ b/lib/gitlab/database.rb @@ -1,16 +1,23 @@ module Gitlab module Database + def self.adapter_name + connection.adapter_name + end + def self.mysql? - ActiveRecord::Base.connection.adapter_name.downcase == 'mysql2' + adapter_name.downcase == 'mysql2' end def self.postgresql? - ActiveRecord::Base.connection.adapter_name.downcase == 'postgresql' + adapter_name.downcase == 'postgresql' + end + + def self.version + database_version.match(/\A(?:PostgreSQL |)([^\s]+).*\z/)[1] end def true_value - case ActiveRecord::Base.connection.adapter_name.downcase - when 'postgresql' + if self.class.postgresql? "'t'" else 1 @@ -18,12 +25,31 @@ module Gitlab end def false_value - case ActiveRecord::Base.connection.adapter_name.downcase - when 'postgresql' + if self.class.postgresql? "'f'" else 0 end end + + private + + def self.connection + ActiveRecord::Base.connection + end + + def self.database_version + row = connection.execute("SELECT VERSION()").first + + if postgresql? + row['version'] + else + row.first + end + end + + def connection + self.class.connection + end end end diff --git a/spec/lib/gitlab/database_spec.rb b/spec/lib/gitlab/database_spec.rb index 8461e8ce50d..bd8688fefa1 100644 --- a/spec/lib/gitlab/database_spec.rb +++ b/spec/lib/gitlab/database_spec.rb @@ -14,4 +14,24 @@ describe Gitlab::Database, lib: true do it { is_expected.to satisfy { |val| val == true || val == false } } end + + describe '.version' do + context "on mysql" do + it "extracts the version number" do + allow(described_class).to receive(:database_version). + and_return("5.7.12-standard") + + expect(described_class.version).to eq '5.7.12-standard' + end + end + + context "on postgresql" do + it "extracts the version number" do + allow(described_class).to receive(:database_version). + and_return("PostgreSQL 9.4.4 on x86_64-apple-darwin14.3.0") + + expect(described_class.version).to eq '9.4.4' + end + end + end end -- cgit v1.2.1 From 599e554ad4df76e0ec270aa0756a98b9044e877f Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Tue, 2 Feb 2016 19:42:19 -0500 Subject: Sidebar works after sidebar ajax calls. --- app/assets/javascripts/application.js.coffee | 2 +- app/assets/javascripts/issuable_context.js.coffee | 2 +- app/assets/stylesheets/pages/issuable.scss | 3 ++- app/views/projects/issues/update.js.haml | 6 +++--- app/views/projects/merge_requests/update.js.haml | 4 ++-- app/views/shared/issuable/_sidebar.html.haml | 2 +- 6 files changed, 10 insertions(+), 9 deletions(-) diff --git a/app/assets/javascripts/application.js.coffee b/app/assets/javascripts/application.js.coffee index 02b0a32539a..be3b326075d 100644 --- a/app/assets/javascripts/application.js.coffee +++ b/app/assets/javascripts/application.js.coffee @@ -212,7 +212,7 @@ $ -> $this = $(this) $this.attr 'value', $this.val() - $('.right-sidebar').on 'click', '.gutter-toggle', (e) -> + $(document).on 'click', 'aside .gutter-toggle', (e) -> e.preventDefault() $this = $(this) $thisIcon = $this.find 'i' diff --git a/app/assets/javascripts/issuable_context.js.coffee b/app/assets/javascripts/issuable_context.js.coffee index c2144aea25e..d17b1123418 100644 --- a/app/assets/javascripts/issuable_context.js.coffee +++ b/app/assets/javascripts/issuable_context.js.coffee @@ -10,7 +10,7 @@ class @IssuableContext $(".issuable-sidebar .inline-update").on "change", ".js-assignee", -> $(this).submit() - $(".edit-link").click (e) -> + $(document).on "click",".edit-link", (e) -> block = $(@).parents('.block') block.find('.selectbox').show() block.find('.value').hide() diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss index 2c8fc509f20..b10670afd40 100644 --- a/app/assets/stylesheets/pages/issuable.scss +++ b/app/assets/stylesheets/pages/issuable.scss @@ -97,7 +97,7 @@ .gutter-toggle { margin-left: 10px; - border-left: 1px solid #F0F0F0; + border-left: 1px solid $border-gray-light; padding-left: 10px; } } @@ -221,6 +221,7 @@ text-align: center; margin-left: -19px; padding-bottom: 10px; + color: #999999; span { display: block; diff --git a/app/views/projects/issues/update.js.haml b/app/views/projects/issues/update.js.haml index 2f0f3fcfb06..3cec66d262b 100644 --- a/app/views/projects/issues/update.js.haml +++ b/app/views/projects/issues/update.js.haml @@ -1,3 +1,3 @@ -$('.issuable-sidebar').html("#{escape_javascript(render 'shared/issuable/sidebar', issuable: @issue)}"); -$('.issuable-sidebar').parent().effect('highlight') -new Issue(); +$('aside.right-sidebar').parent().html("#{escape_javascript(render 'shared/issuable/sidebar', issuable: @issue)}"); +$('aside.right-sidebar').effect('highlight') +new Issue(); \ No newline at end of file diff --git a/app/views/projects/merge_requests/update.js.haml b/app/views/projects/merge_requests/update.js.haml index 93db65ddf79..ce5157d69a2 100644 --- a/app/views/projects/merge_requests/update.js.haml +++ b/app/views/projects/merge_requests/update.js.haml @@ -1,3 +1,3 @@ -$('.issuable-sidebar').html("#{escape_javascript(render 'shared/issuable/sidebar', issuable: @merge_request)}"); -$('.issuable-sidebar').parent().effect('highlight') +$('aside.right-sidebar')[0].outerHTML= "#{escape_javascript(render 'shared/issuable/sidebar', issuable: @merge_request)}"; +$('aside.right-sidebar').effect('highlight') merge_request = new MergeRequest(); diff --git a/app/views/shared/issuable/_sidebar.html.haml b/app/views/shared/issuable/_sidebar.html.haml index 0ed2c9c710d..f4f04a42196 100644 --- a/app/views/shared/issuable/_sidebar.html.haml +++ b/app/views/shared/issuable/_sidebar.html.haml @@ -23,7 +23,7 @@ %a.btn.btn-default.disabled{href: '#'} Next - = form_for [@project.namespace.becomes(Namespace), @project, issuable], remote: true, html: {class: 'issuable-context-form inline-update js-issuable-update', 'data-type' => 'json'} do |f| + = form_for [@project.namespace.becomes(Namespace), @project, issuable], remote: true, html: {class: 'issuable-context-form inline-update js-issuable-update'} do |f| .block.assignee .sidebar-collapsed-icon - if issuable.assignee -- cgit v1.2.1 From 8670411ae7acb93b5113634a3ae5e476ef6d2aee Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Wed, 3 Feb 2016 11:24:14 +0100 Subject: Clean Ci::ApplicationController from unused permission related code --- app/controllers/ci/application_controller.rb | 47 ---------------------------- app/controllers/ci/projects_controller.rb | 5 ++- 2 files changed, 2 insertions(+), 50 deletions(-) diff --git a/app/controllers/ci/application_controller.rb b/app/controllers/ci/application_controller.rb index 59c77653509..5bb7d499cdc 100644 --- a/app/controllers/ci/application_controller.rb +++ b/app/controllers/ci/application_controller.rb @@ -3,52 +3,5 @@ module Ci def self.railtie_helpers_paths "app/helpers/ci" end - - private - - def authorize_access_project! - unless can?(current_user, :read_project, project) - return page_404 - end - end - - def authorize_manage_builds! - unless can?(current_user, :update_build, project) - return page_404 - end - end - - def authenticate_admin! - return render_404 unless current_user.is_admin? - end - - def authorize_manage_project! - unless can?(current_user, :admin_project, project) - return page_404 - end - end - - def page_404 - render file: "#{Rails.root}/public/404.html", status: 404, layout: false - end - - def default_headers - headers['X-Frame-Options'] = 'DENY' - headers['X-XSS-Protection'] = '1; mode=block' - end - - # JSON for infinite scroll via Pager object - def pager_json(partial, count) - html = render_to_string( - partial, - layout: false, - formats: [:html] - ) - - render json: { - html: html, - count: count - } - end end end diff --git a/app/controllers/ci/projects_controller.rb b/app/controllers/ci/projects_controller.rb index 3004c2d27f0..711c2847d5e 100644 --- a/app/controllers/ci/projects_controller.rb +++ b/app/controllers/ci/projects_controller.rb @@ -1,8 +1,7 @@ module Ci class ProjectsController < Ci::ApplicationController - before_action :project, except: [:index] - before_action :authenticate_user!, except: [:index, :build, :badge] - before_action :authorize_access_project!, except: [:index, :badge] + before_action :project + before_action :authorize_read_project!, except: [:badge] before_action :no_cache, only: [:badge] protect_from_forgery -- cgit v1.2.1 From cbd550cfa68581127e344f31d8d7c624bdc52cbb Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Wed, 3 Feb 2016 13:18:37 +0200 Subject: Refactor OAuth provider documentation [ci skip] --- .../img/oauth_provider_admin_application.png | Bin 55533 -> 40579 bytes .../img/oauth_provider_application_form.png | Bin 25075 -> 27974 bytes .../img/oauth_provider_application_id_secret.png | Bin 0 -> 33901 bytes .../img/oauth_provider_authorized_application.png | Bin 17260 -> 32225 bytes .../img/oauth_provider_user_wide_applications.png | Bin 46238 -> 40632 bytes doc/integration/oauth_provider.md | 89 ++++++++++++++++----- 6 files changed, 67 insertions(+), 22 deletions(-) create mode 100644 doc/integration/img/oauth_provider_application_id_secret.png diff --git a/doc/integration/img/oauth_provider_admin_application.png b/doc/integration/img/oauth_provider_admin_application.png index a5f34512aa8..a2d8e14c120 100644 Binary files a/doc/integration/img/oauth_provider_admin_application.png and b/doc/integration/img/oauth_provider_admin_application.png differ diff --git a/doc/integration/img/oauth_provider_application_form.png b/doc/integration/img/oauth_provider_application_form.png index ae135db2627..3a676b22393 100644 Binary files a/doc/integration/img/oauth_provider_application_form.png and b/doc/integration/img/oauth_provider_application_form.png differ diff --git a/doc/integration/img/oauth_provider_application_id_secret.png b/doc/integration/img/oauth_provider_application_id_secret.png new file mode 100644 index 00000000000..6d68df001af Binary files /dev/null and b/doc/integration/img/oauth_provider_application_id_secret.png differ diff --git a/doc/integration/img/oauth_provider_authorized_application.png b/doc/integration/img/oauth_provider_authorized_application.png index d3ce05be9cc..efc3b807d71 100644 Binary files a/doc/integration/img/oauth_provider_authorized_application.png and b/doc/integration/img/oauth_provider_authorized_application.png differ diff --git a/doc/integration/img/oauth_provider_user_wide_applications.png b/doc/integration/img/oauth_provider_user_wide_applications.png index 719e1974068..45ad8a6d468 100644 Binary files a/doc/integration/img/oauth_provider_user_wide_applications.png and b/doc/integration/img/oauth_provider_user_wide_applications.png differ diff --git a/doc/integration/oauth_provider.md b/doc/integration/oauth_provider.md index f0c2a45b6ae..5f8bb57365c 100644 --- a/doc/integration/oauth_provider.md +++ b/doc/integration/oauth_provider.md @@ -1,35 +1,80 @@ -## GitLab as OAuth2 authentication service provider +# GitLab as OAuth2 authentication service provider -This document is about using GitLab as an OAuth authentication service provider to sign into other services. -If you want to use other OAuth authentication service providers to sign into GitLab please see the [OAuth2 client documentation](../api/oauth2.md) +This document is about using GitLab as an OAuth authentication service provider +to sign in to other services. -OAuth2 provides client applications a 'secure delegated access' to server resources on behalf of a resource owner. Or you can allow users to sign in to your application with their GitLab.com account. -In fact OAuth allows to issue access token to third-party clients by an authorization server, -with the approval of the resource owner, or end-user. -Mostly, OAuth2 is using for SSO (Single sign-on). But you can find a lot of different usages for this functionality. -For example, our feature 'GitLab Importer' is using OAuth protocol to give an access to repositories without sharing user credentials to GitLab.com account. -Also GitLab.com application can be used for authentication to your GitLab instance if needed [GitLab OmniAuth](gitlab.md). +If you want to use other OAuth authentication service providers to sign in to +GitLab, please see the [OAuth2 client documentation](../api/oauth2.md). -GitLab has two ways to add new OAuth2 application to an instance, you can add application as regular user and through admin area. So GitLab actually can have an instance-wide and a user-wide applications. There is no defferences between them except the different permission levels. +## Introduction to OAuth -### Adding application through profile -Go to your profile section 'Application' and press button 'New Application' +[OAuth] provides to client applications a 'secure delegated access' to server +resources on behalf of a resource owner. In fact, OAuth allows an authorization +server to issue access tokens to third-party clients with the approval of the +resource owner, or the end-user. -![applications](img/oauth_provider_user_wide_applications.png) +OAuth is mostly used as a Single Sign-On service (SSO), but you can find a +lot of different uses for this functionality. For example, you can allow users +to sign in to your application with their GitLab.com account, or GitLab.com +can be used for authentication to your GitLab instance +(see [GitLab OmniAuth](gitlab.md)). -After this you will see application form, where "Name" is arbitrary name, "Redirect URI" is URL in your app where users will be sent after authorization on GitLab.com. +The 'GitLab Importer' feature is also using the OAuth protocol to give access +to repositories without sharing user credentials to your GitLab.com account. -![application_form](img/oauth_provider_application_form.png) +--- -### Authorized application -Every application you authorized will be shown in your "Authorized application" sections. +GitLab supports two ways of adding a new OAuth2 application to an instance. You +can either add an application as a regular user or add it in the admin area. +What this means is that GitLab can actually have instance-wide and a user-wide +applications. There is no difference between them except for the different +permission levels they are set (user/admin). -![authorized_application](img/oauth_provider_authorized_application.png) +## Adding an application through the profile -As you can see we use default scope "api" here which is only scope we have so far. At any time you can revoke access just clicking button "Revoke". +In order to add a new application via your profile, navigate to +**Profile Settings > Applications** and select **New Application**. -### OAuth applications in admin area +![New OAuth application](img/oauth_provider_user_wide_applications.png) -If you want to create application that does not belong to certain user you can create it from admin area +--- -![admin_application](img/oauth_provider_admin_application.png) +In the application form, enter a **Name** (arbitrary), and make sure to set up +correctly the **Redirect URI** which is the URL where users will be sent after +they authorize with GitLab. + +![New OAuth application form](img/oauth_provider_application_form.png) + +--- + +When you hit **Submit** you will be provided with the application ID and +the application secret which you can then use with your application that +connects to GitLab. + +![OAuth application ID and secret](img/oauth_provider_application_id_secret.png) + +--- + +## OAuth applications in the admin area + +To create an application that does not belong to a certain user, you can create +it from the admin area. + +![OAuth admin_applications](img/oauth_provider_admin_application.png) + +--- + +## Authorized applications + +Every application you authorized to use your GitLab credentials will be shown +in the **Authorized applications** section under **Profile Settings > Applications**. + +![Authorized_applications](img/oauth_provider_authorized_application.png) + +--- + +As you can see, the default scope `api` is used, which is the only scope that +GitLab supports so far. At any time you can revoke any access by just clicking +**Revoke**. + +[oauth]: http://oauth.net/2/ "OAuth website" -- cgit v1.2.1 From e80c79e3ad0efe505541ebac0b149b750cd1cc60 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Wed, 3 Feb 2016 12:41:16 +0100 Subject: Fix build errors --- app/models/ability.rb | 6 +++--- app/views/projects/edit.html.haml | 6 +++++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/app/models/ability.rb b/app/models/ability.rb index 313c6f049b7..a9246dd3dd5 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -57,7 +57,7 @@ class Ability ] if project.allow_guest_to_access_builds? - rules += :read_build + rules << :read_build end rules - project_disabled_features_rules(project) @@ -115,7 +115,7 @@ class Ability rules.push(*project_guest_rules) if project.allow_guest_to_access_builds? - rules += :read_build + rules << :read_build end end @@ -123,7 +123,7 @@ class Ability rules.push(*public_project_rules) if project.allow_guest_to_access_builds? - rules += :read_build + rules << :read_build end end diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml index e3165caad05..fd61ce6a99a 100644 --- a/app/views/projects/edit.html.haml +++ b/app/views/projects/edit.html.haml @@ -130,6 +130,7 @@ %strong git fetch %br %span.descr Faster + .form-group = f.label :build_timeout_in_minutes, 'Timeout', class: 'control-label' .col-sm-10 @@ -157,12 +158,15 @@ %li phpunit --coverage-text --colors=never (PHP) - %code ^\s*Lines:\s*\d+.\d+\% + .form-group .col-sm-offset-2.col-sm-10 .checkbox = f.label :allow_guest_to_access_builds do = f.check_box :allow_guest_to_access_builds - Allow guest to access builds (including build logs and artifacts) + %strong Guests can see builds + .help-block Allow guests and anonymous users to access builds including build trace and artifacts + %fieldset.features %legend Advanced settings -- cgit v1.2.1 From ea14429b7e1de6d0a61bbdb8e8a198a6b0c28b23 Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Wed, 3 Feb 2016 13:56:23 +0200 Subject: Clean up environment variables doc [ci skip] --- doc/administration/environment_variables.md | 65 ++++++++++++++++------------- 1 file changed, 35 insertions(+), 30 deletions(-) diff --git a/doc/administration/environment_variables.md b/doc/administration/environment_variables.md index b0aa420e055..e49b3dc139b 100644 --- a/doc/administration/environment_variables.md +++ b/doc/administration/environment_variables.md @@ -1,56 +1,61 @@ # Environment Variables -## Introduction +GitLab exposes certain environment variables which can be used to override +their defaults values. -Commonly people configure GitLab via the `gitlab.rb` configuration file in the Omnibus package. +People usually configure GitLab via `/etc/gitlab/gitlab.rb` for Omnibus +installations, or `gitlab.yml` for installations from source. -But if you prefer to use environment variables we allow that too. +Below you will find the supported environment variables which you can use to +override certain values. ## Supported environment variables -Variable | Type | Explanation +Variable | Type | Description -------- | ---- | ----------- -`GITLAB_ROOT_PASSWORD` | string | Sets the password for the `root` user on installation -`GITLAB_HOST` | url | Hostname of the GitLab server includes http or https -`RAILS_ENV` | production / development / staging / test | Rails environment -`DATABASE_URL` | url | For example: postgresql://localhost/blog_development -`GITLAB_EMAIL_FROM` | email | Email address used in the "From" field in mails sent by GitLab -`GITLAB_EMAIL_DISPLAY_NAME` | string | Name used in the "From" field in mails sent by GitLab -`GITLAB_EMAIL_REPLY_TO` | email | Email address used in the "Reply-To" field in mails sent by GitLab -`GITLAB_UNICORN_MEMORY_MIN` | integer | The minimum memory threshold (in bytes) for the Unicorn worker killer -`GITLAB_UNICORN_MEMORY_MAX` | integer | The maximum memory threshold (in bytes) for the Unicorn worker killer +`GITLAB_ROOT_PASSWORD` | string | Sets the password for the `root` user on installation +`GITLAB_HOST` | string | The full URL of the GitLab server (including `http://` or `https://`) +`RAILS_ENV` | string | The Rails environment; can be one of `production`, `development`, `staging` or `test` +`DATABASE_URL` | string | The database URL; is of the form: `postgresql://localhost/blog_development` +`GITLAB_EMAIL_FROM` | string | The e-mail address used in the "From" field in e-mails sent by GitLab +`GITLAB_EMAIL_DISPLAY_NAME` | string | The name used in the "From" field in e-mails sent by GitLab +`GITLAB_EMAIL_REPLY_TO` | string | The e-mail address used in the "Reply-To" field in e-mails sent by GitLab +`GITLAB_UNICORN_MEMORY_MIN` | integer | The minimum memory threshold (in bytes) for the Unicorn worker killer (supported only in Omnibus) +`GITLAB_UNICORN_MEMORY_MAX` | integer | The maximum memory threshold (in bytes) for the Unicorn worker killer (supported only in Omnibus) ## Complete database variables The recommended way of specifying your database connection information is to set the `DATABASE_URL` environment variable. This variable only holds connection -information (adapter, database, username, password, host and port), but not -behavior information (encoding, pool). If you don't want to use `DATABASE_URL` -and/or want to set database behavior information, you will have to: +information (`adapter`, `database`, `username`, `password`, `host` and `port`), +but not behavior information (`encoding`, `pool`). If you don't want to use +`DATABASE_URL` and/or want to set database behavior information, you will have +to either: -- copy our template `config/database.yml` file: `cp config/database.yml.env config/database.yml` +- copy our template file: `cp config/database.yml.env config/database.yml`, or - set a value for some `GITLAB_DATABASE_XXX` variables -The list of `GITLAB_DATABASE_XXX` variables that you can set is as follow: +The list of `GITLAB_DATABASE_XXX` variables that you can set is: Variable | Default value | Overridden by `DATABASE_URL`? ---- | --- | --- -`GITLAB_DATABASE_ADAPTER` | `postgresql` | Yes -`GITLAB_DATABASE_DATABASE` | `gitlab_#{ENV['RAILS_ENV']` | Yes -`GITLAB_DATABASE_USERNAME` | `root` | Yes -`GITLAB_DATABASE_PASSWORD` | None | Yes -`GITLAB_DATABASE_HOST` | `localhost` | Yes -`GITLAB_DATABASE_PORT` | `5432` | Yes -`GITLAB_DATABASE_ENCODING` | `unicode` | No -`GITLAB_DATABASE_POOL` | `10` | No +-------- | ------------- | ----------------------------- +`GITLAB_DATABASE_ADAPTER` | `postgresql` (for MySQL use `mysql2`) | Yes +`GITLAB_DATABASE_DATABASE` | `gitlab_#{ENV['RAILS_ENV']` | Yes +`GITLAB_DATABASE_USERNAME` | `root` | Yes +`GITLAB_DATABASE_PASSWORD` | None | Yes +`GITLAB_DATABASE_HOST` | `localhost` | Yes +`GITLAB_DATABASE_PORT` | `5432` | Yes +`GITLAB_DATABASE_ENCODING` | `unicode` | No +`GITLAB_DATABASE_POOL` | `10` | No ## Adding more variables We welcome merge requests to make more settings configurable via variables. -Please make changes in the `config/initializers/1_settings.rb` file. -Please stick to the naming scheme `GITLAB_#{name in 1_settings.rb in upper case}`. +Please make changes in the `config/initializers/1_settings.rb` file and stick +to the naming scheme `GITLAB_#{name in 1_settings.rb in upper case}`. ## Omnibus configuration -It's possible to preconfigure the GitLab image by adding the environment variable: `GITLAB_OMNIBUS_CONFIG` to docker run command. +It's possible to preconfigure the GitLab docker image by adding the environment +variable `GITLAB_OMNIBUS_CONFIG` to the `docker run` command. For more information see the ['preconfigure-docker-container' section in the Omnibus documentation](http://doc.gitlab.com/omnibus/docker/#preconfigure-docker-container). -- cgit v1.2.1 From 9fbe9d97ed29288d065232687023edd74649d553 Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Wed, 3 Feb 2016 14:18:51 +0200 Subject: Unicorn worker killer is not Omnibus specific [ci skip] --- doc/administration/environment_variables.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/administration/environment_variables.md b/doc/administration/environment_variables.md index e49b3dc139b..43ab153d76d 100644 --- a/doc/administration/environment_variables.md +++ b/doc/administration/environment_variables.md @@ -20,8 +20,8 @@ Variable | Type | Description `GITLAB_EMAIL_FROM` | string | The e-mail address used in the "From" field in e-mails sent by GitLab `GITLAB_EMAIL_DISPLAY_NAME` | string | The name used in the "From" field in e-mails sent by GitLab `GITLAB_EMAIL_REPLY_TO` | string | The e-mail address used in the "Reply-To" field in e-mails sent by GitLab -`GITLAB_UNICORN_MEMORY_MIN` | integer | The minimum memory threshold (in bytes) for the Unicorn worker killer (supported only in Omnibus) -`GITLAB_UNICORN_MEMORY_MAX` | integer | The maximum memory threshold (in bytes) for the Unicorn worker killer (supported only in Omnibus) +`GITLAB_UNICORN_MEMORY_MIN` | integer | The minimum memory threshold (in bytes) for the Unicorn worker killer +`GITLAB_UNICORN_MEMORY_MAX` | integer | The maximum memory threshold (in bytes) for the Unicorn worker killer ## Complete database variables -- cgit v1.2.1 From c3d897a9a382b0b3354d29726add5af8c322beb4 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Wed, 3 Feb 2016 13:33:47 +0100 Subject: Properly handle commit status permissions (for a build) --- app/models/ability.rb | 22 ++++++++++++++++++++++ .../commit_statuses/_commit_status.html.haml | 8 ++++---- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/app/models/ability.rb b/app/models/ability.rb index a9246dd3dd5..bf24749b173 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -5,6 +5,12 @@ class Ability return [] unless user.is_a?(User) return [] if user.blocked? + if subject.is_a?(CommitStatus) + rules = project_abilities(user, subject) + rules = filter_build_abilities(rules) if subject.is_a?(Ci::Build) + return rules + end + case subject.class.name when "Project" then project_abilities(user, subject) when "Issue" then issue_abilities(user, subject) @@ -25,6 +31,10 @@ class Ability case true when subject.is_a?(PersonalSnippet) anonymous_personal_snippet_abilities(subject) + when subject.is_a?(CommitStatus) + rules = anonymous_project_abilities(subject) + rules = filter_build_abilities(rules) if subject.is_a?(Ci::Build) + rules when subject.is_a?(Project) || subject.respond_to?(:project) anonymous_project_abilities(subject) when subject.is_a?(Group) || subject.respond_to?(:group) @@ -396,6 +406,18 @@ class Ability rules end + def filter_build_abilities(rules) + # If we can't read build we should also not have that + # ability when looking at this in context of commit_status + unless rules.include?(:read_build) + rules -= [:read_commit_status] + end + unless rules.include?(:update_build) + rules -= [:update_commit_status] + end + rules + end + def abilities @abilities ||= begin abilities = Six.new diff --git a/app/views/projects/commit_statuses/_commit_status.html.haml b/app/views/projects/commit_statuses/_commit_status.html.haml index fba4405cb7d..c02c5983ac8 100644 --- a/app/views/projects/commit_statuses/_commit_status.html.haml +++ b/app/views/projects/commit_statuses/_commit_status.html.haml @@ -1,6 +1,6 @@ %tr.commit_status %td.status - - if commit_status.target_url + - if can?(current_user, :read_commit_status, commit_status) && commit_status.target_url = link_to commit_status.target_url, class: "ci-status ci-#{commit_status.status}" do = ci_icon_for_status(commit_status.status) = commit_status.status @@ -8,7 +8,7 @@ = ci_status_with_icon(commit_status.status) %td.commit_status-link - - if can?(current_user, :read_build, commit_status.project) && commit_status.target_url + - if can?(current_user, :read_commit_status, commit_status) && commit_status.target_url = link_to commit_status.target_url do %strong ##{commit_status.id} - else @@ -66,10 +66,10 @@ %td .pull-right - - if can?(current_user, :read_build, commit_status.project) && commit_status.artifacts_download_url + - if can?(current_user, :read_commit_status, commit_status) && commit_status.artifacts_download_url = link_to commit_status.artifacts_download_url, title: 'Download artifacts' do %i.fa.fa-download - - if can?(current_user, :update_build, commit_status.project) + - if can?(current_user, :update_commit_status, commit_status) - if commit_status.active? - if commit_status.cancel_url = link_to commit_status.cancel_url, method: :post, title: 'Cancel' do -- cgit v1.2.1 From 531767175f0a364a332c74bf27c5f202732ce519 Mon Sep 17 00:00:00 2001 From: Josh Frye Date: Wed, 3 Feb 2016 09:21:37 -0500 Subject: Remove newrelic gem. Closes #12860 --- Gemfile | 2 -- Gemfile.lock | 2 -- config/newrelic.yml | 16 ---------------- 3 files changed, 20 deletions(-) delete mode 100644 config/newrelic.yml diff --git a/Gemfile b/Gemfile index 16a02da5bf9..a8f3619782d 100644 --- a/Gemfile +++ b/Gemfile @@ -303,8 +303,6 @@ group :production do gem "gitlab_meta", '7.0' end -gem "newrelic_rpm", '~> 3.14' - gem 'octokit', '~> 3.8.0' gem "mail_room", "~> 0.6.1" diff --git a/Gemfile.lock b/Gemfile.lock index 62937ab6fd2..6dd8b56fe7f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -479,7 +479,6 @@ GEM net-ldap (0.12.1) net-ssh (3.0.1) netrc (0.11.0) - newrelic_rpm (3.14.1.311) nokogiri (1.6.7.2) mini_portile2 (~> 2.0.0.rc2) nprogress-rails (0.1.6.7) @@ -960,7 +959,6 @@ DEPENDENCIES mysql2 (~> 0.3.16) nested_form (~> 0.3.2) net-ssh (~> 3.0.1) - newrelic_rpm (~> 3.14) nokogiri (= 1.6.7.2) nprogress-rails (~> 0.1.6.7) oauth2 (~> 1.0.0) diff --git a/config/newrelic.yml b/config/newrelic.yml deleted file mode 100644 index 9ef922a38d9..00000000000 --- a/config/newrelic.yml +++ /dev/null @@ -1,16 +0,0 @@ -# New Relic configuration file -# -# This file is here to make sure the New Relic gem stays -# quiet by default. -# -# To enable and configure New Relic, please use -# environment variables, e.g. NEW_RELIC_ENABLED=true - -production: - enabled: false - -development: - enabled: false - -test: - enabled: false -- cgit v1.2.1 From 7aa739ddc720dcba42a2f54934b10f369d4cf566 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Wed, 20 Jan 2016 12:00:28 -0800 Subject: Support download access by PRIVATE-TOKEN header Currently there is no way to download a raw file without embedding the token in the URL, which exposes the token in the URL. There should be an way of sending this information via the header as the API does. Closes https://github.com/gitlabhq/gitlabhq/issues/8137 --- CHANGELOG | 1 + app/controllers/application_controller.rb | 2 ++ 2 files changed, 3 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 7d7154487ad..4c9b00084d5 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -6,6 +6,7 @@ v 8.5.0 (unreleased) - Add "visibility" flag to GET /projects api endpoint - Ignore binary files in code search to prevent Error 500 (Stan Hu) - Render sanitized SVG images (Stan Hu) + - Support download access by PRIVATE-TOKEN header (Stan Hu) - Upgrade gitlab_git to 7.2.23 to fix commit message mentions in first branch push - New UI for pagination - Don't prevent sign out when 2FA enforcement is enabled and user hasn't yet diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 824175c8a6c..7fa2f68ef07 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -60,6 +60,8 @@ class ApplicationController < ActionController::Base params[:authenticity_token].presence elsif params[:private_token].presence params[:private_token].presence + elsif request.headers['PRIVATE-TOKEN'].present? + request.headers['PRIVATE-TOKEN'] end user = user_token && User.find_by_authentication_token(user_token.to_s) -- cgit v1.2.1 From 639b25e34caa27191dc190c62b8d9ad59f9624ff Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 2 Feb 2016 23:31:46 +0100 Subject: Improve UI consistency between projects and groups lists Signed-off-by: Dmitriy Zaporozhets --- CHANGELOG | 1 + app/assets/stylesheets/pages/groups.scss | 20 +++++++++++++++++++- app/views/dashboard/_groups_head.html.haml | 20 +++++++++++++------- app/views/dashboard/groups/index.html.haml | 9 --------- app/views/shared/groups/_group.html.haml | 19 ++++++++++++++++--- 5 files changed, 49 insertions(+), 20 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 7d7154487ad..994e7a35b5f 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -25,6 +25,7 @@ v 8.5.0 (unreleased) - Deprecate API "merge_request/:merge_request_id/...". Use "merge_requests/:merge_request_id/..." instead - Mark inline difference between old and new paths when a file is renamed - Support Akismet spam checking for creation of issues via API (Stan Hu) + - Improve UI consistency between projects and groups lists v 8.4.3 - Increase lfs_objects size column to 8-byte integer to allow files larger diff --git a/app/assets/stylesheets/pages/groups.scss b/app/assets/stylesheets/pages/groups.scss index fdd86979a36..ec6c099df5b 100644 --- a/app/assets/stylesheets/pages/groups.scss +++ b/app/assets/stylesheets/pages/groups.scss @@ -4,7 +4,7 @@ input[type='search'] { width: 225px; vertical-align: bottom; - + @media (max-width: $screen-xs-max) { width: 100px; vertical-align: bottom; @@ -21,3 +21,21 @@ height: 42px; } } + +.group-row { + &.no-description { + .group-name { + line-height: 44px; + } + } + + .stats { + float: right; + line-height: 44px; + color: $gl-gray; + + span { + margin-right: 15px; + } + } +} diff --git a/app/views/dashboard/_groups_head.html.haml b/app/views/dashboard/_groups_head.html.haml index 6ca97a692b4..15e423a3b29 100644 --- a/app/views/dashboard/_groups_head.html.haml +++ b/app/views/dashboard/_groups_head.html.haml @@ -1,7 +1,13 @@ -%ul.nav-links - = nav_link(page: dashboard_groups_path) do - = link_to dashboard_groups_path, title: 'Your groups', data: {placement: 'right'} do - Your Groups - = nav_link(page: explore_groups_path) do - = link_to explore_groups_path, title: 'Explore groups', data: {placement: 'bottom'} do - Explore Groups +.top-area + %ul.nav-links + = nav_link(page: dashboard_groups_path) do + = link_to dashboard_groups_path, title: 'Your groups', data: {placement: 'right'} do + Your Groups + = nav_link(page: explore_groups_path) do + = link_to explore_groups_path, title: 'Explore groups', data: {placement: 'bottom'} do + Explore Groups + - if current_user.can_create_group? + .projects-search-form + = link_to new_group_path, class: "btn btn-new" do + = icon('plus') + New Group diff --git a/app/views/dashboard/groups/index.html.haml b/app/views/dashboard/groups/index.html.haml index d5b7e729e7b..caca91af536 100644 --- a/app/views/dashboard/groups/index.html.haml +++ b/app/views/dashboard/groups/index.html.haml @@ -2,15 +2,6 @@ - header_title "Groups", dashboard_groups_path = render 'dashboard/groups_head' -.gray-content-block - - if current_user.can_create_group? - %span.pull-right.hidden-xs - = link_to new_group_path, class: "btn btn-new" do - %i.fa.fa-plus - New Group - .oneline - Group members have access to all group projects. - %ul.content-list - @group_members.each do |group_member| - group = group_member.group diff --git a/app/views/shared/groups/_group.html.haml b/app/views/shared/groups/_group.html.haml index 778b20fb4f2..aa2ece22485 100644 --- a/app/views/shared/groups/_group.html.haml +++ b/app/views/shared/groups/_group.html.haml @@ -1,5 +1,8 @@ - group_member = local_assigns[:group_member] -%li +- css_class = '' unless local_assigns[:css_class] +- css_class += " no-description" if group.description.blank? + +%li.group-row{ class: css_class } - if group_member .controls.hidden-xs - if can?(current_user, :admin_group, group) @@ -9,6 +12,15 @@ = link_to leave_group_group_members_path(group), data: { confirm: leave_group_message(group.name) }, method: :delete, class: "btn-sm btn btn-grouped", title: 'Leave this group' do %i.fa.fa-sign-out + .stats + %span + = icon('home') + = group.projects.count + + %span + = icon('users') + = group.users.count + = image_tag group_icon(group), class: "avatar s46 hidden-xs" = link_to group, class: 'group-name' do %span.item-title= group.name @@ -17,5 +29,6 @@ as %span #{group_member.human_access} - %div.light - #{pluralize(group.projects.count, "project")}, #{pluralize(group.users.count, "user")} + - if group.description.present? + .light + = markdown(group.description, pipeline: :description) -- cgit v1.2.1 From df922d811520f2b6459e84f1e595d3a0fcfc395c Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 3 Feb 2016 00:07:11 +0100 Subject: Add number_with_delimiter and remove unnecessary dara placement for groups page Signed-off-by: Dmitriy Zaporozhets --- app/views/dashboard/_groups_head.html.haml | 4 ++-- app/views/shared/groups/_group.html.haml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/views/dashboard/_groups_head.html.haml b/app/views/dashboard/_groups_head.html.haml index 15e423a3b29..e52070704d9 100644 --- a/app/views/dashboard/_groups_head.html.haml +++ b/app/views/dashboard/_groups_head.html.haml @@ -1,10 +1,10 @@ .top-area %ul.nav-links = nav_link(page: dashboard_groups_path) do - = link_to dashboard_groups_path, title: 'Your groups', data: {placement: 'right'} do + = link_to dashboard_groups_path, title: 'Your groups' do Your Groups = nav_link(page: explore_groups_path) do - = link_to explore_groups_path, title: 'Explore groups', data: {placement: 'bottom'} do + = link_to explore_groups_path, title: 'Explore groups' do Explore Groups - if current_user.can_create_group? .projects-search-form diff --git a/app/views/shared/groups/_group.html.haml b/app/views/shared/groups/_group.html.haml index aa2ece22485..f7fe6b02641 100644 --- a/app/views/shared/groups/_group.html.haml +++ b/app/views/shared/groups/_group.html.haml @@ -15,11 +15,11 @@ .stats %span = icon('home') - = group.projects.count + = number_with_delimiter(group.projects.count) %span = icon('users') - = group.users.count + = number_with_delimiter(group.users.count) = image_tag group_icon(group), class: "avatar s46 hidden-xs" = link_to group, class: 'group-name' do -- cgit v1.2.1 From 4beae990b37e3583485bb33f03e08e3cc798ff37 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 3 Feb 2016 01:08:30 +0100 Subject: Refactor nav controls section (search and new project/group btn) Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/framework/buttons.scss | 8 +-- app/assets/stylesheets/framework/nav.scss | 62 +++++++++++++++++++ app/assets/stylesheets/pages/projects.scss | 88 +-------------------------- app/views/dashboard/_groups_head.html.haml | 2 +- app/views/dashboard/_projects_head.html.haml | 6 +- app/views/groups/_projects.html.haml | 17 +++--- app/views/projects/forks/index.html.haml | 64 ++++++++++--------- 7 files changed, 107 insertions(+), 140 deletions(-) diff --git a/app/assets/stylesheets/framework/buttons.scss b/app/assets/stylesheets/framework/buttons.scss index c99292c3f83..11df4c24056 100644 --- a/app/assets/stylesheets/framework/buttons.scss +++ b/app/assets/stylesheets/framework/buttons.scss @@ -82,8 +82,7 @@ &.btn-success, &.btn-new, &.btn-create, - &.btn-save, - &.btn-green { + &.btn-save { @include btn-green; } @@ -159,7 +158,6 @@ .input-group-btn { .btn { - @include btn-gray; @include btn-middle; &:hover { @@ -186,8 +184,4 @@ border: 1px solid #c6cacf !important; background-color: #e4e7ed !important; } - - .btn-green { - @include btn-green - } } diff --git a/app/assets/stylesheets/framework/nav.scss b/app/assets/stylesheets/framework/nav.scss index c537d97fb24..1d042dfb439 100644 --- a/app/assets/stylesheets/framework/nav.scss +++ b/app/assets/stylesheets/framework/nav.scss @@ -37,3 +37,65 @@ } } } + +.top-area { + border-bottom: 1px solid #EEE; + + .nav-text { + padding-top: 16px; + padding-bottom: 11px; + display: inline-block; + width: 50%; + line-height: 28px; + } + + .nav-links { + display: inline-block; + width: 50%; + margin-bottom: 0px; + border-bottom: none; + } + + .nav-controls { + width: 50%; + display: inline-block; + float: right; + text-align: right; + padding: 11px 0; + margin-bottom: 0px; + + > .dropdown { + display: inline-block; + } + + input { + display: inline-block; + width: calc(100% - 151px); + + /* Small devices (tablets, 768px and up) */ + @media (min-width: $screen-sm-min) { width: 150px; } + + /* Medium devices (desktops, 992px and up) */ + @media (min-width: $screen-md-min) { width: 200px; } + + /* Large devices (large desktops, 1200px and up) */ + @media (min-width: $screen-lg-min) { width: 300px; } + } + + .btn-new { + width: 135px; + margin-left: 10px; + float: right; + } + + .dropdown-toggle.btn { + margin-top: -3px; + } + } + + @media (max-width: $screen-xs-max) { + .nav-controls { + padding-top: 15px; + } + } +} diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss index e4ea47cc4a2..3d88746ddf7 100644 --- a/app/assets/stylesheets/pages/projects.scss +++ b/app/assets/stylesheets/pages/projects.scss @@ -281,36 +281,6 @@ margin-top: -1px; } -.top-area { - border-bottom: 1px solid #EEE; - - ul.nav-links { - display: inline-block; - width: 50%; - margin-bottom: 0px; - border-bottom: none; - } - - .projects-search-form { - width: 50%; - display: inline-block; - float: right; - padding-top: 11px; - text-align: right; - - .btn-green { - margin-left: 10px; - float: right; - } - } - - @media (max-width: $screen-xs-max) { - .projects-search-form { - padding-top: 15px; - } - } -} - .fork-namespaces { .fork-thumbnail { text-align: center; @@ -386,22 +356,6 @@ pre.light-well { border-color: #f1f1f1; } -.projects-search-form { - padding: $gl-padding 0; - padding-bottom: 0; - margin-bottom: 0px; - - input { - display: inline-block; - width: calc(100% - 151px); - } - - .btn { - display: inline-block; - width: 135px; - } -} - .git-empty { margin: 0 7px 0 7px; @@ -559,52 +513,12 @@ pre.light-well { } } -.cannot-be-merged, +.cannot-be-merged, .cannot-be-merged:hover { color: #E62958; margin-top: 2px; } -/* - * Forks list rendered on Project's forks page - */ - -.forks-top-block { - padding: 16px 0; -} - -.projects-search-form { - .dropdown-toggle.btn { - margin-top: -3px; - } - - &.fork-search-form { - margin: 0; - margin-top: -$gl-padding; - padding-bottom: 0; - - input { - /* Small devices (tablets, 768px and up) */ - @media (min-width: $screen-sm-min) { width: 180px; } - - /* Medium devices (desktops, 992px and up) */ - @media (min-width: $screen-md-min) { width: 350px; } - - /* Large devices (large desktops, 1200px and up) */ - @media (min-width: $screen-lg-min) { width: 400px; } - } - - .sort-forks { - width: 160px; - } - - .fork-link { - float: right; - margin-left: $gl-padding; - } - } -} - .private-forks-notice .private-fork-icon { i:nth-child(1) { color: #2AA056; diff --git a/app/views/dashboard/_groups_head.html.haml b/app/views/dashboard/_groups_head.html.haml index e52070704d9..3d17f74b709 100644 --- a/app/views/dashboard/_groups_head.html.haml +++ b/app/views/dashboard/_groups_head.html.haml @@ -7,7 +7,7 @@ = link_to explore_groups_path, title: 'Explore groups' do Explore Groups - if current_user.can_create_group? - .projects-search-form + .nav-controls = link_to new_group_path, class: "btn btn-new" do = icon('plus') New Group diff --git a/app/views/dashboard/_projects_head.html.haml b/app/views/dashboard/_projects_head.html.haml index 5c4b58cd688..b6301f2238f 100644 --- a/app/views/dashboard/_projects_head.html.haml +++ b/app/views/dashboard/_projects_head.html.haml @@ -12,9 +12,9 @@ = link_to explore_root_path, title: 'Explore', data: {placement: 'right'} do Explore Projects - .projects-search-form + .nav-controls = search_field_tag :filter_projects, nil, placeholder: 'Filter by name...', class: 'projects-list-filter form-control hidden-xs', spellcheck: false - if current_user.can_create_project? - = link_to new_project_path, class: 'btn btn-green' do - %i.fa.fa-plus + = link_to new_project_path, class: 'btn btn-new' do + = icon('plus') New Project diff --git a/app/views/groups/_projects.html.haml b/app/views/groups/_projects.html.haml index bbafc08435a..a829479bb38 100644 --- a/app/views/groups/_projects.html.haml +++ b/app/views/groups/_projects.html.haml @@ -1,11 +1,10 @@ -.projects-list-holder - .projects-search-form - .input-group - = search_field_tag :filter_projects, nil, placeholder: 'Filter by name', class: 'projects-list-filter form-control', spellcheck: false - - if can? current_user, :create_projects, @group - %span.input-group-btn - = link_to new_project_path(namespace_id: @group.id), class: 'btn btn-green' do - %i.fa.fa-plus - New Project +.projects-list-holder.prepend-top-default + .input-group + = search_field_tag :filter_projects, nil, placeholder: 'Filter by name', class: 'projects-list-filter form-control', spellcheck: false + - if can? current_user, :create_projects, @group + %span.input-group-btn + = link_to new_project_path(namespace_id: @group.id), class: 'btn btn-new' do + = icon('plus') + New Project = render 'shared/projects/list', projects: @projects, projects_limit: 20, stars: false, skip_namespace: true diff --git a/app/views/projects/forks/index.html.haml b/app/views/projects/forks/index.html.haml index a362185210a..3fa7155bab7 100644 --- a/app/views/projects/forks/index.html.haml +++ b/app/views/projects/forks/index.html.haml @@ -1,44 +1,42 @@ -.gray-content-block.top-block.clearfix.white.forks-top-block - .pull-left +.top-area + .nav-text - public_count = @public_forks.size - protected_count = @protected_forks.size - full_count_title = "#{public_count} public and #{protected_count} private" == #{pluralize(@all_forks.size, 'fork')}: #{full_count_title} - .pull-right - .projects-search-form.fork-search-form - = search_field_tag :filter_projects, nil, placeholder: 'Search forks', class: 'projects-list-filter form-control', - spellcheck: false, data: { 'filter-selector' => 'span.namespace-name' } + .nav-controls + = search_field_tag :filter_projects, nil, placeholder: 'Search forks', class: 'projects-list-filter form-control', + spellcheck: false, data: { 'filter-selector' => 'span.namespace-name' } - .dropdown.inline.prepend-left-10 - %button.dropdown-toggle.btn.sort-forks{type: 'button', 'data-toggle' => 'dropdown'} - %span.light sort: - - if @sort.present? - = sort_options_hash[@sort] - - else + .dropdown.prepend-left-10 + %button.dropdown-toggle.btn.sort-forks{type: 'button', 'data-toggle' => 'dropdown'} + %span.light sort: + - if @sort.present? + = sort_options_hash[@sort] + - else + = sort_title_recently_created + %b.caret + %ul.dropdown-menu.dropdown-menu-align-right + %li + - excluded_filters = [:state, :scope, :label_name, :milestone_id, :assignee_id, :author_id] + = link_to page_filter_path(sort: sort_value_recently_created, without: excluded_filters) do = sort_title_recently_created - %b.caret - %ul.dropdown-menu.dropdown-menu-align-right - %li - - excluded_filters = [:state, :scope, :label_name, :milestone_id, :assignee_id, :author_id] - = link_to page_filter_path(sort: sort_value_recently_created, without: excluded_filters) do - = sort_title_recently_created - = link_to page_filter_path(sort: sort_value_oldest_created, without: excluded_filters) do - = sort_title_oldest_created - = link_to page_filter_path(sort: sort_value_recently_updated, without: excluded_filters) do - = sort_title_recently_updated - = link_to page_filter_path(sort: sort_value_oldest_updated, without: excluded_filters) do - = sort_title_oldest_updated + = link_to page_filter_path(sort: sort_value_oldest_created, without: excluded_filters) do + = sort_title_oldest_created + = link_to page_filter_path(sort: sort_value_recently_updated, without: excluded_filters) do + = sort_title_recently_updated + = link_to page_filter_path(sort: sort_value_oldest_updated, without: excluded_filters) do + = sort_title_oldest_updated - .fork-link.inline - - if current_user.already_forked?(@project) && current_user.manageable_namespaces.size < 2 - = link_to namespace_project_path(current_user, current_user.fork_of(@project)), title: 'Go to your fork', class: 'pull-right btn btn-new' do - = icon('code-fork fw') - Fork - - else - = link_to new_namespace_project_fork_path(@project.namespace, @project), title: "Fork project", class: 'pull-right btn btn-new' do - = icon('code-fork fw') - Fork + - if current_user.already_forked?(@project) && current_user.manageable_namespaces.size < 2 + = link_to namespace_project_path(current_user, current_user.fork_of(@project)), title: 'Go to your fork', class: 'btn btn-new' do + = icon('code-fork fw') + Fork + - else + = link_to new_namespace_project_fork_path(@project.namespace, @project), title: "Fork project", class: 'btn btn-new' do + = icon('code-fork fw') + Fork .projects-list-holder -- cgit v1.2.1 From ad5acec6e5aa1376e5711cdac531db8f9cca3d01 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 3 Feb 2016 01:50:53 +0100 Subject: Make nav-controls responsive and hide on extra small screens Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/framework/nav.scss | 54 +++++++++++++++++++++++-------- app/views/projects/forks/index.html.haml | 4 +-- 2 files changed, 42 insertions(+), 16 deletions(-) diff --git a/app/assets/stylesheets/framework/nav.scss b/app/assets/stylesheets/framework/nav.scss index 1d042dfb439..6410656847f 100644 --- a/app/assets/stylesheets/framework/nav.scss +++ b/app/assets/stylesheets/framework/nav.scss @@ -39,6 +39,8 @@ } .top-area { + @include clearfix; + border-bottom: 1px solid #EEE; .nav-text { @@ -47,6 +49,11 @@ display: inline-block; width: 50%; line-height: 28px; + + /* Small devices (phones, tablets, 768px and lower) */ + @media (max-width: $screen-sm-min) { + width: 100%; + } } .nav-links { @@ -54,6 +61,11 @@ width: 50%; margin-bottom: 0px; border-bottom: none; + + /* Small devices (phones, tablets, 768px and lower) */ + @media (max-width: $screen-sm-min) { + width: 100%; + } } .nav-controls { @@ -65,37 +77,51 @@ margin-bottom: 0px; > .dropdown { + margin-left: 10px; display: inline-block; } - input { + > .btn { display: inline-block; - width: calc(100% - 151px); + margin-left: 10px; + margin-top: -3px; + } - /* Small devices (tablets, 768px and up) */ - @media (min-width: $screen-sm-min) { width: 150px; } + input { + display: inline-block; /* Medium devices (desktops, 992px and up) */ @media (min-width: $screen-md-min) { width: 200px; } /* Large devices (large desktops, 1200px and up) */ - @media (min-width: $screen-lg-min) { width: 300px; } - } + @media (min-width: $screen-lg-min) { width: 250px; } - .btn-new { - width: 135px; - margin-left: 10px; - float: right; + &.input-short { + /* Medium devices (desktops, 992px and up) */ + @media (min-width: $screen-md-min) { width: 170px; } + + /* Large devices (large desktops, 1200px and up) */ + @media (min-width: $screen-lg-min) { width: 210px; } + } } .dropdown-toggle.btn { margin-top: -3px; } - } - @media (max-width: $screen-xs-max) { - .nav-controls { - padding-top: 15px; + /* Hide on extra small devices (phones) */ + @media (max-width: $screen-xs-max) { + display: none; + } + + /* Small devices (tablets, 768px and lower) */ + @media (max-width: $screen-sm-max) { + width: 100%; + text-align: left; + + input { + width: 300px; + } } } } diff --git a/app/views/projects/forks/index.html.haml b/app/views/projects/forks/index.html.haml index 3fa7155bab7..acb2353d3ca 100644 --- a/app/views/projects/forks/index.html.haml +++ b/app/views/projects/forks/index.html.haml @@ -6,10 +6,10 @@ == #{pluralize(@all_forks.size, 'fork')}: #{full_count_title} .nav-controls - = search_field_tag :filter_projects, nil, placeholder: 'Search forks', class: 'projects-list-filter form-control', + = search_field_tag :filter_projects, nil, placeholder: 'Search forks', class: 'projects-list-filter form-control input-short', spellcheck: false, data: { 'filter-selector' => 'span.namespace-name' } - .dropdown.prepend-left-10 + .dropdown %button.dropdown-toggle.btn.sort-forks{type: 'button', 'data-toggle' => 'dropdown'} %span.light sort: - if @sort.present? -- cgit v1.2.1 From faacb7853478704a37655361c23abffdfd47db6f Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 3 Feb 2016 02:01:33 +0100 Subject: Tried to align form input vertically with other elements for top nav Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/framework/nav.scss | 8 +++----- app/views/dashboard/_projects_head.html.haml | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/app/assets/stylesheets/framework/nav.scss b/app/assets/stylesheets/framework/nav.scss index 6410656847f..252f84a6b48 100644 --- a/app/assets/stylesheets/framework/nav.scss +++ b/app/assets/stylesheets/framework/nav.scss @@ -84,11 +84,13 @@ > .btn { display: inline-block; margin-left: 10px; - margin-top: -3px; } input { + height: 34px; display: inline-block; + position: relative; + top: 1px; /* Medium devices (desktops, 992px and up) */ @media (min-width: $screen-md-min) { width: 200px; } @@ -105,10 +107,6 @@ } } - .dropdown-toggle.btn { - margin-top: -3px; - } - /* Hide on extra small devices (phones) */ @media (max-width: $screen-xs-max) { display: none; diff --git a/app/views/dashboard/_projects_head.html.haml b/app/views/dashboard/_projects_head.html.haml index b6301f2238f..726f669b1d2 100644 --- a/app/views/dashboard/_projects_head.html.haml +++ b/app/views/dashboard/_projects_head.html.haml @@ -8,7 +8,7 @@ = nav_link(page: starred_dashboard_projects_path) do = link_to starred_dashboard_projects_path, title: 'Starred Projects', data: {placement: 'right'} do Starred Projects - = nav_link(page: [explore_root_path, trending_explore_projects_path, starred_explore_projects_path, explore_projects_path], html_options: { class: 'hidden-xs' }) do + = nav_link(page: [explore_root_path, trending_explore_projects_path, starred_explore_projects_path, explore_projects_path]) do = link_to explore_root_path, title: 'Explore', data: {placement: 'right'} do Explore Projects -- cgit v1.2.1 From 754538b99206a778ddf87e0d362fccb0ff2f6c15 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 3 Feb 2016 02:10:33 +0100 Subject: Use right margin for componened other than button for top nav Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/framework/nav.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/assets/stylesheets/framework/nav.scss b/app/assets/stylesheets/framework/nav.scss index 252f84a6b48..e6c59f5a291 100644 --- a/app/assets/stylesheets/framework/nav.scss +++ b/app/assets/stylesheets/framework/nav.scss @@ -77,13 +77,12 @@ margin-bottom: 0px; > .dropdown { - margin-left: 10px; + margin-right: 10px; display: inline-block; } > .btn { display: inline-block; - margin-left: 10px; } input { @@ -91,6 +90,7 @@ display: inline-block; position: relative; top: 1px; + margin-right: 10px; /* Medium devices (desktops, 992px and up) */ @media (min-width: $screen-md-min) { width: 200px; } -- cgit v1.2.1 From ea7bdc78eed8db7ff4b5440b282678b1c5b021f7 Mon Sep 17 00:00:00 2001 From: Patricio Cano Date: Wed, 3 Feb 2016 11:17:14 -0500 Subject: Updated omniuath-saml to the latest version. --- Gemfile | 2 +- Gemfile.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Gemfile b/Gemfile index 16a02da5bf9..a06dbe8e061 100644 --- a/Gemfile +++ b/Gemfile @@ -30,7 +30,7 @@ gem 'omniauth-github', '~> 1.1.1' gem 'omniauth-gitlab', '~> 1.0.0' gem 'omniauth-google-oauth2', '~> 0.2.0' gem 'omniauth-kerberos', '~> 0.3.0', group: :kerberos -gem 'omniauth-saml', '~> 1.4.0' +gem 'omniauth-saml', '~> 1.4.2' gem 'omniauth-shibboleth', '~> 1.2.0' gem 'omniauth-twitter', '~> 1.2.0' gem 'omniauth_crowd', '~> 2.2.0' diff --git a/Gemfile.lock b/Gemfile.lock index 62937ab6fd2..bd767016108 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -532,9 +532,9 @@ GEM omniauth-oauth2 (1.3.1) oauth2 (~> 1.0) omniauth (~> 1.2) - omniauth-saml (1.4.1) + omniauth-saml (1.4.2) omniauth (~> 1.1) - ruby-saml (~> 1.0.0) + ruby-saml (~> 1.1, >= 1.1.1) omniauth-shibboleth (1.2.1) omniauth (>= 1.0.0) omniauth-twitter (1.2.1) @@ -690,7 +690,7 @@ GEM ruby-fogbugz (0.2.1) crack (~> 0.4) ruby-progressbar (1.7.5) - ruby-saml (1.0.0) + ruby-saml (1.1.1) nokogiri (>= 1.5.10) uuid (~> 2.3) ruby2ruby (2.2.0) @@ -974,7 +974,7 @@ DEPENDENCIES omniauth-gitlab (~> 1.0.0) omniauth-google-oauth2 (~> 0.2.0) omniauth-kerberos (~> 0.3.0) - omniauth-saml (~> 1.4.0) + omniauth-saml (~> 1.4.2) omniauth-shibboleth (~> 1.2.0) omniauth-twitter (~> 1.2.0) omniauth_crowd (~> 2.2.0) -- cgit v1.2.1 From 6f8ae85567a360deafc6390e2a9ada6513a89fa3 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 3 Feb 2016 18:05:58 +0100 Subject: Fix missing space between fork and star icons Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/pages/projects.scss | 4 ++++ app/views/shared/projects/_project.html.haml | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss index 3d88746ddf7..dd4ff39c5b8 100644 --- a/app/assets/stylesheets/pages/projects.scss +++ b/app/assets/stylesheets/pages/projects.scss @@ -415,6 +415,10 @@ pre.light-well { a:hover { text-decoration: none; } + + > span { + margin-left: 10px; + } } .project-description { diff --git a/app/views/shared/projects/_project.html.haml b/app/views/shared/projects/_project.html.haml index 2aeeed63c95..e196fc51d2d 100644 --- a/app/views/shared/projects/_project.html.haml +++ b/app/views/shared/projects/_project.html.haml @@ -29,8 +29,8 @@ .project-controls - if ci_commit - = render_ci_status(ci_commit) -   + %span + = render_ci_status(ci_commit) - if forks %span = icon('code-fork') -- cgit v1.2.1 From 8cd25901d3de83d7d03c33361a61308effa13760 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 3 Feb 2016 18:41:55 +0100 Subject: Use top-area component for top page navigation for pages that contains list of items Signed-off-by: Dmitriy Zaporozhets --- app/views/dashboard/milestones/index.html.haml | 8 ++++---- app/views/groups/milestones/index.html.haml | 16 +++++++--------- app/views/help/ui.html.haml | 24 ++++++++++++++++++++++++ app/views/projects/builds/index.html.haml | 23 +++++++++++------------ app/views/projects/labels/index.html.haml | 13 +++++++------ app/views/projects/milestones/index.html.haml | 12 ++++++------ app/views/projects/wikis/_nav.html.haml | 18 +++++++++--------- app/views/shared/_milestones_filter.html.haml | 21 ++++++++++----------- 8 files changed, 78 insertions(+), 57 deletions(-) diff --git a/app/views/dashboard/milestones/index.html.haml b/app/views/dashboard/milestones/index.html.haml index bec1692a4de..2ee167db911 100644 --- a/app/views/dashboard/milestones/index.html.haml +++ b/app/views/dashboard/milestones/index.html.haml @@ -1,12 +1,12 @@ - page_title "Milestones" - header_title "Milestones", dashboard_milestones_path -.project-issuable-filter - .controls - = render 'shared/new_project_item_select', path: 'milestones/new', label: "New Milestone", include_groups: true - +.top-area = render 'shared/milestones_filter' + .nav-controls + = render 'shared/new_project_item_select', path: 'milestones/new', label: "New Milestone", include_groups: true + .gray-content-block List all milestones from all projects you have access to. diff --git a/app/views/groups/milestones/index.html.haml b/app/views/groups/milestones/index.html.haml index b221d3a89a4..ab307708b75 100644 --- a/app/views/groups/milestones/index.html.haml +++ b/app/views/groups/milestones/index.html.haml @@ -1,17 +1,15 @@ - page_title "Milestones" - header_title group_title(@group, "Milestones", group_milestones_path(@group)) -.project-issuable-filter - .controls - - if can?(current_user, :admin_milestones, @group) - .pull-right - %span.pull-right.hidden-xs - = link_to new_group_milestone_path(@group), class: "btn btn-new" do - = icon('plus') - New Milestone - +.top-area = render 'shared/milestones_filter' + .nav-controls + - if can?(current_user, :admin_milestones, @group) + = link_to new_group_milestone_path(@group), class: "btn btn-new" do + = icon('plus') + New Milestone + .gray-content-block Only milestones from %strong #{@group.name} diff --git a/app/views/help/ui.html.haml b/app/views/help/ui.html.haml index 7b45bd09050..746386cab58 100644 --- a/app/views/help/ui.html.haml +++ b/app/views/help/ui.html.haml @@ -138,8 +138,32 @@ %h2#navs Navigation + %h4 + %code .top-area + %p Holder for top page navigation. Includes navigation, search field, sorting and button + + .example + .top-area + %ul.nav-links + %li.active + %a Open + %li + %a Closed + .nav-controls + = text_field_tag 'sample', nil, class: 'form-control' + .dropdown + %button.dropdown-toggle.btn{type: 'button', 'data-toggle' => 'dropdown'} + %span Sort by name + %b.caret + %ul.dropdown-menu + %li + %a Sort by date + + = link_to 'New issue', '#', class: 'btn btn-new' + %h4 %code .nav-links + %p Only nav links without button and search .example %ul.nav-links %li.active diff --git a/app/views/projects/builds/index.html.haml b/app/views/projects/builds/index.html.haml index bbb6944a65a..630d0286f25 100644 --- a/app/views/projects/builds/index.html.haml +++ b/app/views/projects/builds/index.html.haml @@ -1,18 +1,7 @@ - page_title "Builds" = render "header_title" -.project-issuable-filter - .controls - - if can?(current_user, :manage_builds, @project) - .pull-left.hidden-xs - - if @all_builds.running_or_pending.any? - = link_to 'Cancel running', cancel_all_namespace_project_builds_path(@project.namespace, @project), - data: { confirm: 'Are you sure?' }, class: 'btn btn-danger', method: :post - - = link_to ci_lint_path, class: 'btn btn-default' do - = icon('wrench') - %span CI Lint - +.top-area %ul.nav-links %li{class: ('active' if @scope.nil?)} = link_to project_builds_path(@project) do @@ -32,6 +21,16 @@ %span.badge.js-running-count = number_with_delimiter(@all_builds.finished.count(:id)) + .nav-controls + - if can?(current_user, :manage_builds, @project) + - if @all_builds.running_or_pending.any? + = link_to 'Cancel running', cancel_all_namespace_project_builds_path(@project.namespace, @project), + data: { confirm: 'Are you sure?' }, class: 'btn btn-danger', method: :post + + = link_to ci_lint_path, class: 'btn btn-default' do + = icon('wrench') + %span CI Lint + .gray-content-block #{(@scope || 'running').capitalize} builds from this project diff --git a/app/views/projects/labels/index.html.haml b/app/views/projects/labels/index.html.haml index 9081bcfe9b3..cc41130a9dc 100644 --- a/app/views/projects/labels/index.html.haml +++ b/app/views/projects/labels/index.html.haml @@ -1,13 +1,14 @@ - page_title "Labels" = render "header_title" -.gray-content-block.top-block - - if can? current_user, :admin_label, @project - = link_to new_namespace_project_label_path(@project.namespace, @project), class: "pull-right btn btn-new" do - = icon('plus') - New label - .oneline +.top-area + .nav-text Labels can be applied to issues and merge requests. + .nav-controls + - if can? current_user, :admin_label, @project + = link_to new_namespace_project_label_path(@project.namespace, @project), class: "btn btn-new" do + = icon('plus') + New label .labels - if @labels.present? diff --git a/app/views/projects/milestones/index.html.haml b/app/views/projects/milestones/index.html.haml index 114b06457a5..49625b3534b 100644 --- a/app/views/projects/milestones/index.html.haml +++ b/app/views/projects/milestones/index.html.haml @@ -2,15 +2,15 @@ = render "header_title" -.project-issuable-filter - .controls +.top-area + = render 'shared/milestones_filter' + + .nav-controls - 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 - %i.fa.fa-plus + = link_to new_namespace_project_milestone_path(@project.namespace, @project), class: "btn btn-new", title: "New Milestone" do + = icon('plus') New Milestone - = render 'shared/milestones_filter' - .gray-content-block Milestone allows you to group issues and set due date for it diff --git a/app/views/projects/wikis/_nav.html.haml b/app/views/projects/wikis/_nav.html.haml index 69ba301e231..56a53ffff2a 100644 --- a/app/views/projects/wikis/_nav.html.haml +++ b/app/views/projects/wikis/_nav.html.haml @@ -1,12 +1,4 @@ -.project-issuable-filter - .controls - - if can?(current_user, :create_wiki, @project) - = link_to '#modal-new-wiki', class: "add-new-wiki btn btn-new", "data-toggle" => "modal" do - %i.fa.fa-plus - New Page - - = render 'projects/wikis/new' - +.top-area %ul.nav-links = nav_link(html_options: {class: params[:id] == 'home' ? 'active' : '' }) do = link_to 'Home', namespace_project_wiki_path(@project.namespace, @project, :home) @@ -17,3 +9,11 @@ = nav_link(path: 'wikis#git_access') do = link_to namespace_project_wikis_git_access_path(@project.namespace, @project) do Git Access + + .nav-controls + - if can?(current_user, :create_wiki, @project) + = link_to '#modal-new-wiki', class: "add-new-wiki btn btn-new", "data-toggle" => "modal" do + = icon('plus') + New Page + + = render 'projects/wikis/new' diff --git a/app/views/shared/_milestones_filter.html.haml b/app/views/shared/_milestones_filter.html.haml index f77feeb79cd..cf16c203f9c 100644 --- a/app/views/shared/_milestones_filter.html.haml +++ b/app/views/shared/_milestones_filter.html.haml @@ -1,11 +1,10 @@ -.milestones-filters - %ul.nav-links - %li{class: ("active" if params[:state].blank? || params[:state] == 'opened')} - = link_to milestones_filter_path(state: 'opened') do - Open - %li{class: ("active" if params[:state] == 'closed')} - = link_to milestones_filter_path(state: 'closed') do - Closed - %li{class: ("active" if params[:state] == 'all')} - = link_to milestones_filter_path(state: 'all') do - All +%ul.nav-links + %li{class: ("active" if params[:state].blank? || params[:state] == 'opened')} + = link_to milestones_filter_path(state: 'opened') do + Open + %li{class: ("active" if params[:state] == 'closed')} + = link_to milestones_filter_path(state: 'closed') do + Closed + %li{class: ("active" if params[:state] == 'all')} + = link_to milestones_filter_path(state: 'all') do + All -- cgit v1.2.1 From a441658783c5cdcda64f4cbd55ffabe24b646b46 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 3 Feb 2016 18:51:52 +0100 Subject: Remove useless text tips on commonly used pages Signed-off-by: Dmitriy Zaporozhets --- app/views/dashboard/issues.html.haml | 3 --- app/views/dashboard/merge_requests.html.haml | 3 --- app/views/dashboard/milestones/index.html.haml | 3 --- app/views/projects/milestones/index.html.haml | 3 --- 4 files changed, 12 deletions(-) diff --git a/app/views/dashboard/issues.html.haml b/app/views/dashboard/issues.html.haml index 2d3da01178a..f363f035974 100644 --- a/app/views/dashboard/issues.html.haml +++ b/app/views/dashboard/issues.html.haml @@ -16,8 +16,5 @@ = render 'shared/issuable/filter', type: :issues -.gray-content-block.second-block - List all issues from all projects you have access to. - .prepend-top-default = render 'shared/issues' diff --git a/app/views/dashboard/merge_requests.html.haml b/app/views/dashboard/merge_requests.html.haml index c5a5ec21f78..bbe4cc1f824 100644 --- a/app/views/dashboard/merge_requests.html.haml +++ b/app/views/dashboard/merge_requests.html.haml @@ -7,8 +7,5 @@ = render 'shared/issuable/filter', type: :merge_requests -.gray-content-block.second-block - List all merge requests from all projects you have access to. - .prepend-top-default = render 'shared/merge_requests' diff --git a/app/views/dashboard/milestones/index.html.haml b/app/views/dashboard/milestones/index.html.haml index bec1692a4de..eb2979fc13e 100644 --- a/app/views/dashboard/milestones/index.html.haml +++ b/app/views/dashboard/milestones/index.html.haml @@ -7,9 +7,6 @@ = render 'shared/milestones_filter' -.gray-content-block - List all milestones from all projects you have access to. - .milestones %ul.content-list - if @milestones.blank? diff --git a/app/views/projects/milestones/index.html.haml b/app/views/projects/milestones/index.html.haml index 114b06457a5..aa185126b56 100644 --- a/app/views/projects/milestones/index.html.haml +++ b/app/views/projects/milestones/index.html.haml @@ -11,9 +11,6 @@ = render 'shared/milestones_filter' -.gray-content-block - Milestone allows you to group issues and set due date for it - .milestones %ul.content-list = render @milestones -- cgit v1.2.1 From d6ef6c634e58ae81113983c37a55515ad640f18f Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Wed, 3 Feb 2016 13:31:12 -0500 Subject: Support Two-factor Authentication for LDAP users Closes #12653 --- CHANGELOG | 1 + app/controllers/omniauth_callbacks_controller.rb | 9 ++++- app/views/profiles/accounts/show.html.haml | 51 ++++++++++++------------ 3 files changed, 33 insertions(+), 28 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 5f081236c10..305ce4cbaf6 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -16,6 +16,7 @@ v 8.5.0 (unreleased) - Don't vendor minified JS - Display 404 error on group not found - Track project import failure + - Support Two-factor Authentication for LDAP users - Fix visibility level text in admin area (Zeger-Jan van de Weg) - Warn admin during OAuth of granting admin rights (Zeger-Jan van de Weg) - Update the ExternalIssue regex pattern (Blake Hitchcock) diff --git a/app/controllers/omniauth_callbacks_controller.rb b/app/controllers/omniauth_callbacks_controller.rb index 4c13228fce9..9cf76521a0d 100644 --- a/app/controllers/omniauth_callbacks_controller.rb +++ b/app/controllers/omniauth_callbacks_controller.rb @@ -1,4 +1,5 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController + include AuthenticatesWithTwoFactor protect_from_forgery except: [:kerberos, :saml, :cas3] @@ -29,8 +30,12 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController # Do additional LDAP checks for the user filter and EE features if ldap_user.allowed? - log_audit_event(@user, with: :ldap) - sign_in_and_redirect(@user) + if @user.two_factor_enabled? + prompt_for_two_factor(@user) + else + log_audit_event(@user, with: :ldap) + sign_in_and_redirect(@user) + end else flash[:alert] = "Access denied for your LDAP account." redirect_to new_user_session_path diff --git a/app/views/profiles/accounts/show.html.haml b/app/views/profiles/accounts/show.html.haml index 52bfc595fda..9fa96084f94 100644 --- a/app/views/profiles/accounts/show.html.haml +++ b/app/views/profiles/accounts/show.html.haml @@ -31,34 +31,33 @@ - else = f.submit 'Generate', class: "btn btn-default" - - unless current_user.ldap_user? - .panel.panel-default - .panel-heading - Two-factor Authentication - .panel-body - - if current_user.two_factor_enabled? - .pull-right - = link_to 'Disable Two-factor Authentication', profile_two_factor_auth_path, method: :delete, class: 'btn btn-close btn-sm', - data: { confirm: 'Are you sure?' } - %p.text-success - %strong - Two-factor Authentication is enabled - %p - If you lose your recovery codes you can - %strong - = succeed ',' do - = link_to 'generate new ones', codes_profile_two_factor_auth_path, method: :post, data: { confirm: 'Are you sure?' } - invalidating all previous codes. + .panel.panel-default + .panel-heading + Two-factor Authentication + .panel-body + - if current_user.two_factor_enabled? + .pull-right + = link_to 'Disable Two-factor Authentication', profile_two_factor_auth_path, method: :delete, class: 'btn btn-close btn-sm', + data: { confirm: 'Are you sure?' } + %p.text-success + %strong + Two-factor Authentication is enabled + %p + If you lose your recovery codes you can + %strong + = succeed ',' do + = link_to 'generate new ones', codes_profile_two_factor_auth_path, method: :post, data: { confirm: 'Are you sure?' } + invalidating all previous codes. - - else - %p - Increase your account's security by enabling two-factor authentication (2FA). - %p - Each time you log in you’ll be required to provide your username and - password as usual, plus a randomly-generated code from your phone. + - else + %p + Increase your account's security by enabling two-factor authentication (2FA). + %p + Each time you log in you’ll be required to provide your username and + password as usual, plus a randomly-generated code from your phone. - .form-actions - = link_to 'Enable Two-factor Authentication', new_profile_two_factor_auth_path, class: 'btn btn-success' + .form-actions + = link_to 'Enable Two-factor Authentication', new_profile_two_factor_auth_path, class: 'btn btn-success' - if button_based_providers.any? .panel.panel-default -- cgit v1.2.1 From 73bd729ecca27a293c47101dd399e628e221ce2d Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 3 Feb 2016 20:13:26 +0100 Subject: Add sort dropdown to dashboard projects page Signed-off-by: Dmitriy Zaporozhets --- CHANGELOG | 1 + app/assets/stylesheets/pages/explore.scss | 8 -------- app/controllers/dashboard/projects_controller.rb | 1 + app/helpers/explore_helper.rb | 13 ++++++++++++- app/views/dashboard/_projects_head.html.haml | 3 ++- app/views/explore/projects/_dropdown.html.haml | 12 +++--------- app/views/explore/projects/_filter.html.haml | 2 +- app/views/explore/projects/_nav.html.haml | 10 ++++++++++ app/views/explore/projects/index.html.haml | 6 +++++- app/views/explore/projects/starred.html.haml | 12 +++--------- app/views/explore/projects/trending.html.haml | 10 ++-------- 11 files changed, 40 insertions(+), 38 deletions(-) create mode 100644 app/views/explore/projects/_nav.html.haml diff --git a/CHANGELOG b/CHANGELOG index 5f081236c10..481a0f8d243 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -27,6 +27,7 @@ v 8.5.0 (unreleased) - Mark inline difference between old and new paths when a file is renamed - Support Akismet spam checking for creation of issues via API (Stan Hu) - Improve UI consistency between projects and groups lists + - Add sort dropdown to dashboard projects page v 8.4.3 - Increase lfs_objects size column to 8-byte integer to allow files larger diff --git a/app/assets/stylesheets/pages/explore.scss b/app/assets/stylesheets/pages/explore.scss index da06fe9954e..9b92128624c 100644 --- a/app/assets/stylesheets/pages/explore.scss +++ b/app/assets/stylesheets/pages/explore.scss @@ -6,11 +6,3 @@ font-size: 30px; } } - -.explore-trending-block { - .lead { - line-height: 32px; - font-size: 18px; - margin-top: 10px; - } -} diff --git a/app/controllers/dashboard/projects_controller.rb b/app/controllers/dashboard/projects_controller.rb index 0b7fcdf5e9e..721e2a6bcbd 100644 --- a/app/controllers/dashboard/projects_controller.rb +++ b/app/controllers/dashboard/projects_controller.rb @@ -3,6 +3,7 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController def index @projects = current_user.authorized_projects.sorted_by_activity.non_archived + @projects = @projects.sort(@sort = params[:sort]) @projects = @projects.includes(:namespace) @last_push = current_user.recent_push diff --git a/app/helpers/explore_helper.rb b/app/helpers/explore_helper.rb index 0d291f9a87e..3648757428b 100644 --- a/app/helpers/explore_helper.rb +++ b/app/helpers/explore_helper.rb @@ -10,8 +10,19 @@ module ExploreHelper options = exist_opts.merge(options) - path = explore_projects_path + path = if explore_controller? + explore_projects_path + elsif current_action?(:starred) + starred_dashboard_projects_path + else + dashboard_projects_path + end + path << "?#{options.to_param}" path end + + def explore_controller? + controller.class.name.split("::").first == "Explore" + end end diff --git a/app/views/dashboard/_projects_head.html.haml b/app/views/dashboard/_projects_head.html.haml index 726f669b1d2..d865a2c6fae 100644 --- a/app/views/dashboard/_projects_head.html.haml +++ b/app/views/dashboard/_projects_head.html.haml @@ -13,7 +13,8 @@ Explore Projects .nav-controls - = search_field_tag :filter_projects, nil, placeholder: 'Filter by name...', class: 'projects-list-filter form-control hidden-xs', spellcheck: false + = search_field_tag :filter_projects, nil, placeholder: 'Filter by name...', class: 'projects-list-filter form-control hidden-xs input-short', spellcheck: false + = render 'explore/projects/dropdown' - if current_user.can_create_project? = link_to new_project_path, class: 'btn btn-new' do = icon('plus') diff --git a/app/views/explore/projects/_dropdown.html.haml b/app/views/explore/projects/_dropdown.html.haml index a988d4c8154..87c556adc7d 100644 --- a/app/views/explore/projects/_dropdown.html.haml +++ b/app/views/explore/projects/_dropdown.html.haml @@ -3,19 +3,13 @@ %span.light - if @sort.present? = sort_options_hash[@sort] - - elsif current_page?(trending_explore_projects_path) || current_page?(explore_root_path) - Trending projects - - elsif current_page?(starred_explore_projects_path) - Most stars - else - = sort_title_recently_created + = sort_title_recently_updated %b.caret %ul.dropdown-menu %li - = link_to trending_explore_projects_path do - Trending projects - = link_to starred_explore_projects_path do - Most stars + = link_to explore_projects_filter_path(sort: sort_value_name) do + = sort_title_name = link_to explore_projects_filter_path(sort: sort_value_recently_created) do = sort_title_recently_created = link_to explore_projects_filter_path(sort: sort_value_oldest_created) do diff --git a/app/views/explore/projects/_filter.html.haml b/app/views/explore/projects/_filter.html.haml index 28b12c8dca8..66a4b535ae5 100644 --- a/app/views/explore/projects/_filter.html.haml +++ b/app/views/explore/projects/_filter.html.haml @@ -2,6 +2,7 @@ = form_tag explore_projects_filter_path, method: :get, class: 'form-inline form-tiny' do |f| .form-group = search_field_tag :search, params[:search], placeholder: "Filter by name", class: "form-control search-text-input", id: "projects_search", spellcheck: false + = hidden_field_tag :sort, @sort .form-group = button_tag 'Search', class: "btn" @@ -46,4 +47,3 @@ = link_to explore_projects_filter_path(tag: tag.name) do %i.fa.fa-tag = tag.name - = render 'explore/projects/dropdown' diff --git a/app/views/explore/projects/_nav.html.haml b/app/views/explore/projects/_nav.html.haml new file mode 100644 index 00000000000..614b5431779 --- /dev/null +++ b/app/views/explore/projects/_nav.html.haml @@ -0,0 +1,10 @@ +%ul.nav-links + = nav_link(page: [trending_explore_projects_path, explore_root_path]) do + = link_to trending_explore_projects_path do + Trending + = nav_link(page: starred_explore_projects_path) do + = link_to starred_explore_projects_path do + Most stars + = nav_link(page: explore_projects_path) do + = link_to explore_projects_path do + All diff --git a/app/views/explore/projects/index.html.haml b/app/views/explore/projects/index.html.haml index b9a958fbe7b..bee8518d57a 100644 --- a/app/views/explore/projects/index.html.haml +++ b/app/views/explore/projects/index.html.haml @@ -6,7 +6,11 @@ - else = render 'explore/head' -.gray-content-block.clearfix.second-block +.top-area + = render 'explore/projects/nav' + +.gray-content-block.second-block.clearfix = render 'filter' + = render 'projects', projects: @projects = paginate @projects, theme: "gitlab" diff --git a/app/views/explore/projects/starred.html.haml b/app/views/explore/projects/starred.html.haml index 95d46e331f8..16f52f7a530 100644 --- a/app/views/explore/projects/starred.html.haml +++ b/app/views/explore/projects/starred.html.haml @@ -6,12 +6,6 @@ - else = render 'explore/head' -.explore-trending-block - .gray-content-block.second-block - .pull-right - = render 'explore/projects/dropdown' - .oneline - %i.fa.fa-star - See most starred projects - = render 'projects', projects: @starred_projects - = paginate @starred_projects, theme: 'gitlab' += render 'explore/projects/nav' += render 'projects', projects: @starred_projects += paginate @starred_projects, theme: 'gitlab' diff --git a/app/views/explore/projects/trending.html.haml b/app/views/explore/projects/trending.html.haml index fa0b718e48b..adcda810061 100644 --- a/app/views/explore/projects/trending.html.haml +++ b/app/views/explore/projects/trending.html.haml @@ -6,11 +6,5 @@ - else = render 'explore/head' -.explore-trending-block - .gray-content-block.second-block - .pull-right - = render 'explore/projects/dropdown' - .oneline - %i.fa.fa-comments-o - See most discussed projects for last month - = render 'projects', projects: @trending_projects += render 'explore/projects/nav' += render 'projects', projects: @trending_projects -- cgit v1.2.1 From f8a33707b7b0626c5f8e22289197d2054e86d918 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 3 Feb 2016 20:21:26 +0100 Subject: Fix tests Signed-off-by: Dmitriy Zaporozhets --- spec/features/builds_spec.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/spec/features/builds_spec.rb b/spec/features/builds_spec.rb index d37bd103714..5b6f3cb3f15 100644 --- a/spec/features/builds_spec.rb +++ b/spec/features/builds_spec.rb @@ -18,7 +18,7 @@ describe "Builds" do visit namespace_project_builds_path(@project.namespace, @project, scope: :running) end - it { expect(page).to have_selector('.project-issuable-filter li.active', text: 'Running') } + it { expect(page).to have_selector('.nav-links li.active', text: 'Running') } it { expect(page).to have_link 'Cancel running' } it { expect(page).to have_content @build.short_sha } it { expect(page).to have_content @build.ref } @@ -31,7 +31,7 @@ describe "Builds" do visit namespace_project_builds_path(@project.namespace, @project, scope: :finished) end - it { expect(page).to have_selector('.project-issuable-filter li.active', text: 'Finished') } + it { expect(page).to have_selector('.nav-links li.active', text: 'Finished') } it { expect(page).to have_content 'No builds to show' } it { expect(page).to have_link 'Cancel running' } end @@ -42,7 +42,7 @@ describe "Builds" do visit namespace_project_builds_path(@project.namespace, @project) end - it { expect(page).to have_selector('.project-issuable-filter li.active', text: 'All') } + it { expect(page).to have_selector('.nav-links li.active', text: 'All') } it { expect(page).to have_content @build.short_sha } it { expect(page).to have_content @build.ref } it { expect(page).to have_content @build.name } @@ -57,7 +57,7 @@ describe "Builds" do click_link "Cancel running" end - it { expect(page).to have_selector('.project-issuable-filter li.active', text: 'All') } + it { expect(page).to have_selector('.nav-links li.active', text: 'All') } it { expect(page).to have_content 'canceled' } it { expect(page).to have_content @build.short_sha } it { expect(page).to have_content @build.ref } -- cgit v1.2.1 From d6d3a132b887c286b5b74e2a14be327f3a302d26 Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Wed, 3 Feb 2016 14:45:08 -0500 Subject: Fix sidebar replacement for issues & MRs --- app/views/projects/issues/update.js.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/projects/issues/update.js.haml b/app/views/projects/issues/update.js.haml index 3cec66d262b..c8e79ade110 100644 --- a/app/views/projects/issues/update.js.haml +++ b/app/views/projects/issues/update.js.haml @@ -1,3 +1,3 @@ -$('aside.right-sidebar').parent().html("#{escape_javascript(render 'shared/issuable/sidebar', issuable: @issue)}"); +$('aside.right-sidebar')[0].outerHTML = "#{escape_javascript(render 'shared/issuable/sidebar', issuable: @issue)}"); $('aside.right-sidebar').effect('highlight') new Issue(); \ No newline at end of file -- cgit v1.2.1 From bb81eff4bfcdee87095b03df04fd1086924984c0 Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Wed, 3 Feb 2016 15:49:30 -0500 Subject: Issue sidebar bug fix. Thanks @rspeicher. --- app/controllers/projects/issues_controller.rb | 4 +--- app/views/projects/issues/update.js.haml | 4 ++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb index 1b6ea280ad4..68244883803 100644 --- a/app/controllers/projects/issues_controller.rb +++ b/app/controllers/projects/issues_controller.rb @@ -98,9 +98,7 @@ class Projects::IssuesController < Projects::ApplicationController format.json do render json: { saved: @issue.valid?, - assignee_avatar_url: @issue.assignee.try(:avatar_url), - milestone: @issue.milestone.title, - labels: @issue.labels.pluck(:id,:title,:color) + assignee_avatar_url: @issue.assignee.try(:avatar_url) } end end diff --git a/app/views/projects/issues/update.js.haml b/app/views/projects/issues/update.js.haml index c8e79ade110..a54733883b4 100644 --- a/app/views/projects/issues/update.js.haml +++ b/app/views/projects/issues/update.js.haml @@ -1,3 +1,3 @@ -$('aside.right-sidebar')[0].outerHTML = "#{escape_javascript(render 'shared/issuable/sidebar', issuable: @issue)}"); -$('aside.right-sidebar').effect('highlight') +$('aside.right-sidebar')[0].outerHTML = "#{escape_javascript(render 'shared/issuable/sidebar', issuable: @issue)}"; +$('aside.right-sidebar').effect('highlight'); new Issue(); \ No newline at end of file -- cgit v1.2.1 From f660d8d0444fc3c953df93f66c42f9895bfe9ade Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Wed, 3 Feb 2016 16:04:48 -0500 Subject: Fixes sidebar width. --- app/assets/stylesheets/framework/variables.scss | 3 ++- app/assets/stylesheets/pages/issuable.scss | 12 +++++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss index 5e249059c29..44d3d7715d2 100644 --- a/app/assets/stylesheets/framework/variables.scss +++ b/app/assets/stylesheets/framework/variables.scss @@ -13,7 +13,8 @@ $list-font-size: 15px; $sidebar_collapsed_width: 62px; $sidebar_width: 230px; $gutter_collapsed_width: 62px; -$gutter_width: 250px; +$gutter_width: 312px; +$gutter_inner_width: 280px; $avatar_radius: 50%; $code_font_size: 13px; $code_line_height: 1.5; diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss index b10670afd40..6f71ad1f50b 100644 --- a/app/assets/stylesheets/pages/issuable.scss +++ b/app/assets/stylesheets/pages/issuable.scss @@ -74,7 +74,7 @@ border-bottom: 1px solid $border-gray-light; // This prevents the mess when resizing the sidebar // of elements repositioning themselves.. - width: 210px; + width: $gutter_inner_width; overflow-x: hidden; // -- @@ -96,7 +96,7 @@ } .gutter-toggle { - margin-left: 10px; + margin-left: 20px; border-left: 1px solid $border-gray-light; padding-left: 10px; } @@ -175,6 +175,12 @@ } } + .subscribe-button { + span { + margin-top: 0; + } + } + &.right-sidebar-collapsed { width: $sidebar_collapsed_width; padding-top: 0; @@ -211,7 +217,7 @@ } .gutter-toggle { - margin-left: -207px; + margin-left: -$gutter_inner_width + 4; } .sidebar-collapsed-icon { -- cgit v1.2.1 From ccd99efe64b546a0f5e6bd774479cde2861287ef Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 3 Feb 2016 22:48:21 +0100 Subject: Update test after changes build page css Signed-off-by: Dmitriy Zaporozhets --- features/steps/project/builds/summary.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/steps/project/builds/summary.rb b/features/steps/project/builds/summary.rb index 036bc0a499e..4bc670fdfcb 100644 --- a/features/steps/project/builds/summary.rb +++ b/features/steps/project/builds/summary.rb @@ -13,7 +13,7 @@ class Spinach::Features::ProjectBuildsSummary < Spinach::FeatureSteps end step 'I see button to CI Lint' do - page.within('.controls') do + page.within('.nav-controls') do ci_lint_tool_link = page.find_link('CI Lint') expect(ci_lint_tool_link[:href]).to eq ci_lint_path end -- cgit v1.2.1 From 47982e50c4038ed6e56b1dd28b4d4888b33460eb Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Wed, 3 Feb 2016 17:19:54 -0500 Subject: Make Pipelines responsible for defining their custom whitelist This allows for future pipelines to more easily define a custom whitelist. --- lib/banzai/filter/sanitization_filter.rb | 9 +----- lib/banzai/pipeline/description_pipeline.rb | 13 +++++++- spec/lib/banzai/filter/sanitization_filter_spec.rb | 22 ------------- .../banzai/pipeline/description_pipeline_spec.rb | 37 ++++++++++++++++++++++ 4 files changed, 50 insertions(+), 31 deletions(-) create mode 100644 spec/lib/banzai/pipeline/description_pipeline_spec.rb diff --git a/lib/banzai/filter/sanitization_filter.rb b/lib/banzai/filter/sanitization_filter.rb index d1e11eedec3..04ddfe53ed6 100644 --- a/lib/banzai/filter/sanitization_filter.rb +++ b/lib/banzai/filter/sanitization_filter.rb @@ -8,14 +8,7 @@ module Banzai # Extends HTML::Pipeline::SanitizationFilter with a custom whitelist. class SanitizationFilter < HTML::Pipeline::SanitizationFilter def whitelist - # Descriptions are more heavily sanitized, allowing only a few elements. - # See http://git.io/vkuAN - if context[:inline_sanitization] - whitelist = LIMITED - whitelist[:elements] -= %w(pre code img ol ul li) - else - whitelist = super - end + whitelist = super customize_whitelist(whitelist) diff --git a/lib/banzai/pipeline/description_pipeline.rb b/lib/banzai/pipeline/description_pipeline.rb index 20e24ace352..f2395867658 100644 --- a/lib/banzai/pipeline/description_pipeline.rb +++ b/lib/banzai/pipeline/description_pipeline.rb @@ -4,9 +4,20 @@ module Banzai def self.transform_context(context) super(context).merge( # SanitizationFilter - inline_sanitization: true + whitelist: whitelist ) end + + private + + def self.whitelist + # Descriptions are more heavily sanitized, allowing only a few elements. + # See http://git.io/vkuAN + whitelist = Banzai::Filter::SanitizationFilter::LIMITED + whitelist[:elements] -= %w(pre code img ol ul li) + + whitelist + end end end end diff --git a/spec/lib/banzai/filter/sanitization_filter_spec.rb b/spec/lib/banzai/filter/sanitization_filter_spec.rb index 9c63d227044..e14a6dbf922 100644 --- a/spec/lib/banzai/filter/sanitization_filter_spec.rb +++ b/spec/lib/banzai/filter/sanitization_filter_spec.rb @@ -177,26 +177,4 @@ describe Banzai::Filter::SanitizationFilter, lib: true do expect(act.to_html).to eq exp end end - - context 'when inline_sanitization is true' do - it 'uses a stricter whitelist' do - doc = filter('

Description

', inline_sanitization: true) - expect(doc.to_html.strip).to eq 'Description' - end - - %w(pre code img ol ul li).each do |elem| - it "removes '#{elem}' elements" do - act = "<#{elem}>Description" - expect(filter(act, inline_sanitization: true).to_html.strip). - to eq 'Description' - end - end - - %w(b i strong em a ins del sup sub p).each do |elem| - it "still allows '#{elem}' elements" do - exp = act = "<#{elem}>Description" - expect(filter(act, inline_sanitization: true).to_html).to eq exp - end - end - end end diff --git a/spec/lib/banzai/pipeline/description_pipeline_spec.rb b/spec/lib/banzai/pipeline/description_pipeline_spec.rb new file mode 100644 index 00000000000..76f42071810 --- /dev/null +++ b/spec/lib/banzai/pipeline/description_pipeline_spec.rb @@ -0,0 +1,37 @@ +require 'rails_helper' + +describe Banzai::Pipeline::DescriptionPipeline do + def parse(html) + # When we pass HTML to Redcarpet, it gets wrapped in `p` tags... + # ...except when we pass it pre-wrapped text. Rabble rabble. + unwrap = !html.start_with?('

') + + output = described_class.to_html(html, project: spy) + + output.gsub!(%r{\A

(.*)

(.*)\z}, '\1\2') if unwrap + + output + end + + it 'uses a limited whitelist' do + doc = parse('# Description') + + expect(doc.strip).to eq 'Description' + end + + %w(pre code img ol ul li).each do |elem| + it "removes '#{elem}' elements" do + act = "<#{elem}>Description" + + expect(parse(act).strip).to eq 'Description' + end + end + + %w(b i strong em a ins del sup sub p).each do |elem| + it "still allows '#{elem}' elements" do + exp = act = "<#{elem}>Description" + + expect(parse(act).strip).to eq exp + end + end +end -- cgit v1.2.1 From de6f2884eaf096ff16062aa1fb3f8e518b69c2b5 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 3 Feb 2016 23:27:00 +0100 Subject: Sort projects by last activity for project switcher in header Signed-off-by: Dmitriy Zaporozhets --- app/assets/javascripts/api.js.coffee | 3 ++- app/assets/javascripts/project_select.js.coffee | 3 ++- app/helpers/projects_helper.rb | 5 ++++- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/app/assets/javascripts/api.js.coffee b/app/assets/javascripts/api.js.coffee index 746fa3cea87..3e0fdb3f795 100644 --- a/app/assets/javascripts/api.js.coffee +++ b/app/assets/javascripts/api.js.coffee @@ -47,7 +47,7 @@ callback(namespaces) # Return projects list. Filtered by query - projects: (query, callback) -> + projects: (query, order, callback) -> url = Api.buildUrl(Api.projects_path) $.ajax( @@ -55,6 +55,7 @@ data: private_token: gon.api_token search: query + order_by: order per_page: 20 dataType: "json" ).done (projects) -> diff --git a/app/assets/javascripts/project_select.js.coffee b/app/assets/javascripts/project_select.js.coffee index 0ae274f3363..be8ab9b428d 100644 --- a/app/assets/javascripts/project_select.js.coffee +++ b/app/assets/javascripts/project_select.js.coffee @@ -3,6 +3,7 @@ class @ProjectSelect $('.ajax-project-select').each (i, select) -> @groupId = $(select).data('group-id') @includeGroups = $(select).data('include-groups') + @orderBy = $(select).data('order-by') || 'id' placeholder = "Search for project" placeholder += " or group" if @includeGroups @@ -28,7 +29,7 @@ class @ProjectSelect if @groupId Api.groupProjects @groupId, query.term, projectsCallback else - Api.projects query.term, projectsCallback + Api.projects query.term, @orderBy, projectsCallback id: (project) -> project.web_url diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index e7e472cbb5b..0aaa6774298 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -57,7 +57,10 @@ module ProjectsHelper link_output = simple_sanitize(project.name) link_output += content_tag :span, nil, { class: "fa fa-chevron-down dropdown-toggle-caret" } if current_user - link_output += project_select_tag :project_path, class: "project-item-select js-projects-dropdown", data: { include_groups: false } if current_user + if current_user + link_output += project_select_tag :project_path, class: "project-item-select js-projects-dropdown", + data: { include_groups: false, order_by: 'last_activity_at' } + end link_output end -- cgit v1.2.1 From e0efdc4bf759ed8129d12aed16e68fb7392eddc7 Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Wed, 3 Feb 2016 20:35:26 -0500 Subject: Make size changes based on screen resize. --- app/assets/javascripts/application.js.coffee | 36 ++++++++++++++++++++++++++++ app/assets/stylesheets/pages/issuable.scss | 1 + 2 files changed, 37 insertions(+) diff --git a/app/assets/javascripts/application.js.coffee b/app/assets/javascripts/application.js.coffee index be3b326075d..1abc4794f21 100644 --- a/app/assets/javascripts/application.js.coffee +++ b/app/assets/javascripts/application.js.coffee @@ -212,6 +212,13 @@ $ -> $this = $(this) $this.attr 'value', $this.val() + $(document).on 'breakpoint:change', (e, breakpoint) -> + if breakpoint is 'sm' or breakpoint is 'xs' + $gutterIcon = $('.gutter-toggle').find('i') + if $gutterIcon.hasClass('fa-angle-double-right') + $gutterIcon.closest('a').trigger('click') + + $(document).on 'click', 'aside .gutter-toggle', (e) -> e.preventDefault() $this = $(this) @@ -240,4 +247,33 @@ $ -> $('.right-sidebar') .hasClass('right-sidebar-collapsed'), { path: '/' }) + bootstrapBreakpoint = undefined; + checkBootstrapBreakpoints = -> + if $('.device-xs').is(':visible') + bootstrapBreakpoint = "xs" + else if $('.device-sm').is(':visible') + bootstrapBreakpoint = "sm" + else if $('.device-md').is(':visible') + bootstrapBreakpoint = "md" + else if $('.device-lg').is(':visible') + bootstrapBreakpoint = "lg" + + setBootstrapBreakpoints = -> + if $('.device-xs').length + return + + $("body") + .append('
'+ + '
'+ + '
'+ + '
') + checkBootstrapBreakpoints() + + $(window).on "resize", (e) -> + oldBootstrapBreakpoint = bootstrapBreakpoint + checkBootstrapBreakpoints() + if bootstrapBreakpoint != oldBootstrapBreakpoint + $(document).trigger('breakpoint:change',[bootstrapBreakpoint]) + + setBootstrapBreakpoints() new Aside() diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss index 6f71ad1f50b..3bfbd9e17b7 100644 --- a/app/assets/stylesheets/pages/issuable.scss +++ b/app/assets/stylesheets/pages/issuable.scss @@ -184,6 +184,7 @@ &.right-sidebar-collapsed { width: $sidebar_collapsed_width; padding-top: 0; + overflow-x: hidden; hr { margin: 0; -- cgit v1.2.1 From 9f8acf8a8378741d00ed1f665c0f5f692057ac8d Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 4 Feb 2016 09:57:17 +0100 Subject: Satisfy rubocop Signed-off-by: Dmitriy Zaporozhets --- app/helpers/projects_helper.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 0aaa6774298..dc487a31d97 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -58,7 +58,8 @@ module ProjectsHelper link_output += content_tag :span, nil, { class: "fa fa-chevron-down dropdown-toggle-caret" } if current_user if current_user - link_output += project_select_tag :project_path, class: "project-item-select js-projects-dropdown", + link_output += project_select_tag :project_path, + class: "project-item-select js-projects-dropdown", data: { include_groups: false, order_by: 'last_activity_at' } end -- cgit v1.2.1 From 020623f3bbdb25c07e31985f0fe072988ba0eff2 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Tue, 2 Feb 2016 15:51:48 +0100 Subject: Improve CI API specs related to operations on build Conflicts: spec/factories/ci/builds.rb --- spec/factories/ci/builds.rb | 15 ++++++++++ spec/requests/ci/api/builds_spec.rb | 55 +++++++++++++++++++++++-------------- 2 files changed, 49 insertions(+), 21 deletions(-) diff --git a/spec/factories/ci/builds.rb b/spec/factories/ci/builds.rb index d2db77f6286..f0ae3a18561 100644 --- a/spec/factories/ci/builds.rb +++ b/spec/factories/ci/builds.rb @@ -65,5 +65,20 @@ FactoryGirl.define do build.trace = 'BUILD TRACE' end end + + trait :artifacts do + after(:create) do |build, _| + build.artifacts_file = + fixture_file_upload(Rails.root + + 'spec/fixtures/ci_build_artifacts.zip', + 'application/zip') + + build.artifacts_metadata = + fixture_file_upload(Rails.root + + 'spec/fixtures/ci_build_artifacts_metadata.gz', + 'application/x-gzip') + build.save! + end + end end end diff --git a/spec/requests/ci/api/builds_spec.rb b/spec/requests/ci/api/builds_spec.rb index 244947762dd..e1b6f981538 100644 --- a/spec/requests/ci/api/builds_spec.rb +++ b/spec/requests/ci/api/builds_spec.rb @@ -151,8 +151,8 @@ describe Ci::API::API do context "Artifacts" do let(:file_upload) { fixture_file_upload(Rails.root + 'spec/fixtures/banana_sample.gif', 'image/gif') } let(:file_upload2) { fixture_file_upload(Rails.root + 'spec/fixtures/dk.png', 'image/gif') } - let(:commit) { FactoryGirl.create(:ci_commit, project: project) } - let(:build) { FactoryGirl.create(:ci_build, commit: commit, runner_id: runner.id) } + let(:commit) { create(:ci_commit, project: project) } + let(:build) { create(:ci_build, commit: commit, runner_id: runner.id) } let(:authorize_url) { ci_api("/builds/#{build.id}/artifacts/authorize") } let(:post_url) { ci_api("/builds/#{build.id}/artifacts") } let(:delete_url) { ci_api("/builds/#{build.id}/artifacts") } @@ -349,33 +349,46 @@ describe Ci::API::API do end end - describe "DELETE /builds/:id/artifacts" do - before do - build.run! - post delete_url, token: build.token, file: file_upload - end + describe 'DELETE /builds/:id/artifacts' do + let(:build) { create(:ci_build, :artifacts) } + before { delete delete_url, token: build.token } - it "should delete artifact build" do - build.success - delete delete_url, token: build.token + it 'should respond valid status' do expect(response.status).to eq(200) end - end - describe "GET /builds/:id/artifacts" do - before do - build.run! + it 'should remove artifacts file' do + expect(build.artifacts_file.exists?).to be_falsy end - it "should download artifact" do - build.update_attributes(artifacts_file: file_upload) - get get_url, token: build.token - expect(response.status).to eq(200) + it 'should remove artifacts metadata' do + expect(build.artifacts_metadata.exists?).to be_falsy + end + end + + describe 'GET /builds/:id/artifacts' do + before { get get_url, token: build.token } + + context 'build has artifacts' do + let(:build) { create(:ci_build, :artifacts) } + let(:download_headers) do + { 'Content-Transfer-Encoding'=>'binary', + 'Content-Disposition'=>'attachment; filename=ci_build_artifacts.zip' } + end + + it 'should respond with valid status' do + expect(response.status).to eq(200) + end + + it 'should download artifact' do + expect(response.headers).to include download_headers + end end - it "should fail to download if no artifact uploaded" do - get get_url, token: build.token - expect(response.status).to eq(404) + context 'build does not has artifacts' do + it 'should respond with not found' do + expect(response.status).to eq(404) + end end end end -- cgit v1.2.1 From 53c917a6c6b410dbc56c75f3282ced8f95829d57 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Thu, 4 Feb 2016 10:16:21 +0100 Subject: Remove unmaintainable db schema comment from build factory --- spec/factories/ci/builds.rb | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/spec/factories/ci/builds.rb b/spec/factories/ci/builds.rb index f0ae3a18561..c1b6ecd329a 100644 --- a/spec/factories/ci/builds.rb +++ b/spec/factories/ci/builds.rb @@ -1,30 +1,3 @@ -# == Schema Information -# -# Table name: builds -# -# id :integer not null, primary key -# project_id :integer -# status :string(255) -# finished_at :datetime -# trace :text -# created_at :datetime -# updated_at :datetime -# started_at :datetime -# runner_id :integer -# commit_id :integer -# coverage :float -# commands :text -# job_id :integer -# name :string(255) -# deploy :boolean default(FALSE) -# options :text -# allow_failure :boolean default(FALSE), not null -# stage :string(255) -# trigger_request_id :integer -# - -# Read about factories at https://github.com/thoughtbot/factory_girl - FactoryGirl.define do factory :ci_build, class: Ci::Build do name 'test' -- cgit v1.2.1 From bf6d69483725a99d20a88479e469f55567c7b9fd Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Thu, 4 Feb 2016 10:24:14 +0100 Subject: Extract shared context level up in build specs Also improve performance of specs by joining some of examples. --- spec/requests/ci/api/builds_spec.rb | 73 +++++++++---------------------------- 1 file changed, 17 insertions(+), 56 deletions(-) diff --git a/spec/requests/ci/api/builds_spec.rb b/spec/requests/ci/api/builds_spec.rb index e1b6f981538..01b369720ca 100644 --- a/spec/requests/ci/api/builds_spec.rb +++ b/spec/requests/ci/api/builds_spec.rb @@ -160,12 +160,10 @@ describe Ci::API::API do let(:headers) { { "GitLab-Workhorse" => "1.0" } } let(:headers_with_token) { headers.merge(Ci::API::Helpers::BUILD_TOKEN_HEADER => build.token) } + before { build.run! } + describe "POST /builds/:id/artifacts/authorize" do context "should authorize posting artifact to running build" do - before do - build.run! - end - it "using token as parameter" do post authorize_url, { token: build.token }, headers expect(response.status).to eq(200) @@ -180,10 +178,6 @@ describe Ci::API::API do end context "should fail to post too large artifact" do - before do - build.run! - end - it "using token as parameter" do stub_application_setting(max_artifacts_size: 0) post authorize_url, { token: build.token, filesize: 100 }, headers @@ -197,8 +191,8 @@ describe Ci::API::API do end end - context "should get denied" do - it do + context 'token is invalid' do + it 'should respond with forbidden'do post authorize_url, { token: 'invalid', filesize: 100 } expect(response.status).to eq(403) end @@ -206,17 +200,13 @@ describe Ci::API::API do end describe "POST /builds/:id/artifacts" do - context "Disable sanitizer" do + context "disable sanitizer" do before do # by configuring this path we allow to pass temp file from any path allow(ArtifactUploader).to receive(:artifacts_upload_path).and_return('/') end context "should post artifact to running build" do - before do - build.run! - end - it "uses regual file post" do upload_artifacts(file_upload, headers_with_token, false) expect(response.status).to eq(201) @@ -244,10 +234,7 @@ describe Ci::API::API do let(:stored_artifacts_file) { build.reload.artifacts_file.file } let(:stored_metadata_file) { build.reload.artifacts_metadata.file } - before do - build.run! - post(post_url, post_data, headers_with_token) - end + before { post(post_url, post_data, headers_with_token) } context 'post data accelerated by workhorse is correct' do let(:post_data) do @@ -257,11 +244,8 @@ describe Ci::API::API do 'metadata.name' => metadata.original_filename } end - it 'responds with valid status' do - expect(response.status).to eq(201) - end - it 'stores artifacts and artifacts metadata' do + expect(response.status).to eq(201) expect(stored_artifacts_file.original_filename).to eq(artifacts.original_filename) expect(stored_metadata_file.original_filename).to eq(metadata.original_filename) end @@ -282,56 +266,42 @@ describe Ci::API::API do end end - - context "should fail to post too large artifact" do - before do - build.run! - end - - it do + context "artifacts file is too large" do + it "should fail to post too large artifact" do stub_application_setting(max_artifacts_size: 0) upload_artifacts(file_upload, headers_with_token) expect(response.status).to eq(413) end end - context "should fail to post artifacts without file" do - before do - build.run! - end - - it do + context "artifacts post request does not contain file" do + it "should fail to post artifacts without file" do post post_url, {}, headers_with_token expect(response.status).to eq(400) end end - context "should fail to post artifacts without GitLab-Workhorse" do - before do - build.run! - end - - it do + context 'GitLab Workhorse is not configured' do + it "should fail to post artifacts without GitLab-Workhorse" do post post_url, { token: build.token }, {} expect(response.status).to eq(403) end end end - context "should fail to post artifacts for outside of tmp path" do + context "artifacts are being stored outside of tmp path" do before do # by configuring this path we allow to pass file from @tmpdir only # but all temporary files are stored in system tmp directory @tmpdir = Dir.mktmpdir allow(ArtifactUploader).to receive(:artifacts_upload_path).and_return(@tmpdir) - build.run! end after do FileUtils.remove_entry @tmpdir end - it do + it "should fail to post artifacts for outside of tmp path" do upload_artifacts(file_upload, headers_with_token) expect(response.status).to eq(400) end @@ -353,15 +323,9 @@ describe Ci::API::API do let(:build) { create(:ci_build, :artifacts) } before { delete delete_url, token: build.token } - it 'should respond valid status' do + it 'should remove build artifacts' do expect(response.status).to eq(200) - end - - it 'should remove artifacts file' do expect(build.artifacts_file.exists?).to be_falsy - end - - it 'should remove artifacts metadata' do expect(build.artifacts_metadata.exists?).to be_falsy end end @@ -376,11 +340,8 @@ describe Ci::API::API do 'Content-Disposition'=>'attachment; filename=ci_build_artifacts.zip' } end - it 'should respond with valid status' do - expect(response.status).to eq(200) - end - it 'should download artifact' do + expect(response.status).to eq(200) expect(response.headers).to include download_headers end end -- cgit v1.2.1 From 5f7be11aa6d5d9edc31baa09b50ac21ee80533aa Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Thu, 4 Feb 2016 11:09:42 +0100 Subject: Simplify abilities --- app/models/ability.rb | 39 +++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/app/models/ability.rb b/app/models/ability.rb index bf24749b173..e1767ed8dd1 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -5,10 +5,9 @@ class Ability return [] unless user.is_a?(User) return [] if user.blocked? + # We check with `is_a?`, because CommitStatus uses inheritance if subject.is_a?(CommitStatus) - rules = project_abilities(user, subject) - rules = filter_build_abilities(rules) if subject.is_a?(Ci::Build) - return rules + return commit_status_abilities(user, subject) end case subject.class.name @@ -32,9 +31,7 @@ class Ability when subject.is_a?(PersonalSnippet) anonymous_personal_snippet_abilities(subject) when subject.is_a?(CommitStatus) - rules = anonymous_project_abilities(subject) - rules = filter_build_abilities(rules) if subject.is_a?(Ci::Build) - rules + anonymous_commit_status_abilities(subject) when subject.is_a?(Project) || subject.respond_to?(:project) anonymous_project_abilities(subject) when subject.is_a?(Group) || subject.respond_to?(:group) @@ -66,9 +63,8 @@ class Ability :download_code ] - if project.allow_guest_to_access_builds? - rules << :read_build - end + # Allow to read builds by anonymous user if guests are allowed + rules << :read_build if project.allow_guest_to_access_builds? rules - project_disabled_features_rules(project) else @@ -76,6 +72,13 @@ class Ability end end + def anonymous_commit_status_abilities(subject) + rules = anonymous_project_abilities(subject.project) + # If subject is Ci::Build which inherits from CommitStatus filter the abilities + rules = filter_build_abilities(rules) if subject.is_a?(Ci::Build) + rules + end + def anonymous_group_abilities(subject) group = if subject.is_a?(Group) subject @@ -123,18 +126,15 @@ class Ability elsif team.guest?(user) rules.push(*project_guest_rules) - - if project.allow_guest_to_access_builds? - rules << :read_build - end end if project.public? || project.internal? rules.push(*public_project_rules) + end - if project.allow_guest_to_access_builds? - rules << :read_build - end + # Allow to read builds if guests are allowed + if team.guest?(user) || project.public? || project.internal? + rules << :read_build if project.allow_guest_to_access_builds? end if project.owner == user || user.admin? @@ -406,6 +406,13 @@ class Ability rules end + def commit_status_abilities(user, subject) + rules = project_abilities(user, subject.project) + # If subject is Ci::Build which inherits from CommitStatus filter the abilities + rules = filter_build_abilities(rules) if subject.is_a?(Ci::Build) + rules + end + def filter_build_abilities(rules) # If we can't read build we should also not have that # ability when looking at this in context of commit_status -- cgit v1.2.1 From 6a5a175d9fd1d72cdaab033eefc4191561e619cc Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Thu, 4 Feb 2016 11:14:12 +0100 Subject: Expose allow_guest_to_access_builds in GitLab API --- doc/api/projects.md | 10 ++++++++-- lib/api/entities.rb | 1 + lib/api/projects.rb | 12 +++++++++--- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/doc/api/projects.md b/doc/api/projects.md index 3f372c955d2..873927f0e74 100644 --- a/doc/api/projects.md +++ b/doc/api/projects.md @@ -80,7 +80,9 @@ Parameters: "avatar_url": "http://example.com/uploads/project/avatar/4/uploads/avatar.png", "shared_runners_enabled": true, "forks_count": 0, - "star_count": 0 + "star_count": 0, + "runners_token": "b8547b1dc37721d05889db52fa2f02", + "allow_guest_to_access_builds": true }, { "id": 6, @@ -137,7 +139,8 @@ Parameters: "shared_runners_enabled": true, "forks_count": 0, "star_count": 0, - "runners_token": "b8547b1dc37721d05889db52fa2f02" + "runners_token": "b8547b1dc37721d05889db52fa2f02", + "allow_guest_to_access_builds": true } ] ``` @@ -424,6 +427,7 @@ Parameters: - `public` (optional) - if `true` same as setting visibility_level = 20 - `visibility_level` (optional) - `import_url` (optional) +- `allow_guest_to_access_builds` (optional) ### Create project for user @@ -446,6 +450,7 @@ Parameters: - `public` (optional) - if `true` same as setting visibility_level = 20 - `visibility_level` (optional) - `import_url` (optional) +- `allow_guest_to_access_builds` (optional) ### Edit project @@ -469,6 +474,7 @@ Parameters: - `snippets_enabled` (optional) - `public` (optional) - if `true` same as setting visibility_level = 20 - `visibility_level` (optional) +- `allow_guest_to_access_builds` (optional) On success, method returns 200 with the updated project. If parameters are invalid, 400 is returned. diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 82a75734de0..3a68b2c7801 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -72,6 +72,7 @@ module API expose :star_count, :forks_count expose :open_issues_count, if: lambda { |project, options| project.issues_enabled? && project.default_issues_tracker? } expose :runners_token, if: lambda { |_project, options| options[:user_can_admin_project] } + expose :allow_guest_to_access_builds end class ProjectMember < UserBasic diff --git a/lib/api/projects.rb b/lib/api/projects.rb index 1f991e600e3..f68598e991b 100644 --- a/lib/api/projects.rb +++ b/lib/api/projects.rb @@ -99,6 +99,7 @@ module API # public (optional) - if true same as setting visibility_level = 20 # visibility_level (optional) - 0 by default # import_url (optional) + # allow_guest_to_access_builds (optional) # Example Request # POST /projects post do @@ -115,7 +116,8 @@ module API :namespace_id, :public, :visibility_level, - :import_url] + :import_url, + :allow_guest_to_access_builds] attrs = map_public_to_visibility_level(attrs) @project = ::Projects::CreateService.new(current_user, attrs).execute if @project.saved? @@ -145,6 +147,7 @@ module API # public (optional) - if true same as setting visibility_level = 20 # visibility_level (optional) # import_url (optional) + # allow_guest_to_access_builds (optional) # Example Request # POST /projects/user/:user_id post "user/:user_id" do @@ -161,7 +164,8 @@ module API :shared_runners_enabled, :public, :visibility_level, - :import_url] + :import_url, + :allow_guest_to_access_builds] attrs = map_public_to_visibility_level(attrs) @project = ::Projects::CreateService.new(user, attrs).execute if @project.saved? @@ -205,6 +209,7 @@ module API # shared_runners_enabled (optional) # public (optional) - if true same as setting visibility_level = 20 # visibility_level (optional) - visibility level of a project + # allow_guest_to_access_builds (optional) # Example Request # PUT /projects/:id put ':id' do @@ -219,7 +224,8 @@ module API :snippets_enabled, :shared_runners_enabled, :public, - :visibility_level] + :visibility_level, + :allow_guest_to_access_builds] attrs = map_public_to_visibility_level(attrs) authorize_admin_project authorize! :rename_project, user_project if attrs[:name].present? -- cgit v1.2.1 From c6e0228ca9937b10ad8e2620501d4fe221108d9a Mon Sep 17 00:00:00 2001 From: Zeger-Jan van de Weg Date: Thu, 4 Feb 2016 11:51:12 +0100 Subject: Hide remove source branch button when new commit is added to branch Fixes #3339 This MR hides the 'Remove source branch' button when a new commit is added to the source branch --- CHANGELOG | 1 + app/models/merge_request.rb | 3 ++- spec/models/merge_request_spec.rb | 8 +++++++- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 481a0f8d243..a3c3fb67b19 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -28,6 +28,7 @@ v 8.5.0 (unreleased) - Support Akismet spam checking for creation of issues via API (Stan Hu) - Improve UI consistency between projects and groups lists - Add sort dropdown to dashboard projects page + - Hide remove source branch button when the MR is merged but new commits are pushed (Zeger-Jan van de Weg) v 8.4.3 - Increase lfs_objects size column to 8-byte integer to allow files larger diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 89b6c49b362..00362352508 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -284,7 +284,8 @@ class MergeRequest < ActiveRecord::Base def can_remove_source_branch?(current_user) !source_project.protected_branch?(source_branch) && !source_project.root_ref?(source_branch) && - Ability.abilities.allowed?(current_user, :push_code, source_project) + Ability.abilities.allowed?(current_user, :push_code, source_project) && + last_commit == source_project.commit(source_branch) end def mr_and_commit_notes diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index 46f2f20b986..f9d0e1029d6 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -226,9 +226,15 @@ describe MergeRequest, models: true do expect(subject.can_remove_source_branch?(user2)).to be_falsey end - it "is can be removed in all other cases" do + it "can be removed if the last commit is the head of the source branch" do + allow(subject.source_project).to receive(:commit).and_return(subject.last_commit) + expect(subject.can_remove_source_branch?(user)).to be_truthy end + + it "cannot be removed if the last commit is not also the head of the source branch" do + expect(subject.can_remove_source_branch?(user)).to be_falsey + end end describe "#reset_merge_when_build_succeeds" do -- cgit v1.2.1 From ff5f0894adbabc9a70cb93af9126d8fc19c13d0b Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 4 Feb 2016 12:23:44 +0100 Subject: Sort projects by last activity for new issue dropdown When creating new issue from dashboard page I want to see projects sorted by last activity instead of ID Signed-off-by: Dmitriy Zaporozhets --- app/views/shared/_new_project_item_select.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/shared/_new_project_item_select.html.haml b/app/views/shared/_new_project_item_select.html.haml index 46095912821..1c58345278a 100644 --- a/app/views/shared/_new_project_item_select.html.haml +++ b/app/views/shared/_new_project_item_select.html.haml @@ -1,6 +1,6 @@ - if @projects.any? .prepend-left-10.project-item-select-holder - = project_select_tag :project_path, class: "project-item-select", data: { include_groups: local_assigns[:include_groups] } + = project_select_tag :project_path, class: "project-item-select", data: { include_groups: local_assigns[:include_groups], order_by: 'last_activity_at' } %a.btn.btn-new.new-project-item-select-button = icon('plus') = local_assigns[:label] -- cgit v1.2.1 From 70e44d63f7f1af81ddb0527e3a084c6ab692ea58 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 4 Feb 2016 12:38:25 +0100 Subject: In search autocomplete show only groups and projects you are member of For big instances search autocomplet is flooded with groups you have no access to and insternal/public projects you don't care. It affects way how easily you can go to group/project you are actually member of Signed-off-by: Dmitriy Zaporozhets --- CHANGELOG | 1 + app/helpers/search_helper.rb | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index fc123b22b11..3f457b3fea8 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -28,6 +28,7 @@ v 8.5.0 (unreleased) - Support Akismet spam checking for creation of issues via API (Stan Hu) - Improve UI consistency between projects and groups lists - Add sort dropdown to dashboard projects page + - In seach autocomplete show only groups and projects you are member of v 8.4.3 - Increase lfs_objects size column to 8-byte integer to allow files larger diff --git a/app/helpers/search_helper.rb b/app/helpers/search_helper.rb index d4f78258626..1eb790b1796 100644 --- a/app/helpers/search_helper.rb +++ b/app/helpers/search_helper.rb @@ -70,7 +70,7 @@ module SearchHelper # Autocomplete results for the current user's groups def groups_autocomplete(term, limit = 5) - Group.search(term).limit(limit).map do |group| + current_user.authorized_groups.search(term).limit(limit).map do |group| { label: "group: #{search_result_sanitize(group.name)}", url: group_path(group) @@ -80,7 +80,7 @@ module SearchHelper # Autocomplete results for the current user's projects def projects_autocomplete(term, limit = 5) - ProjectsFinder.new.execute(current_user).search_by_title(term). + current_user.authorized_projects.search_by_title(term). sorted_by_stars.non_archived.limit(limit).map do |p| { label: "project: #{search_result_sanitize(p.name_with_namespace)}", -- cgit v1.2.1 From b4c36130cc285ac25caef842040e44898eaf858d Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Thu, 4 Feb 2016 12:57:46 +0100 Subject: Rename allow_guest_to_access_builds to public_builds --- app/controllers/projects_controller.rb | 2 +- app/models/ability.rb | 10 +- app/views/projects/edit.html.haml | 8 +- ...642_add_allow_guest_to_access_builds_project.rb | 2 +- db/schema.rb | 34 ++--- doc/api/projects.md | 10 +- features/steps/shared/project.rb | 8 ++ lib/api/entities.rb | 4 +- lib/api/projects.rb | 12 +- spec/features/builds_spec.rb | 2 +- spec/features/commits_spec.rb | 152 +++++++++++++-------- .../security/project/public_access_spec.rb | 54 ++++++++ 12 files changed, 202 insertions(+), 96 deletions(-) diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 153e7caaae3..14ca7426c2f 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -227,7 +227,7 @@ class ProjectsController < ApplicationController :issues_enabled, :merge_requests_enabled, :snippets_enabled, :issues_tracker_id, :default_branch, :wiki_enabled, :visibility_level, :import_url, :last_activity_at, :namespace_id, :avatar, :builds_enabled, :build_allow_git_fetch, :build_timeout_in_minutes, :build_coverage_regex, - :allow_guest_to_access_builds, + :public_builds, ) end diff --git a/app/models/ability.rb b/app/models/ability.rb index e1767ed8dd1..a6862f83158 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -64,7 +64,7 @@ class Ability ] # Allow to read builds by anonymous user if guests are allowed - rules << :read_build if project.allow_guest_to_access_builds? + rules << :read_build if project.public_builds? rules - project_disabled_features_rules(project) else @@ -132,9 +132,9 @@ class Ability rules.push(*public_project_rules) end - # Allow to read builds if guests are allowed - if team.guest?(user) || project.public? || project.internal? - rules << :read_build if project.allow_guest_to_access_builds? + # Allow to read builds for internal projects + if project.public? || project.internal? + rules << :read_build if project.public_builds? end if project.owner == user || user.admin? @@ -172,7 +172,6 @@ class Ability :read_project_member, :read_merge_request, :read_note, - :read_commit_status, :create_project, :create_issue, :create_note @@ -187,6 +186,7 @@ class Ability :update_issue, :admin_issue, :admin_label, + :read_commit_status, :read_build, ] end diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml index fd61ce6a99a..fdcb6987471 100644 --- a/app/views/projects/edit.html.haml +++ b/app/views/projects/edit.html.haml @@ -162,10 +162,10 @@ .form-group .col-sm-offset-2.col-sm-10 .checkbox - = f.label :allow_guest_to_access_builds do - = f.check_box :allow_guest_to_access_builds - %strong Guests can see builds - .help-block Allow guests and anonymous users to access builds including build trace and artifacts + = f.label :public_builds do + = f.check_box :public_builds + %strong Public builds + .help-block Allow everyone to access builds for Public and Internal projects %fieldset.features %legend diff --git a/db/migrate/20160202164642_add_allow_guest_to_access_builds_project.rb b/db/migrate/20160202164642_add_allow_guest_to_access_builds_project.rb index 69ce8d08bba..793984343b4 100644 --- a/db/migrate/20160202164642_add_allow_guest_to_access_builds_project.rb +++ b/db/migrate/20160202164642_add_allow_guest_to_access_builds_project.rb @@ -1,5 +1,5 @@ class AddAllowGuestToAccessBuildsProject < ActiveRecord::Migration def change - add_column :projects, :allow_guest_to_access_builds, :boolean, default: true, null: false + add_column :projects, :public_builds, :boolean, default: true, null: false end end diff --git a/db/schema.rb b/db/schema.rb index a04e812ae22..4669a777103 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -650,35 +650,35 @@ ActiveRecord::Schema.define(version: 20160202164642) do t.datetime "created_at" t.datetime "updated_at" t.integer "creator_id" - t.boolean "issues_enabled", default: true, null: false - t.boolean "wall_enabled", default: true, null: false - t.boolean "merge_requests_enabled", default: true, null: false - t.boolean "wiki_enabled", default: true, null: false + t.boolean "issues_enabled", default: true, null: false + t.boolean "wall_enabled", default: true, null: false + t.boolean "merge_requests_enabled", default: true, null: false + t.boolean "wiki_enabled", default: true, null: false t.integer "namespace_id" - t.string "issues_tracker", default: "gitlab", null: false + t.string "issues_tracker", default: "gitlab", null: false t.string "issues_tracker_id" - t.boolean "snippets_enabled", default: true, null: false + t.boolean "snippets_enabled", default: true, null: false t.datetime "last_activity_at" t.string "import_url" - t.integer "visibility_level", default: 0, null: false - t.boolean "archived", default: false, null: false + t.integer "visibility_level", default: 0, null: false + t.boolean "archived", default: false, null: false t.string "avatar" t.string "import_status" - t.float "repository_size", default: 0.0 - t.integer "star_count", default: 0, null: false + t.float "repository_size", default: 0.0 + t.integer "star_count", default: 0, null: false t.string "import_type" t.string "import_source" - t.integer "commit_count", default: 0 + t.integer "commit_count", default: 0 t.text "import_error" t.integer "ci_id" - t.boolean "builds_enabled", default: true, null: false - t.boolean "shared_runners_enabled", default: true, null: false + t.boolean "builds_enabled", default: true, null: false + t.boolean "shared_runners_enabled", default: true, null: false t.string "runners_token" t.string "build_coverage_regex" - t.boolean "build_allow_git_fetch", default: true, null: false - t.integer "build_timeout", default: 3600, null: false - t.boolean "pending_delete", default: false - t.boolean "allow_guest_to_access_builds", default: true, null: false + t.boolean "build_allow_git_fetch", default: true, null: false + t.integer "build_timeout", default: 3600, null: false + t.boolean "pending_delete", default: false + t.boolean "public_builds", default: true, null: false end add_index "projects", ["builds_enabled", "shared_runners_enabled"], name: "index_projects_on_builds_enabled_and_shared_runners_enabled", using: :btree diff --git a/doc/api/projects.md b/doc/api/projects.md index 873927f0e74..9e9486cd87a 100644 --- a/doc/api/projects.md +++ b/doc/api/projects.md @@ -82,7 +82,7 @@ Parameters: "forks_count": 0, "star_count": 0, "runners_token": "b8547b1dc37721d05889db52fa2f02", - "allow_guest_to_access_builds": true + "public_builds": true }, { "id": 6, @@ -140,7 +140,7 @@ Parameters: "forks_count": 0, "star_count": 0, "runners_token": "b8547b1dc37721d05889db52fa2f02", - "allow_guest_to_access_builds": true + "public_builds": true } ] ``` @@ -427,7 +427,7 @@ Parameters: - `public` (optional) - if `true` same as setting visibility_level = 20 - `visibility_level` (optional) - `import_url` (optional) -- `allow_guest_to_access_builds` (optional) +- `public_builds` (optional) ### Create project for user @@ -450,7 +450,7 @@ Parameters: - `public` (optional) - if `true` same as setting visibility_level = 20 - `visibility_level` (optional) - `import_url` (optional) -- `allow_guest_to_access_builds` (optional) +- `public_builds` (optional) ### Edit project @@ -474,7 +474,7 @@ Parameters: - `snippets_enabled` (optional) - `public` (optional) - if `true` same as setting visibility_level = 20 - `visibility_level` (optional) -- `allow_guest_to_access_builds` (optional) +- `public_builds` (optional) On success, method returns 200 with the updated project. If parameters are invalid, 400 is returned. diff --git a/features/steps/shared/project.rb b/features/steps/shared/project.rb index d9c75d12238..1200eb319d7 100644 --- a/features/steps/shared/project.rb +++ b/features/steps/shared/project.rb @@ -240,6 +240,14 @@ module SharedProject end end + step 'public access for builds is enabled' do + @project.update(public_builds: true) + end + + step 'public access for builds is disabled' do + @project.update(public_builds: false) + end + def user_owns_project(user_name:, project_name:, visibility: :private) user = user_exists(user_name, username: user_name.gsub(/\s/, '').underscore) project = Project.find_by(name: project_name) diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 3a68b2c7801..1aa6570bd06 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -72,7 +72,7 @@ module API expose :star_count, :forks_count expose :open_issues_count, if: lambda { |project, options| project.issues_enabled? && project.default_issues_tracker? } expose :runners_token, if: lambda { |_project, options| options[:user_can_admin_project] } - expose :allow_guest_to_access_builds + expose :public_builds end class ProjectMember < UserBasic @@ -384,7 +384,7 @@ module API # for downloading of artifacts (see: https://gitlab.com/gitlab-org/gitlab-ce/issues/4255) expose :download_url do |repo_obj, options| if options[:user_can_download_artifacts] - repo_obj.download_url + repo_obj.artifacts_download_url end end expose :commit, with: RepoCommit do |repo_obj, _options| diff --git a/lib/api/projects.rb b/lib/api/projects.rb index f68598e991b..6067c8b4a5e 100644 --- a/lib/api/projects.rb +++ b/lib/api/projects.rb @@ -99,7 +99,7 @@ module API # public (optional) - if true same as setting visibility_level = 20 # visibility_level (optional) - 0 by default # import_url (optional) - # allow_guest_to_access_builds (optional) + # public_builds (optional) # Example Request # POST /projects post do @@ -117,7 +117,7 @@ module API :public, :visibility_level, :import_url, - :allow_guest_to_access_builds] + :public_builds] attrs = map_public_to_visibility_level(attrs) @project = ::Projects::CreateService.new(current_user, attrs).execute if @project.saved? @@ -147,7 +147,7 @@ module API # public (optional) - if true same as setting visibility_level = 20 # visibility_level (optional) # import_url (optional) - # allow_guest_to_access_builds (optional) + # public_builds (optional) # Example Request # POST /projects/user/:user_id post "user/:user_id" do @@ -165,7 +165,7 @@ module API :public, :visibility_level, :import_url, - :allow_guest_to_access_builds] + :public_builds] attrs = map_public_to_visibility_level(attrs) @project = ::Projects::CreateService.new(user, attrs).execute if @project.saved? @@ -209,7 +209,7 @@ module API # shared_runners_enabled (optional) # public (optional) - if true same as setting visibility_level = 20 # visibility_level (optional) - visibility level of a project - # allow_guest_to_access_builds (optional) + # public_builds (optional) # Example Request # PUT /projects/:id put ':id' do @@ -225,7 +225,7 @@ module API :shared_runners_enabled, :public, :visibility_level, - :allow_guest_to_access_builds] + :public_builds] attrs = map_public_to_visibility_level(attrs) authorize_admin_project authorize! :rename_project, user_project if attrs[:name].present? diff --git a/spec/features/builds_spec.rb b/spec/features/builds_spec.rb index d37bd103714..22e38151bd8 100644 --- a/spec/features/builds_spec.rb +++ b/spec/features/builds_spec.rb @@ -8,7 +8,7 @@ describe "Builds" do @commit = FactoryGirl.create :ci_commit @build = FactoryGirl.create :ci_build, commit: @commit @project = @commit.project - @project.team << [@user, :master] + @project.team << [@user, :developer] end describe "GET /:project/builds" do diff --git a/spec/features/commits_spec.rb b/spec/features/commits_spec.rb index 5a62da10619..dacaa96d760 100644 --- a/spec/features/commits_spec.rb +++ b/spec/features/commits_spec.rb @@ -8,7 +8,6 @@ describe 'Commits' do describe 'CI' do before do login_as :user - project.team << [@user, :master] stub_ci_commit_to_return_yaml_file end @@ -19,6 +18,10 @@ describe 'Commits' do context 'commit status is Generic Commit Status' do let!(:status) { FactoryGirl.create :generic_commit_status, commit: commit } + before do + project.team << [@user, :reporter] + end + describe 'Commit builds' do before do visit ci_status_path(commit) @@ -37,85 +40,126 @@ describe 'Commits' do context 'commit status is Ci Build' do let!(:build) { FactoryGirl.create :ci_build, commit: commit } + let(:artifacts_file) { fixture_file_upload(Rails.root + 'spec/fixtures/banana_sample.gif', 'image/gif') } - describe 'Project commits' do + context 'when logged as developer' do before do - visit namespace_project_commits_path(project.namespace, project, :master) + project.team << [@user, :developer] end - it 'should show build status' do - page.within("//li[@id='commit-#{commit.short_sha}']") do - expect(page).to have_css(".ci-status-link") + describe 'Project commits' do + before do + visit namespace_project_commits_path(project.namespace, project, :master) end - end - end - describe 'Commit builds' do - before do - visit ci_status_path(commit) + it 'should show build status' do + page.within("//li[@id='commit-#{commit.short_sha}']") do + expect(page).to have_css(".ci-status-link") + end + end end - it { expect(page).to have_content commit.sha[0..7] } - it { expect(page).to have_content commit.git_commit_message } - it { expect(page).to have_content commit.git_author_name } - end - - context 'Download artifacts' do - let(:artifacts_file) { fixture_file_upload(Rails.root + 'spec/fixtures/banana_sample.gif', 'image/gif') } - - before do - build.update_attributes(artifacts_file: artifacts_file) - end + describe 'Commit builds' do + before do + visit ci_status_path(commit) + end - it do - visit ci_status_path(commit) - click_on 'Download artifacts' - expect(page.response_headers['Content-Type']).to eq(artifacts_file.content_type) + it { expect(page).to have_content commit.sha[0..7] } + it { expect(page).to have_content commit.git_commit_message } + it { expect(page).to have_content commit.git_author_name } end - end - describe 'Cancel all builds' do - it 'cancels commit' do - visit ci_status_path(commit) - click_on 'Cancel running' - expect(page).to have_content 'canceled' - end - end + context 'Download artifacts' do + before do + build.update_attributes(artifacts_file: artifacts_file) + end - describe 'Cancel build' do - it 'cancels build' do - visit ci_status_path(commit) - click_on 'Cancel' - expect(page).to have_content 'canceled' + it do + visit ci_status_path(commit) + click_on 'Download artifacts' + expect(page.response_headers['Content-Type']).to eq(artifacts_file.content_type) + end end - end - describe '.gitlab-ci.yml not found warning' do - context 'ci builds enabled' do - it "does not show warning" do + describe 'Cancel all builds' do + it 'cancels commit' do visit ci_status_path(commit) - expect(page).not_to have_content '.gitlab-ci.yml not found in this commit' + click_on 'Cancel running' + expect(page).to have_content 'canceled' end + end - it 'shows warning' do - stub_ci_commit_yaml_file(nil) + describe 'Cancel build' do + it 'cancels build' do visit ci_status_path(commit) - expect(page).to have_content '.gitlab-ci.yml not found in this commit' + click_on 'Cancel' + expect(page).to have_content 'canceled' end end - context 'ci builds disabled' do - before do - stub_ci_builds_disabled - stub_ci_commit_yaml_file(nil) - visit ci_status_path(commit) + describe '.gitlab-ci.yml not found warning' do + context 'ci builds enabled' do + it "does not show warning" do + visit ci_status_path(commit) + expect(page).not_to have_content '.gitlab-ci.yml not found in this commit' + end + + it 'shows warning' do + stub_ci_commit_yaml_file(nil) + visit ci_status_path(commit) + expect(page).to have_content '.gitlab-ci.yml not found in this commit' + end end - it 'does not show warning' do - expect(page).not_to have_content '.gitlab-ci.yml not found in this commit' + context 'ci builds disabled' do + before do + stub_ci_builds_disabled + stub_ci_commit_yaml_file(nil) + visit ci_status_path(commit) + end + + it 'does not show warning' do + expect(page).not_to have_content '.gitlab-ci.yml not found in this commit' + end end end end + + context "when logged as reporter" do + before do + project.team << [@user, :reporter] + build.update_attributes(artifacts_file: artifacts_file) + visit ci_status_path(commit) + end + + it do + expect(page).to have_content commit.sha[0..7] + expect(page).to have_content commit.git_commit_message + expect(page).to have_content commit.git_author_name + expect(page).to have_link('Download artifacts') + expect(page).to_not have_link('Cancel running') + expect(page).to_not have_link('Retry failed') + end + end + + context 'when accessing internal project with disallowed access' do + before do + project.update( + visibility_level: Gitlab::VisibilityLevel::INTERNAL, + public_builds: false) + build.update_attributes(artifacts_file: artifacts_file) + visit ci_status_path(commit) + end + + it do + expect(page).to have_content commit.sha[0..7] + expect(page).to have_content commit.git_commit_message + expect(page).to have_content commit.git_author_name + expect(page).to_not have_link('Download artifacts') + expect(page).to_not have_link('Cancel running') + expect(page).to_not have_link('Retry failed') + end + end end end end diff --git a/spec/features/security/project/public_access_spec.rb b/spec/features/security/project/public_access_spec.rb index 655d2c8b7d9..b98476f854e 100644 --- a/spec/features/security/project/public_access_spec.rb +++ b/spec/features/security/project/public_access_spec.rb @@ -96,6 +96,60 @@ describe "Public Project Access", feature: true do it { is_expected.to be_denied_for :visitor } end + describe "GET /:project_path/builds" do + subject { namespace_project_builds_path(project.namespace, project) } + + context "when allowed for public" do + before { project.update(public_builds: true) } + + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for guest } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_allowed_for :visitor } + end + + context "when disallowed for public" do + before { project.update(public_builds: false) } + + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_denied_for guest } + it { is_expected.to be_denied_for :user } + it { is_expected.to be_denied_for :visitor } + end + end + + describe "GET /:project_path/builds/:id" do + let(:commit) { create(:ci_commit, project: project) } + let(:build) { create(:ci_build, commit: commit) } + subject { namespace_project_build_path(project.namespace, project, build.id) } + + context "when allowed for public" do + before { project.update(public_builds: true) } + + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for guest } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_allowed_for :visitor } + end + + context "when disallowed for public" do + before { project.update(public_builds: false) } + + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_denied_for guest } + it { is_expected.to be_denied_for :user } + it { is_expected.to be_denied_for :visitor } + end + end + describe "GET /:project_path/blob" do before do commit = project.repository.commit -- cgit v1.2.1 From d231b6b9182ce9f68f267af0a073136c898f6892 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Thu, 4 Feb 2016 13:13:01 +0100 Subject: Add behaviour tests for build permissions --- features/project/builds/permissions.feature | 35 +++++++++++++++++++++++++++++ features/steps/project/builds/summary.rb | 8 ------- features/steps/shared/builds.rb | 17 ++++++++++++++ features/steps/shared/project.rb | 4 ++++ 4 files changed, 56 insertions(+), 8 deletions(-) diff --git a/features/project/builds/permissions.feature b/features/project/builds/permissions.feature index 1193bcd74f6..3c7f72335d9 100644 --- a/features/project/builds/permissions.feature +++ b/features/project/builds/permissions.feature @@ -5,6 +5,41 @@ Feature: Project Builds Permissions And project has CI enabled And project has a recent build + Scenario: I try to visit build details as guest + Given I am member of a project with a guest role + When I visit recent build details page + Then page status code should be 404 + + Scenario: I try to visit project builds page as guest + Given I am member of a project with a guest role + When I visit project builds page + Then page status code should be 404 + + Scenario: I try to visit build details of internal project without access to builds + Given The project is internal + And public access for builds is disabled + When I visit recent build details page + Then page status code should be 404 + + Scenario: I try to visit internal project builds page without access to builds + Given The project is internal + And public access for builds is disabled + When I visit project builds page + Then page status code should be 404 + + Scenario: I try to visit build details of internal project with access to builds + Given The project is internal + And public access for builds is enabled + When I visit recent build details page + Then I see details of a build + And I see build trace + + Scenario: I try to visit internal project builds page with access to builds + Given The project is internal + And public access for builds is enabled + When I visit project builds page + Then I see the build + Scenario: I try to download build artifacts as guest Given I am member of a project with a guest role And recent build has artifacts available diff --git a/features/steps/project/builds/summary.rb b/features/steps/project/builds/summary.rb index 036bc0a499e..433253dd44b 100644 --- a/features/steps/project/builds/summary.rb +++ b/features/steps/project/builds/summary.rb @@ -4,14 +4,6 @@ class Spinach::Features::ProjectBuildsSummary < Spinach::FeatureSteps include SharedBuilds include RepoHelpers - step 'I see details of a build' do - expect(page).to have_content "Build ##{@build.id}" - end - - step 'I see build trace' do - expect(page).to have_css '#build-trace' - end - step 'I see button to CI Lint' do page.within('.controls') do ci_lint_tool_link = page.find_link('CI Lint') diff --git a/features/steps/shared/builds.rb b/features/steps/shared/builds.rb index 92bf362879b..726e2e814ad 100644 --- a/features/steps/shared/builds.rb +++ b/features/steps/shared/builds.rb @@ -38,4 +38,21 @@ module SharedBuilds step 'I access artifacts download page' do visit download_namespace_project_build_artifacts_path(@project.namespace, @project, @build) end + + step 'I see details of a build' do + expect(page).to have_content "Build ##{@build.id}" + end + + step 'I see build trace' do + expect(page).to have_css '#build-trace' + end + + step 'I see the build' do + page.within('.commit_status') do + expect(page).to have_content "##{@build.id}" + expect(page).to have_content @build.sha[0..7] + expect(page).to have_content @build.ref + expect(page).to have_content @build.name + end + end end diff --git a/features/steps/shared/project.rb b/features/steps/shared/project.rb index 1200eb319d7..b13e82f276b 100644 --- a/features/steps/shared/project.rb +++ b/features/steps/shared/project.rb @@ -240,6 +240,10 @@ module SharedProject end end + step 'The project is internal' do + @project.update(visibility_level: Gitlab::VisibilityLevel::INTERNAL) + end + step 'public access for builds is enabled' do @project.update(public_builds: true) end -- cgit v1.2.1 From 7b868c61ab371fc9319e6dd1baa2c089bc275618 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 4 Feb 2016 13:20:55 +0100 Subject: refactored migration and spec based on feedback --- ...29135155_remove_dot_atom_path_ending_of_projects.rb | 18 ++++++++++++------ spec/controllers/projects_controller_spec.rb | 4 ++-- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/db/migrate/20160129135155_remove_dot_atom_path_ending_of_projects.rb b/db/migrate/20160129135155_remove_dot_atom_path_ending_of_projects.rb index 9ca695d713f..bb79ac026c2 100644 --- a/db/migrate/20160129135155_remove_dot_atom_path_ending_of_projects.rb +++ b/db/migrate/20160129135155_remove_dot_atom_path_ending_of_projects.rb @@ -4,19 +4,21 @@ class RemoveDotAtomPathEndingOfProjects < ActiveRecord::Migration class ProjectPath attr_reader :old_path, :id, :namespace_path - def initialize(old_path, id, namespace_path) + def initialize(old_path, id, namespace_path, namespace_id) @old_path = old_path @id = id @namespace_path = namespace_path + @namespace_id = namespace_id end def clean_path - @_clean_path ||= PathCleaner.clean(@old_path) + @_clean_path ||= PathCleaner.clean(@old_path, @namespace_id) end end class PathCleaner - def initialize(path) + def initialize(path, namespace_id) + @namespace_id = namespace_id @path = path end @@ -34,22 +36,24 @@ class RemoveDotAtomPathEndingOfProjects < ActiveRecord::Migration path end + private + def cleaned_path @_cleaned_path ||= @path.gsub(/\.atom\z/, '-atom') end def path_exists?(path) - Project.find_by_path(path) + Project.find_by_path_and_namespace_id(path, @namespace_id) end end def projects_with_dot_atom - select_all("SELECT p.id, p.path, n.path as namespace_path FROM projects p inner join namespaces n on n.id = p.namespace_id WHERE lower(p.path) LIKE '%.atom'") + select_all("SELECT p.id, p.path, n.path as namespace_path, n.id as namespace_id FROM projects p inner join namespaces n on n.id = p.namespace_id WHERE lower(p.path) LIKE '%.atom'") end def up projects_with_dot_atom.each do |project| - project_path = ProjectPath.new(project['path'], project['id'], project['namespace_path']) + project_path = ProjectPath.new(project['path'], project['id'], project['namespace_path'], project['namespace_id']) clean_path(project_path) if rename_project_repo(project_path) end end @@ -66,5 +70,7 @@ class RemoveDotAtomPathEndingOfProjects < ActiveRecord::Migration gitlab_shell.mv_repository("#{old_path_with_namespace}.wiki", "#{new_path_with_namespace}.wiki") gitlab_shell.mv_repository(old_path_with_namespace, new_path_with_namespace) + rescue + false end end diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb index 245cf96d644..6eee4dfe229 100644 --- a/spec/controllers/projects_controller_spec.rb +++ b/spec/controllers/projects_controller_spec.rb @@ -88,10 +88,10 @@ describe ProjectsController do end context "when the url contains .atom" do - let(:public_project_with_dot_atom) { create(:project, :public, name: 'my.atom', path: 'my.atom') } + let(:public_project_with_dot_atom) { build(:project, :public, name: 'my.atom', path: 'my.atom') } it 'expect an error creating the project' do - expect { public_project_with_dot_atom }.to raise_error(ActiveRecord::RecordInvalid) + expect(public_project_with_dot_atom).not_to be_valid end end end -- cgit v1.2.1 From c64c106091ee5526e9413b9929205134c0ce114f Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Thu, 4 Feb 2016 14:43:52 +0100 Subject: Update ability model after comments --- app/models/ability.rb | 39 +++++++++++++++------------------------ 1 file changed, 15 insertions(+), 24 deletions(-) diff --git a/app/models/ability.rb b/app/models/ability.rb index a6862f83158..00f5f3a93b3 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -5,22 +5,18 @@ class Ability return [] unless user.is_a?(User) return [] if user.blocked? - # We check with `is_a?`, because CommitStatus uses inheritance - if subject.is_a?(CommitStatus) - return commit_status_abilities(user, subject) - end - - case subject.class.name - when "Project" then project_abilities(user, subject) - when "Issue" then issue_abilities(user, subject) - when "Note" then note_abilities(user, subject) - when "ProjectSnippet" then project_snippet_abilities(user, subject) - when "PersonalSnippet" then personal_snippet_abilities(user, subject) - when "MergeRequest" then merge_request_abilities(user, subject) - when "Group" then group_abilities(user, subject) - when "Namespace" then namespace_abilities(user, subject) - when "GroupMember" then group_member_abilities(user, subject) - when "ProjectMember" then project_member_abilities(user, subject) + case subject + when CommitStatus then commit_status_abilities(user, subject) + when Project then project_abilities(user, subject) + when Issue then issue_abilities(user, subject) + when Note then note_abilities(user, subject) + when ProjectSnippet then project_snippet_abilities(user, subject) + when PersonalSnippet then personal_snippet_abilities(user, subject) + when MergeRequest then merge_request_abilities(user, subject) + when Group then group_abilities(user, subject) + when Namespace then namespace_abilities(user, subject) + when GroupMember then group_member_abilities(user, subject) + when ProjectMember then project_member_abilities(user, subject) else [] end.concat(global_abilities(user)) end @@ -130,10 +126,8 @@ class Ability if project.public? || project.internal? rules.push(*public_project_rules) - end - # Allow to read builds for internal projects - if project.public? || project.internal? + # Allow to read builds for internal projects rules << :read_build if project.public_builds? end @@ -416,11 +410,8 @@ class Ability def filter_build_abilities(rules) # If we can't read build we should also not have that # ability when looking at this in context of commit_status - unless rules.include?(:read_build) - rules -= [:read_commit_status] - end - unless rules.include?(:update_build) - rules -= [:update_commit_status] + %w(read create update admin).each do |rule| + rules -= [:"#{rule}_commit_status"] unless rules.include?(:"#{rule}_build") end rules end -- cgit v1.2.1 From f25ba6e03c6635b75a46e6f53c3cfee8109b74f9 Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Thu, 4 Feb 2016 08:50:25 -0500 Subject: Resize sidebar on initial page refresh. --- app/assets/javascripts/application.js.coffee | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/application.js.coffee b/app/assets/javascripts/application.js.coffee index 1abc4794f21..b7c465401be 100644 --- a/app/assets/javascripts/application.js.coffee +++ b/app/assets/javascripts/application.js.coffee @@ -269,11 +269,19 @@ $ -> '
') checkBootstrapBreakpoints() - $(window).on "resize", (e) -> + fitSidebarForSize = -> oldBootstrapBreakpoint = bootstrapBreakpoint checkBootstrapBreakpoints() if bootstrapBreakpoint != oldBootstrapBreakpoint - $(document).trigger('breakpoint:change',[bootstrapBreakpoint]) + $(document).trigger('breakpoint:change', [bootstrapBreakpoint]) + + checkInitialSidebarSize = -> + if bootstrapBreakpoint is "xs" or "sm" + $(document).trigger('breakpoint:change', [bootstrapBreakpoint]) + + $(window).on "resize", (e) -> + fitSidebarForSize() setBootstrapBreakpoints() + checkInitialSidebarSize() new Aside() -- cgit v1.2.1 From 5dc77d7577bf19586f6cd756678d0c2660e7f868 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 4 Feb 2016 15:35:03 +0100 Subject: refactored migration based on feedback --- .../20160129135155_remove_dot_atom_path_ending_of_projects.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/db/migrate/20160129135155_remove_dot_atom_path_ending_of_projects.rb b/db/migrate/20160129135155_remove_dot_atom_path_ending_of_projects.rb index bb79ac026c2..091de54978b 100644 --- a/db/migrate/20160129135155_remove_dot_atom_path_ending_of_projects.rb +++ b/db/migrate/20160129135155_remove_dot_atom_path_ending_of_projects.rb @@ -61,7 +61,7 @@ class RemoveDotAtomPathEndingOfProjects < ActiveRecord::Migration private def clean_path(project_path) - execute "UPDATE projects SET path = '#{project_path.clean_path}' WHERE id = #{project_path.id}" + execute "UPDATE projects SET path = #{sanitize(project_path.clean_path)} WHERE id = #{project_path.id}" end def rename_project_repo(project_path) @@ -73,4 +73,8 @@ class RemoveDotAtomPathEndingOfProjects < ActiveRecord::Migration rescue false end + + def sanitize(value) + ActiveRecord::Base.connection.quote(value) + end end -- cgit v1.2.1 From a7c441aa17ba64eb702b583ac9198cdace599d2e Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Thu, 4 Feb 2016 16:32:41 +0100 Subject: Use `delete` instead of assignment operator when filtering build abilities --- app/models/ability.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/ability.rb b/app/models/ability.rb index 00f5f3a93b3..a866eadeebb 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -411,7 +411,7 @@ class Ability # If we can't read build we should also not have that # ability when looking at this in context of commit_status %w(read create update admin).each do |rule| - rules -= [:"#{rule}_commit_status"] unless rules.include?(:"#{rule}_build") + rules.delete(:"#{rule}_commit_status") unless rules.include?(:"#{rule}_build") end rules end -- cgit v1.2.1 From f835fa8d750b3b8b13b3b6e24780c1e4e01b9796 Mon Sep 17 00:00:00 2001 From: Eric L Frederich Date: Thu, 4 Feb 2016 10:42:36 -0500 Subject: fix documentation bug / typo --- doc/customization/issue_closing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/customization/issue_closing.md b/doc/customization/issue_closing.md index 00edfc97ed9..194b8e00299 100644 --- a/doc/customization/issue_closing.md +++ b/doc/customization/issue_closing.md @@ -16,7 +16,7 @@ Here, `%{issue_ref}` is a complex regular expression defined inside GitLab, that For example: ``` -git commit -m "Awesome commit message (Fix #20, Fixes #21 and Closes group/otherproject#2). This commit is also related to #17 and fixes #18, #19 and https://gitlab.example.com/group/otherproject/issues/23." +git commit -m "Awesome commit message (Fix #20, Fixes #21 and Closes group/otherproject#22). This commit is also related to #17 and fixes #18, #19 and https://gitlab.example.com/group/otherproject/issues/23." ``` will close `#18`, `#19`, `#20`, and `#21` in the project this commit is pushed to, as well as `#22` and `#23` in group/otherproject. `#17` won't be closed as it does not match the pattern. It also works with multiline commit messages. -- cgit v1.2.1 From 9f86fcde400de28fb544e59247b8925e4ff4d09a Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 4 Feb 2016 17:00:32 +0100 Subject: Fix broken tests Signed-off-by: Dmitriy Zaporozhets --- spec/helpers/search_helper_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/helpers/search_helper_spec.rb b/spec/helpers/search_helper_spec.rb index f0d553f5f1d..601b6915e27 100644 --- a/spec/helpers/search_helper_spec.rb +++ b/spec/helpers/search_helper_spec.rb @@ -42,9 +42,9 @@ describe SearchHelper do expect(search_autocomplete_opts(project.name).size).to eq(1) end - it "includes the public group" do + it "should not include the public group" do group = create(:group) - expect(search_autocomplete_opts(group.name).size).to eq(1) + expect(search_autocomplete_opts(group.name).size).to eq(0) end context "with a current project" do -- cgit v1.2.1 From 2e6c5fb28e2fb924addffd29345dab45b7980905 Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Thu, 4 Feb 2016 11:10:11 -0500 Subject: Properly link to the right issue or merge request --- app/helpers/application_helper.rb | 20 ++++++++++++++++++++ app/views/shared/issuable/_sidebar.html.haml | 4 ++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 00f38932861..14f098d8355 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -293,6 +293,26 @@ module ApplicationHelper end end + def issuable_link_next(project,issuable) + if project.nil? + nil + elsif current_controller?(:issues) + namespace_project_issue_path(project.namespace, project, next_issuable_for(project, issuable.id).try(:iid)) + elsif current_controller?(:merge_requests) + namespace_project_merge_request_path(project.namespace, project, next_issuable_for(project, issuable.id).try(:iid)) + end + end + + def issuable_link_prev(project,issuable) + if project.nil? + nil + elsif current_controller?(:issues) + namespace_project_issue_path(project.namespace, project, prev_issuable_for(project, issuable.id).try(:iid)) + elsif current_controller?(:merge_requests) + namespace_project_merge_request_path(project.namespace, project, prev_issuable_for(project, issuable.id).try(:iid)) + end + end + def issuable_count(entity, project) if project.nil? 0 diff --git a/app/views/shared/issuable/_sidebar.html.haml b/app/views/shared/issuable/_sidebar.html.haml index f4f04a42196..cab500d7244 100644 --- a/app/views/shared/issuable/_sidebar.html.haml +++ b/app/views/shared/issuable/_sidebar.html.haml @@ -13,12 +13,12 @@ = icon('angle-double-right') .issuable-nav.pull-right.btn-group{role: 'group', "aria-label" => '...'} - if has_prev_issuable?(@project, issuable.id) - = link_to 'Prev', namespace_project_issue_path(@project.namespace, @project, prev_issuable_for(@project, issuable.id).try(:iid)), class: 'btn btn-default' + = link_to 'Prev', issuable_link_prev(@project, issuable), class: 'btn btn-default' - else %a.btn.btn-default.disabled{href: '#'} Prev - if has_next_issuable?(@project, issuable.id) - = link_to 'Next', namespace_project_issue_path(@project.namespace, @project, next_issuable_for(@project, issuable.id).try(:iid)), class: 'btn btn-default' + = link_to 'Next', issuable_link_next(@project, issuable), class: 'btn btn-default' - else %a.btn.btn-default.disabled{href: '#'} Next -- cgit v1.2.1 From 87b61db7ed6b782423397626b6ea414c43f24a15 Mon Sep 17 00:00:00 2001 From: Josh Frye Date: Wed, 3 Feb 2016 13:47:38 -0500 Subject: Page project list on dashboard --- app/controllers/dashboard/projects_controller.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/controllers/dashboard/projects_controller.rb b/app/controllers/dashboard/projects_controller.rb index 721e2a6bcbd..a205ab7d34a 100644 --- a/app/controllers/dashboard/projects_controller.rb +++ b/app/controllers/dashboard/projects_controller.rb @@ -5,6 +5,7 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController @projects = current_user.authorized_projects.sorted_by_activity.non_archived @projects = @projects.sort(@sort = params[:sort]) @projects = @projects.includes(:namespace) + @projects = @projects.page(params[:page]).per(PER_PAGE) @last_push = current_user.recent_push respond_to do |format| @@ -21,6 +22,7 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController @projects = current_user.starred_projects @projects = @projects.includes(:namespace, :forked_from_project, :tags) @projects = @projects.sort(@sort = params[:sort]) + @projects = @projects.page(params[:page]).per(PER_PAGE) @last_push = current_user.recent_push @groups = [] -- cgit v1.2.1 From 7522ac0b3cf4a777fda5dce3baa699970e5133a6 Mon Sep 17 00:00:00 2001 From: Josh Frye Date: Wed, 3 Feb 2016 16:33:01 -0500 Subject: Paginate + ajax filter dashboard projects --- app/assets/javascripts/projects_list.js.coffee | 26 ++++++++++---------- app/controllers/application_controller.rb | 5 ++-- app/controllers/dashboard/projects_controller.rb | 12 ++++++++++ app/controllers/explore/projects_controller.rb | 12 +++++----- app/views/dashboard/_projects_head.html.haml | 13 +++++----- app/views/dashboard/projects/_projects.html.haml | 5 +++- app/views/explore/projects/_projects.html.haml | 4 ++-- app/views/explore/projects/starred.html.haml | 4 ++-- app/views/explore/projects/trending.html.haml | 2 +- app/views/shared/projects/_list.html.haml | 30 +++++++++++++----------- 10 files changed, 67 insertions(+), 46 deletions(-) diff --git a/app/assets/javascripts/projects_list.js.coffee b/app/assets/javascripts/projects_list.js.coffee index b71509dbc5a..b4776493629 100644 --- a/app/assets/javascripts/projects_list.js.coffee +++ b/app/assets/javascripts/projects_list.js.coffee @@ -11,16 +11,18 @@ class @ProjectsList uiBox = $('div.projects-list-holder') filterSelector = $(this).data('filter-selector') || 'span.filter-title' - if terms == "" || terms == undefined - uiBox.find("ul.projects-list li").show() - else - uiBox.find("ul.projects-list li").each (index) -> - name = $(this).find(filterSelector).text() - - if name.toLowerCase().search(terms.toLowerCase()) == -1 - $(this).hide() - else - $(this).show() + $('.projects-list-holder').css("opacity", '0.5') + form = $("#project-list-form") + project_filter_url = form.attr('action') + '?' + form.serialize() + $.ajax + type: "GET" + url: form.attr('action') + data: form.serialize() + complete: -> + $('.projects-list-holder').css("opacity", '1.0') + success: (data) -> + $('.projects-list-holder').html(data.html) + # Change url so if user reload a page - search results are saved + history.replaceState {page: project_filter_url}, document.title, project_filter_url + dataType: "json" uiBox.find("ul.projects-list li.bottom").hide() - - diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 7fa2f68ef07..c189f498951 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -277,9 +277,10 @@ class ApplicationController < ActionController::Base } end - def view_to_html_string(partial) + def view_to_html_string(partial, locals = nil) render_to_string( - partial, + partial: partial, + locals: locals, layout: false, formats: [:html] ) diff --git a/app/controllers/dashboard/projects_controller.rb b/app/controllers/dashboard/projects_controller.rb index a205ab7d34a..2f56228ff75 100644 --- a/app/controllers/dashboard/projects_controller.rb +++ b/app/controllers/dashboard/projects_controller.rb @@ -5,6 +5,13 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController @projects = current_user.authorized_projects.sorted_by_activity.non_archived @projects = @projects.sort(@sort = params[:sort]) @projects = @projects.includes(:namespace) + + terms = params['filter_projects'] + + if terms.present? + @projects = @projects.search(terms) + end + @projects = @projects.page(params[:page]).per(PER_PAGE) @last_push = current_user.recent_push @@ -15,6 +22,11 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController load_events render layout: false end + format.json do + render json: { + html: view_to_html_string("dashboard/projects/projects", locals: { projects: @projects }) + } + end end end diff --git a/app/controllers/explore/projects_controller.rb b/app/controllers/explore/projects_controller.rb index a5aeaed66c5..2689bf4f1ec 100644 --- a/app/controllers/explore/projects_controller.rb +++ b/app/controllers/explore/projects_controller.rb @@ -11,14 +11,14 @@ class Explore::ProjectsController < Explore::ApplicationController end def trending - @trending_projects = TrendingProjectsFinder.new.execute(current_user) - @trending_projects = @trending_projects.non_archived - @trending_projects = @trending_projects.page(params[:page]).per(PER_PAGE) + @projects = TrendingProjectsFinder.new.execute(current_user) + @projects = @projects.non_archived + @projects = @projects.page(params[:page]).per(PER_PAGE) end def starred - @starred_projects = ProjectsFinder.new.execute(current_user) - @starred_projects = @starred_projects.reorder('star_count DESC') - @starred_projects = @starred_projects.page(params[:page]).per(PER_PAGE) + @projects = ProjectsFinder.new.execute(current_user) + @projects = @projects.reorder('star_count DESC') + @projects = @projects.page(params[:page]).per(PER_PAGE) end end diff --git a/app/views/dashboard/_projects_head.html.haml b/app/views/dashboard/_projects_head.html.haml index d865a2c6fae..17eed52957d 100644 --- a/app/views/dashboard/_projects_head.html.haml +++ b/app/views/dashboard/_projects_head.html.haml @@ -13,9 +13,10 @@ Explore Projects .nav-controls - = search_field_tag :filter_projects, nil, placeholder: 'Filter by name...', class: 'projects-list-filter form-control hidden-xs input-short', spellcheck: false - = render 'explore/projects/dropdown' - - if current_user.can_create_project? - = link_to new_project_path, class: 'btn btn-new' do - = icon('plus') - New Project + = form_tag '', method: :get, class: 'project-list-form', id: 'project-list-form' do |f| + .append-right-10.hidden-xs.hidden-sm + = search_field_tag :filter_projects, params[:filter_projects], placeholder: 'Filter by name...', class: 'projects-list-filter form-control issue_search search-text-input', spellcheck: false, id: 'projects-list-filter' + - if current_user.can_create_project? + = link_to new_project_path, class: 'btn btn-new' do + = icon('plus') + New Project diff --git a/app/views/dashboard/projects/_projects.html.haml b/app/views/dashboard/projects/_projects.html.haml index cea9ffcc748..35ef73071c0 100644 --- a/app/views/dashboard/projects/_projects.html.haml +++ b/app/views/dashboard/projects/_projects.html.haml @@ -1,3 +1,6 @@ .projects-list-holder - = render 'shared/projects/list', projects: @projects, ci: true + = render 'shared/projects/list', ci: true + + :javascript + new ProjectsList(); diff --git a/app/views/explore/projects/_projects.html.haml b/app/views/explore/projects/_projects.html.haml index 669079e9521..b64a4918761 100644 --- a/app/views/explore/projects/_projects.html.haml +++ b/app/views/explore/projects/_projects.html.haml @@ -1,6 +1,6 @@ -- if projects.any? +- if @projects.any? .public-projects - = render 'shared/projects/list', projects: projects + = render 'shared/projects/list' - else .nothing-here-block No such projects diff --git a/app/views/explore/projects/starred.html.haml b/app/views/explore/projects/starred.html.haml index 16f52f7a530..0bdd0a57fe6 100644 --- a/app/views/explore/projects/starred.html.haml +++ b/app/views/explore/projects/starred.html.haml @@ -7,5 +7,5 @@ = render 'explore/head' = render 'explore/projects/nav' -= render 'projects', projects: @starred_projects -= paginate @starred_projects, theme: 'gitlab' += render 'projects', projects: @projects += paginate @projects, theme: 'gitlab' diff --git a/app/views/explore/projects/trending.html.haml b/app/views/explore/projects/trending.html.haml index adcda810061..ec461755103 100644 --- a/app/views/explore/projects/trending.html.haml +++ b/app/views/explore/projects/trending.html.haml @@ -7,4 +7,4 @@ = render 'explore/head' = render 'explore/projects/nav' -= render 'projects', projects: @trending_projects += render 'projects', projects: @projects diff --git a/app/views/shared/projects/_list.html.haml b/app/views/shared/projects/_list.html.haml index b3f45373f6b..80795063f6f 100644 --- a/app/views/shared/projects/_list.html.haml +++ b/app/views/shared/projects/_list.html.haml @@ -8,18 +8,20 @@ - show_last_commit_as_description = false unless local_assigns[:show_last_commit_as_description] == true %ul.projects-list - - projects.each_with_index do |project, i| - - css_class = (i >= projects_limit) ? 'hide' : nil - = render "shared/projects/project", project: project, skip_namespace: skip_namespace, - avatar: avatar, stars: stars, css_class: css_class, ci: ci, use_creator_avatar: use_creator_avatar, - forks: forks, show_last_commit_as_description: show_last_commit_as_description + - if @projects.any? + - @projects.each_with_index do |project, i| + - css_class = (i >= projects_limit) ? 'hide' : nil + = render "shared/projects/project", project: project, skip_namespace: skip_namespace, + avatar: avatar, stars: stars, css_class: css_class, ci: ci, use_creator_avatar: use_creator_avatar, + forks: forks, show_last_commit_as_description: show_last_commit_as_description - - if projects.size > projects_limit - %li.bottom.center - .light - #{projects_limit} of #{pluralize(projects.count, 'project')} displayed. - = link_to '#', class: 'js-expand' do - Show all - -:javascript - new ProjectsList(); + - if @projects.size > projects_limit + %li.bottom.center + .light + #{projects_limit} of #{pluralize(@projects.count, 'project')} displayed. + = link_to '#', class: 'js-expand' do + Show all + = paginate @projects, theme: "gitlab" + - else + %h3 No projects found + %p.slead Try searching for a different project. -- cgit v1.2.1 From 2c871ca1968846871ed264cad34b50611eecae3b Mon Sep 17 00:00:00 2001 From: Josh Frye Date: Wed, 3 Feb 2016 17:24:14 -0500 Subject: Delay filter until user stops typing --- app/assets/javascripts/dashboard.js.coffee | 2 +- app/assets/javascripts/issues.js.coffee | 2 +- app/assets/javascripts/projects_list.js.coffee | 49 ++++++++++++++---------- app/assets/javascripts/user.js.coffee | 2 +- app/views/dashboard/_projects_head.html.haml | 2 +- app/views/dashboard/projects/_projects.html.haml | 2 +- 6 files changed, 33 insertions(+), 26 deletions(-) diff --git a/app/assets/javascripts/dashboard.js.coffee b/app/assets/javascripts/dashboard.js.coffee index 00ee503ff16..dc0b9597d1f 100644 --- a/app/assets/javascripts/dashboard.js.coffee +++ b/app/assets/javascripts/dashboard.js.coffee @@ -1,3 +1,3 @@ class @Dashboard constructor: -> - new ProjectsList() + ProjectsList.init() diff --git a/app/assets/javascripts/issues.js.coffee b/app/assets/javascripts/issues.js.coffee index a0acf3028bf..54e00741424 100644 --- a/app/assets/javascripts/issues.js.coffee +++ b/app/assets/javascripts/issues.js.coffee @@ -45,7 +45,7 @@ filterResults: => form = $("#issue_search_form") - search = $("#issue_search").val() + search = $("#projects-list-filter").val() $('.issues-holder').css("opacity", '0.5') issues_url = form.attr('action') + '?' + form.serialize() diff --git a/app/assets/javascripts/projects_list.js.coffee b/app/assets/javascripts/projects_list.js.coffee index b4776493629..384b95118c9 100644 --- a/app/assets/javascripts/projects_list.js.coffee +++ b/app/assets/javascripts/projects_list.js.coffee @@ -1,28 +1,35 @@ -class @ProjectsList - constructor: -> +@ProjectsList = + init: -> $(".projects-list .js-expand").on 'click', (e) -> e.preventDefault() list = $(this).closest('.projects-list') list.find("li").show() list.find("li.bottom").hide() + this.initSearch() - $(".projects-list-filter").keyup -> - terms = $(this).val() - uiBox = $('div.projects-list-holder') - filterSelector = $(this).data('filter-selector') || 'span.filter-title' + initSearch: -> + @timer = null + $("#projects-list-filter").keyup -> + clearTimeout(@timer) + @timer = setTimeout(ProjectsList.filterResults, 500) - $('.projects-list-holder').css("opacity", '0.5') - form = $("#project-list-form") - project_filter_url = form.attr('action') + '?' + form.serialize() - $.ajax - type: "GET" - url: form.attr('action') - data: form.serialize() - complete: -> - $('.projects-list-holder').css("opacity", '1.0') - success: (data) -> - $('.projects-list-holder').html(data.html) - # Change url so if user reload a page - search results are saved - history.replaceState {page: project_filter_url}, document.title, project_filter_url - dataType: "json" - uiBox.find("ul.projects-list li.bottom").hide() + filterResults: => + form = $("#project-list-form") + search = $("#issue_search").val() + uiBox = $('div.projects-list-holder') + + $('.projects-list-holder').css("opacity", '0.5') + + project_filter_url = form.attr('action') + '?' + form.serialize() + $.ajax + type: "GET" + url: form.attr('action') + data: form.serialize() + complete: -> + $('.projects-list-holder').css("opacity", '1.0') + success: (data) -> + $('.projects-list-holder').html(data.html) + # Change url so if user reload a page - search results are saved + history.replaceState {page: project_filter_url}, document.title, project_filter_url + dataType: "json" + uiBox.find("ul.projects-list li.bottom").hide() diff --git a/app/assets/javascripts/user.js.coffee b/app/assets/javascripts/user.js.coffee index ec4271b092c..eb7f7bb26b1 100644 --- a/app/assets/javascripts/user.js.coffee +++ b/app/assets/javascripts/user.js.coffee @@ -1,7 +1,7 @@ class @User constructor: -> $('.profile-groups-avatars').tooltip("placement": "top") - new ProjectsList() + ProjectsList.init() $('.hide-project-limit-message').on 'click', (e) -> path = '/' diff --git a/app/views/dashboard/_projects_head.html.haml b/app/views/dashboard/_projects_head.html.haml index 17eed52957d..ab2da1824c5 100644 --- a/app/views/dashboard/_projects_head.html.haml +++ b/app/views/dashboard/_projects_head.html.haml @@ -15,7 +15,7 @@ .nav-controls = form_tag '', method: :get, class: 'project-list-form', id: 'project-list-form' do |f| .append-right-10.hidden-xs.hidden-sm - = search_field_tag :filter_projects, params[:filter_projects], placeholder: 'Filter by name...', class: 'projects-list-filter form-control issue_search search-text-input', spellcheck: false, id: 'projects-list-filter' + = search_field_tag :filter_projects, params[:filter_projects], placeholder: 'Filter by name...', class: 'projects-list-filter form-control search-text-input', spellcheck: false, id: 'projects-list-filter' - if current_user.can_create_project? = link_to new_project_path, class: 'btn btn-new' do = icon('plus') diff --git a/app/views/dashboard/projects/_projects.html.haml b/app/views/dashboard/projects/_projects.html.haml index 35ef73071c0..c08247cd9ac 100644 --- a/app/views/dashboard/projects/_projects.html.haml +++ b/app/views/dashboard/projects/_projects.html.haml @@ -3,4 +3,4 @@ = render 'shared/projects/list', ci: true :javascript - new ProjectsList(); + ProjectsList.init() -- cgit v1.2.1 From a1b475acab5c1214cea7fc05ed3ab9be8c713cb1 Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Thu, 4 Feb 2016 11:49:46 -0500 Subject: Puts shortcut key in the right place. --- app/views/help/_shortcuts.html.haml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/views/help/_shortcuts.html.haml b/app/views/help/_shortcuts.html.haml index 9ee6f07b26b..8e982718d23 100644 --- a/app/views/help/_shortcuts.html.haml +++ b/app/views/help/_shortcuts.html.haml @@ -40,10 +40,6 @@ %td.shortcut .key enter %td Open Selection - %tr - %td.shortcut - .key t - %td Go to finding file %tbody %tr %th @@ -161,6 +157,10 @@ .key s %td Go to snippets + %tr + %td.shortcut + .key t + %td Go to finding file .col-lg-4 %table.shortcut-mappings %tbody{ class: 'hidden-shortcut network', style: 'display:none' } -- cgit v1.2.1 From b1757c200ca219b2c9c40c3895252014f6a22379 Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Thu, 4 Feb 2016 12:29:32 -0500 Subject: Change placeholder text to just 'search' --- app/helpers/application_helper.rb | 12 ------------ app/views/layouts/_search.html.haml | 2 +- 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index a2458ad3be0..819bc1be3fa 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -169,18 +169,6 @@ module ApplicationHelper Gitlab.config.extra end - def search_placeholder - if @project && @project.persisted? - 'Search' - elsif @snippet || @snippets || @show_snippets - 'Search snippets' - elsif @group && @group.persisted? - 'Search in this group' - else - 'Search' - end - end - # Render a `time` element with Javascript-based relative date and tooltip # # time - Time object diff --git a/app/views/layouts/_search.html.haml b/app/views/layouts/_search.html.haml index a44f5762a6b..659f5a7756b 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 form-control", spellcheck: false + = search_field_tag "search", nil, placeholder: 'search', class: "search-input form-control", spellcheck: false = hidden_field_tag :group_id, @group.try(:id) - if @project && @project.persisted? = hidden_field_tag :project_id, @project.id -- cgit v1.2.1 From 9b925d79c9bfcd1be46bd52e275570a1005a3a79 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 4 Feb 2016 18:36:16 +0100 Subject: WIP - fix and spec for cross reference issue with forks --- app/services/system_note_service.rb | 4 ++-- spec/services/system_note_service_spec.rb | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/app/services/system_note_service.rb b/app/services/system_note_service.rb index 1083bcec054..34b6636c39f 100644 --- a/app/services/system_note_service.rb +++ b/app/services/system_note_service.rb @@ -291,8 +291,8 @@ class SystemNoteService notes = notes.where(noteable_id: noteable.id) end - gfm_reference = mentioner.gfm_reference(noteable.project) - notes = notes.where(note: cross_reference_note_content(gfm_reference)) + gfm_reference = mentioner.gfm_reference(nil) + notes = notes.where('note LIKE ?', "#{cross_reference_note_prefix}%#{gfm_reference}") notes.count > 0 end diff --git a/spec/services/system_note_service_spec.rb b/spec/services/system_note_service_spec.rb index d3364a71022..a3d3147a79b 100644 --- a/spec/services/system_note_service_spec.rb +++ b/spec/services/system_note_service_spec.rb @@ -424,6 +424,22 @@ describe SystemNoteService, services: true do to be_falsey end end + + context 'commit from fork' do + let(:author2) { create(:user) } + let(:forked_project) { Projects::ForkService.new(project, author2).execute } + let(:service) { CreateCommitBuildsService.new } + let(:commit2) { forked_project.commit } + + before do + described_class.cross_reference(commit0, commit2, author2) + end + + it 'is falsey when is a fork mentioning an external issue' do + expect(described_class.cross_reference_exists?(commit0, commit2)). + to be_falsey + end + end end include JiraServiceHelper -- cgit v1.2.1 From c663ca434fb6c8a2251e4251c6f0f9d13660ccbe Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 4 Feb 2016 18:38:11 +0100 Subject: remove unnecessary lower function on SQL --- db/migrate/20160129135155_remove_dot_atom_path_ending_of_projects.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/migrate/20160129135155_remove_dot_atom_path_ending_of_projects.rb b/db/migrate/20160129135155_remove_dot_atom_path_ending_of_projects.rb index 091de54978b..d3ea956952e 100644 --- a/db/migrate/20160129135155_remove_dot_atom_path_ending_of_projects.rb +++ b/db/migrate/20160129135155_remove_dot_atom_path_ending_of_projects.rb @@ -48,7 +48,7 @@ class RemoveDotAtomPathEndingOfProjects < ActiveRecord::Migration end def projects_with_dot_atom - select_all("SELECT p.id, p.path, n.path as namespace_path, n.id as namespace_id FROM projects p inner join namespaces n on n.id = p.namespace_id WHERE lower(p.path) LIKE '%.atom'") + select_all("SELECT p.id, p.path, n.path as namespace_path, n.id as namespace_id FROM projects p inner join namespaces n on n.id = p.namespace_id WHERE p.path LIKE '%.atom'") end def up -- cgit v1.2.1 From 2ad094132de3c491511261bf0e6a2e577fd699dd Mon Sep 17 00:00:00 2001 From: Josh Frye Date: Wed, 3 Feb 2016 18:21:14 -0500 Subject: Various filter fixes --- app/assets/javascripts/dashboard.js.coffee | 33 ++++++++++++++++-- app/assets/javascripts/dispatcher.js.coffee | 2 +- app/assets/javascripts/issues.js.coffee | 2 +- app/assets/javascripts/projects_list.js.coffee | 43 +++++++++--------------- app/assets/javascripts/user.js.coffee | 2 +- app/controllers/application_controller.rb | 4 +-- app/controllers/dashboard/projects_controller.rb | 14 ++++++-- app/controllers/explore/projects_controller.rb | 12 +++---- app/controllers/groups_controller.rb | 1 + app/controllers/users_controller.rb | 3 +- app/models/event.rb | 2 +- app/views/dashboard/_projects_head.html.haml | 4 +-- app/views/dashboard/projects/_projects.html.haml | 4 +-- app/views/explore/projects/_projects.html.haml | 4 +-- app/views/explore/projects/starred.html.haml | 4 +-- app/views/explore/projects/trending.html.haml | 2 +- app/views/projects/show.atom.builder | 2 +- app/views/shared/projects/_list.html.haml | 14 ++++---- 18 files changed, 90 insertions(+), 62 deletions(-) diff --git a/app/assets/javascripts/dashboard.js.coffee b/app/assets/javascripts/dashboard.js.coffee index dc0b9597d1f..0229c588b41 100644 --- a/app/assets/javascripts/dashboard.js.coffee +++ b/app/assets/javascripts/dashboard.js.coffee @@ -1,3 +1,30 @@ -class @Dashboard - constructor: -> - ProjectsList.init() +@Dashboard = + init: -> + this.initSearch() + + initSearch: -> + @timer = null + $("#project-filter-form-field").keyup -> + clearTimeout(@timer) + @timer = setTimeout(Dashboard.filterResults, 500) + + filterResults: => + $('.projects-list-holder').css("opacity", '0.5') + + form = null + form = $("#project-filter-form") + search = $("#project-filter-form-field").val() + project_filter_url = form.attr('action') + '?' + form.serialize() + + $.ajax + type: "GET" + url: form.attr('action') + data: form.serialize() + complete: -> + $('.projects-list-holder').css("opacity", '1.0') + success: (data) -> + $('div.projects-list-holder').replaceWith(data.html) + # Change url so if user reload a page - search results are saved + history.replaceState {page: project_filter_url}, document.title, project_filter_url + dataType: "json" + #uiBox.find("ul.projects-list li.bottom").hide() diff --git a/app/assets/javascripts/dispatcher.js.coffee b/app/assets/javascripts/dispatcher.js.coffee index 2cdf01d874c..d4a2b74b143 100644 --- a/app/assets/javascripts/dispatcher.js.coffee +++ b/app/assets/javascripts/dispatcher.js.coffee @@ -58,7 +58,7 @@ class Dispatcher shortcut_handler = new ShortcutsNavigation() MergeRequests.init() when 'dashboard:show', 'root:show' - new Dashboard() + Dashboard.init() when 'dashboard:activity' new Activities() when 'dashboard:projects:starred' diff --git a/app/assets/javascripts/issues.js.coffee b/app/assets/javascripts/issues.js.coffee index 54e00741424..a0acf3028bf 100644 --- a/app/assets/javascripts/issues.js.coffee +++ b/app/assets/javascripts/issues.js.coffee @@ -45,7 +45,7 @@ filterResults: => form = $("#issue_search_form") - search = $("#projects-list-filter").val() + search = $("#issue_search").val() $('.issues-holder').css("opacity", '0.5') issues_url = form.attr('action') + '?' + form.serialize() diff --git a/app/assets/javascripts/projects_list.js.coffee b/app/assets/javascripts/projects_list.js.coffee index 384b95118c9..ebf7140b7e3 100644 --- a/app/assets/javascripts/projects_list.js.coffee +++ b/app/assets/javascripts/projects_list.js.coffee @@ -1,35 +1,24 @@ -@ProjectsList = - init: -> +class @ProjectsList + constructor: -> $(".projects-list .js-expand").on 'click', (e) -> e.preventDefault() list = $(this).closest('.projects-list') list.find("li").show() list.find("li.bottom").hide() - this.initSearch() - initSearch: -> - @timer = null - $("#projects-list-filter").keyup -> - clearTimeout(@timer) - @timer = setTimeout(ProjectsList.filterResults, 500) + $(".projects-list-filter").keyup -> + terms = $(this).val() + uiBox = $('div.projects-list-holder') + filterSelector = $(this).data('filter-selector') || 'span.filter-title' - filterResults: => - form = $("#project-list-form") - search = $("#issue_search").val() - uiBox = $('div.projects-list-holder') + if terms == "" || terms == undefined + uiBox.find("ul.projects-list li").show() + else + uiBox.find("ul.projects-list li").each (index) -> + name = $(this).find(filterSelector).text() - $('.projects-list-holder').css("opacity", '0.5') - - project_filter_url = form.attr('action') + '?' + form.serialize() - $.ajax - type: "GET" - url: form.attr('action') - data: form.serialize() - complete: -> - $('.projects-list-holder').css("opacity", '1.0') - success: (data) -> - $('.projects-list-holder').html(data.html) - # Change url so if user reload a page - search results are saved - history.replaceState {page: project_filter_url}, document.title, project_filter_url - dataType: "json" - uiBox.find("ul.projects-list li.bottom").hide() + if name.toLowerCase().search(terms.toLowerCase()) == -1 + $(this).hide() + else + $(this).show() + uiBox.find("ul.projects-list li.bottom").hide() diff --git a/app/assets/javascripts/user.js.coffee b/app/assets/javascripts/user.js.coffee index eb7f7bb26b1..ec4271b092c 100644 --- a/app/assets/javascripts/user.js.coffee +++ b/app/assets/javascripts/user.js.coffee @@ -1,7 +1,7 @@ class @User constructor: -> $('.profile-groups-avatars').tooltip("placement": "top") - ProjectsList.init() + new ProjectsList() $('.hide-project-limit-message').on 'click', (e) -> path = '/' diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index c189f498951..48b1f95acb9 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -277,9 +277,9 @@ class ApplicationController < ActionController::Base } end - def view_to_html_string(partial, locals = nil) + def view_to_html_string(partial, locals = {}) render_to_string( - partial: partial, + partial, locals: locals, layout: false, formats: [:html] diff --git a/app/controllers/dashboard/projects_controller.rb b/app/controllers/dashboard/projects_controller.rb index 2f56228ff75..cd3a25866af 100644 --- a/app/controllers/dashboard/projects_controller.rb +++ b/app/controllers/dashboard/projects_controller.rb @@ -24,7 +24,7 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController end format.json do render json: { - html: view_to_html_string("dashboard/projects/projects", locals: { projects: @projects }) + html: view_to_html_string("dashboard/projects/_projects", locals: { projects: @projects }) } end end @@ -34,6 +34,13 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController @projects = current_user.starred_projects @projects = @projects.includes(:namespace, :forked_from_project, :tags) @projects = @projects.sort(@sort = params[:sort]) + + terms = params['filter_projects'] + + if terms.present? + @projects = @projects.search(terms) + end + @projects = @projects.page(params[:page]).per(PER_PAGE) @last_push = current_user.recent_push @groups = [] @@ -42,8 +49,9 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController format.html format.json do - load_events - pager_json("events/_events", @events.count) + render json: { + html: view_to_html_string("dashboard/projects/projects", locals: { projects: @projects }) + } end end end diff --git a/app/controllers/explore/projects_controller.rb b/app/controllers/explore/projects_controller.rb index 2689bf4f1ec..a5aeaed66c5 100644 --- a/app/controllers/explore/projects_controller.rb +++ b/app/controllers/explore/projects_controller.rb @@ -11,14 +11,14 @@ class Explore::ProjectsController < Explore::ApplicationController end def trending - @projects = TrendingProjectsFinder.new.execute(current_user) - @projects = @projects.non_archived - @projects = @projects.page(params[:page]).per(PER_PAGE) + @trending_projects = TrendingProjectsFinder.new.execute(current_user) + @trending_projects = @trending_projects.non_archived + @trending_projects = @trending_projects.page(params[:page]).per(PER_PAGE) end def starred - @projects = ProjectsFinder.new.execute(current_user) - @projects = @projects.reorder('star_count DESC') - @projects = @projects.page(params[:page]).per(PER_PAGE) + @starred_projects = ProjectsFinder.new.execute(current_user) + @starred_projects = @starred_projects.reorder('star_count DESC') + @starred_projects = @starred_projects.page(params[:page]).per(PER_PAGE) end end diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index ad6b3eae932..90475c17c17 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -41,6 +41,7 @@ class GroupsController < Groups::ApplicationController def show @last_push = current_user.recent_push if current_user @projects = @projects.includes(:namespace) + @projects = @projects.page(params[:page]).per(PER_PAGE) respond_to do |format| format.html diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 280228dbcc0..6055b606086 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -4,8 +4,9 @@ class UsersController < ApplicationController def show @contributed_projects = contributed_projects.joined(@user).reject(&:forked?) - + @projects = PersonalProjectsFinder.new(@user).execute(current_user) + @projects = @projects.page(params[:page]).per(PER_PAGE) @groups = @user.groups.order_id_desc diff --git a/app/models/event.rb b/app/models/event.rb index 4be23a1cf72..9a0bbf50f8b 100644 --- a/app/models/event.rb +++ b/app/models/event.rb @@ -49,7 +49,7 @@ class Event < ActiveRecord::Base scope :code_push, -> { where(action: PUSHED) } scope :in_projects, ->(projects) do - where(project_id: projects.select(:id).reorder(nil)).recent + where(project_id: projects.map(&:id)).recent end scope :with_associations, -> { includes(project: :namespace) } diff --git a/app/views/dashboard/_projects_head.html.haml b/app/views/dashboard/_projects_head.html.haml index ab2da1824c5..911f57f69e4 100644 --- a/app/views/dashboard/_projects_head.html.haml +++ b/app/views/dashboard/_projects_head.html.haml @@ -13,9 +13,9 @@ Explore Projects .nav-controls - = form_tag '', method: :get, class: 'project-list-form', id: 'project-list-form' do |f| + = form_tag request.original_url, method: :get, class: 'project-filter-form', id: 'project-filter-form' do |f| .append-right-10.hidden-xs.hidden-sm - = search_field_tag :filter_projects, params[:filter_projects], placeholder: 'Filter by name...', class: 'projects-list-filter form-control search-text-input', spellcheck: false, id: 'projects-list-filter' + = search_field_tag :filter_projects, params[:filter_projects], placeholder: 'Filter by name...', class: 'project-filter-form-field form-control search-text-input', spellcheck: false, id: 'project-filter-form-field' - if current_user.can_create_project? = link_to new_project_path, class: 'btn btn-new' do = icon('plus') diff --git a/app/views/dashboard/projects/_projects.html.haml b/app/views/dashboard/projects/_projects.html.haml index c08247cd9ac..933a3edd0f0 100644 --- a/app/views/dashboard/projects/_projects.html.haml +++ b/app/views/dashboard/projects/_projects.html.haml @@ -1,6 +1,6 @@ .projects-list-holder - = render 'shared/projects/list', ci: true + = render 'shared/projects/list', projects: @projects, ci: true :javascript - ProjectsList.init() + Dashboard.init() diff --git a/app/views/explore/projects/_projects.html.haml b/app/views/explore/projects/_projects.html.haml index b64a4918761..669079e9521 100644 --- a/app/views/explore/projects/_projects.html.haml +++ b/app/views/explore/projects/_projects.html.haml @@ -1,6 +1,6 @@ -- if @projects.any? +- if projects.any? .public-projects - = render 'shared/projects/list' + = render 'shared/projects/list', projects: projects - else .nothing-here-block No such projects diff --git a/app/views/explore/projects/starred.html.haml b/app/views/explore/projects/starred.html.haml index 0bdd0a57fe6..8450a1394c0 100644 --- a/app/views/explore/projects/starred.html.haml +++ b/app/views/explore/projects/starred.html.haml @@ -7,5 +7,5 @@ = render 'explore/head' = render 'explore/projects/nav' -= render 'projects', projects: @projects -= paginate @projects, theme: 'gitlab' += render 'projects', projects: @starred_projects += paginate @projects, theme: 'gitlab' if @projects diff --git a/app/views/explore/projects/trending.html.haml b/app/views/explore/projects/trending.html.haml index ec461755103..adcda810061 100644 --- a/app/views/explore/projects/trending.html.haml +++ b/app/views/explore/projects/trending.html.haml @@ -7,4 +7,4 @@ = render 'explore/head' = render 'explore/projects/nav' -= render 'projects', projects: @projects += render 'projects', projects: @trending_projects diff --git a/app/views/projects/show.atom.builder b/app/views/projects/show.atom.builder index 2468509242a..9b3d3f069d9 100644 --- a/app/views/projects/show.atom.builder +++ b/app/views/projects/show.atom.builder @@ -4,7 +4,7 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear xml.link href: namespace_project_url(@project.namespace, @project, format: :atom, private_token: current_user.try(:private_token)), rel: "self", type: "application/atom+xml" xml.link href: namespace_project_url(@project.namespace, @project), rel: "alternate", type: "text/html" xml.id namespace_project_url(@project.namespace, @project) - xml.updated @events[0].updated_at.xmlschema if @events[0? + xml.updated @events[0].updated_at.xmlschema if @events[0] @events.each do |event| event_to_atom(xml, event) diff --git a/app/views/shared/projects/_list.html.haml b/app/views/shared/projects/_list.html.haml index 80795063f6f..83188e58135 100644 --- a/app/views/shared/projects/_list.html.haml +++ b/app/views/shared/projects/_list.html.haml @@ -8,20 +8,22 @@ - show_last_commit_as_description = false unless local_assigns[:show_last_commit_as_description] == true %ul.projects-list - - if @projects.any? - - @projects.each_with_index do |project, i| + - if projects.any? + - projects.each_with_index do |project, i| - css_class = (i >= projects_limit) ? 'hide' : nil = render "shared/projects/project", project: project, skip_namespace: skip_namespace, avatar: avatar, stars: stars, css_class: css_class, ci: ci, use_creator_avatar: use_creator_avatar, forks: forks, show_last_commit_as_description: show_last_commit_as_description - - if @projects.size > projects_limit + - if projects.size > projects_limit %li.bottom.center .light - #{projects_limit} of #{pluralize(@projects.count, 'project')} displayed. + #{projects_limit} of #{pluralize(projects.count, 'project')} displayed. = link_to '#', class: 'js-expand' do Show all - = paginate @projects, theme: "gitlab" + = paginate projects, theme: "gitlab" if !projects.kind_of?(Array) - else %h3 No projects found - %p.slead Try searching for a different project. + +:javascript + new ProjectsList(); -- cgit v1.2.1 From 6e79ce2efd68b59f3814c1107f6bd70c95fa1405 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Fri, 18 Dec 2015 14:20:15 +0100 Subject: Allow link_to_label to take an optional type arg You can set type: :merge_request to create a link to merge request lists instead of issues list. Accept both Symbol & String as type argument for the link_to_label helper --- CHANGELOG | 1 + app/helpers/labels_helper.rb | 13 +++++++-- .../merge_requests/_merge_request.html.haml | 2 +- app/views/shared/issuable/_sidebar.html.haml | 4 +-- spec/helpers/labels_helper_spec.rb | 33 ++++++++++------------ 5 files changed, 29 insertions(+), 24 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index b7e8822fdd6..d43b8f69063 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -13,6 +13,7 @@ v 8.5.0 (unreleased) set it up - Fix diff comments loaded by AJAX to load comment with diff in discussion tab - Whitelist raw "abbr" elements when parsing Markdown (Benedict Etzel) + - Fix label links for a merge request pointing to issues list - Don't vendor minified JS - Display 404 error on group not found - Track project import failure diff --git a/app/helpers/labels_helper.rb b/app/helpers/labels_helper.rb index 92eac0560bd..1c7fcc13b42 100644 --- a/app/helpers/labels_helper.rb +++ b/app/helpers/labels_helper.rb @@ -7,6 +7,8 @@ module LabelsHelper # project - Project object which will be used as the context for the label's # link. If omitted, defaults to `@project`, or the label's own # project. + # type - The type of item the link will point to (:issue or + # :merge_request). If omitted, defaults to :issue. # block - An optional block that will be passed to `link_to`, forming the # body of the link element. If omitted, defaults to # `render_colored_label`. @@ -23,14 +25,19 @@ module LabelsHelper # # Force the generated link to use a provided project # link_to_label(label, project: Project.last) # + # # Force the generated link to point to merge requests instead of issues + # link_to_label(label, type: :merge_request) + # # # Customize link body with a block # link_to_label(label) { "My Custom Label Text" } # # Returns a String - def link_to_label(label, project: nil, &block) + def link_to_label(label, project: nil, type: :issue, &block) project ||= @project || label.project - link = namespace_project_issues_path(project.namespace, project, - label_name: label.name) + link = send("namespace_project_#{type.to_s.pluralize}_path", + project.namespace, + project, + label_name: label.name) if block_given? link_to link, &block diff --git a/app/views/projects/merge_requests/_merge_request.html.haml b/app/views/projects/merge_requests/_merge_request.html.haml index a051729dc32..e25bf917b43 100644 --- a/app/views/projects/merge_requests/_merge_request.html.haml +++ b/app/views/projects/merge_requests/_merge_request.html.haml @@ -53,7 +53,7 @@ - if merge_request.labels.any?   - merge_request.labels.each do |label| - = link_to_label(label, project: merge_request.project) + = link_to_label(label, project: merge_request.project, type: 'merge_request') - if merge_request.tasks?   %span.task-status diff --git a/app/views/shared/issuable/_sidebar.html.haml b/app/views/shared/issuable/_sidebar.html.haml index cab500d7244..75a7d9be2c1 100644 --- a/app/views/shared/issuable/_sidebar.html.haml +++ b/app/views/shared/issuable/_sidebar.html.haml @@ -90,7 +90,7 @@ .value.issuable-show-labels - if issuable.labels.any? - issuable.labels.each do |label| - = link_to_label(label) + = link_to_label(label, type: issuable.to_ability_name) - else .light None .selectbox @@ -129,4 +129,4 @@ :javascript new Subscription("#{toggle_subscription_path(issuable)}"); - new IssuableContext(); \ No newline at end of file + new IssuableContext(); diff --git a/spec/helpers/labels_helper_spec.rb b/spec/helpers/labels_helper_spec.rb index 0b9176357bc..4f129eca183 100644 --- a/spec/helpers/labels_helper_spec.rb +++ b/spec/helpers/labels_helper_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe LabelsHelper do describe 'link_to_label' do let(:project) { create(:empty_project) } - let(:label) { create(:label, project: project) } + let(:label) { create(:label, project: project) } context 'with @project set' do before do @@ -11,34 +11,31 @@ describe LabelsHelper do end it 'uses the instance variable' do - expect(label).not_to receive(:project) - link_to_label(label) + expect(link_to_label(label)).to match %r{.*} end end context 'without @project set' do it "uses the label's project" do - expect(label).to receive(:project).and_return(project) - link_to_label(label) + expect(link_to_label(label)).to match %r{.*} end end - context 'with a named project argument' do - it 'uses the provided project' do - arg = double('project') - expect(arg).to receive(:namespace).and_return('foo') - expect(arg).to receive(:to_param).and_return('foo') + context 'with a project argument' do + let(:another_project) { double('project', namespace: 'foo3', to_param: 'bar3') } - link_to_label(label, project: arg) + it 'links to merge requests page' do + expect(link_to_label(label, project: another_project)).to match %r{.*} end + end - it 'takes precedence over other types' do - @project = project - expect(@project).not_to receive(:namespace) - expect(label).not_to receive(:project) - - arg = double('project', namespace: 'foo', to_param: 'foo') - link_to_label(label, project: arg) + context 'with a type argument' do + ['issue', :issue, 'merge_request', :merge_request].each do |type| + context "set to #{type}" do + it 'links to correct page' do + expect(link_to_label(label, type: type)).to match %r{.*} + end + end end end -- cgit v1.2.1 From 74a4ff614335ce82d92a7501227898053f806b6e Mon Sep 17 00:00:00 2001 From: Josh Frye Date: Thu, 4 Feb 2016 13:24:43 -0500 Subject: Remove js line --- app/assets/javascripts/dashboard.js.coffee | 1 - 1 file changed, 1 deletion(-) diff --git a/app/assets/javascripts/dashboard.js.coffee b/app/assets/javascripts/dashboard.js.coffee index 0229c588b41..e96b84147ba 100644 --- a/app/assets/javascripts/dashboard.js.coffee +++ b/app/assets/javascripts/dashboard.js.coffee @@ -27,4 +27,3 @@ # Change url so if user reload a page - search results are saved history.replaceState {page: project_filter_url}, document.title, project_filter_url dataType: "json" - #uiBox.find("ul.projects-list li.bottom").hide() -- cgit v1.2.1 From b263ab618c59ff9e377780c6120ab60fd97aefd0 Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Thu, 4 Feb 2016 16:30:33 +0100 Subject: Dedicated method for counting commits between refs gitlab_git 8.1 adds the ability to count the amount of commits between two references without having to allocate anything but regular Rugged::Commit objects. This in turn speeds up the process of counting the number of commits a branch is ahead/behind by about 3.5x. --- Gemfile | 2 +- Gemfile.lock | 4 ++-- app/models/repository.rb | 7 +++++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/Gemfile b/Gemfile index a06dbe8e061..08fb9216e9f 100644 --- a/Gemfile +++ b/Gemfile @@ -50,7 +50,7 @@ gem "browser", '~> 1.0.0' # Extracting information from a git repository # Provide access to Gitlab::Git library -gem "gitlab_git", '~> 8.0.0' +gem "gitlab_git", '~> 8.1' # LDAP Auth # GitLab fork with several improvements to original library. For full list of changes diff --git a/Gemfile.lock b/Gemfile.lock index bd767016108..88496163c89 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -357,7 +357,7 @@ GEM posix-spawn (~> 0.3) gitlab_emoji (0.2.0) gemojione (~> 2.1) - gitlab_git (8.0.0) + gitlab_git (8.1.0) activesupport (~> 4.0) charlock_holmes (~> 0.7.3) github-linguist (~> 4.7.0) @@ -933,7 +933,7 @@ DEPENDENCIES github-markup (~> 1.3.1) gitlab-flowdock-git-hook (~> 1.0.1) gitlab_emoji (~> 0.2.0) - gitlab_git (~> 8.0.0) + gitlab_git (~> 8.1) gitlab_meta (= 7.0) gitlab_omniauth-ldap (~> 1.2.1) gollum-lib (~> 4.1.0) diff --git a/app/models/repository.rb b/app/models/repository.rb index 130daddd9d1..e813c946bc1 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -184,8 +184,11 @@ class Repository cache.fetch(:"diverging_commit_counts_#{branch.name}") do # Rugged seems to throw a `ReferenceError` when given branch_names rather # than SHA-1 hashes - number_commits_behind = commits_between(branch.target, root_ref_hash).size - number_commits_ahead = commits_between(root_ref_hash, branch.target).size + number_commits_behind = raw_repository. + count_commits_between(branch.target, root_ref_hash) + + number_commits_ahead = raw_repository. + count_commits_between(root_ref_hash, branch.target) { behind: number_commits_behind, ahead: number_commits_ahead } end -- cgit v1.2.1 From 34096bf3494007ecc5135dfa9f661439c107ab60 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 4 Feb 2016 19:44:52 +0100 Subject: New padding for lists * improve consistency for list padding * reduce padding for project/group/events lists Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/framework/avatar.scss | 4 +++- app/assets/stylesheets/framework/lists.scss | 1 - app/assets/stylesheets/framework/variables.scss | 2 +- app/assets/stylesheets/pages/dashboard.scss | 4 ---- app/assets/stylesheets/pages/events.scss | 9 +++------ app/assets/stylesheets/pages/issues.scss | 6 +----- app/assets/stylesheets/pages/projects.scss | 5 ++--- app/views/events/_event.html.haml | 4 ++-- app/views/shared/groups/_group.html.haml | 2 +- app/views/shared/projects/_project.html.haml | 4 ++-- 10 files changed, 15 insertions(+), 26 deletions(-) diff --git a/app/assets/stylesheets/framework/avatar.scss b/app/assets/stylesheets/framework/avatar.scss index 36e582d4854..b7ffa3e6ffb 100644 --- a/app/assets/stylesheets/framework/avatar.scss +++ b/app/assets/stylesheets/framework/avatar.scss @@ -24,6 +24,7 @@ &.s26 { width: 26px; height: 26px; margin-right: 8px; } &.s32 { width: 32px; height: 32px; margin-right: 10px; } &.s36 { width: 36px; height: 36px; margin-right: 10px; } + &.s40 { width: 40px; height: 40px; margin-right: 10px; } &.s46 { width: 46px; height: 46px; margin-right: 15px; } &.s48 { width: 48px; height: 48px; margin-right: 10px; } &.s60 { width: 60px; height: 60px; margin-right: 12px; } @@ -40,7 +41,8 @@ &.s16 { font-size: 12px; line-height: 1.33; } &.s24 { font-size: 14px; line-height: 1.8; } &.s26 { font-size: 20px; line-height: 1.33; } - &.s32 { font-size: 22px; line-height: 32px; } + &.s32 { font-size: 20px; line-height: 32px; } + &.s40 { font-size: 16px; line-height: 40px; } &.s60 { font-size: 32px; line-height: 60px; } &.s90 { font-size: 36px; line-height: 90px; } &.s110 { font-size: 40px; line-height: 112px; font-weight: 300; } diff --git a/app/assets/stylesheets/framework/lists.scss b/app/assets/stylesheets/framework/lists.scss index c6bc6fb324d..5c65383ec1a 100644 --- a/app/assets/stylesheets/framework/lists.scss +++ b/app/assets/stylesheets/framework/lists.scss @@ -109,7 +109,6 @@ ul.content-list { padding: 0; > li { - padding: $gl-padding 0; border-color: $table-border-color; color: $gl-gray; diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss index 44d3d7715d2..efc3366e99c 100644 --- a/app/assets/stylesheets/framework/variables.scss +++ b/app/assets/stylesheets/framework/variables.scss @@ -28,7 +28,7 @@ $gl-padding: 16px; $gl-btn-padding: 10px; $gl-vert-padding: 6px; $gl-padding-top:10px; -$gl-avatar-size: 46px; +$gl-avatar-size: 40px; $secondary-text: #7f8fa4; $error-exclamation-point: #E62958; diff --git a/app/assets/stylesheets/pages/dashboard.scss b/app/assets/stylesheets/pages/dashboard.scss index 25a86cd0f94..88639399148 100644 --- a/app/assets/stylesheets/pages/dashboard.scss +++ b/app/assets/stylesheets/pages/dashboard.scss @@ -40,10 +40,6 @@ .avatar { @include border-radius(50%); } - - .identicon { - line-height: 46px; - } } .dash-project-access-icon { diff --git a/app/assets/stylesheets/pages/events.scss b/app/assets/stylesheets/pages/events.scss index 8fa15b35748..35df9a61c86 100644 --- a/app/assets/stylesheets/pages/events.scss +++ b/app/assets/stylesheets/pages/events.scss @@ -4,7 +4,7 @@ */ .event-item { font-size: $gl-font-size; - padding: $gl-padding 0 $gl-padding ($gl-avatar-size + 15px); + padding: $gl-padding-top 0 $gl-padding-top ($gl-avatar-size + $gl-padding-top); border-bottom: 1px solid $table-border-color; color: #7f8fa4; @@ -16,7 +16,7 @@ .event-title, .event-item-timestamp { - line-height: 44px; + line-height: 40px; } } @@ -25,7 +25,7 @@ } .avatar { - margin-left: -($gl-avatar-size + 15px); + margin-left: -($gl-avatar-size + $gl-padding-top); } .event-title { @@ -41,7 +41,6 @@ margin-right: 174px; .event-note { - margin-top: 5px; word-wrap: break-word; .md { @@ -98,8 +97,6 @@ &:last-child { border:none } .event_commits { - margin-top: 9px; - li { &.commit { background: transparent; diff --git a/app/assets/stylesheets/pages/issues.scss b/app/assets/stylesheets/pages/issues.scss index dd6a251f811..8694bd654a7 100644 --- a/app/assets/stylesheets/pages/issues.scss +++ b/app/assets/stylesheets/pages/issues.scss @@ -65,10 +65,6 @@ form.edit-issue { width: 3em; } -.merge-request-info { - padding-left: 5px; -} - .merge-request-status { color: $gl-gray; font-size: 15px; @@ -143,4 +139,4 @@ form.edit-issue { .issue-closed-by-widget { color: $secondary-text; margin-left: 52px; -} \ No newline at end of file +} diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss index dd4ff39c5b8..046bae672fc 100644 --- a/app/assets/stylesheets/pages/projects.scss +++ b/app/assets/stylesheets/pages/projects.scss @@ -391,12 +391,11 @@ pre.light-well { @include basic-list; .project-row { - padding: $gl-padding 0; border-color: $table-border-color; &.no-description { .project { - line-height: 44px; + line-height: 40px; } } @@ -409,7 +408,7 @@ pre.light-well { .project-controls { float: right; color: $gl-gray; - line-height: 45px; + line-height: 40px; color: #7f8fa4; a:hover { diff --git a/app/views/events/_event.html.haml b/app/views/events/_event.html.haml index 46432a92348..36fb2d51629 100644 --- a/app/views/events/_event.html.haml +++ b/app/views/events/_event.html.haml @@ -3,8 +3,8 @@ .event-item-timestamp #{time_ago_with_tooltip(event.created_at)} - = cache [event, current_application_settings, "v2.1"] do - = image_tag avatar_icon(event.author_email, 46), class: "avatar s46", alt:'' + = cache [event, current_application_settings, "v2.2"] do + = image_tag avatar_icon(event.author_email, 40), class: "avatar s40", alt:'' - if event.created_project? = render "events/event/created_project", event: event - elsif event.push? diff --git a/app/views/shared/groups/_group.html.haml b/app/views/shared/groups/_group.html.haml index f7fe6b02641..289b0bfe1eb 100644 --- a/app/views/shared/groups/_group.html.haml +++ b/app/views/shared/groups/_group.html.haml @@ -21,7 +21,7 @@ = icon('users') = number_with_delimiter(group.users.count) - = image_tag group_icon(group), class: "avatar s46 hidden-xs" + = image_tag group_icon(group), class: "avatar s40 hidden-xs" = link_to group, class: 'group-name' do %span.item-title= group.name diff --git a/app/views/shared/projects/_project.html.haml b/app/views/shared/projects/_project.html.haml index e196fc51d2d..00bf9dcd2d5 100644 --- a/app/views/shared/projects/_project.html.haml +++ b/app/views/shared/projects/_project.html.haml @@ -16,9 +16,9 @@ - if avatar .dash-project-avatar - if use_creator_avatar - = image_tag avatar_icon(project.creator.email, 46), class: "avatar s46", alt:'' + = image_tag avatar_icon(project.creator.email, 40), class: "avatar s40", alt:'' - else - = project_icon(project, alt: '', class: 'avatar project-avatar s46') + = project_icon(project, alt: '', class: 'avatar project-avatar s40') %span.project-full-name %span.namespace-name - if project.namespace && !skip_namespace -- cgit v1.2.1 From 3f1bd844f1f645d3d97caec4aa2504fde63b31fd Mon Sep 17 00:00:00 2001 From: Josh Frye Date: Thu, 4 Feb 2016 14:02:19 -0500 Subject: Implement changes from MR feedback --- app/controllers/explore/projects_controller.rb | 12 ++++++------ app/views/dashboard/_projects_head.html.haml | 14 +++++++------- app/views/explore/projects/starred.html.haml | 2 +- app/views/explore/projects/trending.html.haml | 2 +- app/views/shared/projects/_list.html.haml | 2 +- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/app/controllers/explore/projects_controller.rb b/app/controllers/explore/projects_controller.rb index a5aeaed66c5..2689bf4f1ec 100644 --- a/app/controllers/explore/projects_controller.rb +++ b/app/controllers/explore/projects_controller.rb @@ -11,14 +11,14 @@ class Explore::ProjectsController < Explore::ApplicationController end def trending - @trending_projects = TrendingProjectsFinder.new.execute(current_user) - @trending_projects = @trending_projects.non_archived - @trending_projects = @trending_projects.page(params[:page]).per(PER_PAGE) + @projects = TrendingProjectsFinder.new.execute(current_user) + @projects = @projects.non_archived + @projects = @projects.page(params[:page]).per(PER_PAGE) end def starred - @starred_projects = ProjectsFinder.new.execute(current_user) - @starred_projects = @starred_projects.reorder('star_count DESC') - @starred_projects = @starred_projects.page(params[:page]).per(PER_PAGE) + @projects = ProjectsFinder.new.execute(current_user) + @projects = @projects.reorder('star_count DESC') + @projects = @projects.page(params[:page]).per(PER_PAGE) end end diff --git a/app/views/dashboard/_projects_head.html.haml b/app/views/dashboard/_projects_head.html.haml index 911f57f69e4..91712ce6fc5 100644 --- a/app/views/dashboard/_projects_head.html.haml +++ b/app/views/dashboard/_projects_head.html.haml @@ -13,10 +13,10 @@ Explore Projects .nav-controls - = form_tag request.original_url, method: :get, class: 'project-filter-form', id: 'project-filter-form' do |f| - .append-right-10.hidden-xs.hidden-sm - = search_field_tag :filter_projects, params[:filter_projects], placeholder: 'Filter by name...', class: 'project-filter-form-field form-control search-text-input', spellcheck: false, id: 'project-filter-form-field' - - if current_user.can_create_project? - = link_to new_project_path, class: 'btn btn-new' do - = icon('plus') - New Project + .pull-right + = form_tag request.original_url, method: :get, class: 'pull-left project-filter-form', id: 'project-filter-form' do |f| + = search_field_tag :filter_projects, params[:filter_projects], placeholder: 'Filter by name...', class: 'pull-left form-control project-filter-form-field form-control', spellcheck: false, id: 'project-filter-form-field' + - if current_user.can_create_project? + = link_to new_project_path, class: 'btn btn-new pull-left' do + = icon('plus') + New Project diff --git a/app/views/explore/projects/starred.html.haml b/app/views/explore/projects/starred.html.haml index 8450a1394c0..1b5269c7b68 100644 --- a/app/views/explore/projects/starred.html.haml +++ b/app/views/explore/projects/starred.html.haml @@ -7,5 +7,5 @@ = render 'explore/head' = render 'explore/projects/nav' -= render 'projects', projects: @starred_projects += render 'projects', projects: @projects = paginate @projects, theme: 'gitlab' if @projects diff --git a/app/views/explore/projects/trending.html.haml b/app/views/explore/projects/trending.html.haml index adcda810061..ec461755103 100644 --- a/app/views/explore/projects/trending.html.haml +++ b/app/views/explore/projects/trending.html.haml @@ -7,4 +7,4 @@ = render 'explore/head' = render 'explore/projects/nav' -= render 'projects', projects: @trending_projects += render 'projects', projects: @projects diff --git a/app/views/shared/projects/_list.html.haml b/app/views/shared/projects/_list.html.haml index 83188e58135..67edb264b7e 100644 --- a/app/views/shared/projects/_list.html.haml +++ b/app/views/shared/projects/_list.html.haml @@ -15,7 +15,7 @@ avatar: avatar, stars: stars, css_class: css_class, ci: ci, use_creator_avatar: use_creator_avatar, forks: forks, show_last_commit_as_description: show_last_commit_as_description - - if projects.size > projects_limit + - if projects.size > projects_limit && projects.kind_of?(Array) %li.bottom.center .light #{projects_limit} of #{pluralize(projects.count, 'project')} displayed. -- cgit v1.2.1 From 5f38dbc026add6b4afd2d74b4b664d2c63e12222 Mon Sep 17 00:00:00 2001 From: Drew Blessing Date: Thu, 4 Feb 2016 13:40:42 -0600 Subject: Increase project import timeout from 4 minutes to 15 minutes Many users were experiencing timeouts when we only allowed 4 minutes before a timeout. A 15 minute timeout is more than reasonable and prevents us from having to add a configuration for this. Fixes gitlab-org/gitlab-ee#246 --- CHANGELOG | 1 + app/views/shared/_import_form.html.haml | 2 +- lib/gitlab/backend/shell.rb | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index b7e8822fdd6..76e776742b4 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -14,6 +14,7 @@ v 8.5.0 (unreleased) - Fix diff comments loaded by AJAX to load comment with diff in discussion tab - Whitelist raw "abbr" elements when parsing Markdown (Benedict Etzel) - Don't vendor minified JS + - Increase project import timeout to 15 minutes - Display 404 error on group not found - Track project import failure - Support Two-factor Authentication for LDAP users diff --git a/app/views/shared/_import_form.html.haml b/app/views/shared/_import_form.html.haml index 285af56ad73..627814bcfae 100644 --- a/app/views/shared/_import_form.html.haml +++ b/app/views/shared/_import_form.html.haml @@ -11,6 +11,6 @@ %li If your HTTP repository is not publicly accessible, add authentication information to the URL: https://username:password@gitlab.company.com/group/project.git. %li - The import will time out after 4 minutes. For big repositories, use a clone/push combination. + The import will time out after 15 minutes. For repositories that take longer, use a clone/push combination. %li To migrate an SVN repository, check out #{link_to "this document", "http://doc.gitlab.com/ce/workflow/importing/migrating_from_svn.html"}. diff --git a/lib/gitlab/backend/shell.rb b/lib/gitlab/backend/shell.rb index f751458ac66..b9bb6e76081 100644 --- a/lib/gitlab/backend/shell.rb +++ b/lib/gitlab/backend/shell.rb @@ -36,7 +36,7 @@ module Gitlab # import_repository("gitlab/gitlab-ci", "https://github.com/randx/six.git") # def import_repository(name, url) - output, status = Popen::popen([gitlab_shell_projects_path, 'import-project', "#{name}.git", url, '240']) + output, status = Popen::popen([gitlab_shell_projects_path, 'import-project', "#{name}.git", url, '900']) raise Error, output unless status.zero? true end -- cgit v1.2.1 From 5d2299ac210df52fefecd507073367952099c91a Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Thu, 4 Feb 2016 14:56:25 -0500 Subject: Fix diff and commit view on merge requests with new sidebar Fixes #3981 --- app/helpers/nav_helper.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/helpers/nav_helper.rb b/app/helpers/nav_helper.rb index 2c299d1d794..75f2ed5e054 100644 --- a/app/helpers/nav_helper.rb +++ b/app/helpers/nav_helper.rb @@ -32,8 +32,10 @@ module NavHelper end def page_gutter_class - - if current_path?('merge_requests#show') || current_path?('issues#show') + if current_path?('merge_requests#show') || + current_path?('merge_requests#diffs') || + current_path?('merge_requests#commits') || + current_path?('issues#show') if cookies[:collapsed_gutter] == 'true' "page-gutter right-sidebar-collapsed" else -- cgit v1.2.1 From be3399868cbcfdce85daa6fdf53a079bc163056a Mon Sep 17 00:00:00 2001 From: Zeger-Jan van de Weg Date: Mon, 2 Nov 2015 19:02:08 +0100 Subject: Minor refactoring on Gitlab::Git --- lib/gitlab/git.rb | 7 ++++--- spec/lib/gitlab/git_spec.rb | 9 +++++++++ 2 files changed, 13 insertions(+), 3 deletions(-) create mode 100644 spec/lib/gitlab/git_spec.rb diff --git a/lib/gitlab/git.rb b/lib/gitlab/git.rb index f065cc5e9e9..a33daeb119f 100644 --- a/lib/gitlab/git.rb +++ b/lib/gitlab/git.rb @@ -1,8 +1,9 @@ module Gitlab module Git - BLANK_SHA = '0' * 40 - TAG_REF_PREFIX = "refs/tags/" - BRANCH_REF_PREFIX = "refs/heads/" + # '0' * 40 -- this was easyer to freeze + BLANK_SHA = "0000000000000000000000000000000000000000".freeze + TAG_REF_PREFIX = "refs/tags/".freeze + BRANCH_REF_PREFIX = "refs/heads/".freeze class << self def ref_name(ref) diff --git a/spec/lib/gitlab/git_spec.rb b/spec/lib/gitlab/git_spec.rb new file mode 100644 index 00000000000..3b4052fa549 --- /dev/null +++ b/spec/lib/gitlab/git_spec.rb @@ -0,0 +1,9 @@ +require 'spec_helper' + +describe Gitlab::Git do + describe "BLANK_SHA" do + it "is a string of 40 zero's" do + expect(Gitlab::Git::BLANK_SHA).to eq('0' * 40) + end + end +end -- cgit v1.2.1 From 5ffec2c953478fbad35d7e7f4fc4b6eb119d7918 Mon Sep 17 00:00:00 2001 From: Zeger-Jan van de Weg Date: Tue, 3 Nov 2015 13:09:18 +0100 Subject: Freeze the expression instead of the literal Also remove the spec for it --- lib/gitlab/git.rb | 3 +-- spec/lib/gitlab/git_spec.rb | 9 --------- 2 files changed, 1 insertion(+), 11 deletions(-) delete mode 100644 spec/lib/gitlab/git_spec.rb diff --git a/lib/gitlab/git.rb b/lib/gitlab/git.rb index a33daeb119f..191bea86ac3 100644 --- a/lib/gitlab/git.rb +++ b/lib/gitlab/git.rb @@ -1,7 +1,6 @@ module Gitlab module Git - # '0' * 40 -- this was easyer to freeze - BLANK_SHA = "0000000000000000000000000000000000000000".freeze + BLANK_SHA = ('0' * 40).freeze TAG_REF_PREFIX = "refs/tags/".freeze BRANCH_REF_PREFIX = "refs/heads/".freeze diff --git a/spec/lib/gitlab/git_spec.rb b/spec/lib/gitlab/git_spec.rb deleted file mode 100644 index 3b4052fa549..00000000000 --- a/spec/lib/gitlab/git_spec.rb +++ /dev/null @@ -1,9 +0,0 @@ -require 'spec_helper' - -describe Gitlab::Git do - describe "BLANK_SHA" do - it "is a string of 40 zero's" do - expect(Gitlab::Git::BLANK_SHA).to eq('0' * 40) - end - end -end -- cgit v1.2.1 From f8526fef0b2bde3b517ee993e5cef48c6c8f5da7 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 5 Feb 2016 11:10:44 +0100 Subject: Fix project filter form rendering Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/framework/nav.scss | 4 ++++ app/views/dashboard/_projects_head.html.haml | 14 +++++++------- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/app/assets/stylesheets/framework/nav.scss b/app/assets/stylesheets/framework/nav.scss index e6c59f5a291..252a586358c 100644 --- a/app/assets/stylesheets/framework/nav.scss +++ b/app/assets/stylesheets/framework/nav.scss @@ -85,6 +85,10 @@ display: inline-block; } + > form { + display: inline-block; + } + input { height: 34px; display: inline-block; diff --git a/app/views/dashboard/_projects_head.html.haml b/app/views/dashboard/_projects_head.html.haml index 91712ce6fc5..d46998ec1e9 100644 --- a/app/views/dashboard/_projects_head.html.haml +++ b/app/views/dashboard/_projects_head.html.haml @@ -13,10 +13,10 @@ Explore Projects .nav-controls - .pull-right - = form_tag request.original_url, method: :get, class: 'pull-left project-filter-form', id: 'project-filter-form' do |f| - = search_field_tag :filter_projects, params[:filter_projects], placeholder: 'Filter by name...', class: 'pull-left form-control project-filter-form-field form-control', spellcheck: false, id: 'project-filter-form-field' - - if current_user.can_create_project? - = link_to new_project_path, class: 'btn btn-new pull-left' do - = icon('plus') - New Project + = form_tag request.original_url, method: :get, class: 'project-filter-form', id: 'project-filter-form' do |f| + = search_field_tag :filter_projects, params[:filter_projects], placeholder: 'Filter by name...', class: 'project-filter-form-field form-control input-short', spellcheck: false, id: 'project-filter-form-field' + = render 'explore/projects/dropdown' + - if current_user.can_create_project? + = link_to new_project_path, class: 'btn btn-new' do + = icon('plus') + New Project -- cgit v1.2.1 From ce39d62c3be5a22cf81904198df2aa201dc0a8cd Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 5 Feb 2016 11:14:38 +0100 Subject: Add support for inline form in nav-controls component Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/framework/nav.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/assets/stylesheets/framework/nav.scss b/app/assets/stylesheets/framework/nav.scss index e6c59f5a291..252a586358c 100644 --- a/app/assets/stylesheets/framework/nav.scss +++ b/app/assets/stylesheets/framework/nav.scss @@ -85,6 +85,10 @@ display: inline-block; } + > form { + display: inline-block; + } + input { height: 34px; display: inline-block; -- cgit v1.2.1 From 92586360217c950ad255fd6ea006c41fd38e3d7f Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 5 Feb 2016 11:35:55 +0100 Subject: Re-use top-are css component for issues/mr pages Signed-off-by: Dmitriy Zaporozhets --- app/views/dashboard/issues.html.haml | 16 ++++++------- app/views/dashboard/merge_requests.html.haml | 7 +++--- app/views/groups/issues.html.haml | 16 ++++++------- app/views/groups/merge_requests.html.haml | 7 +++--- app/views/projects/issues/index.html.haml | 21 +++++++--------- app/views/projects/merge_requests/index.html.haml | 17 +++++++------ app/views/shared/issuable/_filter.html.haml | 29 +---------------------- app/views/shared/issuable/_nav.html.haml | 25 +++++++++++++++++++ app/views/shared/issuable/_search_form.html.haml | 17 +++++++------ 9 files changed, 75 insertions(+), 80 deletions(-) create mode 100644 app/views/shared/issuable/_nav.html.haml diff --git a/app/views/dashboard/issues.html.haml b/app/views/dashboard/issues.html.haml index f363f035974..dfa5f80eef8 100644 --- a/app/views/dashboard/issues.html.haml +++ b/app/views/dashboard/issues.html.haml @@ -4,17 +4,15 @@ - if current_user = auto_discovery_link_tag(:atom, issues_dashboard_url(format: :atom, private_token: current_user.private_token), title: "#{current_user.name} issues") -.project-issuable-filter - .controls - .pull-left - - if current_user - .hidden-xs.pull-left - = link_to issues_dashboard_url(format: :atom, private_token: current_user.private_token), class: 'btn' do - %i.fa.fa-rss - +.top-area + = render 'shared/issuable/nav', type: :issues + .nav-controls + - if current_user + = link_to issues_dashboard_url(format: :atom, private_token: current_user.private_token), class: 'btn' do + = icon('rss') = render 'shared/new_project_item_select', path: 'issues/new', label: "New Issue" - = render 'shared/issuable/filter', type: :issues += render 'shared/issuable/filter', type: :issues .prepend-top-default = render 'shared/issues' diff --git a/app/views/dashboard/merge_requests.html.haml b/app/views/dashboard/merge_requests.html.haml index bbe4cc1f824..fb016599fef 100644 --- a/app/views/dashboard/merge_requests.html.haml +++ b/app/views/dashboard/merge_requests.html.haml @@ -1,11 +1,12 @@ - page_title "Merge Requests" - header_title "Merge Requests", merge_requests_dashboard_path(assignee_id: current_user.id) -.project-issuable-filter - .controls +.top-area + = render 'shared/issuable/nav', type: :merge_requests + .nav-controls = render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New Merge Request" - = render 'shared/issuable/filter', type: :merge_requests += render 'shared/issuable/filter', type: :merge_requests .prepend-top-default = render 'shared/merge_requests' diff --git a/app/views/groups/issues.html.haml b/app/views/groups/issues.html.haml index 90ade1e1680..b0805593fdc 100644 --- a/app/views/groups/issues.html.haml +++ b/app/views/groups/issues.html.haml @@ -4,17 +4,15 @@ - if current_user = auto_discovery_link_tag(:atom, issues_group_url(@group, format: :atom, private_token: current_user.private_token), title: "#{@group.name} issues") -.project-issuable-filter - .controls - .pull-left - - if current_user - .hidden-xs.pull-left - = link_to issues_group_url(@group, format: :atom, private_token: current_user.private_token), class: 'btn' do - %i.fa.fa-rss - +.top-area + = render 'shared/issuable/nav', type: :issues + .nav-controls + - if current_user + = link_to issues_group_url(@group, format: :atom, private_token: current_user.private_token), class: 'btn' do + = icon('rss') = render 'shared/new_project_item_select', path: 'issues/new', label: "New Issue" - = render 'shared/issuable/filter', type: :issues += render 'shared/issuable/filter', type: :issues .gray-content-block.second-block Only issues from diff --git a/app/views/groups/merge_requests.html.haml b/app/views/groups/merge_requests.html.haml index f662f5a8c17..e1c9dd931ee 100644 --- a/app/views/groups/merge_requests.html.haml +++ b/app/views/groups/merge_requests.html.haml @@ -1,11 +1,12 @@ - page_title "Merge Requests" - header_title group_title(@group, "Merge Requests", merge_requests_group_path(@group)) -.project-issuable-filter - .controls +.top-area + = render 'shared/issuable/nav', type: :merge_requests + .nav-controls = render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New Merge Request" - = render 'shared/issuable/filter', type: :merge_requests += render 'shared/issuable/filter', type: :merge_requests .gray-content-block.second-block Only merge requests from diff --git a/app/views/projects/issues/index.html.haml b/app/views/projects/issues/index.html.haml index d6260ab2900..fde9304c0f8 100644 --- a/app/views/projects/issues/index.html.haml +++ b/app/views/projects/issues/index.html.haml @@ -5,22 +5,19 @@ - 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") -.project-issuable-filter - .controls - .pull-left - - if current_user - .hidden-xs.pull-left - = link_to namespace_project_issues_path(@project.namespace, @project, :atom, { private_token: current_user.private_token }), class: 'btn append-right-10' do - %i.fa.fa-rss - +.top-area + = render 'shared/issuable/nav', type: :issues + .nav-controls + - if current_user + = link_to namespace_project_issues_path(@project.namespace, @project, :atom, { private_token: current_user.private_token }), class: 'btn append-right-10' do + = icon('rss') = render 'shared/issuable/search_form', path: namespace_project_issues_path(@project.namespace, @project) - - if can? current_user, :create_issue, @project - = link_to new_namespace_project_issue_path(@project.namespace, @project, issue: { assignee_id: @issuable_finder.assignee.try(:id), milestone_id: @issuable_finder.milestones.try(:first).try(:id) }), class: "btn btn-new pull-left", title: "New Issue", id: "new_issue_link" do - %i.fa.fa-plus + = link_to new_namespace_project_issue_path(@project.namespace, @project, issue: { assignee_id: @issuable_finder.assignee.try(:id), milestone_id: @issuable_finder.milestones.try(:first).try(:id) }), class: "btn btn-new", title: "New Issue", id: "new_issue_link" do + = icon('plus') New Issue - = render 'shared/issuable/filter', type: :issues += render 'shared/issuable/filter', type: :issues .issues-holder = render "issues" diff --git a/app/views/projects/merge_requests/index.html.haml b/app/views/projects/merge_requests/index.html.haml index 8d5d0394a82..e56a44e0a79 100644 --- a/app/views/projects/merge_requests/index.html.haml +++ b/app/views/projects/merge_requests/index.html.haml @@ -2,16 +2,19 @@ = render "header_title" = render 'projects/last_push' -.project-issuable-filter - .controls + +.top-area + = render 'shared/issuable/nav', type: :merge_requests + .nav-controls = render 'shared/issuable/search_form', path: namespace_project_merge_requests_path(@project.namespace, @project) - merge_project = can?(current_user, :create_merge_request, @project) ? @project : (current_user && current_user.fork_of(@project)) - if merge_project - .pull-left.hidden-xs - = link_to new_namespace_project_merge_request_path(merge_project.namespace, merge_project), class: "btn btn-new", title: "New Merge Request" do - %i.fa.fa-plus - New Merge Request - = render 'shared/issuable/filter', type: :merge_requests + = link_to new_namespace_project_merge_request_path(merge_project.namespace, merge_project), class: "btn btn-new", title: "New Merge Request" do + = icon('plus') + New Merge Request + += render 'shared/issuable/filter', type: :merge_requests + .merge-requests-holder = render 'merge_requests' diff --git a/app/views/shared/issuable/_filter.html.haml b/app/views/shared/issuable/_filter.html.haml index 8d6f47b38ef..b7e350d27af 100644 --- a/app/views/shared/issuable/_filter.html.haml +++ b/app/views/shared/issuable/_filter.html.haml @@ -1,32 +1,5 @@ .issues-filters - .issues-state-filters - %ul.nav-links - - if defined?(type) && type == :merge_requests - - page_context_word = 'merge requests' - - else - - page_context_word = 'issues' - %li{class: ("active" if params[:state] == 'opened')} - = link_to page_filter_path(state: 'opened'), title: "Filter by #{page_context_word} that are currently opened." do - #{state_filters_text_for(:opened, @project)} - - - if defined?(type) && type == :merge_requests - %li{class: ("active" if params[:state] == 'merged')} - = link_to page_filter_path(state: 'merged'), title: 'Filter by merge requests that are currently merged.' do - #{state_filters_text_for(:merged, @project)} - - %li{class: ("active" if params[:state] == 'closed')} - = link_to page_filter_path(state: 'closed'), title: 'Filter by merge requests that are currently closed and unmerged.' do - #{state_filters_text_for(:closed, @project)} - - else - %li{class: ("active" if params[:state] == 'closed')} - = link_to page_filter_path(state: 'closed'), title: 'Filter by issues that are currently closed.' do - #{state_filters_text_for(:closed, @project)} - - %li{class: ("active" if params[:state] == 'all')} - = link_to page_filter_path(state: 'all'), title: "Show all #{page_context_word}." do - #{state_filters_text_for(:all, @project)} - - .issues-details-filters.gray-content-block + .issues-details-filters.gray-content-block.second-block = 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' && can?(current_user, :admin_issue, @project) .check-all-holder diff --git a/app/views/shared/issuable/_nav.html.haml b/app/views/shared/issuable/_nav.html.haml new file mode 100644 index 00000000000..a6970b7eebb --- /dev/null +++ b/app/views/shared/issuable/_nav.html.haml @@ -0,0 +1,25 @@ +%ul.nav-links.issues-state-filters + - if defined?(type) && type == :merge_requests + - page_context_word = 'merge requests' + - else + - page_context_word = 'issues' + %li{class: ("active" if params[:state] == 'opened')} + = link_to page_filter_path(state: 'opened'), title: "Filter by #{page_context_word} that are currently opened." do + #{state_filters_text_for(:opened, @project)} + + - if defined?(type) && type == :merge_requests + %li{class: ("active" if params[:state] == 'merged')} + = link_to page_filter_path(state: 'merged'), title: 'Filter by merge requests that are currently merged.' do + #{state_filters_text_for(:merged, @project)} + + %li{class: ("active" if params[:state] == 'closed')} + = link_to page_filter_path(state: 'closed'), title: 'Filter by merge requests that are currently closed and unmerged.' do + #{state_filters_text_for(:closed, @project)} + - else + %li{class: ("active" if params[:state] == 'closed')} + = link_to page_filter_path(state: 'closed'), title: 'Filter by issues that are currently closed.' do + #{state_filters_text_for(:closed, @project)} + + %li{class: ("active" if params[:state] == 'all')} + = link_to page_filter_path(state: 'all'), title: "Show all #{page_context_word}." do + #{state_filters_text_for(:all, @project)} diff --git a/app/views/shared/issuable/_search_form.html.haml b/app/views/shared/issuable/_search_form.html.haml index 6672ea79629..afad48499b7 100644 --- a/app/views/shared/issuable/_search_form.html.haml +++ b/app/views/shared/issuable/_search_form.html.haml @@ -1,9 +1,8 @@ -= form_tag(path, method: :get, id: "issue_search_form", class: 'pull-left issue-search-form') do - .append-right-10.hidden-xs.hidden-sm - = search_field_tag :issue_search, params[:issue_search], { placeholder: 'Filter by name ...', class: 'form-control issue_search search-text-input', spellcheck: false } - = hidden_field_tag :state, params['state'] - = hidden_field_tag :scope, params['scope'] - = hidden_field_tag :assignee_id, params['assignee_id'] - = hidden_field_tag :author_id, params['author_id'] - = hidden_field_tag :milestone_id, params['milestone_id'] - = hidden_field_tag :label_id, params['label_id'] += form_tag(path, method: :get, id: "issue_search_form", class: 'issue-search-form') do + = search_field_tag :issue_search, params[:issue_search], { placeholder: 'Filter by name ...', class: 'form-control issue_search search-text-input input-short', spellcheck: false } + = hidden_field_tag :state, params['state'] + = hidden_field_tag :scope, params['scope'] + = hidden_field_tag :assignee_id, params['assignee_id'] + = hidden_field_tag :author_id, params['author_id'] + = hidden_field_tag :milestone_id, params['milestone_id'] + = hidden_field_tag :label_id, params['label_id'] -- cgit v1.2.1 From eaad236b452fe24969ec83e72f95e6a8fcf0c8a4 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 5 Feb 2016 11:53:06 +0100 Subject: Remove project-issuable-filter from admin builds page :) Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/pages/issuable.scss | 17 +++-------------- app/views/admin/builds/index.html.haml | 13 ++++++------- spec/features/admin/admin_builds_spec.rb | 12 ++++++------ 3 files changed, 15 insertions(+), 27 deletions(-) diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss index 3bfbd9e17b7..e5026489167 100644 --- a/app/assets/stylesheets/pages/issuable.scss +++ b/app/assets/stylesheets/pages/issuable.scss @@ -29,17 +29,6 @@ } } -.project-issuable-filter { - .controls { - float: right; - margin-top: 11px; - } - - .nav-links { - text-align: left; - } -} - .issuable-details { section { .issuable-discussion { @@ -72,7 +61,7 @@ @include clearfix; padding: $gl-padding 0; border-bottom: 1px solid $border-gray-light; - // This prevents the mess when resizing the sidebar + // This prevents the mess when resizing the sidebar // of elements repositioning themselves.. width: $gutter_inner_width; overflow-x: hidden; @@ -206,7 +195,7 @@ } &.right-sidebar-collapsed { - .issuable-count, + .issuable-count, .issuable-nav, .assignee > *, .milestone > *, @@ -243,4 +232,4 @@ display: none; } } -} \ No newline at end of file +} diff --git a/app/views/admin/builds/index.html.haml b/app/views/admin/builds/index.html.haml index ebf2b7b60e7..5931efdefe6 100644 --- a/app/views/admin/builds/index.html.haml +++ b/app/views/admin/builds/index.html.haml @@ -1,9 +1,4 @@ -.project-issuable-filter - .controls - .pull-left.hidden-xs - - if @all_builds.running_or_pending.any? - = link_to 'Cancel all', cancel_all_admin_builds_path, data: { confirm: 'Are you sure?' }, class: 'btn btn-danger', method: :post - +.top-area %ul.nav-links %li{class: ('active' if @scope.nil?)} = link_to admin_builds_path do @@ -20,7 +15,11 @@ Finished %span.badge.js-running-count= number_with_delimiter(@all_builds.finished.count(:id)) -.gray-content-block + .nav-controls + - if @all_builds.running_or_pending.any? + = link_to 'Cancel all', cancel_all_admin_builds_path, data: { confirm: 'Are you sure?' }, class: 'btn btn-danger', method: :post + +.gray-content-block.second-block #{(@scope || 'running').capitalize} builds %ul.content-list diff --git a/spec/features/admin/admin_builds_spec.rb b/spec/features/admin/admin_builds_spec.rb index b955d0b0c46..2e9851fb442 100644 --- a/spec/features/admin/admin_builds_spec.rb +++ b/spec/features/admin/admin_builds_spec.rb @@ -18,7 +18,7 @@ describe 'Admin Builds' do visit admin_builds_path - expect(page).to have_selector('.project-issuable-filter li.active', text: 'All') + expect(page).to have_selector('.nav-links li.active', text: 'All') expect(page.all('.build-link').size).to eq(4) expect(page).to have_link 'Cancel all' end @@ -28,7 +28,7 @@ describe 'Admin Builds' do it 'shows a message' do visit admin_builds_path - expect(page).to have_selector('.project-issuable-filter li.active', text: 'All') + expect(page).to have_selector('.nav-links li.active', text: 'All') expect(page).to have_content 'No builds to show' expect(page).not_to have_link 'Cancel all' end @@ -44,7 +44,7 @@ describe 'Admin Builds' do visit admin_builds_path(scope: :running) - expect(page).to have_selector('.project-issuable-filter li.active', text: 'Running') + expect(page).to have_selector('.nav-links li.active', text: 'Running') expect(page.find('.build-link')).to have_content(build1.id) expect(page.find('.build-link')).not_to have_content(build2.id) expect(page.find('.build-link')).not_to have_content(build3.id) @@ -58,7 +58,7 @@ describe 'Admin Builds' do visit admin_builds_path(scope: :running) - expect(page).to have_selector('.project-issuable-filter li.active', text: 'Running') + expect(page).to have_selector('.nav-links li.active', text: 'Running') expect(page).to have_content 'No builds to show' expect(page).not_to have_link 'Cancel all' end @@ -74,7 +74,7 @@ describe 'Admin Builds' do visit admin_builds_path(scope: :finished) - expect(page).to have_selector('.project-issuable-filter li.active', text: 'Finished') + expect(page).to have_selector('.nav-links li.active', text: 'Finished') expect(page.find('.build-link')).not_to have_content(build1.id) expect(page.find('.build-link')).not_to have_content(build2.id) expect(page.find('.build-link')).to have_content(build3.id) @@ -88,7 +88,7 @@ describe 'Admin Builds' do visit admin_builds_path(scope: :finished) - expect(page).to have_selector('.project-issuable-filter li.active', text: 'Finished') + expect(page).to have_selector('.nav-links li.active', text: 'Finished') expect(page).to have_content 'No builds to show' expect(page).to have_link 'Cancel all' end -- cgit v1.2.1 From f1102b3373ecd294e625edf541d47552d5dc489f Mon Sep 17 00:00:00 2001 From: Josh Frye Date: Fri, 5 Feb 2016 09:02:50 -0500 Subject: Frontend changes from MR feedback --- app/assets/javascripts/dashboard.js.coffee | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/app/assets/javascripts/dashboard.js.coffee b/app/assets/javascripts/dashboard.js.coffee index e96b84147ba..dd295088312 100644 --- a/app/assets/javascripts/dashboard.js.coffee +++ b/app/assets/javascripts/dashboard.js.coffee @@ -4,12 +4,13 @@ initSearch: -> @timer = null - $("#project-filter-form-field").keyup -> + $("#project-filter-form-field").on('keyup', -> clearTimeout(@timer) @timer = setTimeout(Dashboard.filterResults, 500) + ) filterResults: => - $('.projects-list-holder').css("opacity", '0.5') + $('.projects-list-holder').fadeTo(250, 0.5) form = null form = $("#project-filter-form") @@ -21,7 +22,7 @@ url: form.attr('action') data: form.serialize() complete: -> - $('.projects-list-holder').css("opacity", '1.0') + $('.projects-list-holder').fadeTo(250, 1) success: (data) -> $('div.projects-list-holder').replaceWith(data.html) # Change url so if user reload a page - search results are saved -- cgit v1.2.1 From cf1349adb7cba2e791a1f8d59e3a6a976b54e071 Mon Sep 17 00:00:00 2001 From: kkm Date: Thu, 22 Oct 2015 18:52:17 -0700 Subject: Remember user's inline/tabular diff view preference in a cookie --- CHANGELOG | 1 + app/controllers/projects/application_controller.rb | 7 +++++++ app/controllers/projects/commit_controller.rb | 2 ++ app/controllers/projects/merge_requests_controller.rb | 2 ++ 4 files changed, 12 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index d43b8f69063..e1ef5b8d45d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -22,6 +22,7 @@ v 8.5.0 (unreleased) - Fix visibility level text in admin area (Zeger-Jan van de Weg) - Warn admin during OAuth of granting admin rights (Zeger-Jan van de Weg) - Update the ExternalIssue regex pattern (Blake Hitchcock) + - Remember user's inline/tabular diff view preference in a cookie (Kirill Katsnelson) - Optimized performance of finding issues to be closed by a merge request - Revert "Add IP check against DNSBLs at account sign-up" - Fix API to keep request parameters in Link header (Michael Potthoff) diff --git a/app/controllers/projects/application_controller.rb b/app/controllers/projects/application_controller.rb index dd32d509191..9096910b82c 100644 --- a/app/controllers/projects/application_controller.rb +++ b/app/controllers/projects/application_controller.rb @@ -26,6 +26,13 @@ class Projects::ApplicationController < ApplicationController end end + protected + + def apply_diff_view_cookie! + view = params[:view] || cookies[:diff_view] + cookies.permanent[:diff_view] = params[:view] = view if view + end + private def builds_enabled diff --git a/app/controllers/projects/commit_controller.rb b/app/controllers/projects/commit_controller.rb index f5a169e5aa9..5a084e123a1 100644 --- a/app/controllers/projects/commit_controller.rb +++ b/app/controllers/projects/commit_controller.rb @@ -13,6 +13,8 @@ class Projects::CommitController < Projects::ApplicationController def show return git_not_found! unless @commit + apply_diff_view_cookie! + @line_notes = commit.notes.inline @note = @project.build_commit_note(commit) @notes = commit.notes.not_inline.fresh diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index ed3050d59aa..9d588c370aa 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -57,6 +57,8 @@ class Projects::MergeRequestsController < Projects::ApplicationController end def diffs + apply_diff_view_cookie! + @commit = @merge_request.last_commit @base_commit = @merge_request.diff_base_commit -- cgit v1.2.1 From f6d816f9fe5dae55ed980b48aac7366c46f95461 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Fri, 5 Feb 2016 12:34:51 +0100 Subject: Add a controller test for the new 'diff_view' cookie --- app/controllers/projects/application_controller.rb | 4 +--- .../controllers/projects/merge_requests_controller_spec.rb | 14 +++++++++++++- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/app/controllers/projects/application_controller.rb b/app/controllers/projects/application_controller.rb index 9096910b82c..a326bc58215 100644 --- a/app/controllers/projects/application_controller.rb +++ b/app/controllers/projects/application_controller.rb @@ -26,15 +26,13 @@ class Projects::ApplicationController < ApplicationController end end - protected + private def apply_diff_view_cookie! view = params[:view] || cookies[:diff_view] cookies.permanent[:diff_view] = params[:view] = view if view end - private - def builds_enabled return render_404 unless @project.builds_enabled? end diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb index 6aaec224f6e..183cfef3611 100644 --- a/spec/controllers/projects/merge_requests_controller_spec.rb +++ b/spec/controllers/projects/merge_requests_controller_spec.rb @@ -188,7 +188,7 @@ describe Projects::MergeRequestsController do expect(response).to render_template('diffs') end end - + context 'as json' do it 'renders the diffs template to a string' do go format: 'json' @@ -199,6 +199,18 @@ describe Projects::MergeRequestsController do end end + describe 'GET diffs with view' do + it 'saves the preferred diff view in a cookie' do + get :diffs, + namespace_id: project.namespace.to_param, + project_id: project.to_param, + id: merge_request.iid, + view: 'parallel' + + expect(response.cookies['diff_view']).to eq('parallel') + end + end + describe 'GET commits' do def go(format: 'html') get :commits, -- cgit v1.2.1 From bf94ddef78c2326bdae28317bb22d1f7c55a2acf Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Fri, 5 Feb 2016 16:53:00 +0200 Subject: Fix wrong Ruby SHA and replace with sha256sum [ci skip] --- doc/install/installation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/install/installation.md b/doc/install/installation.md index a2c23bd52e5..db791ea6182 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -124,7 +124,7 @@ Download Ruby and compile it: mkdir /tmp/ruby && cd /tmp/ruby curl -O --progress https://cache.ruby-lang.org/pub/ruby/2.2/ruby-2.2.4.tar.gz - echo 'e2e195a4a58133e3ad33b955c829bb536fa3c075 ruby-2.2.4.tar.gz' | shasum -c - && tar xzf ruby-2.2.4.tar.gz + echo 'b6eff568b48e0fda76e5a36333175df049b204e91217aa32a65153cc0cdcb761 ruby-2.2.4.tar.gz' | sha256sum -c - && tar xzf ruby-2.2.4.tar.gz cd ruby-2.2.4 ./configure --disable-install-rdoc make -- cgit v1.2.1 From 989caaebdc698fd1dffd44e01b24f0c420842632 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 5 Feb 2016 16:01:10 +0100 Subject: Improve admin broadcast messages page * Show latest broadcast messages first on admin page * Use nice looking pagination Signed-off-by: Dmitriy Zaporozhets --- app/controllers/admin/broadcast_messages_controller.rb | 2 +- app/views/admin/broadcast_messages/index.html.haml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/admin/broadcast_messages_controller.rb b/app/controllers/admin/broadcast_messages_controller.rb index 4735b27c65d..a470d865408 100644 --- a/app/controllers/admin/broadcast_messages_controller.rb +++ b/app/controllers/admin/broadcast_messages_controller.rb @@ -2,7 +2,7 @@ class Admin::BroadcastMessagesController < Admin::ApplicationController before_action :finder, only: [:edit, :update, :destroy] def index - @broadcast_messages = BroadcastMessage.reorder("starts_at ASC").page(params[:page]) + @broadcast_messages = BroadcastMessage.reorder("ends_at DESC").page(params[:page]) @broadcast_message = BroadcastMessage.new end diff --git a/app/views/admin/broadcast_messages/index.html.haml b/app/views/admin/broadcast_messages/index.html.haml index 49e33698b63..c05538a393c 100644 --- a/app/views/admin/broadcast_messages/index.html.haml +++ b/app/views/admin/broadcast_messages/index.html.haml @@ -34,4 +34,4 @@ = link_to icon('pencil-square-o'), edit_admin_broadcast_message_path(message), title: 'Edit', class: 'btn btn-xs' = link_to icon('times'), admin_broadcast_message_path(message), method: :delete, remote: true, title: 'Remove', class: 'js-remove-tr btn btn-xs btn-danger' - = paginate @broadcast_messages + = paginate @broadcast_messages, theme: 'gitlab' -- cgit v1.2.1 From a95c6e38c6311b8b096a35e6ed81c5a4b11b6c9f Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Fri, 5 Feb 2016 17:06:25 +0200 Subject: Add ruby version update info in doc_styleguide [ci skip] --- doc/development/doc_styleguide.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/doc/development/doc_styleguide.md b/doc/development/doc_styleguide.md index caaa4032db2..96d1dffbc52 100644 --- a/doc/development/doc_styleguide.md +++ b/doc/development/doc_styleguide.md @@ -120,6 +120,17 @@ Inside the document: `http://doc.gitlab.com/ce/administration/restart_gitlab.html`. Replace `reconfigure` with `restart` where appropriate. +## Installation guide + +- **Ruby:** + In [step 2 of the installation guide](../install/installation.md#2-ruby), + we install Ruby from source. Whenever there is a new version that needs to + be updated, remember to change it throughout the codeblock and also replace + the sha256sum (it can be found in the [downloads page][ruby-dl] of the Ruby + website). + +[ruby-dl]: https://www.ruby-lang.org/en/downloads/ "Ruby download website" + ## API Here is a list of must-have items. Use them in the exact order that appears -- cgit v1.2.1 From 1a9630acc5acc102fb4d31e35af844f4dabb7656 Mon Sep 17 00:00:00 2001 From: Josh Frye Date: Fri, 5 Feb 2016 10:27:59 -0500 Subject: Fix double paging --- app/controllers/dashboard/projects_controller.rb | 2 +- app/views/explore/projects/index.html.haml | 1 - app/views/explore/projects/starred.html.haml | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/app/controllers/dashboard/projects_controller.rb b/app/controllers/dashboard/projects_controller.rb index cd3a25866af..0bcc78a8bc7 100644 --- a/app/controllers/dashboard/projects_controller.rb +++ b/app/controllers/dashboard/projects_controller.rb @@ -50,7 +50,7 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController format.json do render json: { - html: view_to_html_string("dashboard/projects/projects", locals: { projects: @projects }) + html: view_to_html_string("dashboard/projects/_projects", locals: { projects: @projects }) } end end diff --git a/app/views/explore/projects/index.html.haml b/app/views/explore/projects/index.html.haml index bee8518d57a..dca75498573 100644 --- a/app/views/explore/projects/index.html.haml +++ b/app/views/explore/projects/index.html.haml @@ -13,4 +13,3 @@ = render 'filter' = render 'projects', projects: @projects -= paginate @projects, theme: "gitlab" diff --git a/app/views/explore/projects/starred.html.haml b/app/views/explore/projects/starred.html.haml index 1b5269c7b68..ec461755103 100644 --- a/app/views/explore/projects/starred.html.haml +++ b/app/views/explore/projects/starred.html.haml @@ -8,4 +8,3 @@ = render 'explore/projects/nav' = render 'projects', projects: @projects -= paginate @projects, theme: 'gitlab' if @projects -- cgit v1.2.1 From 94af78ac4a7a0b76eb370a22320ee6410b6a4695 Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Fri, 5 Feb 2016 18:20:29 +0200 Subject: Faster snippet search --- CHANGELOG | 1 + app/helpers/snippets_helper.rb | 6 ++-- app/views/search/results/_snippet_blob.html.haml | 44 +++++++++++++----------- lib/gitlab/snippet_search_results.rb | 8 ++--- 4 files changed, 30 insertions(+), 29 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index d43b8f69063..b510ade27e8 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -34,6 +34,7 @@ v 8.5.0 (unreleased) - Add sort dropdown to dashboard projects page - Hide remove source branch button when the MR is merged but new commits are pushed (Zeger-Jan van de Weg) - In seach autocomplete show only groups and projects you are member of + - Faster snippet search v 8.4.3 - Increase lfs_objects size column to 8-byte integer to allow files larger diff --git a/app/helpers/snippets_helper.rb b/app/helpers/snippets_helper.rb index bc36434f549..41ae4048992 100644 --- a/app/helpers/snippets_helper.rb +++ b/app/helpers/snippets_helper.rb @@ -33,7 +33,7 @@ module SnippetsHelper # surrounding code. # # @returns Array, unique and sorted. - def matching_lines(lined_content, surrounding_lines) + def matching_lines(lined_content, surrounding_lines, query) used_lines = [] lined_content.each_with_index do |line, line_number| used_lines.concat bounded_line_numbers( @@ -51,9 +51,9 @@ module SnippetsHelper # surrounding_lines() worth of unmatching lines. # # @returns a hash with {snippet_object, snippet_chunks:{data,start_line}} - def chunk_snippet(snippet, surrounding_lines = 3) + def chunk_snippet(snippet, query, surrounding_lines = 3) lined_content = snippet.content.split("\n") - used_lines = matching_lines(lined_content, surrounding_lines) + used_lines = matching_lines(lined_content, surrounding_lines, query) snippet_chunk = [] snippet_chunks = [] diff --git a/app/views/search/results/_snippet_blob.html.haml b/app/views/search/results/_snippet_blob.html.haml index dcd61199717..6b77d24f50c 100644 --- a/app/views/search/results/_snippet_blob.html.haml +++ b/app/views/search/results/_snippet_blob.html.haml @@ -1,46 +1,50 @@ +- snippet_blob = chunk_snippet(snippet_blob, @search_term) +- snippet = snippet_blob[:snippet_object] +- snippet_chunks = snippet_blob[:snippet_chunks] + .search-result-row %span - = snippet_blob[:snippet_object].title + = snippet.title by - = link_to user_snippets_path(snippet_blob[:snippet_object].author) do - = image_tag avatar_icon(snippet_blob[:snippet_object].author_email), class: "avatar avatar-inline s16", alt: '' - = snippet_blob[:snippet_object].author_name - %span.light #{time_ago_with_tooltip(snippet_blob[:snippet_object].created_at)} + = link_to user_snippets_path(snippet.author) do + = image_tag avatar_icon(snippet.author_email), class: "avatar avatar-inline s16", alt: '' + = snippet.author_name + %span.light #{time_ago_with_tooltip(snippet.created_at)} %h4.snippet-title - - snippet_path = reliable_snippet_path(snippet_blob[:snippet_object]) + - snippet_path = reliable_snippet_path(snippet) = link_to snippet_path do .file-holder .file-title %i.fa.fa-file - %strong= snippet_blob[:snippet_object].file_name - - if markup?(snippet_blob[:snippet_object].file_name) + %strong= snippet.file_name + - if markup?(snippet.file_name) .file-content.wiki - - snippet_blob[:snippet_chunks].each do |snippet| - - unless snippet[:data].empty? - = render_markup(snippet_blob[:snippet_object].file_name, snippet[:data]) + - snippet_chunks.each do |chunk| + - unless chunk[:data].empty? + = render_markup(snippet.file_name, chunk[:data]) - else .file-content.code .nothing-here-block Empty file - else .file-content.code.js-syntax-highlight .line-numbers - - snippet_blob[:snippet_chunks].each do |snippet| - - unless snippet[:data].empty? - - snippet[:data].lines.to_a.size.times do |index| - - offset = defined?(snippet[:start_line]) ? snippet[:start_line] : 1 + - snippet_chunks.each do |chunk| + - unless chunk[:data].empty? + - chunk[:data].lines.to_a.size.times do |index| + - offset = defined?(chunk[:start_line]) ? chunk[:start_line] : 1 - i = index + offset = link_to snippet_path+"#L#{i}", id: "L#{i}", rel: "#L#{i}", class: "diff-line-num" do %i.fa.fa-link = i - - unless snippet == snippet_blob[:snippet_chunks].last + - unless snippet == snippet_chunks.last %a.diff-line-num = "." %pre.code %code - - snippet_blob[:snippet_chunks].each do |snippet| - - unless snippet[:data].empty? - = snippet[:data] - - unless snippet == snippet_blob[:snippet_chunks].last + - snippet_chunks.each do |chunk| + - unless chunk[:data].empty? + = chunk[:data] + - unless chunk == snippet_chunks.last %a = "..." - else diff --git a/lib/gitlab/snippet_search_results.rb b/lib/gitlab/snippet_search_results.rb index 38364a0b151..cadb010ef03 100644 --- a/lib/gitlab/snippet_search_results.rb +++ b/lib/gitlab/snippet_search_results.rb @@ -14,7 +14,7 @@ module Gitlab when 'snippet_titles' Kaminari.paginate_array(snippet_titles).page(page).per(per_page) when 'snippet_blobs' - Kaminari.paginate_array(snippet_blobs).page(page).per(per_page) + snippet_blobs.page(page).per(per_page) else super end @@ -39,11 +39,7 @@ module Gitlab end def snippet_blobs - search = Snippet.where(id: limit_snippet_ids).search_code(query) - search = search.order('updated_at DESC').to_a - snippets = [] - search.each { |e| snippets << chunk_snippet(e) } - snippets + Snippet.where(id: limit_snippet_ids).search_code(query).order('updated_at DESC') end def default_scope -- cgit v1.2.1 From 8f929b8747daf446bb6d31197e69f8948b951189 Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Fri, 5 Feb 2016 18:27:12 +0200 Subject: one more improvement to snippet search --- lib/gitlab/snippet_search_results.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/gitlab/snippet_search_results.rb b/lib/gitlab/snippet_search_results.rb index cadb010ef03..addda95be2b 100644 --- a/lib/gitlab/snippet_search_results.rb +++ b/lib/gitlab/snippet_search_results.rb @@ -12,7 +12,7 @@ module Gitlab def objects(scope, page = nil) case scope when 'snippet_titles' - Kaminari.paginate_array(snippet_titles).page(page).per(per_page) + snippet_titles.page(page).per(per_page) when 'snippet_blobs' snippet_blobs.page(page).per(per_page) else -- cgit v1.2.1 From aa5eca47db61a365736517ff1a7cc5a42c2f9ed9 Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Fri, 5 Feb 2016 18:05:25 +0200 Subject: Make sure the public/uploads/ directory is created [ci skip] --- doc/install/installation.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/install/installation.md b/doc/install/installation.md index db791ea6182..3eb9b1767c5 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -267,6 +267,9 @@ sudo usermod -aG redis git sudo chmod -R u+rwX tmp/pids/ sudo chmod -R u+rwX tmp/sockets/ + # Create the public/uploads/ directory + sudo -u git -H mkdir public/uploads/ + # Make sure GitLab can write to the public/uploads/ directory sudo chmod -R u+rwX public/uploads -- cgit v1.2.1 -- cgit v1.2.1 From 80812a5d46782d5a7996c419d3ddccd205194150 Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Thu, 4 Feb 2016 19:53:54 -0500 Subject: Edited time ago location change. Change edited icon to word. Change edited text color to gray cc/ @creamzy --- app/assets/javascripts/application.js.coffee | 87 ++++++++++++---------- app/assets/stylesheets/pages/issuable.scss | 6 ++ app/views/projects/issues/show.html.haml | 9 +-- .../projects/merge_requests/show/_mr_box.html.haml | 5 ++ .../merge_requests/show/_mr_title.html.haml | 5 -- 5 files changed, 62 insertions(+), 50 deletions(-) diff --git a/app/assets/javascripts/application.js.coffee b/app/assets/javascripts/application.js.coffee index e54bfce058a..37ce34b1632 100644 --- a/app/assets/javascripts/application.js.coffee +++ b/app/assets/javascripts/application.js.coffee @@ -211,44 +211,49 @@ $ -> $this.attr 'value', $this.val() return - $(document).on 'keyup', 'input[type="search"]' , (e) -> - $this = $(this) - $this.attr 'value', $this.val() - - $(document).on 'breakpoint:change', (e, breakpoint) -> - if breakpoint is 'sm' or breakpoint is 'xs' - $gutterIcon = $('.gutter-toggle').find('i') - if $gutterIcon.hasClass('fa-angle-double-right') - $gutterIcon.closest('a').trigger('click') - - - $(document).on 'click', 'aside .gutter-toggle', (e) -> - e.preventDefault() - $this = $(this) - $thisIcon = $this.find 'i' - if $thisIcon.hasClass('fa-angle-double-right') - $thisIcon.removeClass('fa-angle-double-right') - .addClass('fa-angle-double-left') - $this - .closest('aside') - .removeClass('right-sidebar-expanded') - .addClass('right-sidebar-collapsed') - $('.page-with-sidebar') - .removeClass('right-sidebar-expanded') - .addClass('right-sidebar-collapsed') - else - $thisIcon.removeClass('fa-angle-double-left') - .addClass('fa-angle-double-right') - $this - .closest('aside') - .removeClass('right-sidebar-collapsed') - .addClass('right-sidebar-expanded') - $('.page-with-sidebar') - .removeClass('right-sidebar-collapsed') - .addClass('right-sidebar-expanded') - $.cookie("collapsed_gutter", - $('.right-sidebar') - .hasClass('right-sidebar-collapsed'), { path: '/' }) + $(document) + .off 'keyup', 'input[type="search"]' + .on 'keyup', 'input[type="search"]' , (e) -> + $this = $(this) + $this.attr 'value', $this.val() + + $(document) + .off 'breakpoint:change' + .on 'breakpoint:change', (e, breakpoint) -> + if breakpoint is 'sm' or breakpoint is 'xs' + $gutterIcon = $('.gutter-toggle').find('i') + if $gutterIcon.hasClass('fa-angle-double-right') + $gutterIcon.closest('a').trigger('click') + + $(document) + .off 'click', 'aside .gutter-toggle' + .on 'click', 'aside .gutter-toggle', (e) -> + e.preventDefault() + $this = $(this) + $thisIcon = $this.find 'i' + if $thisIcon.hasClass('fa-angle-double-right') + $thisIcon.removeClass('fa-angle-double-right') + .addClass('fa-angle-double-left') + $this + .closest('aside') + .removeClass('right-sidebar-expanded') + .addClass('right-sidebar-collapsed') + $('.page-with-sidebar') + .removeClass('right-sidebar-expanded') + .addClass('right-sidebar-collapsed') + else + $thisIcon.removeClass('fa-angle-double-left') + .addClass('fa-angle-double-right') + $this + .closest('aside') + .removeClass('right-sidebar-collapsed') + .addClass('right-sidebar-expanded') + $('.page-with-sidebar') + .removeClass('right-sidebar-collapsed') + .addClass('right-sidebar-expanded') + $.cookie("collapsed_gutter", + $('.right-sidebar') + .hasClass('right-sidebar-collapsed'), { path: '/' }) bootstrapBreakpoint = undefined; checkBootstrapBreakpoints = -> @@ -282,8 +287,10 @@ $ -> if bootstrapBreakpoint is "xs" or "sm" $(document).trigger('breakpoint:change', [bootstrapBreakpoint]) - $(window).on "resize", (e) -> - fitSidebarForSize() + $(window) + .off "resize" + .on "resize", (e) -> + fitSidebarForSize() setBootstrapBreakpoints() checkInitialSidebarSize() diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss index e5026489167..9d5dc42b6cc 100644 --- a/app/assets/stylesheets/pages/issuable.scss +++ b/app/assets/stylesheets/pages/issuable.scss @@ -233,3 +233,9 @@ } } } + +.detail-page-description { + small { + color: $gray-darkest; + } +} \ No newline at end of file diff --git a/app/views/projects/issues/show.html.haml b/app/views/projects/issues/show.html.haml index 030f4a2e644..121c775560f 100644 --- a/app/views/projects/issues/show.html.haml +++ b/app/views/projects/issues/show.html.haml @@ -15,11 +15,6 @@ opened by #{link_to_member(@project, @issue.author, size: 24)} · = time_ago_with_tooltip(@issue.created_at, placement: 'bottom', html_class: 'issue_created_ago') - - if @issue.updated_at != @issue.created_at - %span - · - = icon('edit', title: 'edited') - = time_ago_with_tooltip(@issue.updated_at, placement: 'bottom', html_class: 'issue_edited_ago') .pull-right - if can?(current_user, :create_issue, @project) @@ -46,6 +41,10 @@ = markdown(@issue.description, cache_key: [@issue, "description"]) %textarea.hidden.js-task-list-field = @issue.description + - if @issue.updated_at != @issue.created_at + %small + Edited + = time_ago_with_tooltip(@issue.updated_at, placement: 'bottom', html_class: 'issue_edited_ago') .merge-requests = render 'merge_requests' diff --git a/app/views/projects/merge_requests/show/_mr_box.html.haml b/app/views/projects/merge_requests/show/_mr_box.html.haml index 905823f79d9..602f787e6cf 100644 --- a/app/views/projects/merge_requests/show/_mr_box.html.haml +++ b/app/views/projects/merge_requests/show/_mr_box.html.haml @@ -10,3 +10,8 @@ = markdown(@merge_request.description, cache_key: [@merge_request, "description"]) %textarea.hidden.js-task-list-field = @merge_request.description + + - if @merge_request.updated_at != @merge_request.created_at + %small + Edited + = time_ago_with_tooltip(@merge_request.updated_at, placement: 'bottom') diff --git a/app/views/projects/merge_requests/show/_mr_title.html.haml b/app/views/projects/merge_requests/show/_mr_title.html.haml index fc6fb2a0d42..473fbff721b 100644 --- a/app/views/projects/merge_requests/show/_mr_title.html.haml +++ b/app/views/projects/merge_requests/show/_mr_title.html.haml @@ -8,11 +8,6 @@ opened by #{link_to_member(@project, @merge_request.author, size: 24)} · = time_ago_with_tooltip(@merge_request.created_at) - - if @merge_request.updated_at != @merge_request.created_at - %span - · - = icon('edit', title: 'edited') - = time_ago_with_tooltip(@merge_request.updated_at, placement: 'bottom') .issue-btn-group.pull-right - if can?(current_user, :update_merge_request, @merge_request) -- cgit v1.2.1 From 2e8fe0bdb274e8cdc80d0e38fe340832c70adfb2 Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Fri, 5 Feb 2016 11:07:28 -0500 Subject: Add JS style changes. Thanks @rspeicher --- app/assets/javascripts/application.js.coffee | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/application.js.coffee b/app/assets/javascripts/application.js.coffee index 37ce34b1632..367bd098bfd 100644 --- a/app/assets/javascripts/application.js.coffee +++ b/app/assets/javascripts/application.js.coffee @@ -232,7 +232,8 @@ $ -> $this = $(this) $thisIcon = $this.find 'i' if $thisIcon.hasClass('fa-angle-double-right') - $thisIcon.removeClass('fa-angle-double-right') + $thisIcon + .removeClass('fa-angle-double-right') .addClass('fa-angle-double-left') $this .closest('aside') @@ -242,7 +243,8 @@ $ -> .removeClass('right-sidebar-expanded') .addClass('right-sidebar-collapsed') else - $thisIcon.removeClass('fa-angle-double-left') + $thisIcon + .removeClass('fa-angle-double-left') .addClass('fa-angle-double-right') $this .closest('aside') -- cgit v1.2.1 From a64d881bac1e7b846a718ce1f105b7e39f4dd1b3 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 5 Feb 2016 17:43:05 +0100 Subject: fixed spec - at last! --- spec/services/system_note_service_spec.rb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/spec/services/system_note_service_spec.rb b/spec/services/system_note_service_spec.rb index a3d3147a79b..655efa0670b 100644 --- a/spec/services/system_note_service_spec.rb +++ b/spec/services/system_note_service_spec.rb @@ -428,15 +428,14 @@ describe SystemNoteService, services: true do context 'commit from fork' do let(:author2) { create(:user) } let(:forked_project) { Projects::ForkService.new(project, author2).execute } - let(:service) { CreateCommitBuildsService.new } let(:commit2) { forked_project.commit } before do - described_class.cross_reference(commit0, commit2, author2) + described_class.cross_reference(noteable, commit2, author2) end it 'is falsey when is a fork mentioning an external issue' do - expect(described_class.cross_reference_exists?(commit0, commit2)). + expect(described_class.cross_reference_exists?(noteable, commit2)). to be_falsey end end -- cgit v1.2.1 From 2611acfd92078785cab0c072b3c79e994ac212b3 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 5 Feb 2016 19:32:12 +0100 Subject: Improve placeholder: search -> Search Signed-off-by: Dmitriy Zaporozhets --- app/views/layouts/_search.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/layouts/_search.html.haml b/app/views/layouts/_search.html.haml index 659f5a7756b..20042e21bf2 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', class: "search-input form-control", spellcheck: false + = search_field_tag "search", nil, placeholder: 'Search', class: "search-input form-control", spellcheck: false = hidden_field_tag :group_id, @group.try(:id) - if @project && @project.persisted? = hidden_field_tag :project_id, @project.id -- cgit v1.2.1 From 0a094cb1dfe7328214c8516d60d51deb13c8fc1a Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 5 Feb 2016 18:56:37 +0000 Subject: Changed the project switcher dropdown toggle Moved the positioning of the dropdown to be more aligned with the title Closes #13219 and #13214 --- app/assets/stylesheets/framework/header.scss | 9 +++++++++ app/helpers/projects_helper.rb | 4 ++-- spec/javascripts/fixtures/project_title.html.haml | 4 ++-- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss index 7871a33b6c5..a81e258573d 100644 --- a/app/assets/stylesheets/framework/header.scss +++ b/app/assets/stylesheets/framework/header.scss @@ -91,8 +91,17 @@ header { .dropdown-toggle-caret { position: relative; top: -2px; + width: 12px; + line-height: 12px; margin-left: 5px; font-size: 10px; + text-align: center; + cursor: pointer; + } + + .project-item-select { + right: auto; + left: 0; } } diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 2e9741a8622..04d1f3a0ac2 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -59,9 +59,8 @@ module ProjectsHelper link_to(simple_sanitize(owner.name), user_path(owner)) end - project_link = link_to project_path(project), { class: "project-item-select-holder #{"js-projects-dropdown-toggle" if current_user}" } do + project_link = link_to project_path(project), { class: "project-item-select-holder" } do link_output = simple_sanitize(project.name) - link_output += content_tag :span, nil, { class: "fa fa-chevron-down dropdown-toggle-caret" } if current_user if current_user link_output += project_select_tag :project_path, @@ -71,6 +70,7 @@ module ProjectsHelper link_output end + project_link += content_tag :span, nil, { class: "fa fa-chevron-down dropdown-toggle-caret js-projects-dropdown-toggle" } if current_user full_title = namespace_link + ' / ' + project_link full_title += ' · '.html_safe + link_to(simple_sanitize(name), url) if name diff --git a/spec/javascripts/fixtures/project_title.html.haml b/spec/javascripts/fixtures/project_title.html.haml index 4286d1be669..a3bae7045ba 100644 --- a/spec/javascripts/fixtures/project_title.html.haml +++ b/spec/javascripts/fixtures/project_title.html.haml @@ -1,7 +1,7 @@ %h1.title %a GitLab Org - %a.project-item-select-holder.js-projects-dropdown-toggle{href: "/gitlab-org/gitlab-test"} + %a.project-item-select-holder{href: "/gitlab-org/gitlab-test"} GitLab Test - %span.fa.fa-chevron-down.dropdown-toggle-caret %input#project_path.project-item-select.js-projects-dropdown.ajax-project-select{type: "hidden", name: "project_path", "data-include-groups" => "false"} + %span.fa.fa-chevron-down.dropdown-toggle-caret.js-projects-dropdown-toggle -- cgit v1.2.1 From 08064767615ad7b0e2599aed94c53117516e8377 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Fri, 5 Feb 2016 20:17:58 +0100 Subject: Remove current_user && when can? is used --- app/views/admin/builds/_build.html.haml | 2 +- app/views/projects/builds/show.html.haml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/admin/builds/_build.html.haml b/app/views/admin/builds/_build.html.haml index bd7fb0b36f4..34d955568f2 100644 --- a/app/views/admin/builds/_build.html.haml +++ b/app/views/admin/builds/_build.html.haml @@ -63,7 +63,7 @@ - if can?(current_user, :read_build, project) && build.artifacts? = link_to build.artifacts_download_url, title: 'Download artifacts' do %i.fa.fa-download - - if current_user && can?(current_user, :update_build, build.project) + - if can?(current_user, :update_build, build.project) - if build.active? - if build.cancel_url = link_to build.cancel_url, method: :post, title: 'Cancel' do diff --git a/app/views/projects/builds/show.html.haml b/app/views/projects/builds/show.html.haml index c43d6c3b427..ca1441a20d8 100644 --- a/app/views/projects/builds/show.html.haml +++ b/app/views/projects/builds/show.html.haml @@ -101,7 +101,7 @@ .build-widget %h4.title Build ##{@build.id} - - if current_user && can?(current_user, :update_build, @project) + - if can?(current_user, :update_build, @project) .pull-right - if @build.cancel_url = link_to "Cancel", @build.cancel_url, class: 'btn btn-sm btn-danger', method: :post -- cgit v1.2.1 From 4a878e1dfacf4510aa95c81e1ecb815289eee3c1 Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Fri, 5 Feb 2016 14:40:50 -0500 Subject: Add `j` and `k` shortcuts --- app/assets/javascripts/shortcuts_issuable.coffee | 19 +++++++++++++++++++ app/views/shared/issuable/_sidebar.html.haml | 4 ++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/shortcuts_issuable.coffee b/app/assets/javascripts/shortcuts_issuable.coffee index f717a753cf8..cefa1857d7f 100644 --- a/app/assets/javascripts/shortcuts_issuable.coffee +++ b/app/assets/javascripts/shortcuts_issuable.coffee @@ -16,12 +16,31 @@ class @ShortcutsIssuable extends ShortcutsNavigation @replyWithSelectedText() return false ) + Mousetrap.bind('j', => + @prevIssue() + return false + ) + Mousetrap.bind('k', => + @nextIssue() + return false + ) + if isMergeRequest @enabledHelp.push('.hidden-shortcut.merge_requests') else @enabledHelp.push('.hidden-shortcut.issues') + prevIssue: -> + $prevBtn = $('.prev-btn') + if not $prevBtn.hasClass('disabled') + Turbolinks.visit($prevBtn.attr('href')) + + nextIssue: -> + $nextBtn = $('.next-btn') + if not $nextBtn.hasClass('disabled') + Turbolinks.visit($nextBtn.attr('href')) + replyWithSelectedText: -> if window.getSelection selected = window.getSelection().toString() diff --git a/app/views/shared/issuable/_sidebar.html.haml b/app/views/shared/issuable/_sidebar.html.haml index 75a7d9be2c1..ae96a45453f 100644 --- a/app/views/shared/issuable/_sidebar.html.haml +++ b/app/views/shared/issuable/_sidebar.html.haml @@ -13,12 +13,12 @@ = icon('angle-double-right') .issuable-nav.pull-right.btn-group{role: 'group', "aria-label" => '...'} - if has_prev_issuable?(@project, issuable.id) - = link_to 'Prev', issuable_link_prev(@project, issuable), class: 'btn btn-default' + = link_to 'Prev', issuable_link_prev(@project, issuable), class: 'btn btn-default prev-btn' - else %a.btn.btn-default.disabled{href: '#'} Prev - if has_next_issuable?(@project, issuable.id) - = link_to 'Next', issuable_link_next(@project, issuable), class: 'btn btn-default' + = link_to 'Next', issuable_link_next(@project, issuable), class: 'btn btn-default next-btn' - else %a.btn.btn-default.disabled{href: '#'} Next -- cgit v1.2.1 From b79d9e801713d13ba2d52b5c5de9b84567327b69 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 5 Feb 2016 20:02:46 +0000 Subject: Uses icon helper for dropdown toggle icon --- app/helpers/projects_helper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 04d1f3a0ac2..dd49283089d 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -70,7 +70,7 @@ module ProjectsHelper link_output end - project_link += content_tag :span, nil, { class: "fa fa-chevron-down dropdown-toggle-caret js-projects-dropdown-toggle" } if current_user + project_link += icon "chevron-down", class: "dropdown-toggle-caret js-projects-dropdown-toggle" if current_user full_title = namespace_link + ' / ' + project_link full_title += ' · '.html_safe + link_to(simple_sanitize(name), url) if name -- cgit v1.2.1 From 932c5eb886abacceb0613f2de6e77ff50660a861 Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Fri, 5 Feb 2016 15:06:46 -0500 Subject: Changes sidebar width --- app/assets/stylesheets/framework/variables.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss index efc3366e99c..b8386362637 100644 --- a/app/assets/stylesheets/framework/variables.scss +++ b/app/assets/stylesheets/framework/variables.scss @@ -13,8 +13,8 @@ $list-font-size: 15px; $sidebar_collapsed_width: 62px; $sidebar_width: 230px; $gutter_collapsed_width: 62px; -$gutter_width: 312px; -$gutter_inner_width: 280px; +$gutter_width: 290px; +$gutter_inner_width: 258px; $avatar_radius: 50%; $code_font_size: 13px; $code_line_height: 1.5; -- cgit v1.2.1 From b724f0871ac3d3af5e19bdd45553e50a92d4a4f0 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 5 Feb 2016 20:08:28 +0000 Subject: Project dropdown test span -> i --- spec/javascripts/fixtures/project_title.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/javascripts/fixtures/project_title.html.haml b/spec/javascripts/fixtures/project_title.html.haml index a3bae7045ba..e5850b62659 100644 --- a/spec/javascripts/fixtures/project_title.html.haml +++ b/spec/javascripts/fixtures/project_title.html.haml @@ -4,4 +4,4 @@ %a.project-item-select-holder{href: "/gitlab-org/gitlab-test"} GitLab Test %input#project_path.project-item-select.js-projects-dropdown.ajax-project-select{type: "hidden", name: "project_path", "data-include-groups" => "false"} - %span.fa.fa-chevron-down.dropdown-toggle-caret.js-projects-dropdown-toggle + %i.fa.chevron-down.dropdown-toggle-caret.js-projects-dropdown-toggle -- cgit v1.2.1 From 9cc321ca17d775c417c7bbeb1fb9b0636dd338b4 Mon Sep 17 00:00:00 2001 From: Roman Rott Date: Wed, 3 Feb 2016 19:18:55 +0200 Subject: fixed issue with poor logo transition animation on safari updates after code review: moved coffee code to appropriate file, updated css to not use js-prefixed selectors Updated comments and Changelog Removed duplicate line in changelog --- CHANGELOG | 1 + app/assets/javascripts/logo.js.coffee | 5 +++++ app/assets/stylesheets/framework/sidebar.scss | 15 ++++++++++++++- app/views/layouts/_page.html.haml | 3 ++- app/views/layouts/ci/_page.html.haml | 3 ++- 5 files changed, 24 insertions(+), 3 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index b7e8822fdd6..d9adc13bf5f 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -33,6 +33,7 @@ v 8.5.0 (unreleased) - Add sort dropdown to dashboard projects page - Hide remove source branch button when the MR is merged but new commits are pushed (Zeger-Jan van de Weg) - In seach autocomplete show only groups and projects you are member of + - Fixed logo animation on Safari. v 8.4.3 - Increase lfs_objects size column to 8-byte integer to allow files larger diff --git a/app/assets/javascripts/logo.js.coffee b/app/assets/javascripts/logo.js.coffee index a5879c8b793..e7d884662ea 100644 --- a/app/assets/javascripts/logo.js.coffee +++ b/app/assets/javascripts/logo.js.coffee @@ -42,3 +42,8 @@ work = -> $(document).on('page:fetch', start) $(document).on('page:change', stop) + +$ -> + # Make logo clickable + $('#logo').on 'click', -> + $('#js-shortcuts-home').get(0).click() diff --git a/app/assets/stylesheets/framework/sidebar.scss b/app/assets/stylesheets/framework/sidebar.scss index b7f532c0771..b141928f706 100644 --- a/app/assets/stylesheets/framework/sidebar.scss +++ b/app/assets/stylesheets/framework/sidebar.scss @@ -45,6 +45,19 @@ overflow: hidden; transition-duration: .3s; + .home { + z-index: 1; + position: absolute; + left: 0px; + } + + #logo { + z-index: 2; + position: absolute; + width: 58px; + cursor: pointer; + } + a { float: left; height: $header-height; @@ -70,7 +83,7 @@ width: 158px; float: left; margin: 0; - margin-left: 14px; + margin-left: 50px; font-size: 19px; line-height: 41px; font-weight: normal; diff --git a/app/views/layouts/_page.html.haml b/app/views/layouts/_page.html.haml index 0c1b5eec95a..e53d5b07801 100644 --- a/app/views/layouts/_page.html.haml +++ b/app/views/layouts/_page.html.haml @@ -2,8 +2,9 @@ = render "layouts/broadcast" .sidebar-wrapper.nicescroll{ class: nav_sidebar_class } .header-logo - = link_to root_path, class: 'home', title: 'Dashboard', id: 'js-shortcuts-home' do + %a#logo = brand_header_logo + = link_to root_path, class: 'home', title: 'Dashboard', id: 'js-shortcuts-home' do .gitlab-text-container %h3 GitLab diff --git a/app/views/layouts/ci/_page.html.haml b/app/views/layouts/ci/_page.html.haml index 7e90af21b21..3cfd36720f0 100644 --- a/app/views/layouts/ci/_page.html.haml +++ b/app/views/layouts/ci/_page.html.haml @@ -2,8 +2,9 @@ = render "layouts/broadcast" .sidebar-wrapper.nicescroll{ class: nav_sidebar_class } .header-logo - = link_to root_path, class: 'home', title: 'Dashboard', id: 'js-shortcuts-home' do + %a#logo = brand_header_logo + = link_to root_path, class: 'home', title: 'Dashboard', id: 'js-shortcuts-home' do .gitlab-text-container %h3 GitLab -- cgit v1.2.1 From 24f048be72e6179c36b8f986017b7ba52e97b47d Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Fri, 5 Feb 2016 16:02:11 -0500 Subject: Update CHANGELOG [ci skip] --- CHANGELOG | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index e1ef5b8d45d..fb21ae94524 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -22,7 +22,7 @@ v 8.5.0 (unreleased) - Fix visibility level text in admin area (Zeger-Jan van de Weg) - Warn admin during OAuth of granting admin rights (Zeger-Jan van de Weg) - Update the ExternalIssue regex pattern (Blake Hitchcock) - - Remember user's inline/tabular diff view preference in a cookie (Kirill Katsnelson) + - Remember user's inline/side-by-side diff view preference in a cookie (Kirill Katsnelson) - Optimized performance of finding issues to be closed by a merge request - Revert "Add IP check against DNSBLs at account sign-up" - Fix API to keep request parameters in Link header (Michael Potthoff) -- cgit v1.2.1 From 551ce0f245d92245c1365754d1a60818a5a6ca36 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Fri, 5 Feb 2016 16:03:20 -0500 Subject: Add spec for assigning view param from cookie --- .../projects/merge_requests_controller_spec.rb | 24 +++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb index 183cfef3611..9450a389d81 100644 --- a/spec/controllers/projects/merge_requests_controller_spec.rb +++ b/spec/controllers/projects/merge_requests_controller_spec.rb @@ -200,15 +200,29 @@ describe Projects::MergeRequestsController do end describe 'GET diffs with view' do + def go(extra_params = {}) + params = { + namespace_id: project.namespace.to_param, + project_id: project.to_param, + id: merge_request.iid + } + + get :diffs, params.merge(extra_params) + end + it 'saves the preferred diff view in a cookie' do - get :diffs, - namespace_id: project.namespace.to_param, - project_id: project.to_param, - id: merge_request.iid, - view: 'parallel' + go view: 'parallel' expect(response.cookies['diff_view']).to eq('parallel') end + + it 'assigns :view param based on cookie' do + request.cookies['diff_view'] = 'parallel' + + go + + expect(controller.params[:view]).to eq 'parallel' + end end describe 'GET commits' do -- cgit v1.2.1 From ebeb35a01cc41eb1b55271644a633397ca4ce7a1 Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Fri, 5 Feb 2016 18:18:34 -0500 Subject: Fix ugly state of dropdown when editing a dropdown, but not changing anything you end up in an ugly state Fixes #13215 --- 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 9d5dc42b6cc..c0b5557bcbd 100644 --- a/app/assets/stylesheets/pages/issuable.scss +++ b/app/assets/stylesheets/pages/issuable.scss @@ -75,7 +75,7 @@ border: none; } - span { + span:not(.select2-container span) { margin-top: 7px; display: inline-block; } -- cgit v1.2.1 From d164f1982a865ea5ba7aa33308804cff755c6858 Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Fri, 5 Feb 2016 18:21:50 -0500 Subject: Change hover color of sidebar buttons --- app/assets/stylesheets/pages/issuable.scss | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss index c0b5557bcbd..95e3758b0f1 100644 --- a/app/assets/stylesheets/pages/issuable.scss +++ b/app/assets/stylesheets/pages/issuable.scss @@ -194,6 +194,11 @@ border: 1px solid $border-gray-normal; } + .btn:hover { + background: $gray-dark; + border: 1px solid $border-gray-dark; + } + &.right-sidebar-collapsed { .issuable-count, .issuable-nav, -- cgit v1.2.1 From 9860bd72abe3cfd81cc4fdf367a65a310674180b Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Fri, 5 Feb 2016 18:25:26 -0500 Subject: Add hover for gutter toggle button --- app/assets/stylesheets/pages/issuable.scss | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss index 95e3758b0f1..93b88a11388 100644 --- a/app/assets/stylesheets/pages/issuable.scss +++ b/app/assets/stylesheets/pages/issuable.scss @@ -88,6 +88,10 @@ margin-left: 20px; border-left: 1px solid $border-gray-light; padding-left: 10px; + + &:hover { + color: $gray-darkest; + } } } @@ -192,11 +196,10 @@ .btn { background: $gray-normal; border: 1px solid $border-gray-normal; - } - - .btn:hover { - background: $gray-dark; - border: 1px solid $border-gray-dark; + &:hover { + background: $gray-dark; + border: 1px solid $border-gray-dark; + } } &.right-sidebar-collapsed { -- cgit v1.2.1 From dcfdef689a250ae4db6a92a1ad4413f2a86c9113 Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Fri, 5 Feb 2016 18:29:17 -0500 Subject: Fix span margin issues --- app/assets/stylesheets/pages/issuable.scss | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss index 93b88a11388..c440388090e 100644 --- a/app/assets/stylesheets/pages/issuable.scss +++ b/app/assets/stylesheets/pages/issuable.scss @@ -75,11 +75,15 @@ border: none; } - span:not(.select2-container span) { + span { margin-top: 7px; display: inline-block; } + .select2-container span { + margin-top: 0; + } + .issuable-count { } -- cgit v1.2.1 From 306c50cecde50b0bbfc9d665a09ecd2fa1676005 Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Fri, 5 Feb 2016 19:43:18 -0500 Subject: Make copy button in collapsed sidebar work. --- app/assets/stylesheets/pages/issuable.scss | 13 +++++++++++++ app/views/shared/issuable/_sidebar.html.haml | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss index c440388090e..ef62f069dc2 100644 --- a/app/assets/stylesheets/pages/issuable.scss +++ b/app/assets/stylesheets/pages/issuable.scss @@ -235,6 +235,19 @@ display: block; margin-top: 0; } + + .btn-clipboard { + border: none; + + &:hover { + background: transparent; + } + + i { + color: #999999; + } + } + } } diff --git a/app/views/shared/issuable/_sidebar.html.haml b/app/views/shared/issuable/_sidebar.html.haml index ae96a45453f..eb19b936e3e 100644 --- a/app/views/shared/issuable/_sidebar.html.haml +++ b/app/views/shared/issuable/_sidebar.html.haml @@ -118,7 +118,7 @@ - project_ref = cross_project_reference(@project, issuable) .block.project-reference .sidebar-collapsed-icon - = icon('clipboard') + = clipboard_button(clipboard_text: project_ref) .title .cross-project-reference %span -- cgit v1.2.1 From b92ce40daaf4093c91303194af918d6340d269c9 Mon Sep 17 00:00:00 2001 From: Aaron Power Date: Wed, 3 Feb 2016 23:29:17 +0000 Subject: Fixed Window's commands for SSH Help. --- doc/ssh/README.md | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/doc/ssh/README.md b/doc/ssh/README.md index 77eb53427e2..a1198e5878f 100644 --- a/doc/ssh/README.md +++ b/doc/ssh/README.md @@ -5,6 +5,12 @@ An SSH key allows you to establish a secure connection between your computer and GitLab. Before generating an SSH key in your shell, check if your system already has one by running the following command: + +**Windows Command Line:** +```bash +type %userprofile%\.ssh\id_rsa.pub +``` +**GNU/Linux/Mac/PowerShell:** ```bash cat ~/.ssh/id_rsa.pub ``` @@ -25,6 +31,12 @@ press enter to use the default. If you use a different name, the key will not be used automatically. Use the command below to show your public key: + +**Windows Command Line:** +```bash +type %userprofile%\.ssh\id_rsa.pub +``` +**GNU/Linux/Mac/PowerShell:** ```bash cat ~/.ssh/id_rsa.pub ``` @@ -36,9 +48,14 @@ with your username and host. To copy your public key to the clipboard, use the code below. Depending on your OS you'll need to use a different command: -**Windows:** +**Windows Command Line:** +```bash +type %userprofile%\.ssh\id_rsa.pub | clip +``` + +**Windows PowerShell:** ```bash -clip < ~/.ssh/id_rsa.pub +cat ~/.ssh/id_rsa.pub | clip ``` **Mac:** -- cgit v1.2.1 From 311f407651e9ad1859bb0e9b6b9d6de79fde1a3d Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Sat, 6 Feb 2016 15:01:37 +0100 Subject: Fix commit status tests --- spec/requests/api/commit_status_spec.rb | 48 ++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 18 deletions(-) diff --git a/spec/requests/api/commit_status_spec.rb b/spec/requests/api/commit_status_spec.rb index 21482fc1070..89b554622ef 100644 --- a/spec/requests/api/commit_status_spec.rb +++ b/spec/requests/api/commit_status_spec.rb @@ -2,18 +2,17 @@ require 'spec_helper' describe API::CommitStatus, api: true do include ApiHelpers - let(:user) { create(:user) } - let(:user2) { create(:user) } - let!(:project) { create(:project, creator_id: user.id) } - let!(:reporter) { create(:project_member, user: user, project: project, access_level: ProjectMember::REPORTER) } - let!(:guest) { create(:project_member, user: user2, project: project, access_level: ProjectMember::GUEST) } + let!(:project) { create(:project) } let(:commit) { project.repository.commit } let!(:ci_commit) { project.ensure_ci_commit(commit.id) } let(:commit_status) { create(:commit_status, commit: ci_commit) } + let(:guest) { create_user(ProjectMember::GUEST) } + let(:reporter) { create_user(ProjectMember::REPORTER) } + let(:developer) { create_user(ProjectMember::DEVELOPER) } describe "GET /projects/:id/repository/commits/:sha/statuses" do it_behaves_like 'a paginated resources' do - let(:request) { get api("/projects/#{project.id}/repository/commits/#{commit.id}/statuses", user) } + let(:request) { get api("/projects/#{project.id}/repository/commits/#{commit.id}/statuses", reporter) } end context "reporter user" do @@ -29,7 +28,7 @@ describe API::CommitStatus, api: true do end it "should return latest commit statuses" do - get api("/projects/#{project.id}/repository/commits/#{commit.id}/statuses", user) + get api("/projects/#{project.id}/repository/commits/#{commit.id}/statuses", reporter) expect(response.status).to eq(200) expect(json_response).to be_an Array @@ -39,7 +38,7 @@ describe API::CommitStatus, api: true do end it "should return all commit statuses" do - get api("/projects/#{project.id}/repository/commits/#{commit.id}/statuses?all=1", user) + get api("/projects/#{project.id}/repository/commits/#{commit.id}/statuses?all=1", reporter) expect(response.status).to eq(200) expect(json_response).to be_an Array @@ -47,7 +46,7 @@ describe API::CommitStatus, api: true do end it "should return latest commit statuses for specific ref" do - get api("/projects/#{project.id}/repository/commits/#{commit.id}/statuses?ref=develop", user) + get api("/projects/#{project.id}/repository/commits/#{commit.id}/statuses?ref=develop", reporter) expect(response.status).to eq(200) expect(json_response).to be_an Array @@ -55,7 +54,7 @@ describe API::CommitStatus, api: true do end it "should return latest commit statuses for specific name" do - get api("/projects/#{project.id}/repository/commits/#{commit.id}/statuses?name=coverage", user) + get api("/projects/#{project.id}/repository/commits/#{commit.id}/statuses?name=coverage", reporter) expect(response.status).to eq(200) expect(json_response).to be_an Array @@ -65,7 +64,7 @@ describe API::CommitStatus, api: true do context "guest user" do it "should not return project commits" do - get api("/projects/#{project.id}/repository/commits/#{commit.id}/statuses", user2) + get api("/projects/#{project.id}/repository/commits/#{commit.id}/statuses", guest) expect(response.status).to eq(403) end end @@ -81,10 +80,10 @@ describe API::CommitStatus, api: true do describe 'POST /projects/:id/statuses/:sha' do let(:post_url) { "/projects/#{project.id}/statuses/#{commit.id}" } - context 'reporter user' do + context 'developer user' do context 'should create commit status' do it 'with only required parameters' do - post api(post_url, user), state: 'success' + post api(post_url, developer), state: 'success' expect(response.status).to eq(201) expect(json_response['sha']).to eq(commit.id) expect(json_response['status']).to eq('success') @@ -95,7 +94,7 @@ describe API::CommitStatus, api: true do end it 'with all optional parameters' do - post api(post_url, user), state: 'success', context: 'coverage', ref: 'develop', target_url: 'url', description: 'test' + post api(post_url, developer), state: 'success', context: 'coverage', ref: 'develop', target_url: 'url', description: 'test' expect(response.status).to eq(201) expect(json_response['sha']).to eq(commit.id) expect(json_response['status']).to eq('success') @@ -108,25 +107,32 @@ describe API::CommitStatus, api: true do context 'should not create commit status' do it 'with invalid state' do - post api(post_url, user), state: 'invalid' + post api(post_url, developer), state: 'invalid' expect(response.status).to eq(400) end it 'without state' do - post api(post_url, user) + post api(post_url, developer) expect(response.status).to eq(400) end it 'invalid commit' do - post api("/projects/#{project.id}/statuses/invalid_sha", user), state: 'running' + post api("/projects/#{project.id}/statuses/invalid_sha", developer), state: 'running' expect(response.status).to eq(404) end end end + context 'reporter user' do + it 'should not create commit status' do + post api(post_url, reporter) + expect(response.status).to eq(403) + end + end + context 'guest user' do it 'should not create commit status' do - post api(post_url, user2) + post api(post_url, guest) expect(response.status).to eq(403) end end @@ -138,4 +144,10 @@ describe API::CommitStatus, api: true do end end end + + def create_user(access_level) + user = create(:user) + create(:project_member, user: user, project: project, access_level: access_level) + user + end end -- cgit v1.2.1 From 89b3ddd609063d93f39a02279f0f3e23b8b6b364 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Wed, 3 Feb 2016 23:01:04 -0500 Subject: Allow limited Markdown in Broadcast Messages Closes #11853 --- CHANGELOG | 1 + app/assets/javascripts/admin.js.coffee | 13 ------------- app/assets/javascripts/broadcast_message.js.coffee | 22 ++++++++++++++++++++++ app/assets/stylesheets/pages/admin.scss | 10 ++++++++++ .../admin/broadcast_messages_controller.rb | 4 ++++ app/helpers/broadcast_messages_helper.rb | 6 +++++- app/views/admin/broadcast_messages/_form.html.haml | 7 +++++-- app/views/admin/broadcast_messages/preview.js.haml | 1 + config/routes.rb | 5 ++++- features/admin/broadcast_messages.feature | 6 ++++++ features/steps/admin/broadcast_messages.rb | 14 +++++++++++++- lib/banzai/pipeline/broadcast_message_pipeline.rb | 16 ++++++++++++++++ 12 files changed, 87 insertions(+), 18 deletions(-) create mode 100644 app/assets/javascripts/broadcast_message.js.coffee create mode 100644 app/views/admin/broadcast_messages/preview.js.haml create mode 100644 lib/banzai/pipeline/broadcast_message_pipeline.rb diff --git a/CHANGELOG b/CHANGELOG index 50b27e25492..fba6c3ccd1b 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -19,6 +19,7 @@ v 8.5.0 (unreleased) - Track project import failure - Support Two-factor Authentication for LDAP users - Display database type and version in Administration dashboard + - Allow limited Markdown in Broadcast Messages - Fix visibility level text in admin area (Zeger-Jan van de Weg) - Warn admin during OAuth of granting admin rights (Zeger-Jan van de Weg) - Update the ExternalIssue regex pattern (Blake Hitchcock) diff --git a/app/assets/javascripts/admin.js.coffee b/app/assets/javascripts/admin.js.coffee index eb951f71711..b2b8e1b7ffb 100644 --- a/app/assets/javascripts/admin.js.coffee +++ b/app/assets/javascripts/admin.js.coffee @@ -12,19 +12,6 @@ class @Admin e.preventDefault() $('.js-toggle-colors-container').toggle() - $('input#broadcast_message_color').on 'input', -> - previewColor = $(@).val() - $('div.broadcast-message-preview').css('background-color', previewColor) - - $('input#broadcast_message_font').on 'input', -> - previewColor = $(@).val() - $('div.broadcast-message-preview').css('color', previewColor) - - $('textarea#broadcast_message_message').on 'input', -> - previewMessage = $(@).val() - previewMessage = "Your message here" if previewMessage.trim() == '' - $('div.broadcast-message-preview span').text(previewMessage) - $('.log-tabs a').click (e) -> e.preventDefault() $(this).tab('show') diff --git a/app/assets/javascripts/broadcast_message.js.coffee b/app/assets/javascripts/broadcast_message.js.coffee new file mode 100644 index 00000000000..a38a329c4c2 --- /dev/null +++ b/app/assets/javascripts/broadcast_message.js.coffee @@ -0,0 +1,22 @@ +$ -> + $('input#broadcast_message_color').on 'input', -> + previewColor = $(@).val() + $('div.broadcast-message-preview').css('background-color', previewColor) + + $('input#broadcast_message_font').on 'input', -> + previewColor = $(@).val() + $('div.broadcast-message-preview').css('color', previewColor) + + previewPath = $('textarea#broadcast_message_message').data('preview-path') + + $('textarea#broadcast_message_message').on 'input', -> + message = $(@).val() + + if message == '' + $('.js-broadcast-message-preview').text("Your message here") + else + $.ajax( + url: previewPath + type: "POST" + data: { broadcast_message: { message: message } } + ) diff --git a/app/assets/stylesheets/pages/admin.scss b/app/assets/stylesheets/pages/admin.scss index 144852e7874..a61161810a3 100644 --- a/app/assets/stylesheets/pages/admin.scss +++ b/app/assets/stylesheets/pages/admin.scss @@ -55,6 +55,16 @@ @extend .alert-warning; padding: 10px; text-align: center; + + > div, p { + display: inline; + margin: 0; + + a { + color: inherit; + text-decoration: underline; + } + } } .broadcast-message-preview { diff --git a/app/controllers/admin/broadcast_messages_controller.rb b/app/controllers/admin/broadcast_messages_controller.rb index a470d865408..fc342924987 100644 --- a/app/controllers/admin/broadcast_messages_controller.rb +++ b/app/controllers/admin/broadcast_messages_controller.rb @@ -36,6 +36,10 @@ class Admin::BroadcastMessagesController < Admin::ApplicationController end end + def preview + @message = broadcast_message_params[:message] + end + protected def finder diff --git a/app/helpers/broadcast_messages_helper.rb b/app/helpers/broadcast_messages_helper.rb index 1ed8c710f77..43a29c96bca 100644 --- a/app/helpers/broadcast_messages_helper.rb +++ b/app/helpers/broadcast_messages_helper.rb @@ -3,7 +3,7 @@ module BroadcastMessagesHelper return unless message.present? content_tag :div, class: 'broadcast-message', style: broadcast_message_style(message) do - icon('bullhorn') << ' ' << message.message + icon('bullhorn') << ' ' << render_broadcast_message(message.message) end end @@ -31,4 +31,8 @@ module BroadcastMessagesHelper 'Pending' end end + + def render_broadcast_message(message) + Banzai.render(message, pipeline: :broadcast_message).html_safe + end end diff --git a/app/views/admin/broadcast_messages/_form.html.haml b/app/views/admin/broadcast_messages/_form.html.haml index 953b8b69368..5c9403fa0c2 100644 --- a/app/views/admin/broadcast_messages/_form.html.haml +++ b/app/views/admin/broadcast_messages/_form.html.haml @@ -1,6 +1,7 @@ .broadcast-message-preview{ style: broadcast_message_style(@broadcast_message) } = icon('bullhorn') - %span= @broadcast_message.message || "Your message here" + .js-broadcast-message-preview + = render_broadcast_message(@broadcast_message.message.presence || "Your message here") = form_for [:admin, @broadcast_message], html: { class: 'broadcast-message-form form-horizontal js-requires-input'} do |f| -if @broadcast_message.errors.any? @@ -10,7 +11,9 @@ .form-group = f.label :message, class: 'control-label' .col-sm-10 - = f.text_area :message, class: "form-control js-quick-submit", rows: 2, required: true + = f.text_area :message, class: "form-control js-quick-submit js-autosize", + required: true, + data: { preview_path: preview_admin_broadcast_messages_path } .form-group.js-toggle-colors-container .col-sm-10.col-sm-offset-2 = link_to 'Customize colors', '#', class: 'js-toggle-colors-link' diff --git a/app/views/admin/broadcast_messages/preview.js.haml b/app/views/admin/broadcast_messages/preview.js.haml new file mode 100644 index 00000000000..fbc9453c72e --- /dev/null +++ b/app/views/admin/broadcast_messages/preview.js.haml @@ -0,0 +1 @@ +$('.js-broadcast-message-preview').html("#{j(render_broadcast_message(@message))}"); diff --git a/config/routes.rb b/config/routes.rb index 034bfaf1bcd..f5951bf3e8d 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -227,7 +227,10 @@ Rails.application.routes.draw do get :test end - resources :broadcast_messages, only: [:index, :edit, :create, :update, :destroy] + resources :broadcast_messages, only: [:index, :edit, :create, :update, :destroy] do + post :preview, on: :collection + end + resource :logs, only: [:show] resource :background_jobs, controller: 'background_jobs', only: [:show] diff --git a/features/admin/broadcast_messages.feature b/features/admin/broadcast_messages.feature index fd3bac77f86..4f9c651561e 100644 --- a/features/admin/broadcast_messages.feature +++ b/features/admin/broadcast_messages.feature @@ -25,3 +25,9 @@ Feature: Admin Broadcast Messages When I remove an existing broadcast message Then I should be redirected to admin messages page And I should not see the removed broadcast message + + @javascript + Scenario: Live preview a customized broadcast message + When I visit admin messages page + And I enter a broadcast message with Markdown + Then I should see a live preview of the rendered broadcast message diff --git a/features/steps/admin/broadcast_messages.rb b/features/steps/admin/broadcast_messages.rb index 6cacdf4764c..af2b4a29313 100644 --- a/features/steps/admin/broadcast_messages.rb +++ b/features/steps/admin/broadcast_messages.rb @@ -19,7 +19,7 @@ class Spinach::Features::AdminBroadcastMessages < Spinach::FeatureSteps end step 'submit form with new customized broadcast message' do - fill_in 'broadcast_message_message', with: 'Application update from 4:00 CST to 5:00 CST' + fill_in 'broadcast_message_message', with: 'Application update from **4:00 CST to 5:00 CST**' fill_in 'broadcast_message_color', with: '#f2dede' fill_in 'broadcast_message_font', with: '#b94a48' select Date.today.next_year.year, from: "broadcast_message_ends_at_1i" @@ -28,6 +28,7 @@ class Spinach::Features::AdminBroadcastMessages < Spinach::FeatureSteps step 'I should see a customized broadcast message' do expect(page).to have_content 'Application update from 4:00 CST to 5:00 CST' + expect(page).to have_selector 'strong', text: '4:00 CST to 5:00 CST' expect(page).to have_selector %(div[style="background-color: #f2dede; color: #b94a48"]) end @@ -51,4 +52,15 @@ class Spinach::Features::AdminBroadcastMessages < Spinach::FeatureSteps step 'I should not see the removed broadcast message' do expect(page).not_to have_content 'Migration to new server' end + + step 'I enter a broadcast message with Markdown' do + fill_in 'broadcast_message_message', with: "Live **Markdown** previews. :tada:" + end + + step 'I should see a live preview of the rendered broadcast message' do + page.within('.broadcast-message-preview') do + expect(page).to have_selector('strong', text: 'Markdown') + expect(page).to have_selector('img.emoji') + end + end end diff --git a/lib/banzai/pipeline/broadcast_message_pipeline.rb b/lib/banzai/pipeline/broadcast_message_pipeline.rb new file mode 100644 index 00000000000..4bb85e24c38 --- /dev/null +++ b/lib/banzai/pipeline/broadcast_message_pipeline.rb @@ -0,0 +1,16 @@ +module Banzai + module Pipeline + class BroadcastMessagePipeline < DescriptionPipeline + def self.filters + @filters ||= [ + Filter::MarkdownFilter, + Filter::SanitizationFilter, + + Filter::EmojiFilter, + Filter::AutolinkFilter, + Filter::ExternalLinkFilter + ] + end + end + end +end -- cgit v1.2.1 From ab0525eafb59f9ea2c6eb4c9d3f4d7dd126ad0f8 Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Sun, 7 Feb 2016 17:56:03 +0200 Subject: Change logo image name in markdown documentation [ci skip] --- doc/markdown/markdown.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/markdown/markdown.md b/doc/markdown/markdown.md index 83c77742b19..f6bffba9fdb 100644 --- a/doc/markdown/markdown.md +++ b/doc/markdown/markdown.md @@ -424,24 +424,24 @@ will point the link to `wikis/style` when the link is inside of a wiki markdown Here's our logo (hover to see the title text): Inline-style: - ![alt text](assets/logo-white.png) + ![alt text](assets/logo.svg) Reference-style: ![alt text1][logo] - [logo]: assets/logo-white.png + [logo]: assets/logo.svg Here's our logo: Inline-style: -![alt text](/assets/logo-white.png) +![alt text](/assets/logo.svg) Reference-style: ![alt text][logo] -[logo]: /assets/logo-white.png +[logo]: /assets/logo.svg ## Blockquotes -- cgit v1.2.1 From 2ad872382b49d4802a9ea5e2c7e8773949d83b2a Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Sun, 7 Feb 2016 15:11:06 -0500 Subject: Update CHANGELOG [ci skip] --- CHANGELOG | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 50b27e25492..983a219703a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -36,6 +36,9 @@ v 8.5.0 (unreleased) - Hide remove source branch button when the MR is merged but new commits are pushed (Zeger-Jan van de Weg) - In seach autocomplete show only groups and projects you are member of +v 8.4.4 + - Update omniauth-saml gem to 1.4.2 + v 8.4.3 - Increase lfs_objects size column to 8-byte integer to allow files larger than 2.1GB -- cgit v1.2.1 From ed093f1ef0a75cd6d4b292f94ae11383f0afd9d6 Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Mon, 8 Feb 2016 00:37:45 +0200 Subject: Clarify when JIRA service was backported to CE [ci skip] --- doc/project_services/jira.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/doc/project_services/jira.md b/doc/project_services/jira.md index d6b2e7f521b..7c12557a321 100644 --- a/doc/project_services/jira.md +++ b/doc/project_services/jira.md @@ -1,5 +1,12 @@ # GitLab JIRA integration +_**Note:** +Full JIRA integration was previously exclusive to GitLab Enterprise Edition. +With [GitLab 8.3 forward][8_3_post], this feature in now [backported][jira-ce] +to GitLab Community Edition as well._ + +--- + GitLab can be configured to interact with [JIRA Core] either using an on-premises instance or the SaaS solution that Atlassian offers. Configuration happens via username and password on a per-project basis. Connecting to a JIRA @@ -210,3 +217,5 @@ You can see from the above image that there are four references to GitLab: [services-templates]: ../project_services/services_templates.md "Services templates documentation" [JIRA Core]: https://www.atlassian.com/software/jira/core "The JIRA Core website" +[jira-ce]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/2146 "MR - Backport JIRA service" +[8_3_post]: https://about.gitlab.com/2015/12/22/gitlab-8-3-released/ "GitLab 8.3 release post" -- cgit v1.2.1 From 9eba0eaac3199ddf581c74b73fe69b94fa3e5498 Mon Sep 17 00:00:00 2001 From: Aaron Hamilton Date: Sat, 6 Feb 2016 23:18:34 +0000 Subject: Prevent rasterization artefacts in the logo, and simplify markup. - Remove sketch-namespaced attributes. - Remove unused groups, and cancel out unnecessary transforms. - Use overlap to avoid rasterization artefacts in the logo. - Extend comment for `#logo` click event handler, as it's a non-obvious hack for Safari. - Remove viewBox parameter and define paths in their final form. --- app/assets/javascripts/logo.js.coffee | 3 ++- app/views/shared/_logo.svg | 28 ++++++++-------------------- 2 files changed, 10 insertions(+), 21 deletions(-) diff --git a/app/assets/javascripts/logo.js.coffee b/app/assets/javascripts/logo.js.coffee index e7d884662ea..35b2fbbba07 100644 --- a/app/assets/javascripts/logo.js.coffee +++ b/app/assets/javascripts/logo.js.coffee @@ -44,6 +44,7 @@ $(document).on('page:fetch', start) $(document).on('page:change', stop) $ -> - # Make logo clickable + # Make logo clickable as part of a workaround for Safari visited + # link behaviour (See !2690). $('#logo').on 'click', -> $('#js-shortcuts-home').get(0).click() diff --git a/app/views/shared/_logo.svg b/app/views/shared/_logo.svg index 3d279ec228c..b07f1c5603e 100644 --- a/app/views/shared/_logo.svg +++ b/app/views/shared/_logo.svg @@ -1,21 +1,9 @@ -ASCII' - - allow(Asciidoctor).to receive(:convert).and_return(html) - expect(Banzai).to receive(:render) - .with(html, context.merge(pipeline: :asciidoc)) - .and_return(filtered_html) - - expect( render('foo', context) ).to eql filtered_html - end - end - def render(*args) described_class.render(*args) end -- cgit v1.2.1 From 4089be8fedbe0499108b32dc0c08b6378efc534c Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 12 Feb 2016 18:01:47 +0100 Subject: woo hoo - getting there with the cross-reference issue. Should fix the problem and updated spec --- app/services/system_note_service.rb | 15 +++++++++++---- spec/services/system_note_service_spec.rb | 10 ++++++---- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/app/services/system_note_service.rb b/app/services/system_note_service.rb index 34b6636c39f..843b44abd17 100644 --- a/app/services/system_note_service.rb +++ b/app/services/system_note_service.rb @@ -280,6 +280,7 @@ class SystemNoteService # mentioner - Mentionable object # # Returns Boolean + def self.cross_reference_exists?(noteable, mentioner) # Initial scope should be system notes of this noteable type notes = Note.system.where(noteable_type: noteable.class) @@ -291,14 +292,20 @@ class SystemNoteService notes = notes.where(noteable_id: noteable.id) end - gfm_reference = mentioner.gfm_reference(nil) - notes = notes.where('note LIKE ?', "#{cross_reference_note_prefix}%#{gfm_reference}") - - notes.count > 0 + notes_for_mentioner(mentioner, noteable, notes).count > 0 end private + def self.notes_for_mentioner(mentioner, noteable, notes) + if mentioner.is_a?(Commit) + notes.where('note LIKE ?', "#{cross_reference_note_prefix}%#{mentioner.to_reference(nil)}") + else + gfm_reference = mentioner.gfm_reference(noteable.project) + notes.where(note: cross_reference_note_content(gfm_reference)) + end + end + def self.create_note(args = {}) Note.create(args.merge(system: true)) end diff --git a/spec/services/system_note_service_spec.rb b/spec/services/system_note_service_spec.rb index 655efa0670b..0c063fcb959 100644 --- a/spec/services/system_note_service_spec.rb +++ b/spec/services/system_note_service_spec.rb @@ -425,18 +425,20 @@ describe SystemNoteService, services: true do end end - context 'commit from fork' do + context 'commit with cross-reference from fork' do let(:author2) { create(:user) } let(:forked_project) { Projects::ForkService.new(project, author2).execute } let(:commit2) { forked_project.commit } before do - described_class.cross_reference(noteable, commit2, author2) + allow(commit0).to receive(:to_reference) { noteable.project.to_reference + + commit0.class.reference_prefix + commit0.id} + described_class.cross_reference(noteable, commit0, author2) end - it 'is falsey when is a fork mentioning an external issue' do + it 'is true when a fork mentions an external issue' do expect(described_class.cross_reference_exists?(noteable, commit2)). - to be_falsey + to be true end end end -- cgit v1.2.1 From 99a50447a15abb49ae6a3225332f850af78744a9 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 12 Feb 2016 18:21:01 +0100 Subject: fix rubocop warning --- spec/services/system_note_service_spec.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/spec/services/system_note_service_spec.rb b/spec/services/system_note_service_spec.rb index 0c063fcb959..9b9732ea01f 100644 --- a/spec/services/system_note_service_spec.rb +++ b/spec/services/system_note_service_spec.rb @@ -431,8 +431,10 @@ describe SystemNoteService, services: true do let(:commit2) { forked_project.commit } before do - allow(commit0).to receive(:to_reference) { noteable.project.to_reference + - commit0.class.reference_prefix + commit0.id} + allow(commit0).to receive(:to_reference) { + noteable.project.to_reference + + commit0.class.reference_prefix + commit0.id + } described_class.cross_reference(noteable, commit0, author2) end -- cgit v1.2.1 From 8a62fbdb42304b1c9012a718819aa0d363249c16 Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Sat, 13 Feb 2016 00:37:43 +0200 Subject: Remove note on backing up GitLab CI as a separate service [ci skip] --- doc/raketasks/backup_restore.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/doc/raketasks/backup_restore.md b/doc/raketasks/backup_restore.md index cdd6652b7b0..f6d1234ac4a 100644 --- a/doc/raketasks/backup_restore.md +++ b/doc/raketasks/backup_restore.md @@ -18,8 +18,6 @@ for two-factor authentication. If you restore a GitLab backup without restoring the database encryption key, users who have two-factor authentication enabled will lose access to your GitLab server. -If you are interested in GitLab CI backup please follow to the [CI backup documentation](https://gitlab.com/gitlab-org/gitlab-ci/blob/master/doc/raketasks/backup_restore.md)* - ``` # use this command if you've installed GitLab with the Omnibus package sudo gitlab-rake gitlab:backup:create -- cgit v1.2.1 From 4646cbc4c65854f8f3d0fc42ec385fb9f31db82b Mon Sep 17 00:00:00 2001 From: Takuya Noguchi Date: Sat, 13 Feb 2016 12:59:55 +0900 Subject: Update omniauth to 1.3.1 for memory performance --- Gemfile | 2 +- Gemfile.lock | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Gemfile b/Gemfile index 9114fdd33ac..a1c57af4bac 100644 --- a/Gemfile +++ b/Gemfile @@ -21,7 +21,7 @@ gem "pg", '~> 0.18.2', group: :postgres gem 'devise', '~> 3.5.4' gem 'devise-async', '~> 0.9.0' gem 'doorkeeper', '~> 2.2.0' -gem 'omniauth', '~> 1.2.2' +gem 'omniauth', '~> 1.3.1' gem 'omniauth-azure-oauth2', '~> 0.0.6' gem 'omniauth-bitbucket', '~> 0.0.2' gem 'omniauth-cas3', '~> 1.1.2' diff --git a/Gemfile.lock b/Gemfile.lock index 98a36724fe0..718285e1665 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -491,9 +491,9 @@ GEM rack (~> 1.2) octokit (3.8.0) sawyer (~> 0.6.0, >= 0.5.3) - omniauth (1.2.2) + omniauth (1.3.1) hashie (>= 1.2, < 4) - rack (~> 1.0) + rack (>= 1.0, < 3) omniauth-azure-oauth2 (0.0.6) jwt (~> 1.0) omniauth (~> 1.0) @@ -963,7 +963,7 @@ DEPENDENCIES nprogress-rails (~> 0.1.6.7) oauth2 (~> 1.0.0) octokit (~> 3.8.0) - omniauth (~> 1.2.2) + omniauth (~> 1.3.1) omniauth-azure-oauth2 (~> 0.0.6) omniauth-bitbucket (~> 0.0.2) omniauth-cas3 (~> 1.1.2) -- cgit v1.2.1 From 7ffcc5a17bc462b652e91c1cff36b8baaeb6a41a Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Fri, 12 Feb 2016 17:41:52 -0800 Subject: Fix duplicate "me" in tooltip of the "thumbsup" awards Emoji Steps to reproduce: 1. Go to a MR or issue 2. Click on "thumbsup" Emoji 3 times 3. Observe the tooltip becomes "me, me" Closes #13374, #12788 --- CHANGELOG | 1 + app/assets/javascripts/awards_handler.coffee | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 9b2d6d58a5c..a3ceca34b07 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 8.5.0 (unreleased) + - Fix duplicate "me" in tooltip of the "thumbsup" awards Emoji (Stan Hu) - Cache various Repository methods to improve performance (Yorick Peterse) - Fix duplicated branch creation/deletion Web hooks/service notifications when using Web UI (Stan Hu) - Ensure rake tasks that don't need a DB connection can be run without one diff --git a/app/assets/javascripts/awards_handler.coffee b/app/assets/javascripts/awards_handler.coffee index 047df4786a9..360acb864f6 100644 --- a/app/assets/javascripts/awards_handler.coffee +++ b/app/assets/javascripts/awards_handler.coffee @@ -49,10 +49,11 @@ class @AwardsHandler counter.text(parseInt(counter.text()) - 1) emojiIcon.removeClass("active") @removeMeFromAuthorList(emoji) - else if emoji =="thumbsup" || emoji == "thumbsdown" + else if emoji == "thumbsup" || emoji == "thumbsdown" emojiIcon.tooltip("destroy") counter.text(0) emojiIcon.removeClass("active") + @removeMeFromAuthorList(emoji) else emojiIcon.tooltip("destroy") emojiIcon.remove() -- cgit v1.2.1 From 46d35cdbe572e7cad434ed9c61fc264160184aba Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Sat, 13 Feb 2016 02:47:15 -0800 Subject: Add spinach tests for award emoji --- features/project/issues/award_emoji.feature | 11 ++++++++++- features/steps/project/issues/award_emoji.rb | 26 ++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/features/project/issues/award_emoji.feature b/features/project/issues/award_emoji.feature index bfde89fd896..2945bb3753a 100644 --- a/features/project/issues/award_emoji.feature +++ b/features/project/issues/award_emoji.feature @@ -7,7 +7,16 @@ Feature: Award Emoji And I visit "Bugfix" issue page @javascript - Scenario: I add and remove award in the issue + Scenario: I repeatedly add and remove thumbsup award in the issue + Given I click the thumbsup award Emoji + Then I have award added + Given I click the thumbsup award Emoji + Then I have no awards added + Given I click the thumbsup award Emoji + Then I have award added + + @javascript + Scenario: I add and remove custom award in the issue Given I click to emoji-picker Then The search field is focused And I click to emoji in the picker diff --git a/features/steps/project/issues/award_emoji.rb b/features/steps/project/issues/award_emoji.rb index 69695d493f3..8b9aa6aabfa 100644 --- a/features/steps/project/issues/award_emoji.rb +++ b/features/steps/project/issues/award_emoji.rb @@ -8,6 +8,15 @@ class Spinach::Features::AwardEmoji < Spinach::FeatureSteps visit namespace_project_issue_path(@project.namespace, @project, @issue) end + step 'I click the thumbsup award Emoji' do + page.within '.awards' do + thumbsup = page.find('.award .emoji-1F44D') + thumbsup.click + thumbsup.hover + sleep 0.3 + end + end + step 'I click to emoji-picker' do page.within '.awards-controls' do page.find('.add-award').click @@ -40,6 +49,23 @@ class Spinach::Features::AwardEmoji < Spinach::FeatureSteps page.within '.awards' do expect(page).to have_selector '.award' expect(page.find('.award.active .counter')).to have_content '1' + expect(page.find('.award.active')['data-original-title']).to eq('me') + end + end + + step 'I have no awards added' do + page.within '.awards' do + expect(page).to have_selector '.award' + expect(page.all('.award').size).to eq(2) + + # Check tooltip data + page.all('.award').each do |element| + expect(element['title']).to eq("") + end + + page.all('.award .counter').each do |element| + expect(element).to have_content '0' + end end end -- cgit v1.2.1 From 19a3d42cb3262a135451e0a557366d4477ac81fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Mon, 15 Feb 2016 11:51:26 +0100 Subject: Re-add section about NGINX config and init script updates in 8.4->8.5 update doc These sections were removed but: - even if the NGINX config wasn't modified, it might be in future updates so it's better to always have it instead of having to remember to add it depending on the changes - the init script update section must be there since it's a safe command line that should be run on every update [ci skip] --- doc/update/8.4-to-8.5.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/doc/update/8.4-to-8.5.md b/doc/update/8.4-to-8.5.md index 42b26439848..408a17ac348 100644 --- a/doc/update/8.4-to-8.5.md +++ b/doc/update/8.4-to-8.5.md @@ -82,6 +82,32 @@ There are new configuration options available for [`gitlab.yml`](config/gitlab.y git diff origin/8-4-stable:config/gitlab.yml.example origin/8-5-stable:config/gitlab.yml.example ``` +#### Nginx configuration + +Ensure you're still up-to-date with the latest NGINX configuration changes: + +```sh +# For HTTPS configurations +git diff origin/8-4-stable:lib/support/nginx/gitlab-ssl origin/8-5-stable:lib/support/nginx/gitlab-ssl + +# For HTTP configurations +git diff origin/8-4-stable:lib/support/nginx/gitlab origin/8-5-stable:lib/support/nginx/gitlab +``` + +If you are using Apache instead of NGINX please see the updated [Apache templates]. +Also note that because Apache does not support upstreams behind Unix sockets you +will need to let gitlab-workhorse listen on a TCP port. You can do this +via [/etc/default/gitlab]. + +[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache +[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-5-stable/lib/support/init.d/gitlab.default.example#L37 + +#### Init script + +Ensure you're still up-to-date with the latest init script changes: + + sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab + ### 8. Start application sudo service gitlab start -- cgit v1.2.1 From 852bd109c15f918602ce6bc11485ad3d10509112 Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Mon, 15 Feb 2016 13:03:42 +0100 Subject: Updated the allocations Gem to 1.0.4 Sometimes the output of Allocations.to_hash may contain garbage. See https://gitlab.com/gitlab-org/allocations/commit/15d3a39f51392013dcf5f88dd21fab31201350ce for more information. --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 718285e1665..d84cc2d0789 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -50,7 +50,7 @@ GEM after_commit_queue (1.3.0) activerecord (>= 3.0) akismet (2.0.0) - allocations (1.0.3) + allocations (1.0.4) annotate (2.6.10) activerecord (>= 3.2, <= 4.3) rake (~> 10.4) -- cgit v1.2.1 From 54613b6af56008588a3cc8a9e9f2ee642ca59a36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Mon, 15 Feb 2016 15:19:23 +0100 Subject: Fix the "x of y" displayed at the top of Issuables' sidebar 1. We now display the index of the current issuable among all its project's issuables, of the same type and with the same state. 2. Also, refactored a bit the Issuable helpers into a new IssuablesHelper module. 3. Added acceptance specs for the sidebar counter. --- app/helpers/application_helper.rb | 70 ---------------------------- app/helpers/issuables_helper.rb | 41 ++++++++++++++++ app/helpers/nav_helper.rb | 18 ++----- app/models/concerns/issuable.rb | 10 ++++ app/views/shared/issuable/_sidebar.html.haml | 17 +++---- features/project/issues/issues.feature | 9 +++- features/project/merge_requests.feature | 1 + features/steps/project/issues/issues.rb | 5 ++ features/steps/shared/issuable.rb | 24 ++++++++++ 9 files changed, 99 insertions(+), 96 deletions(-) create mode 100644 app/helpers/issuables_helper.rb diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 02357e2f23e..ecefa9b006d 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -280,76 +280,6 @@ module ApplicationHelper end end - def issuable_link_next(project,issuable) - if project.nil? - nil - elsif current_controller?(:issues) - namespace_project_issue_path(project.namespace, project, next_issuable_for(project, issuable.id).try(:iid)) - elsif current_controller?(:merge_requests) - namespace_project_merge_request_path(project.namespace, project, next_issuable_for(project, issuable.id).try(:iid)) - end - end - - def issuable_link_prev(project,issuable) - if project.nil? - nil - elsif current_controller?(:issues) - namespace_project_issue_path(project.namespace, project, prev_issuable_for(project, issuable.id).try(:iid)) - elsif current_controller?(:merge_requests) - namespace_project_merge_request_path(project.namespace, project, prev_issuable_for(project, issuable.id).try(:iid)) - end - end - - def issuable_count(entity, project) - if project.nil? - 0 - elsif current_controller?(:issues) - project.issues.send(entity).count - elsif current_controller?(:merge_requests) - project.merge_requests.send(entity).count - end - end - - def next_issuable_for(project, id) - if project.nil? - nil - elsif current_controller?(:issues) - project.issues.where("id > ?", id).last - elsif current_controller?(:merge_requests) - project.merge_requests.where("id > ?", id).last - end - end - - def has_next_issuable?(project, id) - if project.nil? - nil - elsif current_controller?(:issues) - project.issues.where("id > ?", id).last - elsif current_controller?(:merge_requests) - project.merge_requests.where("id > ?", id).last - end - end - - def prev_issuable_for(project, id) - if project.nil? - nil - elsif current_controller?(:issues) - project.issues.where("id < ?", id).first - elsif current_controller?(:merge_requests) - project.merge_requests.where("id < ?", id).first - end - end - - def has_prev_issuable?(project, id) - if project.nil? - nil - elsif current_controller?(:issues) - project.issues.where("id < ?", id).first - elsif current_controller?(:merge_requests) - project.merge_requests.where("id < ?", id).first - end - end - def state_filters_text_for(entity, project) titles = { opened: "Open" diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb new file mode 100644 index 00000000000..ccbd93967a2 --- /dev/null +++ b/app/helpers/issuables_helper.rb @@ -0,0 +1,41 @@ +module IssuablesHelper + + def sidebar_gutter_toggle_icon + sidebar_gutter_collapsed? ? icon('angle-double-left') : icon('angle-double-right') + end + + def sidebar_gutter_collapsed_class + "right-sidebar-#{sidebar_gutter_collapsed? ? 'collapsed' : 'expanded'}" + end + + def issuable_index(issuable) + base_issuable_scope(issuable).where('id < ?', issuable.id).size + 1 + end + + def issuables_count(issuable) + base_issuable_scope(issuable).size + end + + def next_issuable_for(issuable) + base_issuable_scope(issuable).where('id > ?', issuable.id).last + end + + def prev_issuable_for(issuable) + base_issuable_scope(issuable).where('id < ?', issuable.id).first + end + + private + + def sidebar_gutter_collapsed? + cookies[:collapsed_gutter] == 'true' + end + + def base_issuable_scope(issuable) + issuable.project.send(issuable.to_scope_name).send(issuable_state_scope(issuable)) + end + + def issuable_state_scope(issuable) + issuable.open? ? :opened : :closed + end + +end diff --git a/app/helpers/nav_helper.rb b/app/helpers/nav_helper.rb index 75f2ed5e054..29cb753e62c 100644 --- a/app/helpers/nav_helper.rb +++ b/app/helpers/nav_helper.rb @@ -3,18 +3,6 @@ module NavHelper cookies[:collapsed_nav] == 'true' end - def sidebar_gutter_collapsed_class - if cookies[:collapsed_gutter] == 'true' - "right-sidebar-collapsed" - else - "right-sidebar-expanded" - end - end - - def sidebar_gutter_collapsed? - cookies[:collapsed_gutter] == 'true' - end - def nav_sidebar_class if nav_menu_collapsed? "sidebar-collapsed" @@ -32,9 +20,9 @@ module NavHelper end def page_gutter_class - if current_path?('merge_requests#show') || - current_path?('merge_requests#diffs') || - current_path?('merge_requests#commits') || + if current_path?('merge_requests#show') || + current_path?('merge_requests#diffs') || + current_path?('merge_requests#commits') || current_path?('issues#show') if cookies[:collapsed_gutter] == 'true' "page-gutter right-sidebar-collapsed" diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb index cf6aa592e2a..e08687135d6 100644 --- a/app/models/concerns/issuable.rb +++ b/app/models/concerns/issuable.rb @@ -168,6 +168,16 @@ module Issuable self.class.to_s.underscore end + # Convert this Issuable class name to a format usable for scoping + # + # Examples: + # + # issuable.class # => MergeRequest + # issuable.to_scope_name # => "merge_requests" + def to_scope_name + self.class.to_s.tableize + end + # Returns a Hash of attributes to be used for Twitter card metadata def card_attributes { diff --git a/app/views/shared/issuable/_sidebar.html.haml b/app/views/shared/issuable/_sidebar.html.haml index ae96a45453f..cb5378964bc 100644 --- a/app/views/shared/issuable/_sidebar.html.haml +++ b/app/views/shared/issuable/_sidebar.html.haml @@ -2,23 +2,20 @@ .issuable-sidebar .block %span.issuable-count.pull-left - = issuable.iid + = issuable_index(issuable) of - = issuable_count(:all, @project) + = issuables_count(issuable) %span.pull-right %a.gutter-toggle{href: '#'} - - if sidebar_gutter_collapsed? - = icon('angle-double-left') - - else - = icon('angle-double-right') + = sidebar_gutter_toggle_icon .issuable-nav.pull-right.btn-group{role: 'group', "aria-label" => '...'} - - if has_prev_issuable?(@project, issuable.id) - = link_to 'Prev', issuable_link_prev(@project, issuable), class: 'btn btn-default prev-btn' + - if prev_issuable = prev_issuable_for(issuable) + = link_to 'Prev', [@project.namespace.becomes(Namespace), @project, prev_issuable], class: 'btn btn-default prev-btn' - else %a.btn.btn-default.disabled{href: '#'} Prev - - if has_next_issuable?(@project, issuable.id) - = link_to 'Next', issuable_link_next(@project, issuable), class: 'btn btn-default next-btn' + - if next_issuable = next_issuable_for(issuable) + = link_to 'Next', [@project.namespace.becomes(Namespace), @project, next_issuable], class: 'btn btn-default next-btn' - else %a.btn.btn-default.disabled{href: '#'} Next diff --git a/features/project/issues/issues.feature b/features/project/issues/issues.feature index 0b3d03aa2a5..ca2399d85a9 100644 --- a/features/project/issues/issues.feature +++ b/features/project/issues/issues.feature @@ -25,9 +25,16 @@ Feature: Project Issues Scenario: I visit issue page Given I click link "Release 0.4" Then I should see issue "Release 0.4" + And I should see "1 of 2" in the sidebar + + Scenario: I navigate between issues + Given I click link "Release 0.4" + Then I click link "Next" in the sidebar + Then I should see issue "Tweet control" + And I should see "2 of 2" in the sidebar @javascript - Scenario: I visit issue page + Scenario: I filter by author Given I add a user to project "Shop" And I click "author" dropdown Then I see current user as the first user diff --git a/features/project/merge_requests.feature b/features/project/merge_requests.feature index ca1ee6b3c2b..5995e787961 100644 --- a/features/project/merge_requests.feature +++ b/features/project/merge_requests.feature @@ -39,6 +39,7 @@ Feature: Project Merge Requests Scenario: I visit merge request page Given I click link "Bug NS-04" Then I should see merge request "Bug NS-04" + And I should see "1 of 1" in the sidebar Scenario: I close merge request page Given I click link "Bug NS-04" diff --git a/features/steps/project/issues/issues.rb b/features/steps/project/issues/issues.rb index d556b73f9fd..09a89e99831 100644 --- a/features/steps/project/issues/issues.rb +++ b/features/steps/project/issues/issues.rb @@ -54,6 +54,10 @@ class Spinach::Features::ProjectIssues < Spinach::FeatureSteps expect(page).to have_content "Release 0.4" end + step 'I should see issue "Tweet control"' do + expect(page).to have_content "Tweet control" + end + step 'I click link "New Issue"' do click_link "New Issue" end @@ -301,4 +305,5 @@ class Spinach::Features::ProjectIssues < Spinach::FeatureSteps def filter_issue(text) fill_in 'issue_search', with: text end + end diff --git a/features/steps/shared/issuable.rb b/features/steps/shared/issuable.rb index 25c2b476f43..2117feaedb8 100644 --- a/features/steps/shared/issuable.rb +++ b/features/steps/shared/issuable.rb @@ -119,6 +119,24 @@ module SharedIssuable end end + step 'I should see "1 of 1" in the sidebar' do + expect_sidebar_content('1 of 1') + end + + step 'I should see "1 of 2" in the sidebar' do + expect_sidebar_content('1 of 2') + end + + step 'I should see "2 of 2" in the sidebar' do + expect_sidebar_content('2 of 2') + end + + step 'I click link "Next" in the sidebar' do + page.within '.issuable-sidebar' do + click_link 'Next' + end + end + def create_issuable_for_project(project_name:, title:, type: :issue) project = Project.find_by(name: project_name) @@ -159,4 +177,10 @@ module SharedIssuable expect(page).to have_content("mentioned in #{issuable.class.to_s.titleize.downcase} #{issuable.to_reference(project)}") end + def expect_sidebar_content(content) + page.within '.issuable-sidebar' do + expect(page).to have_content content + end + end + end -- cgit v1.2.1 From 20e79f714a4b98526d5eeffc82c0de89c8369c4e Mon Sep 17 00:00:00 2001 From: James Lopez Date: Mon, 15 Feb 2016 15:51:00 +0100 Subject: refactored GitPushService and updated spec --- app/services/git_push_service.rb | 47 ++++++++++++++------------------- app/workers/post_receive.rb | 7 ++++- spec/services/git_push_service_spec.rb | 48 +++++++++++++++++----------------- 3 files changed, 49 insertions(+), 53 deletions(-) diff --git a/app/services/git_push_service.rb b/app/services/git_push_service.rb index 5362dd401be..b203065e708 100644 --- a/app/services/git_push_service.rb +++ b/app/services/git_push_service.rb @@ -1,19 +1,10 @@ -class GitPushService - attr_accessor :project, :user, :push_data, :push_commits +class GitPushService < BaseService + attr_accessor :push_data, :push_commits include Gitlab::CurrentSettings include Gitlab::Access - def initialize(project, user, oldrev, newrev, ref) - # TODO: Consider passing an options hash instead https://github.com/bbatsov/ruby-style-guide#too-many-params - @project = project - @user = user - @oldrev = oldrev - @newrev = newrev - @ref = ref - end - # This method will be called after each git update - # and only if the provided user and project is present in GitLab. + # and only if the provided user and project are present in GitLab. # # All callbacks for post receive action should be placed here. # @@ -41,14 +32,14 @@ class GitPushService # Use the pushed commits that aren't reachable by the default branch # as a heuristic. This may include more commits than are actually pushed, but # that shouldn't matter because we check for existing cross-references later. - @push_commits = @project.repository.commits_between(@project.default_branch, @newrev) + @push_commits = @project.repository.commits_between(@project.default_branch, params[:newrev]) # don't process commits for the initial push to the default branch process_commit_messages end elsif push_to_existing_branch? # Collect data for this git push - @push_commits = @project.repository.commits_between(@oldrev, @newrev) + @push_commits = @project.repository.commits_between(params[:oldrev], params[:newrev]) process_commit_messages end # Update merge requests that may be affected by this push. A new branch @@ -59,17 +50,17 @@ class GitPushService protected def update_merge_requests - @project.update_merge_requests(@oldrev, @newrev, @ref, @user) + @project.update_merge_requests(params[:oldrev], params[:newrev], params[:ref], current_user) - EventCreateService.new.push(@project, @user, build_push_data) + EventCreateService.new.push(@project, current_user, build_push_data) @project.execute_hooks(build_push_data.dup, :push_hooks) @project.execute_services(build_push_data.dup, :push_hooks) - CreateCommitBuildsService.new.execute(@project, @user, build_push_data) + CreateCommitBuildsService.new.execute(@project, current_user, build_push_data) ProjectCacheWorker.perform_async(@project.id) end def process_default_branch - @push_commits = project.repository.commits(@newrev) + @push_commits = project.repository.commits(params[:newrev]) # Ensure HEAD points to the default branch in case it is not master project.change_head(branch_name) @@ -103,7 +94,7 @@ class GitPushService # Close issues if these commits were pushed to the project's default branch and the commit message matches the # closing regex. Exclude any mentioned Issues from cross-referencing even if the commits are being pushed to # a different branch. - closed_issues = commit.closes_issues(user) + closed_issues = commit.closes_issues(current_user) closed_issues.each do |issue| Issues::CloseService.new(project, authors[commit], {}).execute(issue, commit) end @@ -115,36 +106,36 @@ class GitPushService def build_push_data @push_data ||= Gitlab::PushDataBuilder. - build(@project, @user, @oldrev, @newrev, @ref, push_commits) + build(@project, current_user, params[:oldrev], params[:newrev], params[:ref], push_commits) end def push_to_existing_branch? # Return if this is not a push to a branch (e.g. new commits) - Gitlab::Git.branch_ref?(@ref) && !Gitlab::Git.blank_ref?(@oldrev) + Gitlab::Git.branch_ref?(params[:ref]) && !Gitlab::Git.blank_ref?(params[:oldrev]) end def push_to_new_branch? - Gitlab::Git.branch_ref?(@ref) && Gitlab::Git.blank_ref?(@oldrev) + Gitlab::Git.branch_ref?(params[:ref]) && Gitlab::Git.blank_ref?(params[:oldrev]) end def push_remove_branch? - Gitlab::Git.branch_ref?(@ref) && Gitlab::Git.blank_ref?(@newrev) + Gitlab::Git.branch_ref?(params[:ref]) && Gitlab::Git.blank_ref?(params[:newrev]) end def push_to_branch? - Gitlab::Git.branch_ref?(@ref) + Gitlab::Git.branch_ref?(params[:ref]) end def is_default_branch? - Gitlab::Git.branch_ref?(@ref) && - (Gitlab::Git.ref_name(@ref) == project.default_branch || project.default_branch.nil?) + Gitlab::Git.branch_ref?(params[:ref]) && + (Gitlab::Git.ref_name(params[:ref]) == project.default_branch || project.default_branch.nil?) end def commit_user(commit) - commit.author || user + commit.author || current_user end def branch_name - @_branch_name ||= Gitlab::Git.ref_name(@ref) + @_branch_name ||= Gitlab::Git.ref_name(params[:ref]) end end diff --git a/app/workers/post_receive.rb b/app/workers/post_receive.rb index 80081ac5f49..9e7934b84d8 100644 --- a/app/workers/post_receive.rb +++ b/app/workers/post_receive.rb @@ -38,7 +38,12 @@ class PostReceive if Gitlab::Git.tag_ref?(ref) GitTagPushService.new.execute(project, @user, oldrev, newrev, ref) else - GitPushService.new(project, @user, oldrev, newrev, ref).execute + GitPushService.new(project, @user, + { + oldrev: oldrev, + newrev: newrev, + ref: ref + }).execute end end end diff --git a/spec/services/git_push_service_spec.rb b/spec/services/git_push_service_spec.rb index ad18f48ff91..f953f226e67 100644 --- a/spec/services/git_push_service_spec.rb +++ b/spec/services/git_push_service_spec.rb @@ -16,7 +16,7 @@ describe GitPushService, services: true do describe 'Push branches' do context 'new branch' do subject do - service = described_class.new(project, user, @blankrev, @newrev, @ref) + service = described_class.new(project, user, { oldrev: @blankrev, newrev: @newrev, ref: @ref }) service.execute end @@ -37,7 +37,7 @@ describe GitPushService, services: true do context 'existing branch' do subject do - service = described_class.new(project, user, @oldrev, @newrev, @ref) + service = described_class.new(project, user, { oldrev: @oldrev, newrev: @newrev, ref: @ref }) service.execute end @@ -52,7 +52,7 @@ describe GitPushService, services: true do context 'rm branch' do subject do - service = described_class.new(project, user, @oldrev, @blankrev, @ref) + service = described_class.new(project, user, { oldrev: @oldrev, newrev: @blankrev, ref: @ref }) service.execute end @@ -74,7 +74,7 @@ describe GitPushService, services: true do describe "Git Push Data" do before do - service = described_class.new(project, user, @oldrev, @newrev, @ref) + service = described_class.new(project, user, { oldrev: @oldrev, newrev: @newrev, ref: @ref }) service.execute @push_data = service.push_data @commit = project.commit(@newrev) @@ -137,7 +137,7 @@ describe GitPushService, services: true do describe "Push Event" do before do - service = described_class.new(project, user, @oldrev, @newrev, @ref) + service = described_class.new(project, user, { oldrev: @oldrev, newrev: @newrev, ref: @ref }) service.execute @event = Event.last @push_data = service.push_data @@ -152,7 +152,7 @@ describe GitPushService, services: true do it "when pushing a new branch for the first time" do expect(project).to receive(:update_merge_requests). with(@blankrev, 'newrev', 'refs/heads/master', user) - service = described_class.new(project, user, @blankrev, 'newrev', 'refs/heads/master') + service = described_class.new(project, user, { oldrev: @blankrev, newrev: 'newrev', ref: 'refs/heads/master' }) service.execute end end @@ -164,7 +164,7 @@ describe GitPushService, services: true do expect(project).to receive(:execute_hooks) expect(project.default_branch).to eq("master") expect(project.protected_branches).to receive(:create).with({ name: "master", developers_can_push: false }) - service = described_class.new(project, user, @blankrev, 'newrev', 'refs/heads/master') + service = described_class.new(project, user, { oldrev: @blankrev, newrev: 'newrev', ref: 'refs/heads/master' }) service.execute end @@ -174,7 +174,7 @@ describe GitPushService, services: true do expect(project).to receive(:execute_hooks) expect(project.default_branch).to eq("master") expect(project.protected_branches).not_to receive(:create) - service = described_class.new(project, user, @blankrev, 'newrev', 'refs/heads/master') + service = described_class.new(project, user, { oldrev: @blankrev, newrev: 'newrev', ref: 'refs/heads/master' }) service.execute end @@ -184,13 +184,13 @@ describe GitPushService, services: true do expect(project).to receive(:execute_hooks) expect(project.default_branch).to eq("master") expect(project.protected_branches).to receive(:create).with({ name: "master", developers_can_push: true }) - service = described_class.new(project, user, @blankrev, 'newrev', 'refs/heads/master') + service = described_class.new(project, user, { oldrev: @blankrev, newrev: 'newrev', ref: 'refs/heads/master' }) service.execute end it "when pushing new commits to existing branch" do expect(project).to receive(:execute_hooks) - service = described_class.new(project, user, 'oldrev', 'newrev', 'refs/heads/master') + service = described_class.new(project, user, { oldrev: 'oldrev', newrev: 'newrev', ref: 'refs/heads/master' }) service.execute end end @@ -214,7 +214,7 @@ describe GitPushService, services: true do it "creates a note if a pushed commit mentions an issue" do expect(SystemNoteService).to receive(:cross_reference).with(issue, commit, commit_author) - service = described_class.new(project, user, @oldrev, @newrev, @ref) + service = described_class.new(project, user, { oldrev: @oldrev, newrev: @newrev, ref: @ref }) service.execute end @@ -224,7 +224,7 @@ describe GitPushService, services: true do expect(SystemNoteService).not_to receive(:cross_reference).with(issue, commit, commit_author) - service = described_class.new(project, user, @oldrev, @newrev, @ref) + service = described_class.new(project, user, { oldrev: @oldrev, newrev: @newrev, ref: @ref }) service.execute end @@ -236,7 +236,7 @@ describe GitPushService, services: true do ) expect(SystemNoteService).to receive(:cross_reference).with(issue, commit, user) - service = described_class.new(project, user, @oldrev, @newrev, @ref) + service = described_class.new(project, user, { oldrev: @oldrev, newrev: @newrev, ref: @ref }) service.execute end @@ -247,7 +247,7 @@ describe GitPushService, services: true do expect(SystemNoteService).to receive(:cross_reference).with(issue, commit, commit_author) - service = described_class.new(project, user, @blankrev, @newrev, 'refs/heads/other') + service = described_class.new(project, user, { oldrev: @blankrev, newrev: @newrev, ref: 'refs/heads/other' }) service.execute end @@ -273,20 +273,20 @@ describe GitPushService, services: true do context "to default branches" do it "closes issues" do - service = described_class.new(project, user, @oldrev, @newrev, @ref) + service = described_class.new(project, user, { oldrev: @oldrev, newrev: @newrev, ref: @ref }) service.execute expect(Issue.find(issue.id)).to be_closed end it "adds a note indicating that the issue is now closed" do expect(SystemNoteService).to receive(:change_status).with(issue, project, commit_author, "closed", closing_commit) - service = described_class.new(project, user, @oldrev, @newrev, @ref) + service = described_class.new(project, user, { oldrev: @oldrev, newrev: @newrev, ref: @ref }) service.execute end it "doesn't create additional cross-reference notes" do expect(SystemNoteService).not_to receive(:cross_reference) - service = described_class.new(project, user, @oldrev, @newrev, @ref) + service = described_class.new(project, user, { oldrev: @oldrev, newrev: @newrev, ref: @ref }) service.execute end @@ -295,7 +295,7 @@ describe GitPushService, services: true do # The push still shouldn't create cross-reference notes. expect do - service = described_class.new(project, user, @oldrev, @newrev, 'refs/heads/hurf') + service = described_class.new(project, user, { oldrev: @oldrev, newrev: @newrev, ref: 'refs/heads/hurf' }) service.execute end.not_to change { Note.where(project_id: project.id, system: true).count } end @@ -309,12 +309,12 @@ describe GitPushService, services: true do it "creates cross-reference notes" do expect(SystemNoteService).to receive(:cross_reference).with(issue, closing_commit, commit_author) - service = described_class.new(project, user, @oldrev, @newrev, @ref) + service = described_class.new(project, user, { oldrev: @oldrev, newrev: @newrev, ref: @ref }) service.execute end it "doesn't close issues" do - service = described_class.new(project, user, @oldrev, @newrev, @ref) + service = described_class.new(project, user, { oldrev: @oldrev, newrev: @newrev, ref: @ref }) service.execute expect(Issue.find(issue.id)).to be_opened end @@ -352,7 +352,7 @@ describe GitPushService, services: true do let(:message) { "this is some work.\n\nrelated to JIRA-1" } it "should initiate one api call to jira server to mention the issue" do - service = described_class.new(project, user, @oldrev, @newrev, @ref) + service = described_class.new(project, user, { oldrev: @oldrev, newrev: @newrev, ref: @ref }) service.execute expect(WebMock).to have_requested(:post, jira_api_comment_url).with( @@ -371,7 +371,7 @@ describe GitPushService, services: true do } }.to_json - service = described_class.new(project, user, @oldrev, @newrev, @ref) + service = described_class.new(project, user, { oldrev: @oldrev, newrev: @newrev, ref: @ref }) service.execute expect(WebMock).to have_requested(:post, jira_api_transition_url).with( @@ -384,7 +384,7 @@ describe GitPushService, services: true do body: "Issue solved with [#{closing_commit.id}|http://localhost/#{project.path_with_namespace}/commit/#{closing_commit.id}]." }.to_json - service = described_class.new(project, user, @oldrev, @newrev, @ref) + service = described_class.new(project, user, { oldrev: @oldrev, newrev: @newrev, ref: @ref }) service.execute expect(WebMock).to have_requested(:post, jira_api_comment_url).with( @@ -405,7 +405,7 @@ describe GitPushService, services: true do end it 'push to first branch updates HEAD' do - service = described_class.new(project, user, @blankrev, @newrev, new_ref) + service = described_class.new(project, user, { oldrev: @blankrev, newrev: @newrev, ref: new_ref }) service.execute end end -- cgit v1.2.1 From 447568d15f9ec2d47a15fc04aeb2cb507cd6a55c Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Mon, 15 Feb 2016 14:13:47 -0500 Subject: Fix undefined method `postgresql?` during migration --- lib/gitlab/database.rb | 8 ++------ spec/lib/gitlab/database_spec.rb | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/lib/gitlab/database.rb b/lib/gitlab/database.rb index 6ebb8027553..6f9da69983a 100644 --- a/lib/gitlab/database.rb +++ b/lib/gitlab/database.rb @@ -17,7 +17,7 @@ module Gitlab end def true_value - if self.class.postgresql? + if Gitlab::Database.postgresql? "'t'" else 1 @@ -25,7 +25,7 @@ module Gitlab end def false_value - if self.class.postgresql? + if Gitlab::Database.postgresql? "'f'" else 0 @@ -47,9 +47,5 @@ module Gitlab row.first end end - - def connection - self.class.connection - end end end diff --git a/spec/lib/gitlab/database_spec.rb b/spec/lib/gitlab/database_spec.rb index bd8688fefa1..d0a447753b7 100644 --- a/spec/lib/gitlab/database_spec.rb +++ b/spec/lib/gitlab/database_spec.rb @@ -1,5 +1,9 @@ require 'spec_helper' +class MigrationTest + include Gitlab::Database +end + describe Gitlab::Database, lib: true do # These are just simple smoke tests to check if the methods work (regardless # of what they may return). @@ -34,4 +38,32 @@ describe Gitlab::Database, lib: true do end end end + + describe '#true_value' do + it 'returns correct value for PostgreSQL' do + expect(described_class).to receive(:postgresql?).and_return(true) + + expect(MigrationTest.new.true_value).to eq "'t'" + end + + it 'returns correct value for MySQL' do + expect(described_class).to receive(:postgresql?).and_return(false) + + expect(MigrationTest.new.true_value).to eq 1 + end + end + + describe '#false_value' do + it 'returns correct value for PostgreSQL' do + expect(described_class).to receive(:postgresql?).and_return(true) + + expect(MigrationTest.new.false_value).to eq "'f'" + end + + it 'returns correct value for MySQL' do + expect(described_class).to receive(:postgresql?).and_return(false) + + expect(MigrationTest.new.false_value).to eq 0 + end + end end -- cgit v1.2.1 From f5ab126fd0e607811638ca36b6752d5c74535adf Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Mon, 15 Feb 2016 15:48:16 -0500 Subject: Ensure Commit#show responds 404 instead of 500 when given an invalid ID Closes #13467 --- app/controllers/projects/commit_controller.rb | 4 +-- .../controllers/projects/commit_controller_spec.rb | 37 ++++++++++++++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 spec/controllers/projects/commit_controller_spec.rb diff --git a/app/controllers/projects/commit_controller.rb b/app/controllers/projects/commit_controller.rb index 21f4d9f44ec..36951b91372 100644 --- a/app/controllers/projects/commit_controller.rb +++ b/app/controllers/projects/commit_controller.rb @@ -11,8 +11,6 @@ class Projects::CommitController < Projects::ApplicationController before_action :define_show_vars, only: [:show, :builds] def show - return git_not_found! unless @commit - apply_diff_view_cookie! @line_notes = commit.notes.inline @@ -68,6 +66,8 @@ class Projects::CommitController < Projects::ApplicationController end def define_show_vars + return git_not_found! unless commit + if params[:w].to_i == 1 @diffs = commit.diffs({ ignore_whitespace_change: true }) else diff --git a/spec/controllers/projects/commit_controller_spec.rb b/spec/controllers/projects/commit_controller_spec.rb new file mode 100644 index 00000000000..438e776ec4b --- /dev/null +++ b/spec/controllers/projects/commit_controller_spec.rb @@ -0,0 +1,37 @@ +require 'rails_helper' + +describe Projects::CommitController do + describe 'GET show' do + let(:project) { create(:project) } + + before do + user = create(:user) + project.team << [user, :master] + + sign_in(user) + end + + context 'with valid id' do + it 'responds with 200' do + go id: project.commit.id + + expect(response).to be_ok + end + end + + context 'with invalid id' do + it 'responds with 404' do + go id: project.commit.id.reverse + + expect(response).to be_not_found + end + end + + def go(id:) + get :show, + namespace_id: project.namespace.to_param, + project_id: project.to_param, + id: id + end + end +end -- cgit v1.2.1 From 012c75d1b0a24aff3c31ca5b5d475e06d5f77428 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Mon, 15 Feb 2016 15:52:39 -0500 Subject: Properly render the `errors/git_not_found` page --- app/controllers/application_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 48b1f95acb9..7afe3c0c471 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -164,7 +164,7 @@ class ApplicationController < ActionController::Base end def git_not_found! - render html: "errors/git_not_found", layout: "errors", status: 404 + render "errors/git_not_found", layout: "errors", status: 404 end def method_missing(method_sym, *arguments, &block) -- cgit v1.2.1 From 789aef7f26597f026859b2ddd29fab1120ce8abe Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Mon, 15 Feb 2016 16:06:45 -0500 Subject: Handle nil commits in Gitlab::PushDataBuilder.build Closes #13469 --- lib/gitlab/push_data_builder.rb | 2 ++ spec/lib/gitlab/push_data_builder_spec.rb | 21 ++++++++++++--------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/lib/gitlab/push_data_builder.rb b/lib/gitlab/push_data_builder.rb index 4f9cdef3869..efcb23c0c6d 100644 --- a/lib/gitlab/push_data_builder.rb +++ b/lib/gitlab/push_data_builder.rb @@ -22,6 +22,8 @@ module Gitlab # } # def build(project, user, oldrev, newrev, ref, commits = [], message = nil) + commits = Array(commits) + # Total commits count commits_count = commits.size diff --git a/spec/lib/gitlab/push_data_builder_spec.rb b/spec/lib/gitlab/push_data_builder_spec.rb index 3ef61685398..5ec9a84c5ab 100644 --- a/spec/lib/gitlab/push_data_builder_spec.rb +++ b/spec/lib/gitlab/push_data_builder_spec.rb @@ -1,12 +1,12 @@ require 'spec_helper' -describe 'Gitlab::PushDataBuilder', lib: true do +describe Gitlab::PushDataBuilder, lib: true do let(:project) { create(:project) } let(:user) { create(:user) } - describe :build_sample do - let(:data) { Gitlab::PushDataBuilder.build_sample(project, user) } + describe '.build_sample' do + let(:data) { described_class.build_sample(project, user) } it { expect(data).to be_a(Hash) } it { expect(data[:before]).to eq('6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9') } @@ -22,13 +22,11 @@ describe 'Gitlab::PushDataBuilder', lib: true do it { expect(data[:commits].first[:removed]).to eq([]) } end - describe :build do + describe '.build' do let(:data) do - Gitlab::PushDataBuilder.build(project, - user, - Gitlab::Git::BLANK_SHA, - '8a2a6eb295bb170b34c24c76c49ed0e9b2eaf34b', - 'refs/tags/v1.1.0') + described_class.build(project, user, Gitlab::Git::BLANK_SHA, + '8a2a6eb295bb170b34c24c76c49ed0e9b2eaf34b', + 'refs/tags/v1.1.0') end it { expect(data).to be_a(Hash) } @@ -38,5 +36,10 @@ describe 'Gitlab::PushDataBuilder', lib: true do it { expect(data[:ref]).to eq('refs/tags/v1.1.0') } it { expect(data[:commits]).to be_empty } it { expect(data[:total_commits_count]).to be_zero } + + it 'does not raise an error when given nil commits' do + expect { described_class.build(spy, spy, spy, spy, spy, nil) }. + not_to raise_error + end end end -- cgit v1.2.1 From 807765b6a779239c6bb706ab6dbe742efe0e3e64 Mon Sep 17 00:00:00 2001 From: Alfredo Sumaran Date: Mon, 15 Feb 2016 16:29:22 -0500 Subject: Move issue details after action buttons --- app/views/projects/issues/show.html.haml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/app/views/projects/issues/show.html.haml b/app/views/projects/issues/show.html.haml index fe977fd700c..d635a879491 100644 --- a/app/views/projects/issues/show.html.haml +++ b/app/views/projects/issues/show.html.haml @@ -6,16 +6,6 @@ .issue .detail-page-header - .status-box{ class: "status-box-closed #{issue_button_visibility(@issue, false)}"} Closed - .status-box{ class: "status-box-open #{issue_button_visibility(@issue, true)}"} Open - %span.identifier - Issue ##{@issue.iid} - %span.creator - · - opened by #{link_to_member(@project, @issue.author, size: 24)} - · - = time_ago_with_tooltip(@issue.created_at, placement: 'bottom', html_class: 'issue_created_ago') - .pull-right - if can?(current_user, :create_issue, @project) = link_to new_namespace_project_issue_path(@project.namespace, @project), class: 'btn btn-nr btn-grouped new-issue-link btn-success', title: 'New Issue', id: 'new_issue_link' do @@ -29,6 +19,16 @@ = icon('pencil-square-o') Edit + .status-box{ class: "status-box-closed #{issue_button_visibility(@issue, false)}"} Closed + .status-box{ class: "status-box-open #{issue_button_visibility(@issue, true)}"} Open + %span.identifier + Issue ##{@issue.iid} + %span.creator + · + opened by #{link_to_member(@project, @issue.author, size: 24)} + · + = time_ago_with_tooltip(@issue.created_at, placement: 'bottom', html_class: 'issue_created_ago') + .issue-details.issuable-details .detail-page-description.content-block %h2.title -- cgit v1.2.1 From 4af93e0296b53985cd5c96e8d7733d00d313f5be Mon Sep 17 00:00:00 2001 From: Alfredo Sumaran Date: Mon, 15 Feb 2016 16:30:17 -0500 Subject: Prevent split time into multiple lines for better reading --- app/assets/stylesheets/pages/detail_page.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/assets/stylesheets/pages/detail_page.scss b/app/assets/stylesheets/pages/detail_page.scss index 529a43548c8..542842e0d43 100644 --- a/app/assets/stylesheets/pages/detail_page.scss +++ b/app/assets/stylesheets/pages/detail_page.scss @@ -12,6 +12,10 @@ .identifier { color: #5c5d5e; } + + .issue_created_ago { + white-space: nowrap; + } } .detail-page-description { -- cgit v1.2.1 From ae13389b0b8654abcffead659788580e8c1f1a15 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Mon, 15 Feb 2016 16:38:27 -0500 Subject: Provide explicit html format when rendering git_not_found page Prior, if the request format was, for example, .zip, we'd get an `ActionView::MissingTemplate` error. --- app/controllers/application_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 7afe3c0c471..2c329b60a19 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -164,7 +164,7 @@ class ApplicationController < ActionController::Base end def git_not_found! - render "errors/git_not_found", layout: "errors", status: 404 + render "errors/git_not_found.html", layout: "errors", status: 404 end def method_missing(method_sym, *arguments, &block) -- cgit v1.2.1 From 828f7a12dc24bd5fb8073c40b229525f711989c3 Mon Sep 17 00:00:00 2001 From: Alfredo Sumaran Date: Mon, 15 Feb 2016 16:46:21 -0500 Subject: Prevent author name to split into multiple lines --- app/assets/stylesheets/pages/detail_page.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/stylesheets/pages/detail_page.scss b/app/assets/stylesheets/pages/detail_page.scss index 542842e0d43..0bddc83f5c0 100644 --- a/app/assets/stylesheets/pages/detail_page.scss +++ b/app/assets/stylesheets/pages/detail_page.scss @@ -13,7 +13,7 @@ color: #5c5d5e; } - .issue_created_ago { + .issue_created_ago, .author_link { white-space: nowrap; } } -- cgit v1.2.1 From 3de6edd6041a725aaffba95603d4eb2912627d42 Mon Sep 17 00:00:00 2001 From: Sytse Sijbrandij Date: Mon, 15 Feb 2016 19:38:36 -0800 Subject: Updates to git flow documentation. --- doc/workflow/gitlab_flow.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/doc/workflow/gitlab_flow.md b/doc/workflow/gitlab_flow.md index be32f0c720b..0b205ea6de7 100644 --- a/doc/workflow/gitlab_flow.md +++ b/doc/workflow/gitlab_flow.md @@ -187,12 +187,15 @@ If you have an issue that spans across multiple repositories, the best thing is ![Vim screen showing the rebase view](rebase.png) With git you can use an interactive rebase (`rebase -i`) to squash multiple commits into one and reorder them. +In GitLab EE and .com you can also [rebase before merge](http://doc.gitlab.com/ee/workflow/rebase_before_merge.html) from the web interface. This functionality is useful if you made a couple of commits for small changes during development and want to replace them with a single commit or if you want to make the order more logical. However you should never rebase commits you have pushed to a remote server. Somebody can have referred to the commits or cherry-picked them. When you rebase you change the identifier (SHA-1) of the commit and this is confusing. If you do that the same change will be known under multiple identifiers and this can cause much confusion. If people already reviewed your code it will be hard for them to review only the improvements you made since then if you have rebased everything into one commit. +Another reasons not to rebase is that you lose authorship information, maybe someone created a merge request, another person pushed a commit on there to improve it and a third one merged it. +In this case rebasing all the commits into one prevent the other authors from being properly attributed and sharing part of the [git blame](https://git-scm.com/docs/git-blame). People are encouraged to commit often and to frequently push to the remote repository so other people are aware what everyone is working on. This will lead to many commits per change which makes the history harder to understand. @@ -221,13 +224,11 @@ You can reuse recorded resolutions (rerere) sometimes, but without rebasing you There has to be a better way to avoid many merge commits. The way to prevent creating many merge commits is to not frequently merge master into the feature branch. -We'll discuss the three reasons to merge in master: leveraging code, solving merge conflicts and long running branches. +We'll discuss the three reasons to merge in master: leveraging code, merge conflicts, and long running branches. If you need to leverage some code that was introduced in master after you created the feature branch you can sometimes solve this by just cherry-picking a commit. If your feature branch has a merge conflict, creating a merge commit is a normal way of solving this. -You should aim to prevent merge conflicts where they are likely to occur. -One example is the CHANGELOG file where each significant change in the codebase is documented under a version header. -Instead of everyone adding their change at the bottom of the list for the current version it is better to randomly insert it in the current list for that version. -This it is likely that multiple feature branches that add to the CHANGELOG can be merged before a conflict occurs. +You can prevent some merge conflicts by using [gitattributes](http://git-scm.com/docs/gitattributes) for files that can be in a random order. +For example in GitLab our changelog file is specified in .gitattributes as `CHANGELOG merge=union` so that there are fewer merge conflicts in it. The last reason for creating merge commits is having long lived branches that you want to keep up to date with the latest state of the project. Martin Fowler, in [his article about feature branches](http://martinfowler.com/bliki/FeatureBranch.html) talks about this Continuous Integration (CI). At GitLab we are guilty of confusing CI with branch testing. Quoting Martin Fowler: "I've heard people say they are doing CI because they are running builds, perhaps using a CI server, on every branch with every commit. -- cgit v1.2.1 From 11913a762a3ed6514594e6ac6ffe1717dd362ae1 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Tue, 16 Feb 2016 09:01:56 +0100 Subject: updated system note service and spec based on feedback --- app/services/system_note_service.rb | 4 +++- spec/services/system_note_service_spec.rb | 4 ---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/app/services/system_note_service.rb b/app/services/system_note_service.rb index 843b44abd17..edced010811 100644 --- a/app/services/system_note_service.rb +++ b/app/services/system_note_service.rb @@ -274,7 +274,9 @@ class SystemNoteService # Check if a cross reference to a noteable from a mentioner already exists # # This method is used to prevent multiple notes being created for a mention - # when a issue is updated, for example. + # when a issue is updated, for example. The method also calls notes_for_mentioner + # to check if the mentioner is a commit, and return matches only on commit hash + # instead of project + commit, to avoid repeated mentions from forks. # # noteable - Noteable object being referenced # mentioner - Mentionable object diff --git a/spec/services/system_note_service_spec.rb b/spec/services/system_note_service_spec.rb index 9b9732ea01f..1bdc03af12d 100644 --- a/spec/services/system_note_service_spec.rb +++ b/spec/services/system_note_service_spec.rb @@ -431,10 +431,6 @@ describe SystemNoteService, services: true do let(:commit2) { forked_project.commit } before do - allow(commit0).to receive(:to_reference) { - noteable.project.to_reference + - commit0.class.reference_prefix + commit0.id - } described_class.cross_reference(noteable, commit0, author2) end -- cgit v1.2.1 From 5cd20de7499840463eb1ee91793359ea52f29af8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Tue, 16 Feb 2016 10:48:37 +0100 Subject: Eager-load image blob data in diffs Since gitlab_git 8.0, blob data are lazy-loaded so we have to call blob.load_all_data!(repo) to eager-load them. Fixes #13458. --- app/views/projects/diffs/_image.html.haml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/views/projects/diffs/_image.html.haml b/app/views/projects/diffs/_image.html.haml index 058b71b21f5..4fcf7ea0b26 100644 --- a/app/views/projects/diffs/_image.html.haml +++ b/app/views/projects/diffs/_image.html.haml @@ -1,4 +1,5 @@ - diff = diff_file.diff +- file.load_all_data!(@project.repository) - if diff.renamed_file || diff.new_file || diff.deleted_file .image %span.wrap @@ -6,6 +7,7 @@ %img{src: "data:#{file.mime_type};base64,#{Base64.encode64(file.data)}"} %p.image-info= "#{number_to_human_size file.size}" - else + - old_file.load_all_data!(@project.repository) .image %div.two-up.view %span.wrap -- cgit v1.2.1 From f253f72529824198a591e06537d321917eca1d5e Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Tue, 16 Feb 2016 12:13:13 +0100 Subject: Cleaned up Repository#initialize The "default_branch" argument is never used and the "project" argument isn't optional. --- app/models/project.rb | 2 +- app/models/project_wiki.rb | 2 +- app/models/repository.rb | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/models/project.rb b/app/models/project.rb index f11c6d7c6be..d18131a6762 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -342,7 +342,7 @@ class Project < ActiveRecord::Base end def repository - @repository ||= Repository.new(path_with_namespace, nil, self) + @repository ||= Repository.new(path_with_namespace, self) end def commit(id = 'HEAD') diff --git a/app/models/project_wiki.rb b/app/models/project_wiki.rb index c847eba8d1c..c96e6f0b8ea 100644 --- a/app/models/project_wiki.rb +++ b/app/models/project_wiki.rb @@ -123,7 +123,7 @@ class ProjectWiki end def repository - Repository.new(path_with_namespace, default_branch, @project) + Repository.new(path_with_namespace, @project) end def default_branch diff --git a/app/models/repository.rb b/app/models/repository.rb index 7f0047a002e..ba275fd9803 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -15,7 +15,7 @@ class Repository Gitlab::Popen.popen(%W(find #{repository_downloads_path} -not -path #{repository_downloads_path} -mmin +120 -delete)) end - def initialize(path_with_namespace, default_branch = nil, project = nil) + def initialize(path_with_namespace, project) @path_with_namespace = path_with_namespace @project = project end -- cgit v1.2.1 From d28fa2ce233e057dc47de17bb6c1f2dff141059a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Tue, 16 Feb 2016 12:58:12 +0100 Subject: Display "iid of max_iid" in Issuables' sidebar --- app/helpers/issuables_helper.rb | 12 ++++-------- app/models/concerns/issuable.rb | 10 ---------- app/views/shared/issuable/_sidebar.html.haml | 2 +- 3 files changed, 5 insertions(+), 19 deletions(-) diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb index ccbd93967a2..91a3aa371ef 100644 --- a/app/helpers/issuables_helper.rb +++ b/app/helpers/issuables_helper.rb @@ -8,20 +8,16 @@ module IssuablesHelper "right-sidebar-#{sidebar_gutter_collapsed? ? 'collapsed' : 'expanded'}" end - def issuable_index(issuable) - base_issuable_scope(issuable).where('id < ?', issuable.id).size + 1 - end - def issuables_count(issuable) - base_issuable_scope(issuable).size + base_issuable_scope(issuable).maximum(:iid) end def next_issuable_for(issuable) - base_issuable_scope(issuable).where('id > ?', issuable.id).last + base_issuable_scope(issuable).where('iid > ?', issuable.iid).last end def prev_issuable_for(issuable) - base_issuable_scope(issuable).where('id < ?', issuable.id).first + base_issuable_scope(issuable).where('iid < ?', issuable.iid).first end private @@ -31,7 +27,7 @@ module IssuablesHelper end def base_issuable_scope(issuable) - issuable.project.send(issuable.to_scope_name).send(issuable_state_scope(issuable)) + issuable.project.send(issuable.class.table_name).send(issuable_state_scope(issuable)) end def issuable_state_scope(issuable) diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb index e08687135d6..cf6aa592e2a 100644 --- a/app/models/concerns/issuable.rb +++ b/app/models/concerns/issuable.rb @@ -168,16 +168,6 @@ module Issuable self.class.to_s.underscore end - # Convert this Issuable class name to a format usable for scoping - # - # Examples: - # - # issuable.class # => MergeRequest - # issuable.to_scope_name # => "merge_requests" - def to_scope_name - self.class.to_s.tableize - end - # Returns a Hash of attributes to be used for Twitter card metadata def card_attributes { diff --git a/app/views/shared/issuable/_sidebar.html.haml b/app/views/shared/issuable/_sidebar.html.haml index cb5378964bc..e1aecdd9436 100644 --- a/app/views/shared/issuable/_sidebar.html.haml +++ b/app/views/shared/issuable/_sidebar.html.haml @@ -2,7 +2,7 @@ .issuable-sidebar .block %span.issuable-count.pull-left - = issuable_index(issuable) + = issuable.iid of = issuables_count(issuable) %span.pull-right -- cgit v1.2.1 From 1de95137906e1b262eeaf2d627469c9a1e47a536 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Tue, 16 Feb 2016 13:03:00 +0100 Subject: Use project.web_url instead deprecated repository.homepage in PushoverService --- app/models/project_services/pushover_service.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/project_services/pushover_service.rb b/app/models/project_services/pushover_service.rb index 3d7e8bbee61..e76d9eca2ab 100644 --- a/app/models/project_services/pushover_service.rb +++ b/app/models/project_services/pushover_service.rb @@ -112,7 +112,7 @@ class PushoverService < Service priority: priority, title: "#{project.name_with_namespace}", message: message, - url: data[:repository][:homepage], + url: data[:project][:web_url], url_title: "See project #{project.name_with_namespace}" } -- cgit v1.2.1 From 719b5889984fe7c970b2e2819396c43f63d76632 Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Tue, 16 Feb 2016 15:09:58 +0200 Subject: sporadic spec fix --- features/steps/project/issues/award_emoji.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/features/steps/project/issues/award_emoji.rb b/features/steps/project/issues/award_emoji.rb index 8b9aa6aabfa..93cf608cc62 100644 --- a/features/steps/project/issues/award_emoji.rb +++ b/features/steps/project/issues/award_emoji.rb @@ -46,6 +46,8 @@ class Spinach::Features::AwardEmoji < Spinach::FeatureSteps end step 'I have award added' do + sleep 0.2 + page.within '.awards' do expect(page).to have_selector '.award' expect(page.find('.award.active .counter')).to have_content '1' -- cgit v1.2.1 From 18390c6a91f9c2d765e1f69a548f0bfd6657d20c Mon Sep 17 00:00:00 2001 From: Alfredo Sumaran Date: Tue, 16 Feb 2016 09:30:34 -0500 Subject: Change "opened by" to just "by" --- app/views/projects/issues/show.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/projects/issues/show.html.haml b/app/views/projects/issues/show.html.haml index d635a879491..c2d33e4e5dc 100644 --- a/app/views/projects/issues/show.html.haml +++ b/app/views/projects/issues/show.html.haml @@ -25,7 +25,7 @@ Issue ##{@issue.iid} %span.creator · - opened by #{link_to_member(@project, @issue.author, size: 24)} + by #{link_to_member(@project, @issue.author, size: 24)} · = time_ago_with_tooltip(@issue.created_at, placement: 'bottom', html_class: 'issue_created_ago') -- cgit v1.2.1 From 15126fc70ffaca07b6e6e487a7d3a4f0318ee882 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Tue, 16 Feb 2016 17:01:25 +0100 Subject: Fix SVG blob rendering --- app/views/projects/blob/_image.html.haml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/app/views/projects/blob/_image.html.haml b/app/views/projects/blob/_image.html.haml index 51fa91b08e4..6955b7086b9 100644 --- a/app/views/projects/blob/_image.html.haml +++ b/app/views/projects/blob/_image.html.haml @@ -1,2 +1,8 @@ .file-content.image_file - %img{ src: namespace_project_raw_path(@project.namespace, @project, @id)} + - if blob_svg?(blob) + - # We need to scrub SVG but we cannot do so in the RawController + - blob.load_all_data!(@repository) + - blob = sanitize_svg(blob) + %img{ src: "data:#{blob.mime_type};base64,#{Base64.encode64(blob.data)}"} + - else + %img{ src: namespace_project_raw_path(@project.namespace, @project, @id)} -- cgit v1.2.1 From 6d80a4c4f9a9fedb586b82a5dea34ae090981d78 Mon Sep 17 00:00:00 2001 From: Alfredo Sumaran Date: Tue, 16 Feb 2016 11:06:15 -0500 Subject: Wrap issue details to prevent content misalignment --- app/assets/stylesheets/pages/detail_page.scss | 4 ++++ app/views/projects/issues/show.html.haml | 21 ++++++++++++--------- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/app/assets/stylesheets/pages/detail_page.scss b/app/assets/stylesheets/pages/detail_page.scss index 0bddc83f5c0..d93b6ee6733 100644 --- a/app/assets/stylesheets/pages/detail_page.scss +++ b/app/assets/stylesheets/pages/detail_page.scss @@ -16,6 +16,10 @@ .issue_created_ago, .author_link { white-space: nowrap; } + + .issue-meta { + margin-left: 65px + } } .detail-page-description { diff --git a/app/views/projects/issues/show.html.haml b/app/views/projects/issues/show.html.haml index c2d33e4e5dc..69a0e2a0c4d 100644 --- a/app/views/projects/issues/show.html.haml +++ b/app/views/projects/issues/show.html.haml @@ -19,15 +19,18 @@ = icon('pencil-square-o') Edit - .status-box{ class: "status-box-closed #{issue_button_visibility(@issue, false)}"} Closed - .status-box{ class: "status-box-open #{issue_button_visibility(@issue, true)}"} Open - %span.identifier - Issue ##{@issue.iid} - %span.creator - · - by #{link_to_member(@project, @issue.author, size: 24)} - · - = time_ago_with_tooltip(@issue.created_at, placement: 'bottom', html_class: 'issue_created_ago') + .pull-left + .status-box{ class: "status-box-closed #{issue_button_visibility(@issue, false)}"} Closed + .status-box{ class: "status-box-open #{issue_button_visibility(@issue, true)}"} Open + + .issue-meta + %span.identifier + Issue ##{@issue.iid} + %span.creator + · + by #{link_to_member(@project, @issue.author, size: 24)} + · + = time_ago_with_tooltip(@issue.created_at, placement: 'bottom', html_class: 'issue_created_ago') .issue-details.issuable-details .detail-page-description.content-block -- cgit v1.2.1 From 24fa458615f4c77eedd8176f905d51a2df87515a Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Tue, 16 Feb 2016 17:29:45 +0100 Subject: Use /raw/ requests for image diffs --- app/views/projects/diffs/_image.html.haml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/app/views/projects/diffs/_image.html.haml b/app/views/projects/diffs/_image.html.haml index 4fcf7ea0b26..e3699c6cab4 100644 --- a/app/views/projects/diffs/_image.html.haml +++ b/app/views/projects/diffs/_image.html.haml @@ -1,19 +1,19 @@ - diff = diff_file.diff -- file.load_all_data!(@project.repository) +- file_raw_path = namespace_project_raw_path(@project.namespace, @project, tree_join(@commit.id, diff.new_path)) +- old_file_raw_path = namespace_project_raw_path(@project.namespace, @project, tree_join(@commit.parent_id, diff.old_path)) - if diff.renamed_file || diff.new_file || diff.deleted_file .image %span.wrap .frame{class: image_diff_class(diff)} - %img{src: "data:#{file.mime_type};base64,#{Base64.encode64(file.data)}"} + %img{src: file_raw_path} %p.image-info= "#{number_to_human_size file.size}" - else - - old_file.load_all_data!(@project.repository) .image %div.two-up.view %span.wrap .frame.deleted %a{href: namespace_project_blob_path(@project.namespace, @project, tree_join(@commit.parent_id, diff.old_path))} - %img{src: "data:#{old_file.mime_type};base64,#{Base64.encode64(old_file.data)}"} + %img{src: old_file_raw_path} %p.image-info.hide %span.meta-filesize= "#{number_to_human_size old_file.size}" | @@ -25,7 +25,7 @@ %span.wrap .frame.added %a{href: namespace_project_blob_path(@project.namespace, @project, tree_join(@commit.id, diff.new_path))} - %img{src: "data:#{file.mime_type};base64,#{Base64.encode64(file.data)}"} + %img{src: file_raw_path} %p.image-info.hide %span.meta-filesize= "#{number_to_human_size file.size}" | @@ -38,10 +38,10 @@ %div.swipe.view.hide .swipe-frame .frame.deleted - %img{src: "data:#{old_file.mime_type};base64,#{Base64.encode64(old_file.data)}"} + %img{src: old_file_raw_path} .swipe-wrap .frame.added - %img{src: "data:#{file.mime_type};base64,#{Base64.encode64(file.data)}"} + %img{src: file_raw_path} %span.swipe-bar %span.top-handle %span.bottom-handle @@ -49,9 +49,9 @@ %div.onion-skin.view.hide .onion-skin-frame .frame.deleted - %img{src: "data:#{old_file.mime_type};base64,#{Base64.encode64(old_file.data)}"} + %img{src: old_file_raw_path} .frame.added - %img{src: "data:#{file.mime_type};base64,#{Base64.encode64(file.data)}"} + %img{src: file_raw_path} .controls .transparent .drag-track -- cgit v1.2.1 From 9ae4fa943ee5eb4b1ec3aa38704ee9395a853b0e Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Tue, 16 Feb 2016 21:32:22 +0200 Subject: Fix Redis installation guide [ci skip] --- doc/install/installation.md | 25 ++++++++----------- doc/install/redis.md | 60 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 15 deletions(-) create mode 100644 doc/install/redis.md diff --git a/doc/install/installation.md b/doc/install/installation.md index 7d3f9d0a2ed..7ae73450afb 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -182,25 +182,20 @@ We recommend using a PostgreSQL database. For MySQL check [MySQL setup guide](da ## 6. Redis -As of this writing, most Debian/Ubuntu distributions ship with Redis 2.2 or -2.4. GitLab requires at least Redis 2.8. +GitLab requires at least Redis 2.8. -Ubuntu users [can use a PPA](https://launchpad.net/~chris-lea/+archive/ubuntu/redis-server) -to install a recent version of Redis. - -The following instructions cover building and installing Redis from scratch: +If you are using Debian 8 or Ubuntu 14.04 and up, then you can simply install +Redis 2.8 with: ```sh -# Build Redis -wget http://download.redis.io/releases/redis-2.8.23.tar.gz -tar xzf redis-2.8.23.tar.gz -cd redis-2.8.23 -make +sudo apt-get install redis-server +``` -# Install Redis -cd utils -sudo ./install_server.sh +If you are using Debian 7 or Ubuntu 12.04, follow the special documentation +on [an alternate Redis installation](redis.md). Once done, follow the rest of +the guide here. +``` # Configure redis to use sockets sudo cp /etc/redis/redis.conf /etc/redis/redis.conf.orig @@ -224,7 +219,7 @@ if [ -d /etc/tmpfiles.d ]; then fi # Activate the changes to redis.conf -sudo service redis_6379 start +sudo service redis-server restart # Add git to the redis group sudo usermod -aG redis git diff --git a/doc/install/redis.md b/doc/install/redis.md new file mode 100644 index 00000000000..4075e6283d0 --- /dev/null +++ b/doc/install/redis.md @@ -0,0 +1,60 @@ +# Install Redis on old distributions + +GitLab requires at least Redis 2.8. The following guide is for Debian 7 and +Ubuntu 12.04. If you are using Debian 8 or Ubuntu 14.04 and up, follow the +[installation guide](installation.md). + +## Install Redis 2.8 in Debian 7 + +Redis 2.8 is included in the Debian Wheezy [backports] repository. + +1. Edit `/etc/apt/sources.list` and add the following line: + + ``` + deb http://http.debian.net/debian wheezy-backports main + ``` + +1. Update the repositories: + + ``` + sudo apt-get update + ``` + +1. Install `redis-server`: + + ``` + sudo apt-get -t wheezy-backports install redis-server + ``` + +1. Follow the rest of the [installation guide](installation.md). + +## Install Redis 2.8 in Ubuntu 12.04 + +We will [use a PPA](https://launchpad.net/~chris-lea/+archive/ubuntu/redis-server) +to install a recent version of Redis. + +1. Install the PPA repository: + + ``` + sudo add-apt-repository ppa:chris-lea/redis-server + ``` + + Your system will now fetch the PPA's key. This enables your Ubuntu system to + verify that the packages in the PPA have not been interfered with since they + were built. + +1. Update the repositories: + + ``` + sudo apt-get update + ``` + +1. Install `redis-server`: + + ``` + sudo apt-get install redis-server + ``` + +1. Follow the rest of the [installation guide](installation.md). + +[backports]: http://backports.debian.org/Instructions/ "Debian backports website" -- cgit v1.2.1 From 458e3c7167257d74a1e3ef4066ce2a2ac3d85de3 Mon Sep 17 00:00:00 2001 From: Richard Hansen Date: Tue, 16 Feb 2016 15:02:18 -0500 Subject: fix table in doc/ci/variables/README.md --- doc/ci/variables/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ci/variables/README.md b/doc/ci/variables/README.md index 018d1898594..9e89e6e395e 100644 --- a/doc/ci/variables/README.md +++ b/doc/ci/variables/README.md @@ -16,7 +16,7 @@ The API_TOKEN will take the Secure Variable value: `SECURE`. ### Predefined variables (Environment Variables) | Variable | Runner | Description | -|-------------------------|-------------| +|-------------------------|-----|--------| | **CI** | 0.4 | Mark that build is executed in CI environment | | **GITLAB_CI** | all | Mark that build is executed in GitLab CI environment | | **CI_SERVER** | all | Mark that build is executed in CI environment | -- cgit v1.2.1 From 594d21cdca107460e080b7884bed49e2634cc275 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Tue, 16 Feb 2016 18:14:47 -0500 Subject: Bump unicorn to `~> 4.9.0` --- Gemfile | 2 +- Gemfile.lock | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index a1c57af4bac..6dcc9b0dd80 100644 --- a/Gemfile +++ b/Gemfile @@ -112,7 +112,7 @@ gem 'diffy', '~> 3.0.3' # Application server group :unicorn do - gem "unicorn", '~> 4.8.2' + gem "unicorn", '~> 4.9.0' gem 'unicorn-worker-killer', '~> 0.4.2' end diff --git a/Gemfile.lock b/Gemfile.lock index 718285e1665..1ca4b7b96b4 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -833,7 +833,7 @@ GEM unf (0.1.4) unf_ext unf_ext (0.0.7.1) - unicorn (4.8.3) + unicorn (4.9.0) kgio (~> 2.6) rack raindrops (~> 0.7) @@ -1034,7 +1034,7 @@ DEPENDENCIES uglifier (~> 2.7.2) underscore-rails (~> 1.8.0) unf (~> 0.1.4) - unicorn (~> 4.8.2) + unicorn (~> 4.9.0) unicorn-worker-killer (~> 0.4.2) version_sorter (~> 2.0.0) virtus (~> 1.0.1) -- cgit v1.2.1 From c569f8b4800424704691925f9e39b415b5eca33c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Wed, 17 Feb 2016 10:17:03 +0100 Subject: Fix a bug preventing from doing subsequent edits in any Issuable sidebar --- app/views/projects/issues/update.js.haml | 2 +- app/views/projects/merge_requests/update.js.haml | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/views/projects/issues/update.js.haml b/app/views/projects/issues/update.js.haml index a54733883b4..986d8c220db 100644 --- a/app/views/projects/issues/update.js.haml +++ b/app/views/projects/issues/update.js.haml @@ -1,3 +1,3 @@ $('aside.right-sidebar')[0].outerHTML = "#{escape_javascript(render 'shared/issuable/sidebar', issuable: @issue)}"; $('aside.right-sidebar').effect('highlight'); -new Issue(); \ No newline at end of file +new IssuableContext(); diff --git a/app/views/projects/merge_requests/update.js.haml b/app/views/projects/merge_requests/update.js.haml index ce5157d69a2..9cce5660e1c 100644 --- a/app/views/projects/merge_requests/update.js.haml +++ b/app/views/projects/merge_requests/update.js.haml @@ -1,3 +1,3 @@ -$('aside.right-sidebar')[0].outerHTML= "#{escape_javascript(render 'shared/issuable/sidebar', issuable: @merge_request)}"; -$('aside.right-sidebar').effect('highlight') -merge_request = new MergeRequest(); +$('aside.right-sidebar')[0].outerHTML = "#{escape_javascript(render 'shared/issuable/sidebar', issuable: @merge_request)}"; +$('aside.right-sidebar').effect('highlight'); +new IssuableContext(); -- cgit v1.2.1 From 5255a54df9778b107734a84acb85230d62d3cff7 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Wed, 17 Feb 2016 10:42:59 +0100 Subject: refactored some stuff based on MR feedback --- app/services/git_push_service.rb | 6 +-- app/workers/post_receive.rb | 7 +-- spec/services/git_push_service_spec.rb | 84 ++++++++++++---------------------- 3 files changed, 34 insertions(+), 63 deletions(-) diff --git a/app/services/git_push_service.rb b/app/services/git_push_service.rb index b203065e708..a1711d234ff 100644 --- a/app/services/git_push_service.rb +++ b/app/services/git_push_service.rb @@ -106,7 +106,7 @@ class GitPushService < BaseService def build_push_data @push_data ||= Gitlab::PushDataBuilder. - build(@project, current_user, params[:oldrev], params[:newrev], params[:ref], push_commits) + build(@project, current_user, params[:oldrev], params[:newrev], params[:ref], push_commits) end def push_to_existing_branch? @@ -128,7 +128,7 @@ class GitPushService < BaseService def is_default_branch? Gitlab::Git.branch_ref?(params[:ref]) && - (Gitlab::Git.ref_name(params[:ref]) == project.default_branch || project.default_branch.nil?) + (Gitlab::Git.ref_name(params[:ref]) == project.default_branch || project.default_branch.nil?) end def commit_user(commit) @@ -136,6 +136,6 @@ class GitPushService < BaseService end def branch_name - @_branch_name ||= Gitlab::Git.ref_name(params[:ref]) + @branch_name ||= Gitlab::Git.ref_name(params[:ref]) end end diff --git a/app/workers/post_receive.rb b/app/workers/post_receive.rb index 9e7934b84d8..14d7813412e 100644 --- a/app/workers/post_receive.rb +++ b/app/workers/post_receive.rb @@ -38,12 +38,7 @@ class PostReceive if Gitlab::Git.tag_ref?(ref) GitTagPushService.new.execute(project, @user, oldrev, newrev, ref) else - GitPushService.new(project, @user, - { - oldrev: oldrev, - newrev: newrev, - ref: ref - }).execute + GitPushService.new(project, @user, oldrev: oldrev, newrev: newrev, ref: ref).execute end end end diff --git a/spec/services/git_push_service_spec.rb b/spec/services/git_push_service_spec.rb index f953f226e67..48e796b6946 100644 --- a/spec/services/git_push_service_spec.rb +++ b/spec/services/git_push_service_spec.rb @@ -16,8 +16,7 @@ describe GitPushService, services: true do describe 'Push branches' do context 'new branch' do subject do - service = described_class.new(project, user, { oldrev: @blankrev, newrev: @newrev, ref: @ref }) - service.execute + execute_service(project, user, @blankrev, @newrev, @ref ) end it { is_expected.to be_truthy } @@ -37,8 +36,7 @@ describe GitPushService, services: true do context 'existing branch' do subject do - service = described_class.new(project, user, { oldrev: @oldrev, newrev: @newrev, ref: @ref }) - service.execute + execute_service(project, user, @oldrev, @newrev, @ref ) end it { is_expected.to be_truthy } @@ -52,8 +50,7 @@ describe GitPushService, services: true do context 'rm branch' do subject do - service = described_class.new(project, user, { oldrev: @oldrev, newrev: @blankrev, ref: @ref }) - service.execute + execute_service(project, user, @oldrev, @blankrev, @ref ) end it { is_expected.to be_truthy } @@ -74,8 +71,7 @@ describe GitPushService, services: true do describe "Git Push Data" do before do - service = described_class.new(project, user, { oldrev: @oldrev, newrev: @newrev, ref: @ref }) - service.execute + service = execute_service(project, user, @oldrev, @newrev, @ref ) @push_data = service.push_data @commit = project.commit(@newrev) end @@ -137,8 +133,7 @@ describe GitPushService, services: true do describe "Push Event" do before do - service = described_class.new(project, user, { oldrev: @oldrev, newrev: @newrev, ref: @ref }) - service.execute + service = execute_service(project, user, @oldrev, @newrev, @ref ) @event = Event.last @push_data = service.push_data end @@ -152,8 +147,7 @@ describe GitPushService, services: true do it "when pushing a new branch for the first time" do expect(project).to receive(:update_merge_requests). with(@blankrev, 'newrev', 'refs/heads/master', user) - service = described_class.new(project, user, { oldrev: @blankrev, newrev: 'newrev', ref: 'refs/heads/master' }) - service.execute + execute_service(project, user, @blankrev, 'newrev', 'refs/heads/master' ) end end end @@ -164,8 +158,7 @@ describe GitPushService, services: true do expect(project).to receive(:execute_hooks) expect(project.default_branch).to eq("master") expect(project.protected_branches).to receive(:create).with({ name: "master", developers_can_push: false }) - service = described_class.new(project, user, { oldrev: @blankrev, newrev: 'newrev', ref: 'refs/heads/master' }) - service.execute + execute_service(project, user, @blankrev, 'newrev', 'refs/heads/master' ) end it "when pushing a branch for the first time with default branch protection disabled" do @@ -174,8 +167,7 @@ describe GitPushService, services: true do expect(project).to receive(:execute_hooks) expect(project.default_branch).to eq("master") expect(project.protected_branches).not_to receive(:create) - service = described_class.new(project, user, { oldrev: @blankrev, newrev: 'newrev', ref: 'refs/heads/master' }) - service.execute + execute_service(project, user, @blankrev, 'newrev', 'refs/heads/master' ) end it "when pushing a branch for the first time with default branch protection set to 'developers can push'" do @@ -184,14 +176,12 @@ describe GitPushService, services: true do expect(project).to receive(:execute_hooks) expect(project.default_branch).to eq("master") expect(project.protected_branches).to receive(:create).with({ name: "master", developers_can_push: true }) - service = described_class.new(project, user, { oldrev: @blankrev, newrev: 'newrev', ref: 'refs/heads/master' }) - service.execute + execute_service(project, user, @blankrev, 'newrev', 'refs/heads/master' ) end it "when pushing new commits to existing branch" do expect(project).to receive(:execute_hooks) - service = described_class.new(project, user, { oldrev: 'oldrev', newrev: 'newrev', ref: 'refs/heads/master' }) - service.execute + execute_service(project, user, 'oldrev', 'newrev', 'refs/heads/master' ) end end end @@ -214,9 +204,7 @@ describe GitPushService, services: true do it "creates a note if a pushed commit mentions an issue" do expect(SystemNoteService).to receive(:cross_reference).with(issue, commit, commit_author) - service = described_class.new(project, user, { oldrev: @oldrev, newrev: @newrev, ref: @ref }) - - service.execute + execute_service(project, user, @oldrev, @newrev, @ref ) end it "only creates a cross-reference note if one doesn't already exist" do @@ -224,9 +212,7 @@ describe GitPushService, services: true do expect(SystemNoteService).not_to receive(:cross_reference).with(issue, commit, commit_author) - service = described_class.new(project, user, { oldrev: @oldrev, newrev: @newrev, ref: @ref }) - - service.execute + execute_service(project, user, @oldrev, @newrev, @ref ) end it "defaults to the pushing user if the commit's author is not known" do @@ -236,9 +222,7 @@ describe GitPushService, services: true do ) expect(SystemNoteService).to receive(:cross_reference).with(issue, commit, user) - service = described_class.new(project, user, { oldrev: @oldrev, newrev: @newrev, ref: @ref }) - - service.execute + execute_service(project, user, @oldrev, @newrev, @ref ) end it "finds references in the first push to a non-default branch" do @@ -247,9 +231,7 @@ describe GitPushService, services: true do expect(SystemNoteService).to receive(:cross_reference).with(issue, commit, commit_author) - service = described_class.new(project, user, { oldrev: @blankrev, newrev: @newrev, ref: 'refs/heads/other' }) - - service.execute + execute_service(project, user, @blankrev, @newrev, 'refs/heads/other' ) end end @@ -273,21 +255,18 @@ describe GitPushService, services: true do context "to default branches" do it "closes issues" do - service = described_class.new(project, user, { oldrev: @oldrev, newrev: @newrev, ref: @ref }) - service.execute + execute_service(project, user, @oldrev, @newrev, @ref ) expect(Issue.find(issue.id)).to be_closed end it "adds a note indicating that the issue is now closed" do expect(SystemNoteService).to receive(:change_status).with(issue, project, commit_author, "closed", closing_commit) - service = described_class.new(project, user, { oldrev: @oldrev, newrev: @newrev, ref: @ref }) - service.execute + execute_service(project, user, @oldrev, @newrev, @ref ) end it "doesn't create additional cross-reference notes" do expect(SystemNoteService).not_to receive(:cross_reference) - service = described_class.new(project, user, { oldrev: @oldrev, newrev: @newrev, ref: @ref }) - service.execute + execute_service(project, user, @oldrev, @newrev, @ref ) end it "doesn't close issues when external issue tracker is in use" do @@ -295,8 +274,7 @@ describe GitPushService, services: true do # The push still shouldn't create cross-reference notes. expect do - service = described_class.new(project, user, { oldrev: @oldrev, newrev: @newrev, ref: 'refs/heads/hurf' }) - service.execute + execute_service(project, user, @oldrev, @newrev, 'refs/heads/hurf' ) end.not_to change { Note.where(project_id: project.id, system: true).count } end end @@ -309,13 +287,11 @@ describe GitPushService, services: true do it "creates cross-reference notes" do expect(SystemNoteService).to receive(:cross_reference).with(issue, closing_commit, commit_author) - service = described_class.new(project, user, { oldrev: @oldrev, newrev: @newrev, ref: @ref }) - service.execute + execute_service(project, user, @oldrev, @newrev, @ref ) end it "doesn't close issues" do - service = described_class.new(project, user, { oldrev: @oldrev, newrev: @newrev, ref: @ref }) - service.execute + execute_service(project, user, @oldrev, @newrev, @ref ) expect(Issue.find(issue.id)).to be_opened end end @@ -352,8 +328,7 @@ describe GitPushService, services: true do let(:message) { "this is some work.\n\nrelated to JIRA-1" } it "should initiate one api call to jira server to mention the issue" do - service = described_class.new(project, user, { oldrev: @oldrev, newrev: @newrev, ref: @ref }) - service.execute + execute_service(project, user, @oldrev, @newrev, @ref ) expect(WebMock).to have_requested(:post, jira_api_comment_url).with( body: /mentioned this issue in/ @@ -371,9 +346,7 @@ describe GitPushService, services: true do } }.to_json - service = described_class.new(project, user, { oldrev: @oldrev, newrev: @newrev, ref: @ref }) - - service.execute + execute_service(project, user, @oldrev, @newrev, @ref ) expect(WebMock).to have_requested(:post, jira_api_transition_url).with( body: transition_body ).once @@ -384,9 +357,7 @@ describe GitPushService, services: true do body: "Issue solved with [#{closing_commit.id}|http://localhost/#{project.path_with_namespace}/commit/#{closing_commit.id}]." }.to_json - service = described_class.new(project, user, { oldrev: @oldrev, newrev: @newrev, ref: @ref }) - - service.execute + execute_service(project, user, @oldrev, @newrev, @ref ) expect(WebMock).to have_requested(:post, jira_api_comment_url).with( body: comment_body ).once @@ -405,8 +376,13 @@ describe GitPushService, services: true do end it 'push to first branch updates HEAD' do - service = described_class.new(project, user, { oldrev: @blankrev, newrev: @newrev, ref: new_ref }) - service.execute + execute_service(project, user, @blankrev, @newrev, new_ref ) end end + + def execute_service(project, user, oldrev, newrev, ref) + service = described_class.new(project, user, oldrev: oldrev, newrev: newrev, ref: ref ) + service.execute + service + end end -- cgit v1.2.1 From 016367c640bf10781e6a5cbabe138257b2a8242e Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Wed, 17 Feb 2016 11:08:10 +0100 Subject: No use to sanitize partial blob data --- app/views/projects/blob/_blob.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/projects/blob/_blob.html.haml b/app/views/projects/blob/_blob.html.haml index 2c5b8dc4356..f3bfe0a18b0 100644 --- a/app/views/projects/blob/_blob.html.haml +++ b/app/views/projects/blob/_blob.html.haml @@ -36,7 +36,7 @@ = render "download", blob: blob - elsif blob.text? - if blob_svg?(blob) - = render "image", blob: sanitize_svg(blob) + = render "image", blob: blob - else = render "text", blob: blob - elsif blob.image? -- cgit v1.2.1 From a87fe2a47220fafdf1eb322f253ea061fe907f95 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Wed, 17 Feb 2016 11:08:47 +0100 Subject: =?UTF-8?q?Fixes=20requested=20by=20R=C3=A9my?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/views/projects/blob/_image.html.haml | 7 ++++--- app/views/projects/diffs/_image.html.haml | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/app/views/projects/blob/_image.html.haml b/app/views/projects/blob/_image.html.haml index 6955b7086b9..113dba5d832 100644 --- a/app/views/projects/blob/_image.html.haml +++ b/app/views/projects/blob/_image.html.haml @@ -1,8 +1,9 @@ .file-content.image_file - if blob_svg?(blob) - - # We need to scrub SVG but we cannot do so in the RawController + - # We need to scrub SVG but we cannot do so in the RawController: it would + - # be wrong/strange if RawController modified the data. - blob.load_all_data!(@repository) - blob = sanitize_svg(blob) - %img{ src: "data:#{blob.mime_type};base64,#{Base64.encode64(blob.data)}"} + %img{src: "data:#{blob.mime_type};base64,#{Base64.encode64(blob.data)}"} - else - %img{ src: namespace_project_raw_path(@project.namespace, @project, @id)} + %img{src: namespace_project_raw_path(@project.namespace, @project, @id)} diff --git a/app/views/projects/diffs/_image.html.haml b/app/views/projects/diffs/_image.html.haml index e3699c6cab4..752e92e2e6b 100644 --- a/app/views/projects/diffs/_image.html.haml +++ b/app/views/projects/diffs/_image.html.haml @@ -5,7 +5,7 @@ .image %span.wrap .frame{class: image_diff_class(diff)} - %img{src: file_raw_path} + %img{src: diff.deleted_file ? old_file_raw_path : file_raw_path} %p.image-info= "#{number_to_human_size file.size}" - else .image -- cgit v1.2.1 From a9e0301c230a81242d476f30d7089565919214b3 Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Tue, 16 Feb 2016 17:31:37 +0100 Subject: Expire caches after forking/importing a repository This ensures the caches for Repository#empty? and Repository#has_visible_content? are flushed after a repository has been imported or forked. Fixes gitlab-org/gitlab-ce#13505 --- app/models/repository.rb | 8 ++++++++ app/workers/repository_fork_worker.rb | 1 + app/workers/repository_import_worker.rb | 1 + spec/models/repository_spec.rb | 11 +++++++++++ spec/workers/repository_fork_worker_spec.rb | 12 ++++++++++++ spec/workers/repository_import_worker_spec.rb | 19 +++++++++++++++++++ 6 files changed, 52 insertions(+) create mode 100644 spec/workers/repository_import_worker_spec.rb diff --git a/app/models/repository.rb b/app/models/repository.rb index ba275fd9803..5696504e7ec 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -258,6 +258,14 @@ class Repository @root_ref = nil end + # Expires the cache(s) used to determine if a repository is empty or not. + def expire_emptiness_caches + cache.expire(:empty?) + @empty = nil + + expire_has_visible_content_cache + end + def expire_has_visible_content_cache cache.expire(:has_visible_content?) @has_visible_content = nil diff --git a/app/workers/repository_fork_worker.rb b/app/workers/repository_fork_worker.rb index 2f991c52339..2572b9d6d98 100644 --- a/app/workers/repository_fork_worker.rb +++ b/app/workers/repository_fork_worker.rb @@ -27,6 +27,7 @@ class RepositoryForkWorker return end + project.repository.expire_emptiness_caches project.import_finish end end diff --git a/app/workers/repository_import_worker.rb b/app/workers/repository_import_worker.rb index e295a9ddd14..0b6f746e118 100644 --- a/app/workers/repository_import_worker.rb +++ b/app/workers/repository_import_worker.rb @@ -18,6 +18,7 @@ class RepositoryImportWorker return end + project.repository.expire_emptiness_caches project.import_finish end end diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index e1ee43e64db..2cd0606a61d 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -355,6 +355,17 @@ describe Repository, models: true do end end + describe '#expire_emptiness_caches' do + let(:cache) { repository.send(:cache) } + + it 'expires the caches' do + expect(cache).to receive(:expire).with(:empty?) + expect(repository).to receive(:expire_has_visible_content_cache) + + repository.expire_emptiness_caches + end + end + describe :skip_merged_commit do subject { repository.commits(Gitlab::Git::BRANCH_REF_PREFIX + "'test'", nil, 100, 0, true).map{ |k| k.id } } diff --git a/spec/workers/repository_fork_worker_spec.rb b/spec/workers/repository_fork_worker_spec.rb index dae31992620..172537474ee 100644 --- a/spec/workers/repository_fork_worker_spec.rb +++ b/spec/workers/repository_fork_worker_spec.rb @@ -19,6 +19,18 @@ describe RepositoryForkWorker do fork_project.namespace.path) end + it 'flushes the empty caches' do + expect_any_instance_of(Gitlab::Shell).to receive(:fork_repository). + with(project.path_with_namespace, fork_project.namespace.path). + and_return(true) + + expect_any_instance_of(Repository).to receive(:expire_emptiness_caches). + and_call_original + + subject.perform(project.id, project.path_with_namespace, + fork_project.namespace.path) + end + it "handles bad fork" do expect_any_instance_of(Gitlab::Shell).to receive(:fork_repository).and_return(false) subject.perform( diff --git a/spec/workers/repository_import_worker_spec.rb b/spec/workers/repository_import_worker_spec.rb new file mode 100644 index 00000000000..6739063543b --- /dev/null +++ b/spec/workers/repository_import_worker_spec.rb @@ -0,0 +1,19 @@ +require 'spec_helper' + +describe RepositoryImportWorker do + let(:project) { create(:project) } + + subject { described_class.new } + + describe '#perform' do + it 'imports a project' do + expect_any_instance_of(Projects::ImportService).to receive(:execute). + and_return({ status: :ok }) + + expect_any_instance_of(Repository).to receive(:expire_emptiness_caches) + expect_any_instance_of(Project).to receive(:import_finish) + + subject.perform(project.id) + end + end +end -- cgit v1.2.1 From b1203108b0eda20f87c75004f035e9e7a51f1124 Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Tue, 16 Feb 2016 23:11:56 +0100 Subject: Flush all repository caches when deleting a repo This ensures that _all_ caches (including any caches normally only flushed under certain conditions) are flushed whenever a project is removed. Because cache keys are based on project namespaces (excluding IDs) not doing so could result in a newly created project re-using old caches (if the project was re-created using the same name). --- app/models/repository.rb | 9 +++++++++ app/services/projects/destroy_service.rb | 14 +++++++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/app/models/repository.rb b/app/models/repository.rb index 5696504e7ec..1c33a7f9679 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -238,6 +238,15 @@ class Repository expire_branch_cache(branch_name) end + # Expires _all_ caches, including those that would normally only be expired + # under specific conditions. + def expire_all_caches! + expire_cache + expire_root_ref_cache + expire_emptiness_caches + expire_has_visible_content_cache + end + def expire_branch_cache(branch_name = nil) # When we push to the root branch we have to flush the cache for all other # branches as their statistics are based on the commits relative to the diff --git a/app/services/projects/destroy_service.rb b/app/services/projects/destroy_service.rb index 294157b4f0e..f4dcb142850 100644 --- a/app/services/projects/destroy_service.rb +++ b/app/services/projects/destroy_service.rb @@ -16,11 +16,15 @@ module Projects return false unless can?(current_user, :remove_project, project) project.team.truncate - project.repository.expire_cache unless project.empty_repo? repo_path = project.path_with_namespace wiki_path = repo_path + '.wiki' + # Flush the cache for both repositories. This has to be done _before_ + # removing the physical repositories as some expiration code depends on + # Git data (e.g. a list of branch names). + flush_caches(project, wiki_path) + Project.transaction do project.destroy! @@ -70,5 +74,13 @@ module Projects def removal_path(path) "#{path}+#{project.id}#{DELETED_FLAG}" end + + def flush_caches(project, wiki_path) + project.repository.expire_all_caches! if project.repository.exists? + + wiki_repo = Repository.new(wiki_path, project) + + wiki_repo.expire_all_caches! if wiki_repo.exists? + end end end -- cgit v1.2.1 From 29bfdf88eab813fd9d5946dcb0126c9dc0d4c83b Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Wed, 17 Feb 2016 06:37:21 -0500 Subject: Fix double scrollbar issues --- app/assets/stylesheets/framework/gitlab-theme.scss | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/app/assets/stylesheets/framework/gitlab-theme.scss b/app/assets/stylesheets/framework/gitlab-theme.scss index 8d9a0aae568..0f68582e447 100644 --- a/app/assets/stylesheets/framework/gitlab-theme.scss +++ b/app/assets/stylesheets/framework/gitlab-theme.scss @@ -118,3 +118,19 @@ body { @include gitlab-theme(#9988CC, $theme-violet, #443366, #332255); } } + +::-webkit-scrollbar{ + width: 3px; +} + +::-webkit-scrollbar-thumb{ + background-color:$theme-charcoal; border-radius: 0; +} + +::-webkit-scrollbar-thumb:hover{ + background-color:$theme-charcoal; +} + +::-webkit-scrollbar-track{ + background-color:#FFF; +} \ No newline at end of file -- cgit v1.2.1 From e9e01bcd960868db39e616c2a254d493097d712f Mon Sep 17 00:00:00 2001 From: Mark Riedesel Date: Thu, 11 Feb 2016 08:52:37 -0600 Subject: Fix 500 error when comparing by tags --- app/models/repository.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/models/repository.rb b/app/models/repository.rb index 7f0047a002e..a5787a05277 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -611,6 +611,8 @@ class Repository end def merge_base(first_commit_id, second_commit_id) + first_commit_id = commit(first_commit_id).try(:id) || first_commit_id + second_commit_id = commit(second_commit_id).try(:id) || second_commit_id rugged.merge_base(first_commit_id, second_commit_id) rescue Rugged::ReferenceError nil -- cgit v1.2.1 From 3d9f8ab3b5cf62b426b1c84f30bf41941a3b0fe3 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Wed, 17 Feb 2016 14:20:49 +0100 Subject: Use gitlab-workhorse 0.6.5 --- GITLAB_WORKHORSE_VERSION | 2 +- doc/install/installation.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/GITLAB_WORKHORSE_VERSION b/GITLAB_WORKHORSE_VERSION index d2b13eb644d..ef5e4454454 100644 --- a/GITLAB_WORKHORSE_VERSION +++ b/GITLAB_WORKHORSE_VERSION @@ -1 +1 @@ -0.6.4 +0.6.5 diff --git a/doc/install/installation.md b/doc/install/installation.md index 7ae73450afb..7f16e6ff5c4 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -353,7 +353,7 @@ GitLab Shell is an SSH access and repository management software developed speci cd /home/git sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-workhorse.git cd gitlab-workhorse - sudo -u git -H git checkout 0.6.4 + sudo -u git -H git checkout 0.6.5 sudo -u git -H make ### Initialize Database and Activate Advanced Features -- cgit v1.2.1 From 9823d00e0b13224ae9e820e7d3f9fade69201e99 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Wed, 17 Feb 2016 11:32:02 -0200 Subject: Add ability to see and sort on vote count from Issues and MR lists --- CHANGELOG | 1 + app/assets/stylesheets/pages/issues.scss | 2 +- app/assets/stylesheets/pages/merge_requests.scss | 4 +- app/helpers/sorting_helper.rb | 18 +++++++ app/models/concerns/issuable.rb | 25 ++++++++++ app/views/projects/issues/_issue.html.haml | 19 ++++++++ .../merge_requests/_merge_request.html.haml | 19 ++++++++ app/views/shared/_sort_dropdown.html.haml | 4 ++ features/project/issues/issues.feature | 10 ++++ features/project/merge_requests.feature | 11 +++++ features/steps/project/issues/issues.rb | 57 ++++++++++++++++++++++ features/steps/project/merge_requests.rb | 50 +++++++++++++++++++ features/steps/shared/issuable.rb | 16 ++++++ spec/factories/notes.rb | 14 ++++++ 14 files changed, 247 insertions(+), 3 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 74bc366d203..08a9b8df4a0 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -62,6 +62,7 @@ v 8.5.0 (unreleased) - Replaces "Create merge request" link with one to the "Merge Request" when one exists - Fix CI builds badge, add a new link to builds badge, deprecate the old one - Fix broken link to project in build notification emails + - Ability to see and sort on vote count from Issues and MR lists v 8.4.4 - Update omniauth-saml gem to 1.4.2 diff --git a/app/assets/stylesheets/pages/issues.scss b/app/assets/stylesheets/pages/issues.scss index 8694bd654a7..1cc853dd4f5 100644 --- a/app/assets/stylesheets/pages/issues.scss +++ b/app/assets/stylesheets/pages/issues.scss @@ -24,7 +24,7 @@ display: inline-block; } - .issue-no-comments { + .issue-no-comments, .issue-no-votes { opacity: 0.5; } } diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss index f033ff15f88..6b497cd56ed 100644 --- a/app/assets/stylesheets/pages/merge_requests.scss +++ b/app/assets/stylesheets/pages/merge_requests.scss @@ -163,7 +163,7 @@ display: inline-block; } - .merge-request-no-comments { + .merge-request-no-comments, .merge-request-no-votes { opacity: 0.5; } } @@ -236,4 +236,4 @@ } } } -} \ No newline at end of file +} diff --git a/app/helpers/sorting_helper.rb b/app/helpers/sorting_helper.rb index 241179b0212..f9026b887da 100644 --- a/app/helpers/sorting_helper.rb +++ b/app/helpers/sorting_helper.rb @@ -11,6 +11,8 @@ module SortingHelper sort_value_largest_repo => sort_title_largest_repo, sort_value_recently_signin => sort_title_recently_signin, sort_value_oldest_signin => sort_title_oldest_signin, + sort_value_downvotes => sort_title_downvotes, + sort_value_upvotes => sort_title_upvotes } end @@ -54,6 +56,14 @@ module SortingHelper 'Oldest sign in' end + def sort_title_downvotes + 'Least popular' + end + + def sort_title_upvotes + 'Most popular' + end + def sort_value_oldest_updated 'updated_asc' end @@ -93,4 +103,12 @@ module SortingHelper def sort_value_oldest_signin 'oldest_sign_in' end + + def sort_value_downvotes + 'downvotes_desc' + end + + def sort_value_upvotes + 'upvotes_desc' + end end diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb index 5136d0196a5..e5f089fb8a0 100644 --- a/app/models/concerns/issuable.rb +++ b/app/models/concerns/issuable.rb @@ -69,10 +69,35 @@ module Issuable case method.to_s when 'milestone_due_asc' then order_milestone_due_asc when 'milestone_due_desc' then order_milestone_due_desc + when 'downvotes_desc' then order_downvotes_desc + when 'upvotes_desc' then order_upvotes_desc else order_by(method) end end + + def order_downvotes_desc + order_votes_desc('thumbsdown') + end + + def order_upvotes_desc + order_votes_desc('thumbsup') + end + + def order_votes_desc(award_emoji_name) + issuable_table = self.arel_table + note_table = Note.arel_table + + join_clause = issuable_table.join(note_table, Arel::Nodes::OuterJoin).on( + note_table[:noteable_id].eq(issuable_table[:id]).and( + note_table[:noteable_type].eq(self.name).and( + note_table[:is_award].eq(true).and(note_table[:note].eq(award_emoji_name)) + ) + ) + ).join_sources + + joins(join_clause).group(issuable_table[:id]).reorder("COUNT(notes.id) DESC") + end end def today? diff --git a/app/views/projects/issues/_issue.html.haml b/app/views/projects/issues/_issue.html.haml index f9cf4910df3..5b0edcfa978 100644 --- a/app/views/projects/issues/_issue.html.haml +++ b/app/views/projects/issues/_issue.html.haml @@ -15,6 +15,25 @@ %li = link_to_member(@project, issue.assignee, name: false, title: "Assigned to :name") + - upvotes, downvotes = issue.upvotes, issue.downvotes + - if upvotes > 0 || downvotes > 0 + %li + = icon('thumbs-up') + = upvotes + - else + %li{ class: 'issue-no-votes' } + = icon('thumbs-up') + = upvotes + + - if upvotes > 0 || downvotes > 0 + %li + = icon('thumbs-down') + = downvotes + - else + %li{ class: 'issue-no-votes' } + = icon('thumbs-down') + = downvotes + - note_count = issue.notes.user.count - if note_count > 0 %li diff --git a/app/views/projects/merge_requests/_merge_request.html.haml b/app/views/projects/merge_requests/_merge_request.html.haml index e25bf917b43..b230b3a0110 100644 --- a/app/views/projects/merge_requests/_merge_request.html.haml +++ b/app/views/projects/merge_requests/_merge_request.html.haml @@ -24,6 +24,25 @@ %li = link_to_member(merge_request.source_project, merge_request.assignee, name: false, title: "Assigned to :name") + - upvotes, downvotes = merge_request.upvotes, merge_request.downvotes + - if upvotes > 0 || downvotes > 0 + %li + = icon('thumbs-up') + = upvotes + - else + %li{ class: 'merge-request-no-votes' } + = icon('thumbs-up') + = upvotes + + - if upvotes > 0 || downvotes > 0 + %li + = icon('thumbs-down') + = downvotes + - else + %li{ class: 'merge-request-no-votes' } + = icon('thumbs-down') + = downvotes + - note_count = merge_request.mr_and_commit_notes.user.count - if note_count > 0 %li diff --git a/app/views/shared/_sort_dropdown.html.haml b/app/views/shared/_sort_dropdown.html.haml index f09ab25276d..e3a6a5a68b6 100644 --- a/app/views/shared/_sort_dropdown.html.haml +++ b/app/views/shared/_sort_dropdown.html.haml @@ -20,3 +20,7 @@ = sort_title_milestone_soon = link_to page_filter_path(sort: sort_value_milestone_later) do = sort_title_milestone_later + = link_to page_filter_path(sort: sort_value_upvotes) do + = sort_title_upvotes + = link_to page_filter_path(sort: sort_value_downvotes) do + = sort_title_downvotes diff --git a/features/project/issues/issues.feature b/features/project/issues/issues.feature index ca2399d85a9..89af58dcef3 100644 --- a/features/project/issues/issues.feature +++ b/features/project/issues/issues.feature @@ -88,6 +88,16 @@ Feature: Project Issues And I visit dashboard merge requests page Then The list should be sorted by "Oldest updated" + @javascript + Scenario: Sort issues by upvotes/downvotes + Given project "Shop" have "Bugfix" open issue + And issue "Release 0.4" have 2 upvotes and 1 downvote + And issue "Tweet control" have 1 upvote and 2 downvotes + And I sort the list by "Most popular" + Then The list should be sorted by "Most popular" + And I sort the list by "Least popular" + Then The list should be sorted by "Least popular" + @javascript Scenario: I search issue Given I fill in issue search with "Re" diff --git a/features/project/merge_requests.feature b/features/project/merge_requests.feature index 5995e787961..495f25f28e7 100644 --- a/features/project/merge_requests.feature +++ b/features/project/merge_requests.feature @@ -107,6 +107,17 @@ Feature: Project Merge Requests And I visit dashboard merge requests page Then The list should be sorted by "Oldest updated" + @javascript + Scenario: Sort merge requests by upvotes/downvotes + Given project "Shop" have "Bug NS-05" open merge request with diffs inside + And project "Shop" have "Bug NS-06" open merge request + And merge request "Bug NS-04" have 2 upvotes and 1 downvote + And merge request "Bug NS-06" have 1 upvote and 2 downvotes + And I sort the list by "Most popular" + Then The list should be sorted by "Most popular" + And I sort the list by "Least popular" + Then The list should be sorted by "Least popular" + @javascript Scenario: Visiting Merge Requests after commenting on diffs Given project "Shop" have "Bug NS-05" open merge request with diffs inside diff --git a/features/steps/project/issues/issues.rb b/features/steps/project/issues/issues.rb index 09a89e99831..54d64bacc52 100644 --- a/features/steps/project/issues/issues.rb +++ b/features/steps/project/issues/issues.rb @@ -174,6 +174,13 @@ class Spinach::Features::ProjectIssues < Spinach::FeatureSteps author: project.users.first) end + step 'project "Shop" have "Bugfix" open issue' do + create(:issue, + title: "Bugfix", + project: project, + author: project.users.first) + end + step 'project "Shop" have "Release 0.3" closed issue' do create(:closed_issue, title: "Release 0.3", @@ -181,6 +188,56 @@ class Spinach::Features::ProjectIssues < Spinach::FeatureSteps author: project.users.first) end + step 'issue "Release 0.4" have 2 upvotes and 1 downvote' do + issue = Issue.find_by(title: 'Release 0.4') + create_list(:upvote_note, 2, project: project, noteable: issue) + create(:downvote_note, project: project, noteable: issue) + end + + step 'issue "Tweet control" have 1 upvote and 2 downvotes' do + issue = Issue.find_by(title: 'Tweet control') + create(:upvote_note, project: project, noteable: issue) + create_list(:downvote_note, 2, project: project, noteable: issue) + end + + step 'The list should be sorted by "Least popular"' do + page.within '.issues-list' do + page.within 'li.issue:nth-child(1)' do + expect(page).to have_content 'Tweet control' + expect(page).to have_content '1 2' + end + + page.within 'li.issue:nth-child(2)' do + expect(page).to have_content 'Release 0.4' + expect(page).to have_content '2 1' + end + + page.within 'li.issue:nth-child(3)' do + expect(page).to have_content 'Bugfix' + expect(page).to have_content '0 0' + end + end + end + + step 'The list should be sorted by "Most popular"' do + page.within '.issues-list' do + page.within 'li.issue:nth-child(1)' do + expect(page).to have_content 'Release 0.4' + expect(page).to have_content '2 1' + end + + page.within 'li.issue:nth-child(2)' do + expect(page).to have_content 'Tweet control' + expect(page).to have_content '1 2' + end + + page.within 'li.issue:nth-child(3)' do + expect(page).to have_content 'Bugfix' + expect(page).to have_content '0 0' + end + end + end + step 'empty project "Empty Project"' do create :empty_project, name: 'Empty Project', namespace: @user.namespace end diff --git a/features/steps/project/merge_requests.rb b/features/steps/project/merge_requests.rb index 337893e6209..2160d8645fd 100644 --- a/features/steps/project/merge_requests.rb +++ b/features/steps/project/merge_requests.rb @@ -138,6 +138,56 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps author: project.users.first) end + step 'merge request "Bug NS-04" have 2 upvotes and 1 downvote' do + merge_request = MergeRequest.find_by(title: 'Bug NS-04') + create_list(:upvote_note, 2, project: project, noteable: merge_request) + create(:downvote_note, project: project, noteable: merge_request) + end + + step 'merge request "Bug NS-06" have 1 upvote and 2 downvotes' do + merge_request = MergeRequest.find_by(title: 'Bug NS-06') + create(:upvote_note, project: project, noteable: merge_request) + create_list(:downvote_note, 2, project: project, noteable: merge_request) + end + + step 'The list should be sorted by "Least popular"' do + page.within '.mr-list' do + page.within 'li.merge-request:nth-child(1)' do + expect(page).to have_content 'Bug NS-06' + expect(page).to have_content '1 2' + end + + page.within 'li.merge-request:nth-child(2)' do + expect(page).to have_content 'Bug NS-04' + expect(page).to have_content '2 1' + end + + page.within 'li.merge-request:nth-child(3)' do + expect(page).to have_content 'Bug NS-05' + expect(page).to have_content '0 0' + end + end + end + + step 'The list should be sorted by "Most popular"' do + page.within '.mr-list' do + page.within 'li.merge-request:nth-child(1)' do + expect(page).to have_content 'Bug NS-04' + expect(page).to have_content '2 1' + end + + page.within 'li.merge-request:nth-child(2)' do + expect(page).to have_content 'Bug NS-06' + expect(page).to have_content '1 2' + end + + page.within 'li.merge-request:nth-child(3)' do + expect(page).to have_content 'Bug NS-05' + expect(page).to have_content '0 0' + end + end + end + step 'I click on the Changes tab' do page.within '.merge-request-tabs' do click_link 'Changes' diff --git a/features/steps/shared/issuable.rb b/features/steps/shared/issuable.rb index 2117feaedb8..ae10c6069a9 100644 --- a/features/steps/shared/issuable.rb +++ b/features/steps/shared/issuable.rb @@ -113,6 +113,22 @@ module SharedIssuable end end + step 'I sort the list by "Least popular"' do + find('button.dropdown-toggle.btn').click + + page.within('ul.dropdown-menu.dropdown-menu-align-right li') do + click_link 'Least popular' + end + end + + step 'I sort the list by "Most popular"' do + find('button.dropdown-toggle.btn').click + + page.within('ul.dropdown-menu.dropdown-menu-align-right li') do + click_link 'Most popular' + end + end + step 'The list should be sorted by "Oldest updated"' do page.within('div.dropdown.inline.prepend-left-10') do expect(page.find('button.dropdown-toggle.btn')).to have_content('Oldest updated') diff --git a/spec/factories/notes.rb b/spec/factories/notes.rb index 35a20adeef3..32c202891d8 100644 --- a/spec/factories/notes.rb +++ b/spec/factories/notes.rb @@ -34,6 +34,8 @@ FactoryGirl.define do factory :note_on_merge_request_diff, traits: [:on_merge_request, :on_diff] factory :note_on_project_snippet, traits: [:on_project_snippet] factory :system_note, traits: [:system] + factory :downvote_note, traits: [:award, :downvote] + factory :upvote_note, traits: [:award, :upvote] trait :on_commit do project @@ -65,6 +67,18 @@ FactoryGirl.define do system true end + trait :award do + is_award true + end + + trait :downvote do + note "thumbsdown" + end + + trait :upvote do + note "thumbsup" + end + trait :with_attachment do attachment { fixture_file_upload(Rails.root + "spec/fixtures/dk.png", "`/png") } end -- cgit v1.2.1 From 16e116bc167b4c6a4e1efccc9fa429163fc28c10 Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Wed, 17 Feb 2016 09:02:34 -0500 Subject: Correct icon for milestones. --- app/views/shared/issuable/_sidebar.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/shared/issuable/_sidebar.html.haml b/app/views/shared/issuable/_sidebar.html.haml index 2aada5c9952..a45775f36b5 100644 --- a/app/views/shared/issuable/_sidebar.html.haml +++ b/app/views/shared/issuable/_sidebar.html.haml @@ -47,7 +47,7 @@ .block.milestone .sidebar-collapsed-icon - = icon('balance-scale') + = icon('clock-o') %span - if issuable.milestone = issuable.milestone.title -- cgit v1.2.1 From 3d3ac87af991319d6960a963c0975c83bf7e4108 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Wed, 17 Feb 2016 15:05:44 +0100 Subject: Redirect /import to project page if no importing at all and repo exists Fixes #13367. --- app/controllers/projects/imports_controller.rb | 12 +++++++++--- app/models/project.rb | 4 ++++ spec/controllers/projects/imports_controller_spec.rb | 12 ++++++++++++ 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/app/controllers/projects/imports_controller.rb b/app/controllers/projects/imports_controller.rb index 07f355c35b1..196996f1752 100644 --- a/app/controllers/projects/imports_controller.rb +++ b/app/controllers/projects/imports_controller.rb @@ -3,6 +3,7 @@ class Projects::ImportsController < Projects::ApplicationController before_action :authorize_admin_project! before_action :require_no_repo, only: [:new, :create] before_action :redirect_if_progress, only: [:new, :create] + before_action :redirect_if_no_import, only: :show def new end @@ -63,14 +64,19 @@ class Projects::ImportsController < Projects::ApplicationController def require_no_repo if @project.repository_exists? - redirect_to(namespace_project_path(@project.namespace, @project)) + redirect_to namespace_project_path(@project.namespace, @project) end end def redirect_if_progress if @project.import_in_progress? - redirect_to namespace_project_import_path(@project.namespace, @project) && - return + redirect_to namespace_project_import_path(@project.namespace, @project) + end + end + + def redirect_if_no_import + if @project.repository_exists? && @project.no_import? + redirect_to namespace_project_path(@project.namespace, @project) end end end diff --git a/app/models/project.rb b/app/models/project.rb index a43878ebcad..95ad88c76ae 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -382,6 +382,10 @@ class Project < ActiveRecord::Base external_import? || forked? end + def no_import? + import_status == 'none' + end + def external_import? import_url.present? end diff --git a/spec/controllers/projects/imports_controller_spec.rb b/spec/controllers/projects/imports_controller_spec.rb index 85d1d1e0524..0147bd2b953 100644 --- a/spec/controllers/projects/imports_controller_spec.rb +++ b/spec/controllers/projects/imports_controller_spec.rb @@ -104,6 +104,18 @@ describe Projects::ImportsController do end end end + + context 'when import never happened' do + before do + project.update_attribute(:import_status, :none) + end + + it 'redirects to namespace_project_path' do + get :show, namespace_id: project.namespace.to_param, project_id: project.to_param + + expect(response).to redirect_to namespace_project_path(project.namespace, project) + end + end end end end -- cgit v1.2.1 From b3bd7c1999a1b2a662c029a608bcf25d50e9ee82 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Wed, 17 Feb 2016 15:22:33 +0100 Subject: Add newline --- spec/support/workhorse_helpers.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/support/workhorse_helpers.rb b/spec/support/workhorse_helpers.rb index c5c5d4c63d1..107b6e30924 100644 --- a/spec/support/workhorse_helpers.rb +++ b/spec/support/workhorse_helpers.rb @@ -13,4 +13,4 @@ module WorkhorseHelpers ] end end -end \ No newline at end of file +end -- cgit v1.2.1 From 42c2064a36f41f83501d9c8183fe93733da7ede6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Wed, 17 Feb 2016 16:31:14 +0100 Subject: Sort line notes used in parallel diff by created_at Fixes #13464. --- app/helpers/diff_helper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/helpers/diff_helper.rb b/app/helpers/diff_helper.rb index f9bacc8ba45..6a3ab3ea40a 100644 --- a/app/helpers/diff_helper.rb +++ b/app/helpers/diff_helper.rb @@ -69,7 +69,7 @@ module DiffHelper end def line_comments - @line_comments ||= @line_notes.select(&:active?).group_by(&:line_code) + @line_comments ||= @line_notes.select(&:active?).sort_by(&:created_at).group_by(&:line_code) end def organize_comments(type_left, type_right, line_code_left, line_code_right) -- cgit v1.2.1 From c110c9bd7f2fabb5c9397291f1f13c6accab70e6 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Wed, 17 Feb 2016 18:29:43 +0100 Subject: refactored spec --- spec/services/git_push_service_spec.rb | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/spec/services/git_push_service_spec.rb b/spec/services/git_push_service_spec.rb index 48e796b6946..994585fb32c 100644 --- a/spec/services/git_push_service_spec.rb +++ b/spec/services/git_push_service_spec.rb @@ -14,10 +14,17 @@ describe GitPushService, services: true do end describe 'Push branches' do + + let(:oldrev) { @oldrev } + let(:newrev) { @newrev } + + subject do + execute_service(project, user, oldrev, newrev, @ref ) + end + context 'new branch' do - subject do - execute_service(project, user, @blankrev, @newrev, @ref ) - end + + let(:oldrev) { @blankrev } it { is_expected.to be_truthy } @@ -35,9 +42,6 @@ describe GitPushService, services: true do end context 'existing branch' do - subject do - execute_service(project, user, @oldrev, @newrev, @ref ) - end it { is_expected.to be_truthy } @@ -49,9 +53,8 @@ describe GitPushService, services: true do end context 'rm branch' do - subject do - execute_service(project, user, @oldrev, @blankrev, @ref ) - end + + let(:newrev) { @blankrev } it { is_expected.to be_truthy } -- cgit v1.2.1 From e5f9c4460f8c888e0a4372e31f22e61b96c2cbe6 Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Wed, 17 Feb 2016 20:34:54 +0200 Subject: Remove remaining sqlite method call --- lib/tasks/gitlab/check.rake | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/tasks/gitlab/check.rake b/lib/tasks/gitlab/check.rake index 54d95cd62a5..81099cb8ba9 100644 --- a/lib/tasks/gitlab/check.rake +++ b/lib/tasks/gitlab/check.rake @@ -16,7 +16,6 @@ namespace :gitlab do check_git_config check_database_config_exists - check_database_is_not_sqlite check_migrations_are_up check_orphaned_group_members check_gitlab_config_exists -- cgit v1.2.1 From 2770de961711076d1e8374bd943382eb14c90ad5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20D=C3=A1vila?= Date: Wed, 17 Feb 2016 21:15:13 -0500 Subject: Reopened MRs should also be considered as open. --- app/models/merge_request.rb | 2 +- .../projects/merge_requests_controller_spec.rb | 34 ++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 1be8061e53d..ea2b0e075f6 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -137,7 +137,7 @@ class MergeRequest < ActiveRecord::Base scope :by_milestone, ->(milestone) { where(milestone_id: milestone) } scope :in_projects, ->(project_ids) { where("source_project_id in (:project_ids) OR target_project_id in (:project_ids)", project_ids: project_ids) } scope :of_projects, ->(ids) { where(target_project_id: ids) } - scope :opened, -> { with_state(:opened) } + scope :opened, -> { with_states(:opened, :reopened) } scope :merged, -> { with_state(:merged) } scope :closed, -> { with_state(:closed) } scope :closed_and_merged, -> { with_states(:closed, :merged) } diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb index 9450a389d81..e82fe26c7a6 100644 --- a/spec/controllers/projects/merge_requests_controller_spec.rb +++ b/spec/controllers/projects/merge_requests_controller_spec.rb @@ -123,6 +123,40 @@ describe Projects::MergeRequestsController do end end + describe 'GET #index' do + def get_merge_requests + get :index, + namespace_id: project.namespace.to_param, + project_id: project.to_param, + state: 'opened' + end + + context 'when filtering by opened state' do + + context 'with opened merge requests' do + it 'should list those merge requests' do + get_merge_requests + + expect(assigns(:merge_requests)).to include(merge_request) + end + end + + context 'with reopened merge requests' do + before do + merge_request.close! + merge_request.reopen! + end + + it 'should list those merge requests' do + get_merge_requests + + expect(assigns(:merge_requests)).to include(merge_request) + end + end + + end + end + describe 'GET diffs' do def go(format: 'html') get :diffs, -- cgit v1.2.1