From a5e20638c2ca2317f88261cd627b2d8453e4445e Mon Sep 17 00:00:00 2001 From: Michael Krane Date: Sun, 27 Apr 2014 11:36:45 +0200 Subject: [PATCH 001/360] Satellites access fix --- doc/install/installation.md | 2 +- doc/update/6.6-to-6.7.md | 2 +- doc/update/6.7-to-6.8.md | 2 +- lib/tasks/gitlab/check.rake | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/install/installation.md b/doc/install/installation.md index 579656eda2..1a9f6406fb 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -202,7 +202,7 @@ You can change `6-8-stable` to `master` if you want the *bleeding edge* version, # Create directory for satellites sudo -u git -H mkdir /home/git/gitlab-satellites - sudo chmod u+rwx,g+rx,o-rwx /home/git/gitlab-satellites + sudo chmod u+rwx,g=rx,o-rwx /home/git/gitlab-satellites # Make sure GitLab can write to the tmp/pids/ and tmp/sockets/ directories sudo chmod -R u+rwX tmp/pids/ diff --git a/doc/update/6.6-to-6.7.md b/doc/update/6.6-to-6.7.md index 0f39c037c9..6a62114489 100644 --- a/doc/update/6.6-to-6.7.md +++ b/doc/update/6.6-to-6.7.md @@ -65,7 +65,7 @@ sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab sudo cp lib/support/logrotate/gitlab /etc/logrotate.d/gitlab # Close access to gitlab-satellites for others -sudo chmod u+rwx,g+rx,o-rwx /home/git/gitlab-satellites +sudo chmod u+rwx,g=rx,o-rwx /home/git/gitlab-satellites ``` diff --git a/doc/update/6.7-to-6.8.md b/doc/update/6.7-to-6.8.md index 63023fd384..b5f8711361 100644 --- a/doc/update/6.7-to-6.8.md +++ b/doc/update/6.7-to-6.8.md @@ -67,7 +67,7 @@ sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab sudo cp lib/support/logrotate/gitlab /etc/logrotate.d/gitlab # Close access to gitlab-satellites for others -sudo chmod u+rwx,g+rx,o-rwx /home/git/gitlab-satellites +sudo chmod u+rwx,g=rx,o-rwx /home/git/gitlab-satellites ``` ### 5. Update config files diff --git a/lib/tasks/gitlab/check.rake b/lib/tasks/gitlab/check.rake index bf015a1fe1..f77b817bb4 100644 --- a/lib/tasks/gitlab/check.rake +++ b/lib/tasks/gitlab/check.rake @@ -458,7 +458,7 @@ namespace :gitlab do else puts "no".red try_fixing_it( - "sudo chmod u+rwx,g+rx,o-rwx #{satellites_path}", + "sudo chmod u+rwx,g=rx,o-rwx #{satellites_path}", ) for_more_information( see_installation_guide_section "GitLab" From 821ab16846f2bc9433ec4429191a57f030887ca5 Mon Sep 17 00:00:00 2001 From: Alexander Mills Date: Fri, 16 May 2014 10:29:12 +0100 Subject: [PATCH 002/360] added SYSV chkconfig property so gitlab starts after MySQLd / nginx --- lib/support/init.d/gitlab | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/support/init.d/gitlab b/lib/support/init.d/gitlab index 3dd4465a6d..7f5014502e 100755 --- a/lib/support/init.d/gitlab +++ b/lib/support/init.d/gitlab @@ -12,6 +12,7 @@ # Default-Stop: 0 1 6 # Short-Description: GitLab git repository management # Description: GitLab git repository management +# chkconfig: - 85 14 ### END INIT INFO From f0b3092d2f7e0a177445727e6c6bd461c19b6ba7 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Mon, 19 May 2014 11:52:02 +0200 Subject: [PATCH 003/360] Recommend issue name. --- doc/release/monthly.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/release/monthly.md b/doc/release/monthly.md index 514d73517b..7c21c5f19a 100644 --- a/doc/release/monthly.md +++ b/doc/release/monthly.md @@ -15,6 +15,8 @@ The RC1 release comes with the task to update the installation and upgrade docs. ### **1. Create an issue for RC1 release** +Consider naming the issue "Release x.x.x.rc1" to make it easier for later searches. + ### **2. Update the installation guide** 1. Check if it references the correct branch `x-x-stable` (doesn't exist yet, but that is okay) From 971dc47907ac54c49a5792697fc02ba350247f86 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Mon, 19 May 2014 12:43:16 +0200 Subject: [PATCH 004/360] Fix typo. --- doc/release/monthly.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/release/monthly.md b/doc/release/monthly.md index 7c21c5f19a..6c788e850e 100644 --- a/doc/release/monthly.md +++ b/doc/release/monthly.md @@ -84,7 +84,7 @@ Make sure the code quality indicators are green / good. ### **5. Set VERSION** -Set VERSION tot x.x.0.rc1 +Change version in VERSION to x.x.0.rc1 ### **6. Tag** From 0660183cb0733e68520e109c9470d9b4f4109194 Mon Sep 17 00:00:00 2001 From: dosire Date: Tue, 20 May 2014 13:29:52 +0200 Subject: [PATCH 005/360] Renamed based on suggestion Martijn. --- PROCESS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PROCESS.md b/PROCESS.md index 23dbfd0c69..89ad12ecd5 100644 --- a/PROCESS.md +++ b/PROCESS.md @@ -13,7 +13,7 @@ Below we describe the contributing process to GitLab for two reasons. So that co - Monitors all issues for feedback (but especially ones commented on since automatically watching them) - Closes issues with no feedback from the reporter for two weeks -### Merge request officers +### Merge marshal - Responds to merge requests the issue team mentions them in and monitors for new merge requests - Provides feedback to the merge request submitter to improve the merge request (style, tests, etc.) From c18e2778b2f1a4a2c3fb8e0f79c400456645e036 Mon Sep 17 00:00:00 2001 From: Olaf Mandel Date: Tue, 20 May 2014 15:22:23 +0200 Subject: [PATCH 006/360] Fix avatar URLs in JS-lists for relative_url_root In user lists created when entering a (partial) user name into a field, the URL to the user avatar was invalid if running with relative_url_root. This patch is the result of: sed -i 's/\(= *\)\(user\.avatar_url\)/\1gon.relative_url_root + \2/' \ app/assets/javascripts/*.coffee --- app/assets/javascripts/project_users_select.js.coffee | 2 +- app/assets/javascripts/users_select.js.coffee | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/project_users_select.js.coffee b/app/assets/javascripts/project_users_select.js.coffee index b0e39610fe..a7fec96040 100644 --- a/app/assets/javascripts/project_users_select.js.coffee +++ b/app/assets/javascripts/project_users_select.js.coffee @@ -37,7 +37,7 @@ projectUserFormatResult: (user) -> if user.avatar_url - avatar = user.avatar_url + avatar = gon.relative_url_root + user.avatar_url else if gon.gravatar_enabled avatar = gon.gravatar_url avatar = avatar.replace('%{hash}', md5(user.email)) diff --git a/app/assets/javascripts/users_select.js.coffee b/app/assets/javascripts/users_select.js.coffee index ce9a505b1e..cab9f6271e 100644 --- a/app/assets/javascripts/users_select.js.coffee +++ b/app/assets/javascripts/users_select.js.coffee @@ -1,7 +1,7 @@ $ -> userFormatResult = (user) -> if user.avatar_url - avatar = user.avatar_url + avatar = gon.relative_url_root + user.avatar_url else if gon.gravatar_enabled avatar = gon.gravatar_url avatar = avatar.replace('%{hash}', md5(user.email)) From ac46130748c31f3052f7ac325f897637e7b326f5 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 20 May 2014 16:36:51 +0300 Subject: [PATCH 007/360] Allow set group avatar when create group. Not only edit page Signed-off-by: Dmitriy Zaporozhets --- app/views/groups/new.html.haml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/app/views/groups/new.html.haml b/app/views/groups/new.html.haml index 955a107e54..ebf5e8571a 100644 --- a/app/views/groups/new.html.haml +++ b/app/views/groups/new.html.haml @@ -13,6 +13,17 @@ .col-sm-10 = f.text_area :description, maxlength: 250, class: "form-control js-gfm-input", rows: 4 + .form-group.group-description-holder + = f.label :avatar, "Group avatar", class: 'control-label' + .col-sm-10 + %a.choose-btn.btn.btn-small.js-choose-group-avatar-button + %i.icon-paper-clip + %span Choose File ... +   + %span.file_name.js-avatar-filename File name... + = f.file_field :avatar, class: "js-group-avatar-input hidden" + .light The maximum file size allowed is 100KB. + .form-group .col-sm-2 .col-sm-10 From b08fe47fe8977905252c73653cece86359922e29 Mon Sep 17 00:00:00 2001 From: Alan Kehoe Date: Tue, 20 May 2014 22:03:34 +0100 Subject: [PATCH 008/360] Update message on the group dashboard page --- app/views/groups/show.html.haml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/views/groups/show.html.haml b/app/views/groups/show.html.haml index 0c62772a5c..17475288a8 100644 --- a/app/views/groups/show.html.haml +++ b/app/views/groups/show.html.haml @@ -5,7 +5,10 @@ = link_to dashboard_path, class: 'btn btn-tiny' do ← To dashboard   - %span.cgray You will only see events from projects in this group + %span.cgray + Currently you are only seeing events from the + = @group.name + group %hr = render 'shared/event_filter' - if @events.any? From d1980adf93e417850fcd3bac8caed1f2c9da7fb4 Mon Sep 17 00:00:00 2001 From: Marc Radulescu Date: Thu, 22 May 2014 10:35:01 +0200 Subject: [PATCH 009/360] typos fixed --- app/views/groups/_projects.html.haml | 2 +- app/views/groups/edit.html.haml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/groups/_projects.html.haml b/app/views/groups/_projects.html.haml index bd4e3156af..41f8cb9da4 100644 --- a/app/views/groups/_projects.html.haml +++ b/app/views/groups/_projects.html.haml @@ -8,7 +8,7 @@ New project %ul.well-list - if projects.blank? - .nothing-here-block This groups has no projects yet + .nothing-here-block This group has no projects yet - projects.each do |project| %li.project-row = link_to project_path(project), class: dom_class(project) do diff --git a/app/views/groups/edit.html.haml b/app/views/groups/edit.html.haml index 500c37ab71..2a5614cff6 100644 --- a/app/views/groups/edit.html.haml +++ b/app/views/groups/edit.html.haml @@ -45,7 +45,7 @@ - if @group.avatar? You can change your group avatar here - else - You can upload an group avatar here + You can upload a group avatar here %a.choose-btn.btn.btn-small.js-choose-group-avatar-button %i.icon-paper-clip %span Choose File ... From b019c06195cf3ca3e097f57c53cbd863165fa077 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Thu, 22 May 2014 11:01:01 +0200 Subject: [PATCH 010/360] Required shell version is now 1.9.4. --- lib/tasks/gitlab/check.rake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tasks/gitlab/check.rake b/lib/tasks/gitlab/check.rake index bf015a1fe1..0387795fa4 100644 --- a/lib/tasks/gitlab/check.rake +++ b/lib/tasks/gitlab/check.rake @@ -779,7 +779,7 @@ namespace :gitlab do end def check_gitlab_shell - required_version = Gitlab::VersionInfo.new(1, 9, 3) + required_version = Gitlab::VersionInfo.new(1, 9, 4) current_version = Gitlab::VersionInfo.parse(gitlab_shell_version) print "GitLab Shell version >= #{required_version} ? ... " From 38d0e001eac2026b8526fc7098bd147df4fc522d Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Thu, 22 May 2014 11:09:00 +0200 Subject: [PATCH 011/360] Version to 6.9.0 --- CHANGELOG | 1 + VERSION | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 2f7874ba72..aaf1879dcc 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -18,6 +18,7 @@ v 6.9.0 - Accept merge request via API (sponsored by O'Reilly Media) - Add more access checks during API calls - Block SSH access for 'disabled' Active Directory users + - Labels for merge requests (Drew Blessing) v 6.8.0 - Ability to at mention users that are participating in issue and merge req. discussion diff --git a/VERSION b/VERSION index fed1b9285f..97f5781528 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -6.9.0.rc1 +6.9.0 From 1ad174fbcdb7c14eb8fbe9820e1152383f41a89e Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 22 May 2014 12:25:44 +0300 Subject: [PATCH 012/360] Improve edit page UI/UX Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/sections/diff.scss | 5 ++++ .../projects/edit_tree/preview.html.haml | 2 +- app/views/projects/edit_tree/show.html.haml | 23 +++++++++++-------- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/app/assets/stylesheets/sections/diff.scss b/app/assets/stylesheets/sections/diff.scss index af44654d5d..24d997c9fc 100644 --- a/app/assets/stylesheets/sections/diff.scss +++ b/app/assets/stylesheets/sections/diff.scss @@ -330,3 +330,8 @@ } } } + +.file-content .diff-file { + margin: 0; + border: none; +} diff --git a/app/views/projects/edit_tree/preview.html.haml b/app/views/projects/edit_tree/preview.html.haml index fc6d3bfbc2..340f68cc05 100644 --- a/app/views/projects/edit_tree/preview.html.haml +++ b/app/views/projects/edit_tree/preview.html.haml @@ -23,4 +23,4 @@ %td.new_line= link_to raw(type == "old" ? " " : line_new) , "##{line_code}", id: line_code %td.line_content{class: "noteable_line #{type} #{line_code}", "line_code" => line_code}= raw diff_line_content(line) - else - %p.nothing_here_message No changes. + .nothing-here-block No changes. diff --git a/app/views/projects/edit_tree/show.html.haml b/app/views/projects/edit_tree/show.html.haml index 93037ef958..32a6d4ef36 100644 --- a/app/views/projects/edit_tree/show.html.haml +++ b/app/views/projects/edit_tree/show.html.haml @@ -1,23 +1,26 @@ -%h3.page-title Edit mode .file-editor + %ul.nav.nav-tabs.js-edit-mode + %li.active + = link_to 'Edit', '#editor' + %li + = link_to editing_preview_title(@blob.name), '#preview', 'data-preview-url' => preview_project_edit_tree_path(@project, @id) + = form_tag(project_edit_tree_path(@project, @id), method: :put, class: "form-horizontal") do .file-holder.file .file-title - .btn-group.js-edit-mode.left-options - = link_to 'Edit', '#editor', class: 'active hover btn btn-tiny' - = link_to editing_preview_title(@blob.name), '#preview', class: 'btn btn-tiny', 'data-preview-url' => preview_project_edit_tree_path(@project, @id) %i.icon-file %span.file_name + %span.monospace.light #{@ref}: = @path - %small - on - %strong= @ref %span.options .btn-group.tree-btn-group = link_to "Cancel", @after_edit_path, class: "btn btn-tiny btn-cancel", data: { confirm: leave_edit_message } .file-content.code %pre.js-edit-mode-pane#editor= @blob.data .js-edit-mode-pane#preview.hide + %center + %h2 + %i.icon-spinner.icon-spin .form-group.commit_message-group = label_tag 'commit_message', class: "control-label" do @@ -61,14 +64,14 @@ paneId = currentLink.attr('href'), currentPane = editModePanes.filter(paneId); - editModeLinks.removeClass('active hover'); - currentLink.addClass('active hover'); + editModeLinks.parent().removeClass('active hover'); + currentLink.parent().addClass('active hover'); editModePanes.hide(); if (paneId == '#preview') { + currentPane.fadeIn(200); $.post(currentLink.data('preview-url'), { content: editor.getValue() }, function(response) { currentPane.empty().append(response); - currentPane.fadeIn(200); }) } else { currentPane.fadeIn(200); From 88781783dd425d1ba4ff5cacf9b4cc4c23a9a35e Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 22 May 2014 14:23:20 +0300 Subject: [PATCH 013/360] Delete branch service with permission checks Signed-off-by: Dmitriy Zaporozhets --- app/services/delete_branch_service.rb | 42 +++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 app/services/delete_branch_service.rb diff --git a/app/services/delete_branch_service.rb b/app/services/delete_branch_service.rb new file mode 100644 index 0000000000..9f48ab4b60 --- /dev/null +++ b/app/services/delete_branch_service.rb @@ -0,0 +1,42 @@ +class DeleteBranchService + def execute(project, branch_name, current_user) + repository = project.repository + branch = repository.find_branch(branch_name) + + # No such branch + unless branch + return error('No such branch') + end + + # Dont allow remove of protected branch + if project.protected_branch?(branch_name) + return error('Protected branch cant be removed') + end + + # Dont allow user to remove branch if he is not allowed to push + unless current_user.can?(:push_code, project) + return error('You dont have push access to repo') + end + + if repository.rm_branch(branch_name) + Event.create_ref_event(project, current_user, branch, 'rm') + success('Branch was removed') + else + return error('Failed to remove branch') + end + end + + def error(message) + { + message: message, + state: :error + } + end + + def success(message) + { + message: message, + state: :success + } + end +end From e089b11b7a4026acc7706e519682f4b7141b2bcd Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 22 May 2014 14:38:48 +0300 Subject: [PATCH 014/360] Add BranchesHelper Signed-off-by: Dmitriy Zaporozhets --- app/helpers/branches_helper.rb | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 app/helpers/branches_helper.rb diff --git a/app/helpers/branches_helper.rb b/app/helpers/branches_helper.rb new file mode 100644 index 0000000000..e08ffccb94 --- /dev/null +++ b/app/helpers/branches_helper.rb @@ -0,0 +1,11 @@ +module BranchesHelper + def can_remove_branch?(project, branch_name) + if project.protected_branch? branch_name + false + elsif branch_name == project.repository.root_ref + false + else + can?(current_user, :push_code, project) + end + end +end From 0455391add2032dddc7353d1b0ae36d591818d3f Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 22 May 2014 14:39:09 +0300 Subject: [PATCH 015/360] Improve branch-removal logic Signed-off-by: Dmitriy Zaporozhets --- app/controllers/projects/branches_controller.rb | 9 ++------- app/services/delete_branch_service.rb | 4 ++++ app/views/projects/branches/_branch.html.haml | 4 ++-- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/app/controllers/projects/branches_controller.rb b/app/controllers/projects/branches_controller.rb index 6a6cbe4818..00811f17ad 100644 --- a/app/controllers/projects/branches_controller.rb +++ b/app/controllers/projects/branches_controller.rb @@ -4,8 +4,7 @@ class Projects::BranchesController < Projects::ApplicationController before_filter :require_non_empty_project before_filter :authorize_code_access! - before_filter :authorize_push!, only: [:create] - before_filter :authorize_admin_project!, only: [:destroy] + before_filter :authorize_push!, only: [:create, :destroy] def index @branches = Kaminari.paginate_array(@repository.branches).page(params[:page]).per(30) @@ -22,11 +21,7 @@ class Projects::BranchesController < Projects::ApplicationController end def destroy - branch = @repository.find_branch(params[:id]) - - if branch && @repository.rm_branch(branch.name) - Event.create_ref_event(@project, current_user, branch, 'rm') - end + DeleteBranchService.new.execute(project, params[:id], current_user) respond_to do |format| format.html { redirect_to project_branches_path(@project) } diff --git a/app/services/delete_branch_service.rb b/app/services/delete_branch_service.rb index 9f48ab4b60..ce2d8093df 100644 --- a/app/services/delete_branch_service.rb +++ b/app/services/delete_branch_service.rb @@ -8,6 +8,10 @@ class DeleteBranchService return error('No such branch') end + if branch_name == repository.root_ref + return error('Cannot remove HEAD branch') + end + # Dont allow remove of protected branch if project.protected_branch?(branch_name) return error('Protected branch cant be removed') diff --git a/app/views/projects/branches/_branch.html.haml b/app/views/projects/branches/_branch.html.haml index f073197709..87f4dd88c2 100644 --- a/app/views/projects/branches/_branch.html.haml +++ b/app/views/projects/branches/_branch.html.haml @@ -16,8 +16,8 @@ %i.icon-copy Compare - - if can?(current_user, :admin_project, @project) && branch.name != @repository.root_ref - = link_to project_branch_path(@project, branch.name), class: 'btn btn-grouped btn-small remove-row', method: :delete, data: { confirm: 'Removed branch cannot be restored. Are you sure?'}, remote: true do + - if can_remove_branch?(@project, branch.name) + = link_to project_branch_path(@project, branch.name), class: 'btn btn-grouped btn-small btn-remove remove-row', method: :delete, data: { confirm: 'Removed branch cannot be restored. Are you sure?'}, remote: true do %i.icon-trash - if commit From a9d60b3b146acf5540b422919fa87fa931801062 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 22 May 2014 14:39:50 +0300 Subject: [PATCH 016/360] Api call to remove branch Signed-off-by: Dmitriy Zaporozhets --- lib/api/branches.rb | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/lib/api/branches.rb b/lib/api/branches.rb index d54f9371fb..32597eb94c 100644 --- a/lib/api/branches.rb +++ b/lib/api/branches.rb @@ -84,6 +84,18 @@ module API present @branch, with: Entities::RepoObject, project: user_project end + + # Delete branch + # + # Parameters: + # id (required) - The ID of a project + # branch (required) - The name of the branch + # Example Request: + # DELETE /projects/:id/repository/branches/:branch + delete ":id/repository/branches/:branch" do + authorize_push_project + DeleteBranchService.new.execute(user_project, params[:branch], current_user) + end end end end From 36cac35b24d7b8318de40bd2e495b8807eef48fc Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 22 May 2014 15:38:47 +0300 Subject: [PATCH 017/360] Dont allow remove of protected branch Signed-off-by: Dmitriy Zaporozhets --- lib/gitlab/git_access.rb | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/lib/gitlab/git_access.rb b/lib/gitlab/git_access.rb index 4f49ca4189..2f8b55aaca 100644 --- a/lib/gitlab/git_access.rb +++ b/lib/gitlab/git_access.rb @@ -44,14 +44,18 @@ module Gitlab def push_allowed?(user, project, ref, oldrev, newrev, forced_push) if user && user_allowed?(user) action = if project.protected_branch?(ref) - if forced_push.to_s == 'true' - :force_push_code_to_protected_branches - else - :push_code_to_protected_branches - end - else - :push_code - end + # we dont allow force push to protected branch + if forced_push.to_s == 'true' + :force_push_code_to_protected_branches + # and we dont allow remove of protected branch + elsif newrev =~ /0000000/ + :remove_protected_branches + else + :push_code_to_protected_branches + end + else + :push_code + end user.can?(action, project) else false From 114e67564dbcfadafc237459a7549e5a85640817 Mon Sep 17 00:00:00 2001 From: dosire Date: Thu, 22 May 2014 14:40:38 +0200 Subject: [PATCH 018/360] The 4.0 raketask is no longer needed and rebuilding of missing satellites is automatic. --- doc/raketasks/README.md | 1 - doc/raketasks/features.md | 36 ------------------------------------ 2 files changed, 37 deletions(-) delete mode 100644 doc/raketasks/features.md diff --git a/doc/raketasks/README.md b/doc/raketasks/README.md index 6be24f0102..b1c97c8223 100644 --- a/doc/raketasks/README.md +++ b/doc/raketasks/README.md @@ -1,6 +1,5 @@ + [Backup restore](backup_restore.md) + [Cleanup](cleanup.md) -+ [Features](features.md) + [Maintenance](maintenance.md) and self-checks + [User management](user_management.md) + [Web hooks](web_hooks.md) diff --git a/doc/raketasks/features.md b/doc/raketasks/features.md deleted file mode 100644 index 018817d219..0000000000 --- a/doc/raketasks/features.md +++ /dev/null @@ -1,36 +0,0 @@ -### Enable usernames and namespaces for user projects - -This command will enable the namespaces feature introduced in v4.0. It will move every project in its namespace folder. - -Note: - -* Because the **repository location will change**, you will need to **update all your git url's** to point to the new location. -* Username can be changed at [Profile / Account](/profile/account) - -**Example:** - -Old path: `git@example.org:myrepo.git` -New path: `git@example.org:username/myrepo.git` or `git@example.org:groupname/myrepo.git` - -``` -bundle exec rake gitlab:enable_namespaces RAILS_ENV=production -``` - - -### Rebuild project satellites - -This command will build missing satellites for projects. After this you will be able to **merge a merge request** via GitLab and use the **online editor**. - -``` -bundle exec rake gitlab:satellites:create RAILS_ENV=production -``` - -Example output: - -``` -Creating satellite for abcd.git -[git clone output] -Creating satellite for abcd2.git -[git clone output] -done -``` From 0957f341b173c95c48906d7545531042cfd39641 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Thu, 22 May 2014 15:18:28 +0200 Subject: [PATCH 019/360] Updates for the monthly release document. --- doc/release/monthly.md | 69 +++++++++++++++++++++++++++++++----------- 1 file changed, 51 insertions(+), 18 deletions(-) diff --git a/doc/release/monthly.md b/doc/release/monthly.md index 6c788e850e..66b3bfcfd6 100644 --- a/doc/release/monthly.md +++ b/doc/release/monthly.md @@ -100,12 +100,34 @@ Tweet about the RC release: > GitLab x.x.x.rc1 is out. This is a release candidate intended for testing only. Please let us know if you find regressions. -### **8. Update Cloud** +### **8. Update gitlab.com** -Merge the RC1 code into Cloud. Once the build is green, deploy in the morning. +Merge the RC1 code into gitlab.com. Once the build is green, deploy in the morning. It is important to do this as soon as possible, so we can catch any errors before we release the full version. +# **21st - Preparation ** + +### **1. Prepare the blog post** + +* Check the changelog of CE and EE for important changes. Based on [release blog template](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/doc/release_blog_template.md) fill in the important information. +* Create a WIP MR for the blog post and cc the team so everyone can give feedback. +* Ask Dmitriy to add screenshots to the WIP MR. +* Decide with team who will be the MVP user. +* Add a note if there are security fixes: This release fixes an important security issue and we advise everyone to upgrade as soon as possible. + +### **2. Q&A** + +Create issue on dev.gitlab.org gitlab repository, named "GitLab X.X release" in order to keep track of the progress. + +Use the omnibus packages or cookbook to test using [this guide](https://dev.gitlab.org/gitlab/gitlab-ee/blob/master/doc/release/manual_testing.md). + +**NOTE** Upgrader can only be tested when tags are pushed to all repositories. Do not forget to confirm it is working before releasing. Note that in the issue. + + +### **3. Fix anything coming out of the QA** + +Create an issue with description of a problem, if it is quick fix fix yourself otherwise contact the team for advice. # **22nd - Release CE and EE** @@ -127,27 +149,31 @@ git push x-x-stable ### **2. Build the Omnibus packages** [Follow this guide](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/release.md) -### **3. QA** -Use the omnibus packages to test using [this guide](https://dev.gitlab.org/gitlab/gitlab-ee/blob/master/doc/release/manual_testing.md) +### **3. Set VERSION to x.x.x and push** +Change the VERSION file in `master` branch of the CE repository and commit. +Cherry-pick into the `x-x-stable` branch of CE. -### **4. Fix anything coming out of the QA** +Change the VERSION file in `master branch of the EE repository and commit. +Cherry-pick into the `x-x-stable-ee` branch of EE. -### **5. Set VERSION to x.x.0** +### **4. Create annotated tag vx.x.x** + +In `x-x-stable` branch check for the sha1 of the commit with VERSION file changed. Tag that commit, -### **6. Create annotated tag vx.x.0** ``` -git tag -a vx.x.0 -m 'Version x.x.0' +git tag -a vx.x.0 -m 'Version x.x.0' xxxxx ``` -### **7. Push VERSION + Tag to master, merge into x-x-stable** +where `xxxxx` is sha1. + +### **5. Push the tag** + ``` -git push origin master +git push origin vx.x.0 ``` -Next, merge the VERSION into the x-x-stable branch. - -### **8. Push to remotes** +### **6. Push to remotes** For GitLab CE, push to dev, GitLab.com and GitHub. @@ -155,15 +181,22 @@ For GitLab EE, push to the subscribers repo. NOTE: You might not have the rights to push to master on dev. Ask Dmitriy. -### **9. Publish blog for new release** -* Mention what GitLab is on the second line: GitLab is open source software to collaborate on code. -* Select and thank the the Most Valuable Person (MVP) of this release. -* Add a note if there are security fixes: This release fixes an important security issue and we advise everyone to upgrade as soon as possible. +### **7. Publish blog for new release** -### **10. Tweet to blog** +Merge the [blog merge request](#1-prepare-the-blog-post) in `www-gitlab-com` repository. + +### **8. Tweet to blog** Send out a tweet to share the good news with the world. List the features in short and link to the blog post. +Proposed tweet for CE "GitLab X.X.X CE is released! It brings *** " + +Proposed tweet for EE "GitLab X.X.X EE is released! It brings *** " + # **23rd - Optional Patch Release** +# **24th - Update GitLab.com** + +Merge the stable release into gitlab.com. Once the build is green deploy the next morning. + # **25th - Release GitLab CI** From b6a88c78500d66aa2965259e7db2574b1818602c Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Thu, 22 May 2014 15:41:33 +0200 Subject: [PATCH 020/360] Update casing of gitlab.com. --- doc/release/monthly.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/release/monthly.md b/doc/release/monthly.md index 66b3bfcfd6..f0c1b8b3e8 100644 --- a/doc/release/monthly.md +++ b/doc/release/monthly.md @@ -100,9 +100,9 @@ Tweet about the RC release: > GitLab x.x.x.rc1 is out. This is a release candidate intended for testing only. Please let us know if you find regressions. -### **8. Update gitlab.com** +### **8. Update GitLab.com** -Merge the RC1 code into gitlab.com. Once the build is green, deploy in the morning. +Merge the RC1 code into GitLab.com. Once the build is green, deploy in the morning. It is important to do this as soon as possible, so we can catch any errors before we release the full version. @@ -197,6 +197,6 @@ Proposed tweet for EE "GitLab X.X.X EE is released! It brings *** Date: Mon, 19 May 2014 11:50:18 +0200 Subject: [PATCH 021/360] add newsletter to release doc Conflicts: doc/release/monthly.md --- doc/release/monthly.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/doc/release/monthly.md b/doc/release/monthly.md index f0c1b8b3e8..40cf47af64 100644 --- a/doc/release/monthly.md +++ b/doc/release/monthly.md @@ -193,6 +193,12 @@ Proposed tweet for CE "GitLab X.X.X CE is released! It brings *** " +### **9. Send out newsletter** + +In mailchimp replicate the former release newsletters to customers / newsletter subscribers (these are two separate things) and modify them accordingly. + +Include a link to the blog post and keep it short. + # **23rd - Optional Patch Release** # **24th - Update GitLab.com** From 3296fb9f3a30fab41bac61b2afbe689cfcbbd15f Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Thu, 22 May 2014 16:27:32 +0200 Subject: [PATCH 022/360] Add missing lines in update guide. --- doc/update/6.8-to-6.9.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/doc/update/6.8-to-6.9.md b/doc/update/6.8-to-6.9.md index a5e644b8a0..4a3e45ae5e 100644 --- a/doc/update/6.8-to-6.9.md +++ b/doc/update/6.8-to-6.9.md @@ -52,6 +52,12 @@ sudo -u git -H bundle install --without development test postgres --deployment # PostgreSQL installations (note: the line below states '--without ... mysql') sudo -u git -H bundle install --without development test mysql --deployment + +# Run database migrations +sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production + +# Clean up assets and cache +sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production ``` ### 5. Update config files From 74079fe2369c20767cb6c639eec1886c9822fefc Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 22 May 2014 18:19:50 +0300 Subject: [PATCH 023/360] Fix scroll to highlighted line. Replace scrollTO js file with gem Signed-off-by: Dmitriy Zaporozhets --- Gemfile | 1 + Gemfile.lock | 3 + app/assets/javascripts/application.js.coffee | 2 +- app/assets/javascripts/blob.js.coffee | 2 +- vendor/assets/javascripts/jquery.scrollto.js | 225 ------------------- 5 files changed, 6 insertions(+), 227 deletions(-) delete mode 100644 vendor/assets/javascripts/jquery.scrollto.js diff --git a/Gemfile b/Gemfile index 7ff7515143..f7e3fe7b6d 100644 --- a/Gemfile +++ b/Gemfile @@ -163,6 +163,7 @@ gem 'select2-rails' gem 'jquery-atwho-rails', "~> 0.3.3" gem "jquery-rails" gem "jquery-ui-rails" +gem "jquery-scrollto-rails" gem "raphael-rails", "~> 2.1.2" gem 'bootstrap-sass', '~> 3.0' gem "font-awesome-rails", '~> 3.2' diff --git a/Gemfile.lock b/Gemfile.lock index f5f31105e1..86c752505b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -250,6 +250,8 @@ GEM jquery-rails (3.1.0) railties (>= 3.0, < 5.0) thor (>= 0.14, < 2.0) + jquery-scrollto-rails (1.4.3) + railties (> 3.1, < 5.0) jquery-turbolinks (2.0.1) railties (>= 3.1.0) turbolinks @@ -607,6 +609,7 @@ DEPENDENCIES jasmine (= 2.0.0.rc5) jquery-atwho-rails (~> 0.3.3) jquery-rails + jquery-scrollto-rails jquery-turbolinks jquery-ui-rails kaminari (~> 0.15.1) diff --git a/app/assets/javascripts/application.js.coffee b/app/assets/javascripts/application.js.coffee index a22ff6dec3..587e51a7a8 100644 --- a/app/assets/javascripts/application.js.coffee +++ b/app/assets/javascripts/application.js.coffee @@ -13,7 +13,7 @@ #= require jquery.history #= require jquery.waitforimages #= require jquery.atwho -#= require jquery.scrollto +#= require jquery.scrollTo #= require jquery.blockUI #= require turbolinks #= require jquery.turbolinks diff --git a/app/assets/javascripts/blob.js.coffee b/app/assets/javascripts/blob.js.coffee index 584f6faea1..9db919e5a6 100644 --- a/app/assets/javascripts/blob.js.coffee +++ b/app/assets/javascripts/blob.js.coffee @@ -26,7 +26,7 @@ class BlobView unless isNaN first_line $("#tree-content-holder .highlight .line").removeClass("hll") $("#LC#{line}").addClass("hll") for line in [first_line..last_line] - $("#L#{first_line}").ScrollTo() unless e? + $.scrollTo("#L#{first_line}") unless e? # parse selected lines from hash # always return first and last line (initialized to NaN) diff --git a/vendor/assets/javascripts/jquery.scrollto.js b/vendor/assets/javascripts/jquery.scrollto.js deleted file mode 100644 index 7f10b7f108..0000000000 --- a/vendor/assets/javascripts/jquery.scrollto.js +++ /dev/null @@ -1,225 +0,0 @@ -/** - * @depends jquery - * @name jquery.scrollto - * @package jquery-scrollto {@link http://balupton.com/projects/jquery-scrollto} - */ - -/** - * jQuery Aliaser - */ -(function(window,undefined){ - // Prepare - var jQuery, $, ScrollTo; - jQuery = $ = window.jQuery; - - /** - * jQuery ScrollTo (balupton edition) - * @version 1.2.0 - * @date July 9, 2012 - * @since 0.1.0, August 27, 2010 - * @package jquery-scrollto {@link http://balupton.com/projects/jquery-scrollto} - * @author Benjamin "balupton" Lupton {@link http://balupton.com} - * @copyright (c) 2010 Benjamin Arthur Lupton {@link http://balupton.com} - * @license MIT License {@link http://creativecommons.org/licenses/MIT/} - */ - ScrollTo = $.ScrollTo = $.ScrollTo || { - /** - * The Default Configuration - */ - config: { - duration: 400, - easing: 'swing', - callback: undefined, - durationMode: 'each', - offsetTop: 0, - offsetLeft: 0 - }, - - /** - * Configure ScrollTo - */ - configure: function(options){ - // Apply Options to Config - $.extend(ScrollTo.config, options||{}); - - // Chain - return this; - }, - - /** - * Perform the Scroll Animation for the Collections - * We use $inline here, so we can determine the actual offset start for each overflow:scroll item - * Each collection is for each overflow:scroll item - */ - scroll: function(collections, config){ - // Prepare - var collection, $container, container, $target, $inline, position, - containerScrollTop, containerScrollLeft, - containerScrollTopEnd, containerScrollLeftEnd, - startOffsetTop, targetOffsetTop, targetOffsetTopAdjusted, - startOffsetLeft, targetOffsetLeft, targetOffsetLeftAdjusted, - scrollOptions, - callback; - - // Determine the Scroll - collection = collections.pop(); - $container = collection.$container; - container = $container.get(0); - $target = collection.$target; - - // Prepare the Inline Element of the Container - $inline = $('').css({ - 'position': 'absolute', - 'top': '0px', - 'left': '0px' - }); - position = $container.css('position'); - - // Insert the Inline Element of the Container - $container.css('position','relative'); - $inline.appendTo($container); - - // Determine the top offset - startOffsetTop = $inline.offset().top; - targetOffsetTop = $target.offset().top; - targetOffsetTopAdjusted = targetOffsetTop - startOffsetTop - parseInt(config.offsetTop,10); - - // Determine the left offset - startOffsetLeft = $inline.offset().left; - targetOffsetLeft = $target.offset().left; - targetOffsetLeftAdjusted = targetOffsetLeft - startOffsetLeft - parseInt(config.offsetLeft,10); - - // Determine current scroll positions - containerScrollTop = container.scrollTop; - containerScrollLeft = container.scrollLeft; - - // Reset the Inline Element of the Container - $inline.remove(); - $container.css('position',position); - - // Prepare the scroll options - scrollOptions = {}; - - // Prepare the callback - callback = function(event){ - // Check - if ( collections.length === 0 ) { - // Callback - if ( typeof config.callback === 'function' ) { - config.callback.apply(this,[event]); - } - } - else { - // Recurse - ScrollTo.scroll(collections,config); - } - // Return true - return true; - }; - - // Handle if we only want to scroll if we are outside the viewport - if ( config.onlyIfOutside ) { - // Determine current scroll positions - containerScrollTopEnd = containerScrollTop + $container.height(); - containerScrollLeftEnd = containerScrollLeft + $container.width(); - - // Check if we are in the range of the visible area of the container - if ( containerScrollTop < targetOffsetTopAdjusted && targetOffsetTopAdjusted < containerScrollTopEnd ) { - targetOffsetTopAdjusted = containerScrollTop; - } - if ( containerScrollLeft < targetOffsetLeftAdjusted && targetOffsetLeftAdjusted < containerScrollLeftEnd ) { - targetOffsetLeftAdjusted = containerScrollLeft; - } - } - - // Determine the scroll options - if ( targetOffsetTopAdjusted !== containerScrollTop ) { - scrollOptions.scrollTop = targetOffsetTopAdjusted; - } - if ( targetOffsetLeftAdjusted !== containerScrollLeft ) { - scrollOptions.scrollLeft = targetOffsetLeftAdjusted; - } - - // Perform the scroll - if ( $.browser.safari && container === document.body ) { - window.scrollTo(scrollOptions.scrollLeft, scrollOptions.scrollTop); - callback(); - } - else if ( scrollOptions.scrollTop || scrollOptions.scrollLeft ) { - $container.animate(scrollOptions, config.duration, config.easing, callback); - } - else { - callback(); - } - - // Return true - return true; - }, - - /** - * ScrollTo the Element using the Options - */ - fn: function(options){ - // Prepare - var collections, config, $container, container; - collections = []; - - // Prepare - var $target = $(this); - if ( $target.length === 0 ) { - // Chain - return this; - } - - // Handle Options - config = $.extend({},ScrollTo.config,options); - - // Fetch - $container = $target.parent(); - container = $container.get(0); - - // Cycle through the containers - while ( ($container.length === 1) && (container !== document.body) && (container !== document) ) { - // Check Container for scroll differences - var scrollTop, scrollLeft; - scrollTop = $container.css('overflow-y') !== 'visible' && container.scrollHeight !== container.clientHeight; - scrollLeft = $container.css('overflow-x') !== 'visible' && container.scrollWidth !== container.clientWidth; - if ( scrollTop || scrollLeft ) { - // Push the Collection - collections.push({ - '$container': $container, - '$target': $target - }); - // Update the Target - $target = $container; - } - // Update the Container - $container = $container.parent(); - container = $container.get(0); - } - - // Add the final collection - collections.push({ - '$container': $( - ($.browser.msie || $.browser.mozilla) ? 'html' : 'body' - ), - '$target': $target - }); - - // Adjust the Config - if ( config.durationMode === 'all' ) { - config.duration /= collections.length; - } - - // Handle - ScrollTo.scroll(collections,config); - - // Chain - return this; - } - }; - - // Apply our jQuery Prototype Function - $.fn.ScrollTo = $.ScrollTo.fn; - -})(window); From ab126c806884f26a42d515b573ce202c49dfafcb Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Thu, 22 May 2014 17:20:50 +0200 Subject: [PATCH 024/360] Add proposed email for mailchimp. --- doc/release/monthly.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/release/monthly.md b/doc/release/monthly.md index 40cf47af64..ed580f666a 100644 --- a/doc/release/monthly.md +++ b/doc/release/monthly.md @@ -199,6 +199,8 @@ In mailchimp replicate the former release newsletters to customers / newsletter Include a link to the blog post and keep it short. +Proposed email for CE: "We have released a new version of GitLab Community Edition and its packages. See our blog post() for more information." + # **23rd - Optional Patch Release** # **24th - Update GitLab.com** From b9d1fc2f3bdebe541795d6ef6e94da9e98b043d3 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 22 May 2014 18:31:22 +0300 Subject: [PATCH 025/360] Improve protected branch explanation Signed-off-by: Dmitriy Zaporozhets --- app/views/projects/protected_branches/index.html.haml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/views/projects/protected_branches/index.html.haml b/app/views/projects/protected_branches/index.html.haml index 4a6e8943a9..e9f67b671b 100644 --- a/app/views/projects/protected_branches/index.html.haml +++ b/app/views/projects/protected_branches/index.html.haml @@ -4,12 +4,12 @@ = render "projects/branches/filter" .col-md-9 .bs-callout.bs-callout-info - %p Protected branches designed to prevent push for all except #{link_to "masters", help_permissions_path, class: "vlink"}. - %p This ability allows: + %p Protected branches designed to %ul - %li keep stable branches secured - %li forced code review before merge to protected branches - %li prevents branch from force push + %li prevent push for all except #{link_to "masters", help_permissions_path, class: "vlink"}. + %li prevent branch from force push + %li prevent branch from removal + %p This ability allows to keep stable branches secured and force code review before merge to protected branches %p Read more about project permissions #{link_to "here", help_permissions_path, class: "underlined-link"} - if can? current_user, :admin_project, @project From babfc068ae2747ce578a90c7cb22fd88f03349bd Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 22 May 2014 20:34:03 +0300 Subject: [PATCH 026/360] Lets start 7.0 development Signed-off-by: Dmitriy Zaporozhets --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 97f5781528..2e45d00c58 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -6.9.0 +7.0.0.pre From 8bf7b62e8169fc1e2b9cf66edd9a66232f285270 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 22 May 2014 20:40:25 +0300 Subject: [PATCH 027/360] First entries for 7.0 CHANGELOG Signed-off-by: Dmitriy Zaporozhets --- CHANGELOG | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index aaf1879dcc..ca0b96b840 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,8 @@ +v 7.0.0 + - The CPU no longer overheats when you hold down the spacebar + - Improve edit file UI + - Add ability to upload group avatar when create + v 6.9.0 - Store Rails cache data in the Redis `cache:gitlab` namespace - Adjust MySQL limits for existing installations From b192aa5694b8df233124c4be58802a9100b0c321 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 22 May 2014 22:34:34 +0300 Subject: [PATCH 028/360] Fix tests Signed-off-by: Dmitriy Zaporozhets --- app/controllers/projects_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index ebb8a90c63..e356d09a27 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -190,6 +190,6 @@ class ProjectsController < ApplicationController end def sorted(users) - users.uniq.sort_by(&:username).map { |user| { username: user.username, name: user.name } } + users.uniq.compact.sort_by(&:username).map { |user| { username: user.username, name: user.name } } end end From ebe2a34a6b81f468187a8049ddae8242b00d1ebe Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 22 May 2014 22:44:32 +0300 Subject: [PATCH 029/360] Add missing feature flag to mr notes spec Signed-off-by: Dmitriy Zaporozhets --- spec/features/notes_on_merge_requests_spec.rb | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/spec/features/notes_on_merge_requests_spec.rb b/spec/features/notes_on_merge_requests_spec.rb index cfb6deb183..45aebf128c 100644 --- a/spec/features/notes_on_merge_requests_spec.rb +++ b/spec/features/notes_on_merge_requests_spec.rb @@ -132,7 +132,7 @@ describe "On a merge request", js: true, feature: true do end end -describe "On a merge request diff", js: true do +describe "On a merge request diff", js: true, feature: true do let(:merge_request) { create(:merge_request, :with_diffs, :simple) } let(:project) { merge_request.source_project } @@ -210,9 +210,3 @@ describe "On a merge request diff", js: true do end end end - -describe "On merge request discussion", js: true do - describe "with merge request diff note" - describe "with commit note" - describe "with commit diff note" -end From 696b9903f08011e37811dc8b8ff4f7da77201d13 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 23 May 2014 09:47:58 +0300 Subject: [PATCH 030/360] Fix spinach tests Signed-off-by: Dmitriy Zaporozhets --- features/steps/group/group.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/steps/group/group.rb b/features/steps/group/group.rb index 820d0ef2a1..5e0c71581f 100644 --- a/features/steps/group/group.rb +++ b/features/steps/group/group.rb @@ -89,7 +89,7 @@ class Groups < Spinach::FeatureSteps Then 'I should see newly created group "Samurai"' do page.should have_content "Samurai" page.should have_content "Tokugawa Shogunate" - page.should have_content "You will only see events from projects in this group" + page.should have_content "Currently you are only seeing events from the" end And 'I change group "Owned" name to "new-name"' do From 6a85cdf1627629ecaa762fa60a7abdbd092cc20a Mon Sep 17 00:00:00 2001 From: Earle Bunao & Neil Calabroso Date: Fri, 23 May 2014 16:22:00 +0800 Subject: [PATCH 031/360] Implements drag and drop upload in creating issues --- Gemfile | 3 + Gemfile.lock | 3 + app/assets/javascripts/application.js.coffee | 1 + .../behaviors/toggler_behavior.coffee | 2 +- .../javascripts/markdown_area.js.coffee | 85 ++++++++++++++++++ app/assets/stylesheets/application.scss | 1 + app/assets/stylesheets/behaviors.scss | 13 ++- .../stylesheets/generic/markdown_area.scss | 58 ++++++++++++ app/assets/stylesheets/sections/notes.scss | 32 ++++--- app/controllers/files_controller.rb | 1 - app/controllers/projects/issues_controller.rb | 4 +- app/controllers/projects_controller.rb | 20 +++++ app/models/issue.rb | 4 + app/uploaders/file_uploader.rb | 41 +++++++++ app/views/layouts/admin.html.haml | 1 + app/views/layouts/projects.html.haml | 1 + app/views/projects/issues/_form.html.haml | 14 +-- app/views/projects/issues/show.html.haml | 2 +- .../projects/merge_requests/_form.html.haml | 10 ++- .../merge_requests/_new_submit.html.haml | 10 ++- app/views/projects/milestones/_form.html.haml | 10 ++- app/views/projects/notes/_form.html.haml | 25 +++--- app/views/projects/wikis/_form.html.haml | 13 ++- config/routes.rb | 3 +- spec/controllers/commits_controller_spec.rb | 3 +- spec/controllers/projects_controller_spec.rb | 44 +++++++++ spec/factories.rb | 2 +- spec/fixtures/banana_sample.gif | Bin 0 -> 71759 bytes spec/fixtures/doc_sample.txt | 3 + spec/fixtures/rails_sample.jpg | Bin 0 -> 35255 bytes 30 files changed, 363 insertions(+), 46 deletions(-) create mode 100644 app/assets/javascripts/markdown_area.js.coffee create mode 100644 app/assets/stylesheets/generic/markdown_area.scss create mode 100644 app/uploaders/file_uploader.rb create mode 100644 spec/controllers/projects_controller_spec.rb create mode 100644 spec/fixtures/banana_sample.gif create mode 100644 spec/fixtures/doc_sample.txt create mode 100644 spec/fixtures/rails_sample.jpg diff --git a/Gemfile b/Gemfile index f7e3fe7b6d..9775334a7c 100644 --- a/Gemfile +++ b/Gemfile @@ -69,6 +69,9 @@ gem "haml-rails" # Files attachments gem "carrierwave" +# Drag and Drop UI +gem 'dropzonejs-rails' + # for aws storage gem "fog", "~> 1.14", group: :aws gem "unf", group: :aws diff --git a/Gemfile.lock b/Gemfile.lock index 86c752505b..3d4a673af1 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -103,6 +103,8 @@ GEM diffy (3.0.3) docile (1.1.1) dotenv (0.9.0) + dropzonejs-rails (0.4.14) + rails (> 3.1) email_spec (1.5.0) launchy (~> 2.1) mail (~> 2.2) @@ -579,6 +581,7 @@ DEPENDENCIES devise (= 3.0.4) devise-async (= 0.8.0) diffy (~> 3.0.3) + dropzonejs-rails email_spec email_validator (~> 1.4.0) enumerize diff --git a/app/assets/javascripts/application.js.coffee b/app/assets/javascripts/application.js.coffee index 587e51a7a8..35e4355466 100644 --- a/app/assets/javascripts/application.js.coffee +++ b/app/assets/javascripts/application.js.coffee @@ -29,6 +29,7 @@ #= require underscore #= require nprogress #= require nprogress-turbolinks +#= require dropzone #= require_tree . window.slugify = (text) -> diff --git a/app/assets/javascripts/behaviors/toggler_behavior.coffee b/app/assets/javascripts/behaviors/toggler_behavior.coffee index d06cb116df..8ac5bfe95d 100644 --- a/app/assets/javascripts/behaviors/toggler_behavior.coffee +++ b/app/assets/javascripts/behaviors/toggler_behavior.coffee @@ -1,6 +1,6 @@ $ -> $("body").on "click", ".js-toggler-target", -> - container = $(@).closest(".js-toggler-container") + container = $(".notes-container") container.toggleClass("on") # Toggle button. Show/hide content inside parent container. diff --git a/app/assets/javascripts/markdown_area.js.coffee b/app/assets/javascripts/markdown_area.js.coffee new file mode 100644 index 0000000000..def5d12a82 --- /dev/null +++ b/app/assets/javascripts/markdown_area.js.coffee @@ -0,0 +1,85 @@ +formatLink = (str) -> + "![" + str.alt + "](" + str.url + ")" + +$(document).ready -> + alertClass = "alert alert-danger alert-dismissable div-dropzone-alert" + alertAttr = "class=\"close\" data-dismiss=\"alert\"" + "aria-hidden=\"true\"" + divHover = "
" + divSpinner = "
" + divAlert = "
" + iconPicture = "" + iconSpinner = "" + btnAlert = "" + project_image_path_upload = window.project_image_path_upload or null + + $("textarea.markdown-area").wrap "
" + + $(".div-dropzone").parent().addClass "div-dropzone-wrapper" + + $(".div-dropzone").append divHover + $(".div-dropzone-hover").append iconPicture + $(".div-dropzone").append divSpinner + $(".div-dropzone-spinner").append iconSpinner + + + dropzone = $(".div-dropzone").dropzone( + url: project_image_path_upload + dictDefaultMessage: "" + clickable: true + paramName: "markdown_img" + maxFilesize: 10 + uploadMultiple: false + acceptedFiles: "image/jpg,image/jpeg,image/gif,image/png" + headers: + "X-CSRF-Token": $("meta[name=\"csrf-token\"]").attr("content") + + previewContainer: false + + processing: -> + $(".div-dropzone-alert").alert "close" + + dragover: -> + $(".div-dropzone > textarea").addClass "div-dropzone-focus" + $(".div-dropzone-hover").css "opacity", 0.7 + return + + dragleave: -> + $(".div-dropzone > textarea").removeClass "div-dropzone-focus" + $(".div-dropzone-hover").css "opacity", 0 + return + + drop: -> + $(".div-dropzone > textarea").removeClass "div-dropzone-focus" + $(".div-dropzone-hover").css "opacity", 0 + $(".div-dropzone > textarea").focus() + return + + success: (header, response) -> + child = $(dropzone[0]).children("textarea") + $(child).val $(child).val() + formatLink(response.link) + "\n" + return + + error: (temp, errorMessage) -> + checkIfMsgExists = $(".error-alert").children().length + if checkIfMsgExists is 0 + $(".error-alert").append divAlert + $(".div-dropzone-alert").append btnAlert + errorMessage + return + + sending: -> + $(".div-dropzone-spinner").css "opacity", 0.7 + return + + complete: -> + $(".dz-preview").remove() + $(".markdown-area").trigger "input" + $(".div-dropzone-spinner").css "opacity", 0 + return + ) + + $(".markdown-selector").click (e) -> + e.preventDefault() + $(".div-dropzone").click() + return + + return \ No newline at end of file diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index c53873f95a..0b372a87a1 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -10,6 +10,7 @@ *= require_self *= require nprogress *= require nprogress-bootstrap + *= require dropzone/basic */ @import "main/*"; diff --git a/app/assets/stylesheets/behaviors.scss b/app/assets/stylesheets/behaviors.scss index 3fdc20485f..64e3c8d9ac 100644 --- a/app/assets/stylesheets/behaviors.scss +++ b/app/assets/stylesheets/behaviors.scss @@ -5,10 +5,19 @@ .js-details-container.open .content { display: block; } .js-details-container.open .content.hide { display: none; } - // Toggler //-------- -.js-toggler-container .turn-on { display: inherit; } +.write-preview-btn .turn-on { display: inherit; } +.write-preview-btn .turn-off { display: none; } + .js-toggler-container .turn-off { display: none; } .js-toggler-container.on .turn-on { display: none; } .js-toggler-container.on .turn-off { display: inherit; } + +.js-toggler-container.on ~ .note-form-actions { + .write-preview-btn .turn-on { display: none; } +} + +.js-toggler-container.on ~ .note-form-actions { + .write-preview-btn .turn-off { display: inherit; } +} diff --git a/app/assets/stylesheets/generic/markdown_area.scss b/app/assets/stylesheets/generic/markdown_area.scss new file mode 100644 index 0000000000..a1fe18b02f --- /dev/null +++ b/app/assets/stylesheets/generic/markdown_area.scss @@ -0,0 +1,58 @@ +.div-dropzone-wrapper { + .div-dropzone { + position: relative; + padding: 0; + border: 0; + margin-bottom: 5px; + + .div-dropzone-focus { + border-color: #66afe9 !important; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6) !important; + outline: 0 !important; + } + + .div-dropzone-hover { + position: absolute; + top: 50%; + left: 50%; + margin-top: -0.5em; + margin-left: -0.6em; + opacity: 0; + font-size: 50px; + transition: opacity 200ms ease-in-out; + } + + .div-dropzone-spinner { + position: absolute; + top: 100%; + left: 100%; + margin-top: -1.1em; + margin-left: -1.1em; + opacity: 0; + font-size: 30px; + transition: opacity 200ms ease-in-out; + } + + .div-dropzone-icon { + display: block; + text-align: center; + font-size: inherit; + } + + .dz-preview { + display: none; + } + } + + .hint { + float: left; + padding: 0; + margin: 0; + } +} + +.div-dropzone-alert { + margin-top: 5px; + margin-bottom: 0; + transition: opacity 200ms ease-in-out; +} diff --git a/app/assets/stylesheets/sections/notes.scss b/app/assets/stylesheets/sections/notes.scss index 7e56781f56..755295be1f 100644 --- a/app/assets/stylesheets/sections/notes.scss +++ b/app/assets/stylesheets/sections/notes.scss @@ -272,21 +272,16 @@ ul.notes { margin-bottom: 0; } .note_text_and_preview { - // makes the "absolute" position for links relative to this - position: relative; - - // preview/edit buttons - > a { - position: absolute; - right: 5px; - bottom: -60px; - } .note_preview { background: #f5f5f5; border: 1px solid #ddd; @include border-radius(4px); min-height: 80px; padding: 4px 6px; + + > p { + overflow-x: auto; + } } .note_text { border: 1px solid #DDD; @@ -310,7 +305,6 @@ ul.notes { float: none; } - .common-note-form { margin: 0; background: #F9F9F9; @@ -318,7 +312,6 @@ ul.notes { border: 1px solid #DDD; } - .note-form-actions { background: #F9F9F9; height: 45px; @@ -333,6 +326,18 @@ ul.notes { .js-notify-commit-author { float: left; } + + .write-preview-btn { + // makes the "absolute" position for links relative to this + position: relative; + + // preview/edit buttons + > a { + position: absolute; + right: 5px; + top: 8px; + } + } } .note-edit-form { @@ -367,3 +372,8 @@ ul.notes { .parallel-comment { padding: 6px; } + +.error-alert > .alert { + margin-top: 5px; + margin-bottom: 5px; +} diff --git a/app/controllers/files_controller.rb b/app/controllers/files_controller.rb index bf30de565e..7937454810 100644 --- a/app/controllers/files_controller.rb +++ b/app/controllers/files_controller.rb @@ -14,4 +14,3 @@ class FilesController < ApplicationController end end end - diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb index 4e7a716bfe..6eec2094f8 100644 --- a/app/controllers/projects/issues_controller.rb +++ b/app/controllers/projects/issues_controller.rb @@ -69,7 +69,9 @@ class Projects::IssuesController < Projects::ApplicationController render :new end end - format.js + format.js do |format| + @link = @issue.attachment.url.to_js + end end end diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index e356d09a27..c15205fb68 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -162,8 +162,28 @@ class ProjectsController < ApplicationController end end + def upload_image + uploader = FileUploader.new('uploads', upload_path, accepted_images) + alt = params['markdown_img'].original_filename + uploader.store!(params['markdown_img']) + link = { 'alt' => File.basename(alt, '.*'), + 'url' => File.join(root_url, uploader.url) } + respond_to do |format| + format.json { render json: { link: link } } + end + end + private + def upload_path + base_dir = FileUploader.generate_dir + File.join(repository.path_with_namespace, base_dir) + end + + def accepted_images + %w(png jpg jpeg gif) + end + def set_title @title = 'New Project' end diff --git a/app/models/issue.rb b/app/models/issue.rb index 16d51345e5..f0c2e55227 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -15,8 +15,12 @@ # milestone_id :integer # state :string(255) # iid :integer +# attachment :string(255) # +require 'carrierwave/orm/activerecord' +require 'file_size_validator' + class Issue < ActiveRecord::Base include Issuable include InternalId diff --git a/app/uploaders/file_uploader.rb b/app/uploaders/file_uploader.rb new file mode 100644 index 0000000000..cbc9271ac1 --- /dev/null +++ b/app/uploaders/file_uploader.rb @@ -0,0 +1,41 @@ +# encoding: utf-8 +class FileUploader < CarrierWave::Uploader::Base + storage :file + + def initialize(base_dir, path = '', allowed_extensions = nil) + @base_dir = base_dir + @path = path + @allowed_extensions = allowed_extensions + end + + def base_dir + @base_dir + end + + def store_dir + File.join(@base_dir, @path) + end + + def cache_dir + File.join(@base_dir, 'tmp', @path) + end + + def extension_white_list + @allowed_extensions + end + + def store!(file) + file.original_filename = self.class.generate_filename(file) + super + end + + def self.generate_filename(file) + original_filename = File.basename(file.original_filename, '.*') + extension = File.extname(file.original_filename) + new_filename = Digest::MD5.hexdigest(original_filename) + extension + end + + def self.generate_dir + SecureRandom.hex(5) + end +end diff --git a/app/views/layouts/admin.html.haml b/app/views/layouts/admin.html.haml index 53e0dbaef9..c7a827555a 100644 --- a/app/views/layouts/admin.html.haml +++ b/app/views/layouts/admin.html.haml @@ -10,3 +10,4 @@ .container .content= yield + = yield :embedded_scripts \ No newline at end of file diff --git a/app/views/layouts/projects.html.haml b/app/views/layouts/projects.html.haml index 3ae4961b13..11c815c52a 100644 --- a/app/views/layouts/projects.html.haml +++ b/app/views/layouts/projects.html.haml @@ -14,3 +14,4 @@ .container .content= yield + = yield :embedded_scripts \ No newline at end of file diff --git a/app/views/projects/issues/_form.html.haml b/app/views/projects/issues/_form.html.haml index 84703229fe..49d1a87743 100644 --- a/app/views/projects/issues/_form.html.haml +++ b/app/views/projects/issues/_form.html.haml @@ -5,6 +5,7 @@ - contribution_guide_url = project_blob_path(@project, tree_join(@repository.root_ref, @repository.contribution_guide.name)) .alert.alert-info.col-sm-10.col-sm-offset-2 ="Please review the #{link_to "guidelines for contribution", contribution_guide_url} to this repository.".html_safe + = form_for [@project, @issue], html: { class: 'form-horizontal issue-form' } do |f| -if @issue.errors.any? .alert.alert-danger @@ -19,8 +20,12 @@ .form-group = f.label :description, 'Description', class: 'control-label' .col-sm-10 - = f.text_area :description, class: "form-control js-gfm-input", rows: 14 - %p.hint Issues are parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}. + = f.text_area :description, class: 'form-control js-gfm-input markdown-area', rows: 14 + .col-sm-12.hint + .pull-left Issues are parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}. + .pull-right Attach images (JPG, PNG, GIF) by dragging & dropping or #{link_to "selecting them", '#', class: 'markdown-selector' }. + .clearfix + .error-alert %hr .form-group .issue-assignee @@ -57,9 +62,6 @@ - cancel_path = @issue.new_record? ? project_issues_path(@project) : project_issue_path(@project, @issue) = link_to "Cancel", cancel_path, class: 'btn btn-cancel' - - - :javascript $("#issue_label_list") .bind( "keydown", function( event ) { @@ -94,3 +96,5 @@ $('#issue_assignee_id').val("#{current_user.id}").trigger("change"); e.preventDefault(); }); + + window.project_image_path_upload = "#{upload_image_project_path @project}"; diff --git a/app/views/projects/issues/show.html.haml b/app/views/projects/issues/show.html.haml index b6d3a8edf4..2c816e788d 100644 --- a/app/views/projects/issues/show.html.haml +++ b/app/views/projects/issues/show.html.haml @@ -73,4 +73,4 @@ = label.name   -.voting_notes#notes= render "projects/notes/notes_with_form" +.voting_notes#notes= render "projects/notes/notes_with_form" \ No newline at end of file diff --git a/app/views/projects/merge_requests/_form.html.haml b/app/views/projects/merge_requests/_form.html.haml index 290a15e266..3088f0cf86 100644 --- a/app/views/projects/merge_requests/_form.html.haml +++ b/app/views/projects/merge_requests/_form.html.haml @@ -22,8 +22,12 @@ .form-group = f.label :description, "Description", class: 'control-label' .col-sm-10 - = f.text_area :description, class: "form-control js-gfm-input", rows: 14 - %p.hint Description is parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}. + = f.text_area :description, class: "form-control js-gfm-input markdown-area", rows: 14 + .col-sm-12.hint + .pull-left Description is parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}. + .pull-right Attach images (JPG, PNG, GIF) by dragging & dropping or #{link_to "selecting them", '#', class: 'markdown-selector' }. + .clearfix + .error-alert %hr .form-group .issue-assignee @@ -98,3 +102,5 @@ return false; } }); + + window.project_image_path_upload = "#{upload_image_project_path @project}"; diff --git a/app/views/projects/merge_requests/_new_submit.html.haml b/app/views/projects/merge_requests/_new_submit.html.haml index b5479be708..dc41ef8135 100644 --- a/app/views/projects/merge_requests/_new_submit.html.haml +++ b/app/views/projects/merge_requests/_new_submit.html.haml @@ -23,8 +23,12 @@ .form-group .light = f.label :description, "Description" - = f.text_area :description, class: "form-control js-gfm-input", rows: 10 - %p.hint Description is parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}. + = f.text_area :description, class: "form-control js-gfm-input markdown-area", rows: 10 + .col-sm-12.hint + .pull-left Description is parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}. + .pull-right Attach images (JPG, PNG, GIF) by dragging & dropping or #{link_to "selecting them", '#', class: 'markdown-selector' }. + .clearfix + .error-alert .form-group .issue-assignee = f.label :assignee_id do @@ -80,3 +84,5 @@ $('#merge_request_assignee_id').val("#{current_user.id}").trigger("change"); e.preventDefault(); }); + + window.project_image_path_upload = "#{upload_image_project_path @project}"; diff --git a/app/views/projects/milestones/_form.html.haml b/app/views/projects/milestones/_form.html.haml index d770bb5b37..7e0fd19d0a 100644 --- a/app/views/projects/milestones/_form.html.haml +++ b/app/views/projects/milestones/_form.html.haml @@ -21,8 +21,12 @@ .form-group = f.label :description, "Description", class: "control-label" .col-sm-10 - = f.text_area :description, maxlength: 2000, class: "form-control", rows: 10 - %p.hint Milestones are parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}. + = f.text_area :description, maxlength: 2000, class: "form-control markdown-area", rows: 10 + .hint + .pull-left Milestones are parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}. + .pull-left Attach images (JPG, PNG, GIF) by dragging & dropping or #{link_to "selecting them", '#', class: 'markdown-selector' }. + .clearfix + .error-alert .col-md-6 .form-group = f.label :due_date, "Due Date", class: "control-label" @@ -45,3 +49,5 @@ dateFormat: "yy-mm-dd", onSelect: function(dateText, inst) { $("#milestone_due_date").val(dateText) } }).datepicker("setDate", $.datepicker.parseDate('yy-mm-dd', $('#milestone_due_date').val())); + + window.project_image_path_upload = "#{upload_image_project_path @project}"; diff --git a/app/views/projects/notes/_form.html.haml b/app/views/projects/notes/_form.html.haml index 3db551e993..cadae9da80 100644 --- a/app/views/projects/notes/_form.html.haml +++ b/app/views/projects/notes/_form.html.haml @@ -5,20 +5,15 @@ = f.hidden_field :noteable_id = f.hidden_field :noteable_type - .note_text_and_preview.js-toggler-container - %a.btn.js-note-preview-button.js-toggler-target.turn-off{ href: "javascript:;", data: {url: preview_project_notes_path(@project)} } - %i.icon-eye-open - Preview - %a.btn.btn-primary.js-note-edit-button.js-toggler-target.turn-off{ href: "javascript:;" } - %i.icon-edit - Write - - = f.text_area :note, size: 255, class: 'note_text js-note-text js-gfm-input turn-on' + .note_text_and_preview.js-toggler-container.notes-container + = f.text_area :note, size: 255, class: 'note_text js-note-text js-gfm-input turn-on markdown-area' .note_preview.js-note-preview.turn-off .hint - .pull-right Comments are parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}. + .pull-left Comments are parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}. + .pull-right Attach images (JPG, PNG, GIF) by dragging & dropping or #{link_to "selecting them", '#', class: 'markdown-selector' }. .clearfix + .error-alert .note-form-actions .buttons @@ -35,4 +30,14 @@ %span.file_name.js-attachment-filename File name... = f.file_field :attachment, class: "js-note-attachment-input hidden" + .write-preview-btn + %a.btn.js-note-preview-button.js-toggler-target.turn-off{ href: "javascript:;", data: {url: preview_project_notes_path(@project)} } + %i.icon-eye-open + Preview + %a.btn.btn-primary.js-note-edit-button.js-toggler-target.turn-off{ href: "javascript:;" } + %i.icon-edit + Write .clearfix + +:javascript + window.project_image_path_upload = "#{upload_image_project_path @project}"; diff --git a/app/views/projects/wikis/_form.html.haml b/app/views/projects/wikis/_form.html.haml index 0c2e33f228..a43e6f073e 100644 --- a/app/views/projects/wikis/_form.html.haml +++ b/app/views/projects/wikis/_form.html.haml @@ -15,7 +15,6 @@ .col-sm-2 .col-sm-10 %p.cgray - Wiki content is parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}. To link to a (new) page you can just type %code [Link Title](page-slug) \. @@ -23,8 +22,12 @@ .form-group = f.label :content, class: 'control-label' .col-sm-10 - = f.text_area :content, class: 'form-control js-gfm-input', rows: 18 - + = f.text_area :content, class: 'form-control js-gfm-input markdown-area', rows: 18 + .col-sm-12.hint + .pull-left Wiki content is parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}. + .pull-right Attach images (JPG, PNG, GIF) by dragging & dropping or #{link_to "selecting them", '#', class: 'markdown-selector' }. + .clearfix + .error-alert .form-group = f.label :commit_message, class: 'control-label' .col-sm-10= f.text_field :message, class: 'form-control', rows: 18 @@ -36,3 +39,7 @@ - else = f.submit 'Create page', class: "btn-create btn" = link_to "Cancel", project_wiki_path(@project, :home), class: "btn btn-cancel" + +:javascript + window.project_image_path_upload = "#{upload_image_project_path @project}"; + diff --git a/config/routes.rb b/config/routes.rb index 7641fe4308..da5a1ba7a8 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -136,8 +136,6 @@ Gitlab::Application.routes.draw do match "/u/:username" => "users#show", as: :user, constraints: { username: /.*/ }, via: :get - - # # Dashboard Area # @@ -178,6 +176,7 @@ Gitlab::Application.routes.draw do post :fork post :archive post :unarchive + post :upload_image get :autocomplete_sources get :import put :retry_import diff --git a/spec/controllers/commits_controller_spec.rb b/spec/controllers/commits_controller_spec.rb index fbf4f29acf..308cfa6921 100644 --- a/spec/controllers/commits_controller_spec.rb +++ b/spec/controllers/commits_controller_spec.rb @@ -6,8 +6,7 @@ describe Projects::CommitsController do before do sign_in(user) - - project.team << [user, :master] + project.creator = user end describe "GET show" do diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb new file mode 100644 index 0000000000..07ca8d2502 --- /dev/null +++ b/spec/controllers/projects_controller_spec.rb @@ -0,0 +1,44 @@ +require('spec_helper') + +describe ProjectsController do + let(:project) { create(:project) } + let(:user) { create(:user) } + let(:png) { fixture_file_upload(Rails.root + 'spec/fixtures/dk.png', 'image/png') } + let(:jpg) { fixture_file_upload(Rails.root + 'spec/fixtures/rails_sample.jpg', 'image/jpg') } + let(:gif) { fixture_file_upload(Rails.root + 'spec/fixtures/banana_sample.gif', 'image/gif') } + let(:txt) { fixture_file_upload(Rails.root + 'spec/fixtures/doc_sample.txt', 'text/plain') } + + describe "POST #upload_image" do + before do + sign_in(user) + end + + context "without params['markdown_img']" do + it "returns an error" do + post :upload_image, id: project.to_param + expect(response.status).to eq(404) + end + end + + context "with invalid file" do + before do + post :upload_image, id: project.to_param, markdown_img: @img + end + + it "returns an error" do + expect(response.status).to eq(404) + end + end + + context "with valid file" do + before do + post :upload_image, id: project.to_param, markdown_img: @img + end + + it "returns a content with original filename and new link." do + link = { alt: 'rails_sample', link: '' }.to_json + expect(response.body).to have_content link + end + end + end +end \ No newline at end of file diff --git a/spec/factories.rb b/spec/factories.rb index 148477d638..41cc99cbcb 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -201,7 +201,7 @@ FactoryGirl.define do end trait :with_attachment do - attachment { fixture_file_upload(Rails.root + "spec/fixtures/dk.png", "image/png") } + attachment { fixture_file_upload(Rails.root + "spec/fixtures/dk.png", "`/png") } end end diff --git a/spec/fixtures/banana_sample.gif b/spec/fixtures/banana_sample.gif new file mode 100644 index 0000000000000000000000000000000000000000..1322ac92d141f2240f3b68b1c4a10b5e18b49e2b GIT binary patch literal 71759 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 B?fU=# literal 0 HcmV?d00001 From 8ec38c17e2dfa103bfbcd50ef5481e6e2c1fd4ef Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 23 May 2014 13:19:39 +0300 Subject: [PATCH 032/360] Mention changes to protected branches Signed-off-by: Dmitriy Zaporozhets --- CHANGELOG | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index ca0b96b840..484d66daa5 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,6 +2,8 @@ v 7.0.0 - The CPU no longer overheats when you hold down the spacebar - Improve edit file UI - Add ability to upload group avatar when create + - Protected branch cannot be removed + - Developers can remove normal branches with UI v 6.9.0 - Store Rails cache data in the Redis `cache:gitlab` namespace From 8ae2d2152b197931725a3f4b9aa3697f37988c20 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 23 May 2014 13:22:10 +0300 Subject: [PATCH 033/360] Fix branch protection help doc Signed-off-by: Dmitriy Zaporozhets --- doc/permissions/permissions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/permissions/permissions.md b/doc/permissions/permissions.md index 9be6423f66..9a3dcefe56 100644 --- a/doc/permissions/permissions.md +++ b/doc/permissions/permissions.md @@ -24,7 +24,7 @@ If a user is a GitLab administrator they receive all permissions. |Manage issue tracker| ||✓|✓|✓| |Add new team members| |||✓|✓| |Push to protected branches| |||✓|✓| -|Remove protected branches| |||✓|✓| +|Enable/Disable branch protection| |||✓|✓| |Edit project| |||✓|✓| |Add Deploy Keys to project| |||✓|✓| |Configure Project Hooks| |||✓|✓| From a5e1624359d9960782cd76f24c6300aeb28a2746 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 23 May 2014 13:27:35 +0300 Subject: [PATCH 034/360] Redirect to tree view after branch created Signed-off-by: Dmitriy Zaporozhets --- app/controllers/projects/branches_controller.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/projects/branches_controller.rb b/app/controllers/projects/branches_controller.rb index 00811f17ad..e4c82d0198 100644 --- a/app/controllers/projects/branches_controller.rb +++ b/app/controllers/projects/branches_controller.rb @@ -15,9 +15,9 @@ class Projects::BranchesController < Projects::ApplicationController end def create - CreateBranchService.new.execute(project, params[:branch_name], params[:ref], current_user) + @branch = CreateBranchService.new.execute(project, params[:branch_name], params[:ref], current_user) - redirect_to project_branches_path(@project) + redirect_to project_tree_path(@project, @branch.name) end def destroy From b44138ae4030bb5b63af4f4d835ddceb06c1b953 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 23 May 2014 13:29:14 +0300 Subject: [PATCH 035/360] Branch link on branches page goes to tree view instead of commits Signed-off-by: Dmitriy Zaporozhets --- app/views/projects/branches/_branch.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/projects/branches/_branch.html.haml b/app/views/projects/branches/_branch.html.haml index 87f4dd88c2..d5f7dacaa0 100644 --- a/app/views/projects/branches/_branch.html.haml +++ b/app/views/projects/branches/_branch.html.haml @@ -1,7 +1,7 @@ - commit = @repository.commit(branch.target) %li %h4 - = link_to project_commits_path(@project, branch.name) do + = link_to project_tree_path(@project, branch.name) do %strong= truncate(branch.name, length: 60) - if branch.name == @repository.root_ref %span.label.label-info default From 695fd3cf2c7e01d06e9c335cae208089a4c6bfbd Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 23 May 2014 14:25:55 +0300 Subject: [PATCH 036/360] Move protected branches to Project settings Signed-off-by: Dmitriy Zaporozhets --- .../projects/branches_controller.rb | 4 +- .../projects/protected_branches_controller.rb | 4 +- app/helpers/tab_helper.rb | 2 +- app/models/repository.rb | 21 ++-- app/views/layouts/nav/_project.html.haml | 2 +- app/views/projects/_settings_nav.html.haml | 4 + app/views/projects/branches/_branch.html.haml | 10 +- app/views/projects/branches/_filter.html.haml | 27 ------ app/views/projects/branches/index.html.haml | 39 ++++++-- app/views/projects/branches/recent.html.haml | 8 -- app/views/projects/commits/_head.html.haml | 4 +- .../protected_branches/index.html.haml | 96 +++++++++---------- config/routes.rb | 7 +- 13 files changed, 109 insertions(+), 119 deletions(-) delete mode 100644 app/views/projects/branches/_filter.html.haml delete mode 100644 app/views/projects/branches/recent.html.haml diff --git a/app/controllers/projects/branches_controller.rb b/app/controllers/projects/branches_controller.rb index 00811f17ad..8c70ae45f0 100644 --- a/app/controllers/projects/branches_controller.rb +++ b/app/controllers/projects/branches_controller.rb @@ -7,7 +7,9 @@ class Projects::BranchesController < Projects::ApplicationController before_filter :authorize_push!, only: [:create, :destroy] def index - @branches = Kaminari.paginate_array(@repository.branches).page(params[:page]).per(30) + @sort = params[:sort] || 'name' + @branches = @repository.branches_sorted_by(@sort) + @branches = Kaminari.paginate_array(@branches).page(params[:page]).per(30) end def recent diff --git a/app/controllers/projects/protected_branches_controller.rb b/app/controllers/projects/protected_branches_controller.rb index cfc1bd99a2..e39e97af8d 100644 --- a/app/controllers/projects/protected_branches_controller.rb +++ b/app/controllers/projects/protected_branches_controller.rb @@ -1,9 +1,9 @@ class Projects::ProtectedBranchesController < Projects::ApplicationController # Authorize - before_filter :authorize_read_project! before_filter :require_non_empty_project + before_filter :authorize_admin_project! - before_filter :authorize_admin_project!, only: [:destroy, :create] + layout "project_settings" def index @branches = @project.protected_branches.to_a diff --git a/app/helpers/tab_helper.rb b/app/helpers/tab_helper.rb index bd373c5f3c..610175f844 100644 --- a/app/helpers/tab_helper.rb +++ b/app/helpers/tab_helper.rb @@ -75,7 +75,7 @@ module TabHelper def project_tab_class return "active" if current_page?(controller: "/projects", action: :edit, id: @project) - if ['services', 'hooks', 'deploy_keys', 'team_members'].include? controller.controller_name + if ['services', 'hooks', 'deploy_keys', 'team_members', 'protected_branches'].include? controller.controller_name "active" end end diff --git a/app/models/repository.rb b/app/models/repository.rb index eadc34127c..b7239236ae 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -55,12 +55,6 @@ class Repository tags.find { |tag| tag.name == name } end - def recent_branches(limit = 20) - branches.sort do |a, b| - commit(b.target).committed_date <=> commit(a.target).committed_date - end[0..limit] - end - def add_branch(branch_name, ref) Rails.cache.delete(cache_key(:branch_names)) @@ -220,4 +214,19 @@ class Repository def clean_old_archives Gitlab::Popen.popen(%W(find #{Gitlab.config.gitlab.repository_downloads_path} -mmin +120 -delete)) end + + def branches_sorted_by(value) + case value + when 'recently_updated' + branches.sort do |a, b| + commit(b.target).committed_date <=> commit(a.target).committed_date + end + when 'last_updated' + branches.sort do |a, b| + commit(a.target).committed_date <=> commit(b.target).committed_date + end + else + branches + end + end end diff --git a/app/views/layouts/nav/_project.html.haml b/app/views/layouts/nav/_project.html.haml index 1f70cf1798..d7d330e2a6 100644 --- a/app/views/layouts/nav/_project.html.haml +++ b/app/views/layouts/nav/_project.html.haml @@ -8,7 +8,7 @@ = link_to 'Files', project_tree_path(@project, @ref || @repository.root_ref) - if project_nav_tab? :commits - = nav_link(controller: %w(commit commits compare repositories protected_branches tags branches)) do + = nav_link(controller: %w(commit commits compare repositories tags branches)) do = link_to "Commits", project_commits_path(@project, @ref || @repository.root_ref) - if project_nav_tab? :network diff --git a/app/views/projects/_settings_nav.html.haml b/app/views/projects/_settings_nav.html.haml index 4c7b088ae9..9b73f06a5b 100644 --- a/app/views/projects/_settings_nav.html.haml +++ b/app/views/projects/_settings_nav.html.haml @@ -19,3 +19,7 @@ = link_to project_services_path(@project) do %i.icon-cogs Services + = nav_link(controller: :protected_branches) do + = link_to project_protected_branches_path(@project) do + %i.icon-lock + Protected branches diff --git a/app/views/projects/branches/_branch.html.haml b/app/views/projects/branches/_branch.html.haml index 87f4dd88c2..a5f382c9a5 100644 --- a/app/views/projects/branches/_branch.html.haml +++ b/app/views/projects/branches/_branch.html.haml @@ -8,6 +8,7 @@ - if @project.protected_branch? branch.name %span.label.label-success %i.icon-lock + protected .pull-right - if can?(current_user, :download_code, @project) = render 'projects/repositories/download_archive', ref: branch.name, btn_class: 'btn-grouped btn-group-small' @@ -21,13 +22,8 @@ %i.icon-trash - if commit - %p - = link_to project_commit_path(@project, commit.id), class: 'commit_short_id' do - = commit.short_id - = image_tag avatar_icon(commit.author_email), class: "avatar s16", alt: '' - %span.light - = gfm escape_once(truncate(commit.title, length: 40)) - #{time_ago_with_tooltip(commit.committed_date)} + %ul.list-unstyled + = render 'projects/commits/inline_commit', commit: commit, project: @project - else %p Cant find HEAD commit for this branch diff --git a/app/views/projects/branches/_filter.html.haml b/app/views/projects/branches/_filter.html.haml deleted file mode 100644 index 7e1478292e..0000000000 --- a/app/views/projects/branches/_filter.html.haml +++ /dev/null @@ -1,27 +0,0 @@ -%ul.nav.nav-pills.nav-stacked - = nav_link(path: 'branches#recent') do - = link_to recent_project_branches_path(@project) do - Recent - .pull-right - = @repository.recent_branches.count - - = nav_link(path: 'protected_branches#index') do - = link_to project_protected_branches_path(@project) do - Protected - %i.icon-lock - .pull-right - = @project.protected_branches.count - - = nav_link(path: 'branches#index') do - = link_to project_branches_path(@project) do - All branches - .pull-right - = @repository.branch_names.count - - -%hr -- if can? current_user, :push_code, @project - = link_to new_project_branch_path(@project), class: 'btn btn-create' do - %i.icon-add-sign - New branch - diff --git a/app/views/projects/branches/index.html.haml b/app/views/projects/branches/index.html.haml index bee04eb013..8bc4a8f7e9 100644 --- a/app/views/projects/branches/index.html.haml +++ b/app/views/projects/branches/index.html.haml @@ -1,10 +1,31 @@ = render "projects/commits/head" -.row - .col-md-3 - = render "filter" - .col-md-9 - - unless @branches.empty? - %ul.bordered-list.top-list.all-branches - - @branches.each do |branch| - = render "projects/branches/branch", branch: branch - = paginate @branches, theme: 'gitlab' +%h3.page-title + Branches + .pull-right + - if can? current_user, :push_code, @project + = link_to new_project_branch_path(@project), class: 'btn btn-create' do + %i.icon-add-sign + New branch +   + .dropdown.inline + %a.dropdown-toggle.btn{href: '#', "data-toggle" => "dropdown"} + %span.light sort: + - if @sort.present? + = @sort.humanize + - else + Name + %b.caret + %ul.dropdown-menu + %li + = link_to project_branches_path(sort: nil) do + Name + = link_to project_branches_path(sort: 'recently_updated') do + Recently updated + = link_to project_branches_path(sort: 'last_updated') do + Last updated +%hr +- unless @branches.empty? + %ul.bordered-list.top-list.all-branches + - @branches.each do |branch| + = render "projects/branches/branch", branch: branch + = paginate @branches, theme: 'gitlab' diff --git a/app/views/projects/branches/recent.html.haml b/app/views/projects/branches/recent.html.haml deleted file mode 100644 index 37d7919121..0000000000 --- a/app/views/projects/branches/recent.html.haml +++ /dev/null @@ -1,8 +0,0 @@ -= render "projects/commits/head" -.row - .col-md-3 - = render "filter" - .col-md-9 - %ul.bordered-list.top-list - - @branches.each do |branch| - = render "projects/branches/branch", branch: branch diff --git a/app/views/projects/commits/_head.html.haml b/app/views/projects/commits/_head.html.haml index 81e3374391..0facfc4b5f 100644 --- a/app/views/projects/commits/_head.html.haml +++ b/app/views/projects/commits/_head.html.haml @@ -7,9 +7,9 @@ = link_to 'Compare', project_compare_index_path(@project, from: @repository.root_ref, to: @ref || @repository.root_ref) = nav_link(html_options: {class: branches_tab_class}) do - = link_to recent_project_branches_path(@project) do + = link_to project_branches_path(@project) do Branches - %span.badge= @repository.branches.length + %span.badge= @repository.branches.size = nav_link(controller: :tags) do = link_to project_tags_path(@project) do diff --git a/app/views/projects/protected_branches/index.html.haml b/app/views/projects/protected_branches/index.html.haml index e9f67b671b..e51bf1d3a8 100644 --- a/app/views/projects/protected_branches/index.html.haml +++ b/app/views/projects/protected_branches/index.html.haml @@ -1,52 +1,50 @@ -= render "projects/commits/head" -.row - .col-md-3 - = render "projects/branches/filter" - .col-md-9 - .bs-callout.bs-callout-info - %p Protected branches designed to - %ul - %li prevent push for all except #{link_to "masters", help_permissions_path, class: "vlink"}. - %li prevent branch from force push - %li prevent branch from removal - %p This ability allows to keep stable branches secured and force code review before merge to protected branches - %p Read more about project permissions #{link_to "here", help_permissions_path, class: "underlined-link"} +%h3.page-title Protected branches +%p.light This ability allows to keep stable branches secured and force code review before merge to protected branches +%hr - - if can? current_user, :admin_project, @project - = form_for [@project, @protected_branch], html: { class: 'form-horizontal' } do |f| - -if @protected_branch.errors.any? - .alert.alert-danger - %ul - - @protected_branch.errors.full_messages.each do |msg| - %li= msg +.bs-callout.bs-callout-info + %p Protected branches designed to + %ul + %li prevent push for all except #{link_to "masters", help_permissions_path, class: "vlink"}. + %li prevent branch from force push + %li prevent branch from removal + %p Read more about project permissions #{link_to "here", help_permissions_path, class: "underlined-link"} - .form-group - = f.label :name, "Branch", class: 'control-label' - .col-sm-10 - = f.select(:name, @project.open_branches.map { |br| [br.name, br.name] } , {include_blank: "Select branch"}, {class: "select2"}) - .form-actions - = f.submit 'Protect', class: "btn-create btn" - - unless @branches.empty? - %h5 Already Protected: - %ul.bordered-list.protected-branches-list - - @branches.each do |branch| - %li - %h4 - = link_to project_commits_path(@project, branch.name) do - %strong= branch.name - - if @project.root_ref?(branch.name) - %span.label.label-info default - %span.label.label-success - %i.icon-lock - .pull-right - - if can? current_user, :admin_project, @project - = link_to 'Unprotect', [@project, branch], data: { confirm: 'Branch will be writable for developers. Are you sure?' }, method: :delete, class: "btn btn-remove btn-small" +- if can? current_user, :admin_project, @project + = form_for [@project, @protected_branch], html: { class: 'form-horizontal' } do |f| + -if @protected_branch.errors.any? + .alert.alert-danger + %ul + - @protected_branch.errors.full_messages.each do |msg| + %li= msg - - if commit = branch.commit - = link_to project_commit_path(@project, commit.id), class: 'commit_short_id' do - = commit.short_id - %span.light - = gfm escape_once(truncate(commit.title, length: 40)) - #{time_ago_with_tooltip(commit.committed_date)} - - else - (branch was removed from repository) + .form-group + = f.label :name, "Branch", class: 'control-label' + .col-sm-10 + = f.select(:name, @project.open_branches.map { |br| [br.name, br.name] } , {include_blank: "Select branch"}, {class: "select2"}) + .form-actions + = f.submit 'Protect', class: "btn-create btn" +- unless @branches.empty? + %h5 Already Protected: + %ul.bordered-list.protected-branches-list + - @branches.each do |branch| + %li + %h4 + = link_to project_commits_path(@project, branch.name) do + %strong= branch.name + - if @project.root_ref?(branch.name) + %span.label.label-info default + %span.label.label-success + %i.icon-lock + .pull-right + - if can? current_user, :admin_project, @project + = link_to 'Unprotect', [@project, branch], data: { confirm: 'Branch will be writable for developers. Are you sure?' }, method: :delete, class: "btn btn-remove btn-small" + + - if commit = branch.commit + = link_to project_commit_path(@project, commit.id), class: 'commit_short_id' do + = commit.short_id + %span.light + = gfm escape_once(truncate(commit.title, length: 40)) + #{time_ago_with_tooltip(commit.committed_date)} + - else + (branch was removed from repository) diff --git a/config/routes.rb b/config/routes.rb index da5a1ba7a8..ada9bb1d77 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -243,12 +243,7 @@ Gitlab::Application.routes.draw do end end - resources :branches, only: [:index, :new, :create, :destroy], constraints: { id: Gitlab::Regex.git_reference_regex } do - collection do - get :recent, constraints: { id: Gitlab::Regex.git_reference_regex } - end - end - + resources :branches, only: [:index, :new, :create, :destroy], constraints: { id: Gitlab::Regex.git_reference_regex } resources :tags, only: [:index, :new, :create, :destroy], constraints: { id: Gitlab::Regex.git_reference_regex } resources :protected_branches, only: [:index, :create, :destroy], constraints: { id: Gitlab::Regex.git_reference_regex } From 484c09792c5c6b4f8f1111978a82cf080a31a920 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 23 May 2014 14:33:20 +0300 Subject: [PATCH 037/360] Fix tests Signed-off-by: Dmitriy Zaporozhets --- app/views/projects/tree/show.html.haml | 2 +- features/steps/project/browse_branches.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/projects/tree/show.html.haml b/app/views/projects/tree/show.html.haml index 6b33493b7d..735ffae9e2 100644 --- a/app/views/projects/tree/show.html.haml +++ b/app/views/projects/tree/show.html.haml @@ -1,6 +1,6 @@ %div.tree-ref-holder = render 'shared/ref_switcher', destination: 'tree', path: @path - if can? current_user, :download_code, @project - = render 'projects/repositories/download_archive', ref: @ref, btn_class: 'btn-group-small tree-ref-holder pull-right', split_button: true + = render 'projects/repositories/download_archive', ref: @ref, btn_class: 'btn-group-small pull-right', split_button: true %div#tree-holder.tree-holder = render "tree", tree: @tree diff --git a/features/steps/project/browse_branches.rb b/features/steps/project/browse_branches.rb index 30c8cef80c..5b5e8ba493 100644 --- a/features/steps/project/browse_branches.rb +++ b/features/steps/project/browse_branches.rb @@ -44,7 +44,7 @@ class ProjectBrowseBranches < Spinach::FeatureSteps end step 'I should see new branch created' do - within '.all-branches' do + within '.tree-ref-holder' do page.should have_content 'deploy_keys' end end From c5922ca97fa83492b0c8419b642be00d820ce0fb Mon Sep 17 00:00:00 2001 From: dosire Date: Fri, 23 May 2014 13:48:56 +0200 Subject: [PATCH 038/360] Don't forget to update the changelog. --- doc/release/monthly.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/release/monthly.md b/doc/release/monthly.md index 514d73517b..526d5d90e4 100644 --- a/doc/release/monthly.md +++ b/doc/release/monthly.md @@ -9,6 +9,10 @@ NOTE: This is a guide for GitLab developers. A release manager is selected that coordinates the entire release of this version. The release manager has to make sure all the steps below are done and delegated where necessary. This person should also make sure this document is kept up to date and issues are created and updated. +### **3. Update Changelog** + +Any changes not yet added to the changelog are added by lead developer and in that merge request the complete team is asked if there is anything missing. + # **18th - Releasing RC1** The RC1 release comes with the task to update the installation and upgrade docs. Be mindful that there might already be merge requests for this on GitLab or GitHub. From 8efc80ef0629bc5916debb4bc476374ac5ad6733 Mon Sep 17 00:00:00 2001 From: dosire Date: Fri, 23 May 2014 14:02:39 +0200 Subject: [PATCH 039/360] Add threaded emails to changelog. --- CHANGELOG | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG b/CHANGELOG index 484d66daa5..2cd68ce414 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -26,6 +26,7 @@ v 6.9.0 - Add more access checks during API calls - Block SSH access for 'disabled' Active Directory users - Labels for merge requests (Drew Blessing) + - Threaded emails by setting a Message-ID (Philip Blatter) v 6.8.0 - Ability to at mention users that are participating in issue and merge req. discussion From 6990f8a8464fd579c7152512d3d3b25b60b6f5c9 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Fri, 23 May 2014 14:07:42 +0200 Subject: [PATCH 040/360] Replace jquery deprecated .live with .on --- app/assets/javascripts/commits.js.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/javascripts/commits.js.coffee b/app/assets/javascripts/commits.js.coffee index 9c004c997e..784d7d20bb 100644 --- a/app/assets/javascripts/commits.js.coffee +++ b/app/assets/javascripts/commits.js.coffee @@ -12,7 +12,7 @@ class CommitsList $('.loading').hide() @init: (ref, limit) -> - $(".day-commits-table li.commit").live 'click', (event) -> + $("body").on "click", ".day-commits-table li.commit", (event) -> if event.target.nodeName != "A" location.href = $(this).attr("url") e.stopPropagation() From 7f84ba8662384cebf5574cbd2da5841aab2eac90 Mon Sep 17 00:00:00 2001 From: dosire Date: Fri, 23 May 2014 14:31:09 +0200 Subject: [PATCH 041/360] Project visibility setting is missed by people sometimes. --- doc/public_access/public_access.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/public_access/public_access.md b/doc/public_access/public_access.md index 76d83e6f3b..bb23a4bfd9 100644 --- a/doc/public_access/public_access.md +++ b/doc/public_access/public_access.md @@ -26,3 +26,7 @@ The public page of users, located at `/u/username` is visible if either: Otherwise, you will be redirected to the sign in page. When visiting the public page of an user, you will only see listed projects which you can view yourself. + +#### Restricting the use of public or internal projects +In [gitlab.yml](https://gitlab.com/gitlab-org/gitlab-ce/blob/dbd88d453b8e6c78a423fa7e692004b1db6ea069/config/gitlab.yml.example#L64) you can disable public projects or public and internal projects for the entire GitLab installation to prevent people making code public by accident. + From d575ee3e90a7b13e4ed29fdea0b611ae8ef50496 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 23 May 2014 15:34:02 +0300 Subject: [PATCH 042/360] Improve branch deletion via API Signed-off-by: Dmitriy Zaporozhets --- doc/api/branches.md | 14 ++++++++++++++ lib/api/branches.rb | 8 +++++++- spec/requests/api/branches_spec.rb | 23 ++++++++++++++++++++++- 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/doc/api/branches.md b/doc/api/branches.md index da9d4193f2..bb2d3fec09 100644 --- a/doc/api/branches.md +++ b/doc/api/branches.md @@ -199,3 +199,17 @@ Parameters: "protected": false } ``` + +## Delete repository branch + + +``` +DELETE /projects/:id/repository/branches/:branch +``` + +Parameters: + ++ `id` (required) - The ID of a project ++ `branch` (required) - The name of the branch + +It return 200 if succeed or 405 if failed with error message explaining reason. diff --git a/lib/api/branches.rb b/lib/api/branches.rb index 32597eb94c..b32a4aa7bc 100644 --- a/lib/api/branches.rb +++ b/lib/api/branches.rb @@ -94,7 +94,13 @@ module API # DELETE /projects/:id/repository/branches/:branch delete ":id/repository/branches/:branch" do authorize_push_project - DeleteBranchService.new.execute(user_project, params[:branch], current_user) + result = DeleteBranchService.new.execute(user_project, params[:branch], current_user) + + if result[:state] == :success + true + else + render_api_error!(result[:message], 405) + end end end end diff --git a/spec/requests/api/branches_spec.rb b/spec/requests/api/branches_spec.rb index abf6a8646e..72589da5d4 100644 --- a/spec/requests/api/branches_spec.rb +++ b/spec/requests/api/branches_spec.rb @@ -91,7 +91,6 @@ describe API::API, api: true do end end - describe "POST /projects/:id/repository/branches" do it "should create a new branch" do post api("/projects/#{project.id}/repository/branches", user), @@ -112,4 +111,26 @@ describe API::API, api: true do response.status.should == 403 end end + + describe "DELETE /projects/:id/repository/branches/:branch" do + before { Repository.any_instance.stub(rm_branch: true) } + + it "should remove branch" do + delete api("/projects/#{project.id}/repository/branches/new_design", user) + response.status.should == 200 + end + + it "should remove protected branch" do + project.protected_branches.create(name: 'new_design') + delete api("/projects/#{project.id}/repository/branches/new_design", user) + response.status.should == 405 + json_response['message'].should == 'Protected branch cant be removed' + end + + it "should not remove HEAD branch" do + delete api("/projects/#{project.id}/repository/branches/master", user) + response.status.should == 405 + json_response['message'].should == 'Cannot remove HEAD branch' + end + end end From 245c04c29a04906113991144d8d4eebc5c6ecf1c Mon Sep 17 00:00:00 2001 From: dosire Date: Fri, 23 May 2014 15:01:02 +0200 Subject: [PATCH 043/360] Change the license to B.V. --- CONTRIBUTING.md | 2 +- LICENSE | 2 +- .../corporate_contributor_license_agreement.md | 14 +++++++------- .../individual_contributor_license_agreement.md | 16 ++++++++-------- doc/workflow/project_features.md | 2 +- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 780db547f8..85f751919e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -78,7 +78,7 @@ If you can, please submit a merge request with the fix or improvements including 1. Be prepared to answer questions and incorporate feedback even if requests for this arrive weeks or months after your MR submittion 1. If your MR touches code that executes shell commands, make sure it adheres to the [shell command guidelines]( doc/development/shell_commands.md). -The **official merge window** is in the beginning of the month from the 1st to the 7th day of the month. The best time to submit a MR and get feedback fast. Before this time the GitLab.com team is still dealing with work that is created by the monthly release such as assisting subscribers with upgrade issues, the release of Enterprise Edition and the upgrade of GitLab Cloud. After the 7th it is already getting closer to the release date of the next version. This means there is less time to fix the issues created by merging large new features. +The **official merge window** is in the beginning of the month from the 1st to the 7th day of the month. The best time to submit a MR and get feedback fast. Before this time the GitLab B.V. team is still dealing with work that is created by the monthly release such as assisting subscribers with upgrade issues, the release of Enterprise Edition and the upgrade of GitLab Cloud. After the 7th it is already getting closer to the release date of the next version. This means there is less time to fix the issues created by merging large new features. Please keep the change in a single MR **as small as possible**. If you want to contribute a large feature think very hard what the minimum viable change is. Can you split functionality? Can you only submit the backend/API code? Can you start with a very simple UI? The smaller a MR is the more likely it is it will be merged, after that you can send more MR's to enhance it. diff --git a/LICENSE b/LICENSE index 8ebd322ffc..d11b8730bf 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2011-2014 Dmitriy Zaporozhets +Copyright (c) 2011-2014 GitLab B.V. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/doc/legal/corporate_contributor_license_agreement.md b/doc/legal/corporate_contributor_license_agreement.md index bbc274f3b0..fb8d52e6bd 100644 --- a/doc/legal/corporate_contributor_license_agreement.md +++ b/doc/legal/corporate_contributor_license_agreement.md @@ -1,14 +1,14 @@ -You accept and agree to the following terms and conditions for Your present and future Contributions submitted to GitLab.com. Except for the license granted herein to GitLab.com and recipients of software distributed by GitLab.com, You reserve all right, title, and interest in and to Your Contributions. +You accept and agree to the following terms and conditions for Your present and future Contributions submitted to GitLab B.V.. Except for the license granted herein to GitLab B.V. and recipients of software distributed by GitLab B.V., You reserve all right, title, and interest in and to Your Contributions. 1. Definitions. - "You" (or "Your") shall mean the copyright owner or legal entity authorized by the copyright owner that is making this Agreement with GitLab.com. For legal entities, the entity making a Contribution and all other entities that control, are controlled by, or are under common control with that entity are considered to be a single Contributor. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + "You" (or "Your") shall mean the copyright owner or legal entity authorized by the copyright owner that is making this Agreement with GitLab B.V.. For legal entities, the entity making a Contribution and all other entities that control, are controlled by, or are under common control with that entity are considered to be a single Contributor. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. - "Contribution" shall mean the code, documentation or other original works of authorship expressly identified in Schedule B, as well as any original work of authorship, including any modifications or additions to an existing work, that is intentionally submitted by You to GitLab.com for inclusion in, or documentation of, any of the products owned or managed by GitLab.com (the "Work"). For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to GitLab.com or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, GitLab.com for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by You as "Not a Contribution." + "Contribution" shall mean the code, documentation or other original works of authorship expressly identified in Schedule B, as well as any original work of authorship, including any modifications or additions to an existing work, that is intentionally submitted by You to GitLab B.V. for inclusion in, or documentation of, any of the products owned or managed by GitLab B.V. (the "Work"). For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to GitLab B.V. or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, GitLab B.V. for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by You as "Not a Contribution." -2. Grant of Copyright License. Subject to the terms and conditions of this Agreement, You hereby grant to GitLab.com and to recipients of software distributed by GitLab.com a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute Your Contributions and such derivative works. +2. Grant of Copyright License. Subject to the terms and conditions of this Agreement, You hereby grant to GitLab B.V. and to recipients of software distributed by GitLab B.V. a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute Your Contributions and such derivative works. -3. Grant of Patent License. Subject to the terms and conditions of this Agreement, You hereby grant to GitLab.com and to recipients of software distributed by GitLab.com a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by You that are necessarily infringed by Your Contribution(s) alone or by combination of Your Contribution(s) with the Work to which such Contribution(s) was submitted. If any entity institutes patent litigation against You or any other entity (including a cross-claim or counterclaim in a lawsuit) alleging that your Contribution, or the Work to which you have contributed, constitutes direct or contributory patent infringement, then any patent licenses granted to that entity under this Agreement for that Contribution or Work shall terminate as of the date such litigation is filed. +3. Grant of Patent License. Subject to the terms and conditions of this Agreement, You hereby grant to GitLab B.V. and to recipients of software distributed by GitLab B.V. a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by You that are necessarily infringed by Your Contribution(s) alone or by combination of Your Contribution(s) with the Work to which such Contribution(s) was submitted. If any entity institutes patent litigation against You or any other entity (including a cross-claim or counterclaim in a lawsuit) alleging that your Contribution, or the Work to which you have contributed, constitutes direct or contributory patent infringement, then any patent licenses granted to that entity under this Agreement for that Contribution or Work shall terminate as of the date such litigation is filed. 4. You represent that You are legally entitled to grant the above license. You represent further that each employee of the Corporation designated on Schedule A below (or in a subsequent written modification to that Schedule) is authorized to submit Contributions on behalf of the Corporation. @@ -16,9 +16,9 @@ You accept and agree to the following terms and conditions for Your present and 6. You are not expected to provide support for Your Contributions, except to the extent You desire to provide support. You may provide support for free, for a fee, or not at all. Unless required by applicable law or agreed to in writing, You provide Your Contributions on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. -7. Should You wish to submit work that is not Your original creation, You may submit it to GitLab.com separately from any Contribution, identifying the complete details of its source and of any license or other restriction (including, but not limited to, related patents, trademarks, and license agreements) of which you are personally aware, and conspicuously marking the work as "Submitted on behalf of a third-party: [named here]". +7. Should You wish to submit work that is not Your original creation, You may submit it to GitLab B.V. separately from any Contribution, identifying the complete details of its source and of any license or other restriction (including, but not limited to, related patents, trademarks, and license agreements) of which you are personally aware, and conspicuously marking the work as "Submitted on behalf of a third-party: [named here]". -8. It is your responsibility to notify GitLab.com when any change is required to the list of designated employees authorized to submit Contributions on behalf of the Corporation, or to the Corporation's Point of Contact with GitLab.com. +8. It is your responsibility to notify GitLab B.V. when any change is required to the list of designated employees authorized to submit Contributions on behalf of the Corporation, or to the Corporation's Point of Contact with GitLab B.V.. --------------------------------------- diff --git a/doc/legal/individual_contributor_license_agreement.md b/doc/legal/individual_contributor_license_agreement.md index eaf5812ca4..7ac9d6e4cd 100644 --- a/doc/legal/individual_contributor_license_agreement.md +++ b/doc/legal/individual_contributor_license_agreement.md @@ -1,24 +1,24 @@ -You accept and agree to the following terms and conditions for Your present and future Contributions submitted to GitLab.com. Except for the license granted herein to GitLab.com and recipients of software distributed by GitLab.com, You reserve all right, title, and interest in and to Your Contributions. +You accept and agree to the following terms and conditions for Your present and future Contributions submitted to GitLab B.V.. Except for the license granted herein to GitLab B.V. and recipients of software distributed by GitLab B.V., You reserve all right, title, and interest in and to Your Contributions. 1. Definitions. - "You" (or "Your") shall mean the copyright owner or legal entity authorized by the copyright owner that is making this Agreement with GitLab.com. For legal entities, the entity making a Contribution and all other entities that control, are controlled by, or are under common control with that entity are considered to be a single Contributor. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + "You" (or "Your") shall mean the copyright owner or legal entity authorized by the copyright owner that is making this Agreement with GitLab B.V.. For legal entities, the entity making a Contribution and all other entities that control, are controlled by, or are under common control with that entity are considered to be a single Contributor. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. - "Contribution" shall mean any original work of authorship, including any modifications or additions to an existing work, that is intentionally submitted by You to GitLab.com for inclusion in, or documentation of, any of the products owned or managed by GitLab.com (the "Work"). For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to GitLab.com or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, GitLab.com for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by You as "Not a Contribution." + "Contribution" shall mean any original work of authorship, including any modifications or additions to an existing work, that is intentionally submitted by You to GitLab B.V. for inclusion in, or documentation of, any of the products owned or managed by GitLab B.V. (the "Work"). For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to GitLab B.V. or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, GitLab B.V. for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by You as "Not a Contribution." -2. Grant of Copyright License. Subject to the terms and conditions of this Agreement, You hereby grant to GitLab.com and to recipients of software distributed by GitLab.com a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute Your Contributions and such derivative works. +2. Grant of Copyright License. Subject to the terms and conditions of this Agreement, You hereby grant to GitLab B.V. and to recipients of software distributed by GitLab B.V. a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute Your Contributions and such derivative works. -3. Grant of Patent License. Subject to the terms and conditions of this Agreement, You hereby grant to GitLab.com and to recipients of software distributed by GitLab.com a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by You that are necessarily infringed by Your Contribution(s) alone or by combination of Your Contribution(s) with the Work to which such Contribution(s) was submitted. If any entity institutes patent litigation against You or any other entity (including a cross-claim or counterclaim in a lawsuit) alleging that your Contribution, or the Work to which you have contributed, constitutes direct or contributory patent infringement, then any patent licenses granted to that entity under this Agreement for that Contribution or Work shall terminate as of the date such litigation is filed. +3. Grant of Patent License. Subject to the terms and conditions of this Agreement, You hereby grant to GitLab B.V. and to recipients of software distributed by GitLab B.V. a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by You that are necessarily infringed by Your Contribution(s) alone or by combination of Your Contribution(s) with the Work to which such Contribution(s) was submitted. If any entity institutes patent litigation against You or any other entity (including a cross-claim or counterclaim in a lawsuit) alleging that your Contribution, or the Work to which you have contributed, constitutes direct or contributory patent infringement, then any patent licenses granted to that entity under this Agreement for that Contribution or Work shall terminate as of the date such litigation is filed. -4. You represent that you are legally entitled to grant the above license. If your employer(s) has rights to intellectual property that you create that includes your Contributions, you represent that you have received permission to make Contributions on behalf of that employer, that your employer has waived such rights for your Contributions to GitLab.com, or that your employer has executed a separate Corporate CLA with GitLab.com. +4. You represent that you are legally entitled to grant the above license. If your employer(s) has rights to intellectual property that you create that includes your Contributions, you represent that you have received permission to make Contributions on behalf of that employer, that your employer has waived such rights for your Contributions to GitLab B.V., or that your employer has executed a separate Corporate CLA with GitLab B.V.. 5. You represent that each of Your Contributions is Your original creation (see section 7 for submissions on behalf of others). You represent that Your Contribution submissions include complete details of any third-party license or other restriction (including, but not limited to, related patents and trademarks) of which you are personally aware and which are associated with any part of Your Contributions. 6. You are not expected to provide support for Your Contributions, except to the extent You desire to provide support. You may provide support for free, for a fee, or not at all. Unless required by applicable law or agreed to in writing, You provide Your Contributions on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON- INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. -7. Should You wish to submit work that is not Your original creation, You may submit it to GitLab.com separately from any Contribution, identifying the complete details of its source and of any license or other restriction (including, but not limited to, related patents, trademarks, and license agreements) of which you are personally aware, and conspicuously marking the work as "Submitted on behalf of a third-party: [[]named here]". +7. Should You wish to submit work that is not Your original creation, You may submit it to GitLab B.V. separately from any Contribution, identifying the complete details of its source and of any license or other restriction (including, but not limited to, related patents, trademarks, and license agreements) of which you are personally aware, and conspicuously marking the work as "Submitted on behalf of a third-party: [[]named here]". -8. You agree to notify GitLab.com of any facts or circumstances of which you become aware that would make these representations inaccurate in any respect. +8. You agree to notify GitLab B.V. of any facts or circumstances of which you become aware that would make these representations inaccurate in any respect. --------------------------------------- diff --git a/doc/workflow/project_features.md b/doc/workflow/project_features.md index 25fe403257..64f4ddaa12 100644 --- a/doc/workflow/project_features.md +++ b/doc/workflow/project_features.md @@ -7,7 +7,7 @@ Below you will find a more elaborate explanation of each of these. Issues is a really powerful, but lightweight issue tracking system. You can make tickets, assign them to people, file them under milestones, order them with labels and have discussion in them. They integrate deeply into GitLab and are easily referenced from anywhere by using # and the issuenumber. -At GitLab.com, we use this for all our project management needs. + ## Merge Requests From 3e1853c5a0d89147a6a44a31a302f93e96c2ed92 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 23 May 2014 16:09:54 +0300 Subject: [PATCH 044/360] More stuff to CHANGELOG Signed-off-by: Dmitriy Zaporozhets --- CHANGELOG | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 2cd68ce414..9d2ac06277 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -4,6 +4,9 @@ v 7.0.0 - Add ability to upload group avatar when create - Protected branch cannot be removed - Developers can remove normal branches with UI + - Remove branch via API (sponsored by O'Reilly Media) + - Move protected branches page to Project settings area + - Redirect to Files view when create new branch via UI v 6.9.0 - Store Rails cache data in the Redis `cache:gitlab` namespace From 1e6766f9edb2a9bda18e89acef64ee03e8d3b2e4 Mon Sep 17 00:00:00 2001 From: Sean Edge Date: Wed, 21 May 2014 21:46:01 -0400 Subject: [PATCH 045/360] Add CreateTagService. Use new service to allow tag creation through API. --- app/services/create_tag_service.rb | 13 +++++++++++++ lib/api/repositories.rb | 16 ++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 app/services/create_tag_service.rb diff --git a/app/services/create_tag_service.rb b/app/services/create_tag_service.rb new file mode 100644 index 0000000000..9776667740 --- /dev/null +++ b/app/services/create_tag_service.rb @@ -0,0 +1,13 @@ +class CreateTagService + def execute(project, tag_name, ref, current_user) + repository = project.repository + repository.add_tag(tag_name, ref) + new_tag = repository.find_tag(tag_name) + + if new_tag + Event.create_ref_event(project, current_user, new_tag, 'add', 'refs/tags') + end + + new_tag + end +end diff --git a/lib/api/repositories.rb b/lib/api/repositories.rb index 076a9ceeb7..e90d7c6612 100644 --- a/lib/api/repositories.rb +++ b/lib/api/repositories.rb @@ -25,6 +25,22 @@ module API present user_project.repo.tags.sort_by(&:name).reverse, with: Entities::RepoObject, project: user_project end + # Create tag + # + # Parameters: + # id (required) - The ID of a project + # tag_name (required) - The name of the tag + # ref (required) - Create tag from commit sha or branch + # Example Request: + # POST /projects/:id/repository/tags + post ':id/repository/tags' do + authorize_push_project + @tag = CreateTagService.new.execute(user_project, params[:tag_name], + params[:ref], current_user) + + present @tag, with: Entities::RepoObject, project: user_project + end + # Get a project repository tree # # Parameters: From d0e794cc1a7eba4d438841d6a661bc41687e624e Mon Sep 17 00:00:00 2001 From: Jeroen van Baarsen Date: Sat, 17 May 2014 11:36:39 +0200 Subject: [PATCH 046/360] Make sure the branch counter gets updated When you delete a branch, the counters wont get updated automaticly, this happends because of the JS nature of the original call. I've fixed this by responding with a JS file, and recalculate the counters. Fixes: #6030 --- app/controllers/projects/branches_controller.rb | 3 ++- app/views/projects/branches/_branch.html.haml | 2 +- app/views/projects/branches/destroy.js.haml | 5 +++++ app/views/projects/commits/_head.html.haml | 2 +- 4 files changed, 9 insertions(+), 3 deletions(-) create mode 100644 app/views/projects/branches/destroy.js.haml diff --git a/app/controllers/projects/branches_controller.rb b/app/controllers/projects/branches_controller.rb index ab8892bbf0..a3ff8b91ea 100644 --- a/app/controllers/projects/branches_controller.rb +++ b/app/controllers/projects/branches_controller.rb @@ -23,11 +23,12 @@ class Projects::BranchesController < Projects::ApplicationController end def destroy + @branch = @repository.find_branch(params[:id]) DeleteBranchService.new.execute(project, params[:id], current_user) respond_to do |format| format.html { redirect_to project_branches_path(@project) } - format.js { render nothing: true } + format.js end end end diff --git a/app/views/projects/branches/_branch.html.haml b/app/views/projects/branches/_branch.html.haml index 2abcd00ee8..54a7b934dd 100644 --- a/app/views/projects/branches/_branch.html.haml +++ b/app/views/projects/branches/_branch.html.haml @@ -1,5 +1,5 @@ - commit = @repository.commit(branch.target) -%li +%li(class="js-branch-#{branch.name}") %h4 = link_to project_tree_path(@project, branch.name) do %strong= truncate(branch.name, length: 60) diff --git a/app/views/projects/branches/destroy.js.haml b/app/views/projects/branches/destroy.js.haml new file mode 100644 index 0000000000..2cba6d3745 --- /dev/null +++ b/app/views/projects/branches/destroy.js.haml @@ -0,0 +1,5 @@ +:plain + $(".js-branch-#{@branch.name}").remove(); + $('.js-recentbranch-count').html("#{@repository.recent_branches.count}") + $('.js-protectedbranch-count').html("#{@project.protected_branches.count}") + $('.js-totalbranch-count').html("#{@repository.branch_names.count}") diff --git a/app/views/projects/commits/_head.html.haml b/app/views/projects/commits/_head.html.haml index 0facfc4b5f..1bb4d9bfab 100644 --- a/app/views/projects/commits/_head.html.haml +++ b/app/views/projects/commits/_head.html.haml @@ -9,7 +9,7 @@ = nav_link(html_options: {class: branches_tab_class}) do = link_to project_branches_path(@project) do Branches - %span.badge= @repository.branches.size + %span.badge.js-totalbranch-count= @repository.branches.size = nav_link(controller: :tags) do = link_to project_tags_path(@project) do From 4ac56fa1db2286848b1bed9df3aeec8685c4cbd3 Mon Sep 17 00:00:00 2001 From: Jeroen van Baarsen Date: Fri, 23 May 2014 20:26:31 +0200 Subject: [PATCH 047/360] Changed some stuff around after rebase --- app/controllers/projects/branches_controller.rb | 2 +- app/views/projects/branches/destroy.js.haml | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/app/controllers/projects/branches_controller.rb b/app/controllers/projects/branches_controller.rb index a3ff8b91ea..3c8e7ec73f 100644 --- a/app/controllers/projects/branches_controller.rb +++ b/app/controllers/projects/branches_controller.rb @@ -23,8 +23,8 @@ class Projects::BranchesController < Projects::ApplicationController end def destroy - @branch = @repository.find_branch(params[:id]) DeleteBranchService.new.execute(project, params[:id], current_user) + @branch_name = params[:id] respond_to do |format| format.html { redirect_to project_branches_path(@project) } diff --git a/app/views/projects/branches/destroy.js.haml b/app/views/projects/branches/destroy.js.haml index 2cba6d3745..ec1661c0aa 100644 --- a/app/views/projects/branches/destroy.js.haml +++ b/app/views/projects/branches/destroy.js.haml @@ -1,5 +1,3 @@ :plain - $(".js-branch-#{@branch.name}").remove(); - $('.js-recentbranch-count').html("#{@repository.recent_branches.count}") - $('.js-protectedbranch-count').html("#{@project.protected_branches.count}") - $('.js-totalbranch-count').html("#{@repository.branch_names.count}") + $(".js-branch-#{@branch_name}").remove(); + $('.js-totalbranch-count').html("#{@repository.branches.size}") From 2490cfbcca368a872a0b66998bf739cc7ded8ae8 Mon Sep 17 00:00:00 2001 From: Sean Edge Date: Fri, 23 May 2014 18:58:49 -0400 Subject: [PATCH 048/360] Update documentaiton for create_tag method. --- doc/api/repositories.md | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/doc/api/repositories.md b/doc/api/repositories.md index 858fad0a0b..f71084c753 100644 --- a/doc/api/repositories.md +++ b/doc/api/repositories.md @@ -35,6 +35,40 @@ Parameters: ] ``` +## Create a new tag + +Creates new tag in the repository that points to the supplied ref. + +``` +POST /projects/:id/repository/tags +``` + +Parameters: + ++ `id` (required) - The ID of a project ++ `tag_name` (required) - The name of a tag ++ `ref` (required) - Create tag using commit sha, another tag name, or branch name. + +```json +[ + { + "name": "v1.0.0", + "commit": { + "id": "2695effb5807a22ff3d138d593fd856244e155e7", + "parents": [], + "message": "Initial commit", + "authored_date": "2012-05-28T04:42:42-07:00", + "author_name": "John Smith", + "author email": "john@example.com" + "committer_name": "Jack Smith", + "committed_date": "2012-05-28T04:42:42-07:00" + "committer_email": "jack@example.com" + }, + "protected": false + } +] +``` + ## List repository tree Get a list of repository files and directories in a project. From cc28b21adce61206e5ca96dfe23bab4cec9a0400 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sat, 24 May 2014 10:30:58 +0300 Subject: [PATCH 049/360] Add drag-n-drop to CHANGELOG Signed-off-by: Dmitriy Zaporozhets --- CHANGELOG | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG b/CHANGELOG index 9d2ac06277..d265d3a0b4 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -7,6 +7,7 @@ v 7.0.0 - Remove branch via API (sponsored by O'Reilly Media) - Move protected branches page to Project settings area - Redirect to Files view when create new branch via UI + - Drag and drop upload of image in every markdown-area (Earle Randolph Bunao and Neil Francis Calabroso) v 6.9.0 - Store Rails cache data in the Redis `cache:gitlab` namespace From 0853eebd1c1d80fdcb467a2cafede6f20e62759f Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sat, 24 May 2014 11:11:45 +0300 Subject: [PATCH 050/360] Improve comments css Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/sections/notes.scss | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/app/assets/stylesheets/sections/notes.scss b/app/assets/stylesheets/sections/notes.scss index 755295be1f..75cb8e5615 100644 --- a/app/assets/stylesheets/sections/notes.scss +++ b/app/assets/stylesheets/sections/notes.scss @@ -83,6 +83,7 @@ ul.notes { overflow: hidden; display: block; position:relative; + border-bottom: 1px solid #eee; p { color: $style_color; } .avatar { @@ -98,22 +99,16 @@ ul.notes { .note-header { padding-bottom: 3px; } + + &:last-child { + border-bottom: none; + } } .note:target { -webkit-animation:target-note 2s linear; background: #fffff0; } - - // paint top or bottom borders depending on notes direction - &:not(.reversed) .note, - &:not(.reversed) .discussion { - border-bottom: 1px solid #eee; - } - &.reversed .note, - &.reversed .discussion { - border-top: 1px solid #eee; - } } .diff-file .notes_holder { @@ -308,14 +303,13 @@ ul.notes { .common-note-form { margin: 0; background: #F9F9F9; - padding: 3px; + padding: 5px; border: 1px solid #DDD; } .note-form-actions { background: #F9F9F9; height: 45px; - padding: 0 5px; .note-form-option { margin-top: 8px; From 5cfaf945cdad16baf877c873c26bc58b004707ae Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sat, 24 May 2014 13:06:44 +0300 Subject: [PATCH 051/360] Improve notes form UI/UX Signed-off-by: Dmitriy Zaporozhets --- .../behaviors/toggler_behavior.coffee | 4 -- .../javascripts/merge_request.js.coffee | 12 +++--- app/assets/javascripts/notes.js.coffee | 30 +++++++++++-- .../stylesheets/generic/markdown_area.scss | 6 --- app/assets/stylesheets/sections/notes.scss | 43 +++++++++++-------- .../projects/merge_requests/_show.html.haml | 2 +- app/views/projects/notes/_form.html.haml | 34 +++++++-------- 7 files changed, 74 insertions(+), 57 deletions(-) diff --git a/app/assets/javascripts/behaviors/toggler_behavior.coffee b/app/assets/javascripts/behaviors/toggler_behavior.coffee index 8ac5bfe95d..1b2ed9efc2 100644 --- a/app/assets/javascripts/behaviors/toggler_behavior.coffee +++ b/app/assets/javascripts/behaviors/toggler_behavior.coffee @@ -1,8 +1,4 @@ $ -> - $("body").on "click", ".js-toggler-target", -> - container = $(".notes-container") - container.toggleClass("on") - # Toggle button. Show/hide content inside parent container. # Button does not change visibility. If button has icon - it changes chevron style. # diff --git a/app/assets/javascripts/merge_request.js.coffee b/app/assets/javascripts/merge_request.js.coffee index 7589fc70cd..b04a81c85e 100644 --- a/app/assets/javascripts/merge_request.js.coffee +++ b/app/assets/javascripts/merge_request.js.coffee @@ -43,7 +43,7 @@ class MergeRequest , 'json' bindEvents: -> - this.$('.nav-tabs').on 'click', 'a', (event) => + this.$('.merge-request-tabs').on 'click', 'a', (event) => a = $(event.currentTarget) href = a.attr('href') @@ -51,7 +51,7 @@ class MergeRequest event.preventDefault() - this.$('.nav-tabs').on 'click', 'li', (event) => + this.$('.merge-request-tabs').on 'click', 'li', (event) => this.activateTab($(event.currentTarget).data('action')) this.$('.accept_merge_request').on 'click', -> @@ -71,15 +71,15 @@ class MergeRequest this.$('.remove_source_branch_widget.failed').show() activateTab: (action) -> - this.$('.nav-tabs li').removeClass 'active' + this.$('.merge-request-tabs li').removeClass 'active' this.$('.tab-content').hide() switch action when 'diffs' - this.$('.nav-tabs .diffs-tab').addClass 'active' + this.$('.merge-request-tabs .diffs-tab').addClass 'active' this.loadDiff() unless @diffs_loaded this.$('.diffs').show() else - this.$('.nav-tabs .notes-tab').addClass 'active' + this.$('.merge-request-tabs .notes-tab').addClass 'active' this.$('.notes').show() showState: (state) -> @@ -107,7 +107,7 @@ class MergeRequest loadDiff: (event) -> $.ajax type: 'GET' - url: this.$('.nav-tabs .diffs-tab a').attr('href') + url: this.$('.merge-request-tabs .diffs-tab a').attr('href') beforeSend: => this.$('.status').addClass 'loading' complete: => diff --git a/app/assets/javascripts/notes.js.coffee b/app/assets/javascripts/notes.js.coffee index 4510718c2f..5be001e0a2 100644 --- a/app/assets/javascripts/notes.js.coffee +++ b/app/assets/javascripts/notes.js.coffee @@ -32,6 +32,9 @@ class Notes # Preview button $(document).on "click", ".js-note-preview-button", @previewNote + # Preview button + $(document).on "click", ".js-note-write-button", @writeNote + # reset main target form after submit $(document).on "ajax:complete", ".js-main-target-form", @resetMainTargetForm @@ -68,6 +71,7 @@ class Notes $(document).off "click", ".js-note-delete" $(document).off "click", ".js-note-attachment-delete" $(document).off "click", ".js-note-preview-button" + $(document).off "click", ".js-note-write-button" $(document).off "ajax:complete", ".js-main-target-form" $(document).off "click", ".js-choose-note-attachment-button" $(document).off "click", ".js-discussion-reply-button" @@ -144,16 +148,36 @@ class Notes # cleanup after successfully creating a diff/discussion note @removeDiscussionNoteForm(form) + ### + Shows write note textarea. + ### + writeNote: (e) -> + e.preventDefault() + form = $(this).closest("form") + # toggle tabs + form.find(".js-note-write-button").parent().addClass "active" + form.find(".js-note-preview-button").parent().removeClass "active" + + # toggle content + form.find(".note-write-holder").show() + form.find(".note-preview-holder").hide() + ### Shows the note preview. Lets the server render GFM into Html and displays it. - - Note: uses the Toggler behavior to toggle preview/edit views/buttons ### previewNote: (e) -> e.preventDefault() form = $(this).closest("form") + # toggle tabs + form.find(".js-note-write-button").parent().removeClass "active" + form.find(".js-note-preview-button").parent().addClass "active" + + # toggle content + form.find(".note-write-holder").hide() + form.find(".note-preview-holder").show() + preview = form.find(".js-note-preview") noteText = form.find(".js-note-text").val() if noteText.trim().length is 0 @@ -179,7 +203,7 @@ class Notes form.find(".js-errors").remove() # reset text and preview - previewContainer = form.find(".js-toggler-container.note_text_and_preview") + previewContainer = form.find(".note-edit-and-preview") previewContainer.removeClass "on" if previewContainer.is(".on") form.find(".js-note-text").val("").trigger "input" diff --git a/app/assets/stylesheets/generic/markdown_area.scss b/app/assets/stylesheets/generic/markdown_area.scss index a1fe18b02f..fbfa72c5e5 100644 --- a/app/assets/stylesheets/generic/markdown_area.scss +++ b/app/assets/stylesheets/generic/markdown_area.scss @@ -43,12 +43,6 @@ display: none; } } - - .hint { - float: left; - padding: 0; - margin: 0; - } } .div-dropzone-alert { diff --git a/app/assets/stylesheets/sections/notes.scss b/app/assets/stylesheets/sections/notes.scss index 75cb8e5615..2758f57bd5 100644 --- a/app/assets/stylesheets/sections/notes.scss +++ b/app/assets/stylesheets/sections/notes.scss @@ -135,10 +135,6 @@ ul.notes { border-width: 1px 0; padding-top: 0; vertical-align: top; - - li { - padding: 5px; - } } } @@ -266,24 +262,33 @@ ul.notes { .clearfix { margin-bottom: 0; } - .note_text_and_preview { - .note_preview { - background: #f5f5f5; - border: 1px solid #ddd; - @include border-radius(4px); - min-height: 80px; - padding: 4px 6px; - > p { - overflow-x: auto; - } + .note-preview-holder, + .note_text { + background: #FFF; + border: 1px solid #ddd; + min-height: 100px; + padding: 5px; + font-size: 14px; + box-shadow: none; + } + + .note-preview-holder { + > p { + overflow-x: auto; } - .note_text { + } + + .note_text { + width: 100%; + } + .nav-tabs { + margin-bottom: 0; + border: none; + + li a, + li.active a { border: 1px solid #DDD; - box-shadow: none; - font-size: 14px; - height: 80px; - width: 100%; } } } diff --git a/app/views/projects/merge_requests/_show.html.haml b/app/views/projects/merge_requests/_show.html.haml index 193c600f77..0166b988e5 100644 --- a/app/views/projects/merge_requests/_show.html.haml +++ b/app/views/projects/merge_requests/_show.html.haml @@ -7,7 +7,7 @@ = render "projects/merge_requests/show/participants" - if @commits.present? - %ul.nav.nav-tabs + %ul.nav.nav-tabs.merge-request-tabs %li.notes-tab{data: {action: 'notes'}} = link_to project_merge_request_path(@project, @merge_request) do %i.icon-comment diff --git a/app/views/projects/notes/_form.html.haml b/app/views/projects/notes/_form.html.haml index cadae9da80..2e84dcea89 100644 --- a/app/views/projects/notes/_form.html.haml +++ b/app/views/projects/notes/_form.html.haml @@ -5,21 +5,28 @@ = f.hidden_field :noteable_id = f.hidden_field :noteable_type - .note_text_and_preview.js-toggler-container.notes-container - = f.text_area :note, size: 255, class: 'note_text js-note-text js-gfm-input turn-on markdown-area' - .note_preview.js-note-preview.turn-off + %ul.nav.nav-tabs + %li.active + = link_to '#note-write-holder', class: 'js-note-write-button' do + Write + %li + = link_to '#note-preview-holder', class: 'js-note-preview-button', data: { url: preview_project_notes_path(@project) } do + Preview + %div + .note-write-holder + = f.text_area :note, size: 255, class: 'note_text js-note-text js-gfm-input markdown-area' - .hint - .pull-left Comments are parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}. - .pull-right Attach images (JPG, PNG, GIF) by dragging & dropping or #{link_to "selecting them", '#', class: 'markdown-selector' }. - .clearfix - .error-alert + .light.clearfix + .pull-left Comments are parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}. + .pull-right Attach images (JPG, PNG, GIF) by dragging & dropping or #{link_to "selecting them", '#', class: 'markdown-selector' }. + + .note-preview-holder.hide + .js-note-preview .note-form-actions .buttons = f.submit 'Add Comment', class: "btn comment-btn btn-grouped js-comment-button" = yield(:note_actions) - %a.btn.grouped.js-close-discussion-note-form Cancel .note-form-option @@ -30,14 +37,5 @@ %span.file_name.js-attachment-filename File name... = f.file_field :attachment, class: "js-note-attachment-input hidden" - .write-preview-btn - %a.btn.js-note-preview-button.js-toggler-target.turn-off{ href: "javascript:;", data: {url: preview_project_notes_path(@project)} } - %i.icon-eye-open - Preview - %a.btn.btn-primary.js-note-edit-button.js-toggler-target.turn-off{ href: "javascript:;" } - %i.icon-edit - Write - .clearfix - :javascript window.project_image_path_upload = "#{upload_image_project_path @project}"; From 50f3280e019290a1c1434967f0beb24c0e938e9d Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sat, 24 May 2014 13:15:23 +0300 Subject: [PATCH 052/360] Remove unused css Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/behaviors.scss | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/app/assets/stylesheets/behaviors.scss b/app/assets/stylesheets/behaviors.scss index 64e3c8d9ac..23f206ce3d 100644 --- a/app/assets/stylesheets/behaviors.scss +++ b/app/assets/stylesheets/behaviors.scss @@ -4,20 +4,3 @@ .js-details-container .content.hide { display: block; } .js-details-container.open .content { display: block; } .js-details-container.open .content.hide { display: none; } - -// Toggler -//-------- -.write-preview-btn .turn-on { display: inherit; } -.write-preview-btn .turn-off { display: none; } - -.js-toggler-container .turn-off { display: none; } -.js-toggler-container.on .turn-on { display: none; } -.js-toggler-container.on .turn-off { display: inherit; } - -.js-toggler-container.on ~ .note-form-actions { - .write-preview-btn .turn-on { display: none; } -} - -.js-toggler-container.on ~ .note-form-actions { - .write-preview-btn .turn-off { display: inherit; } -} From 1bb9aeb565fca50304881e36488b202455bdddd2 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sat, 24 May 2014 14:10:36 +0300 Subject: [PATCH 053/360] Fix specs. Fix note form reset after submit Signed-off-by: Dmitriy Zaporozhets --- app/assets/javascripts/notes.js.coffee | 5 ++--- spec/features/notes_on_merge_requests_spec.rb | 2 +- .../features/security/project/internal_access_spec.rb | 11 ----------- spec/features/security/project/private_access_spec.rb | 11 ----------- spec/features/security/project/public_access_spec.rb | 11 ----------- 5 files changed, 3 insertions(+), 37 deletions(-) diff --git a/app/assets/javascripts/notes.js.coffee b/app/assets/javascripts/notes.js.coffee index 5be001e0a2..a41ee67a84 100644 --- a/app/assets/javascripts/notes.js.coffee +++ b/app/assets/javascripts/notes.js.coffee @@ -203,8 +203,7 @@ class Notes form.find(".js-errors").remove() # reset text and preview - previewContainer = form.find(".note-edit-and-preview") - previewContainer.removeClass "on" if previewContainer.is(".on") + form.find(".js-note-write-button").click() form.find(".js-note-text").val("").trigger "input" ### @@ -254,7 +253,7 @@ class Notes form.removeClass "js-new-note-form" # setup preview buttons - form.find(".js-note-edit-button, .js-note-preview-button").tooltip placement: "left" + form.find(".js-note-write-button, .js-note-preview-button").tooltip placement: "left" previewButton = form.find(".js-note-preview-button") form.find(".js-note-text").on "input", -> if $(this).val().trim() isnt "" diff --git a/spec/features/notes_on_merge_requests_spec.rb b/spec/features/notes_on_merge_requests_spec.rb index 45aebf128c..7f1da3cffd 100644 --- a/spec/features/notes_on_merge_requests_spec.rb +++ b/spec/features/notes_on_merge_requests_spec.rb @@ -44,7 +44,7 @@ describe "On a merge request", js: true, feature: true do it 'should have text and visible edit button' do within(".js-main-target-form") { should have_css(".js-note-preview", text: "This is awesome", visible: true) } within(".js-main-target-form") { should have_css(".js-note-preview-button", visible: false) } - within(".js-main-target-form") { should have_css(".js-note-edit-button", visible: true) } + within(".js-main-target-form") { should have_css(".js-note-write-button", visible: true) } end end end diff --git a/spec/features/security/project/internal_access_spec.rb b/spec/features/security/project/internal_access_spec.rb index f6ab47ed91..eb8422df59 100644 --- a/spec/features/security/project/internal_access_spec.rb +++ b/spec/features/security/project/internal_access_spec.rb @@ -190,17 +190,6 @@ describe "Internal Project Access", feature: true do it { should be_denied_for :visitor } end - describe "GET /:project_path/branches/recent" do - subject { recent_project_branches_path(project) } - - it { should be_allowed_for master } - it { should be_allowed_for reporter } - it { should be_allowed_for :admin } - it { should be_allowed_for guest } - it { should be_allowed_for :user } - it { should be_denied_for :visitor } - end - describe "GET /:project_path/branches" do subject { project_branches_path(project) } diff --git a/spec/features/security/project/private_access_spec.rb b/spec/features/security/project/private_access_spec.rb index 8a0fcb8e9f..186ad35046 100644 --- a/spec/features/security/project/private_access_spec.rb +++ b/spec/features/security/project/private_access_spec.rb @@ -168,17 +168,6 @@ describe "Private Project Access", feature: true do it { should be_denied_for :visitor } end - describe "GET /:project_path/branches/recent" do - subject { recent_project_branches_path(project) } - - it { should be_allowed_for master } - it { should be_allowed_for reporter } - it { should be_allowed_for :admin } - it { should be_denied_for guest } - it { should be_denied_for :user } - it { should be_denied_for :visitor } - end - describe "GET /:project_path/branches" do subject { project_branches_path(project) } diff --git a/spec/features/security/project/public_access_spec.rb b/spec/features/security/project/public_access_spec.rb index eb511bfefe..f5d1cf7b97 100644 --- a/spec/features/security/project/public_access_spec.rb +++ b/spec/features/security/project/public_access_spec.rb @@ -195,17 +195,6 @@ describe "Public Project Access", feature: true do it { should be_denied_for :visitor } end - describe "GET /:project_path/branches/recent" do - subject { recent_project_branches_path(project) } - - it { should be_allowed_for master } - it { should be_allowed_for reporter } - it { should be_allowed_for :admin } - it { should be_allowed_for guest } - it { should be_allowed_for :user } - it { should be_allowed_for :visitor } - end - describe "GET /:project_path/branches" do subject { project_branches_path(project) } From 5a1429ae2110faaf354574f8e6c7866c29102107 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sat, 24 May 2014 14:20:12 +0300 Subject: [PATCH 054/360] Fix branches tests Signed-off-by: Dmitriy Zaporozhets --- features/project/commits/branches.feature | 11 ++++------- features/steps/project/browse_branches.rb | 5 ----- features/steps/shared/paths.rb | 4 ++++ 3 files changed, 8 insertions(+), 12 deletions(-) diff --git a/features/project/commits/branches.feature b/features/project/commits/branches.feature index fcf8b7694f..abebef04fc 100644 --- a/features/project/commits/branches.feature +++ b/features/project/commits/branches.feature @@ -3,20 +3,17 @@ Feature: Project Browse branches Given I sign in as a user And I own project "Shop" And project "Shop" has protected branches - Given I visit project branches page - - Scenario: I can see project recent git branches - Then I should see "Shop" recent branches list Scenario: I can see project all git branches - Given I click link "All" + Given I visit project branches page Then I should see "Shop" all branches list Scenario: I can see project protected git branches - Given I click link "Protected" + Given I visit project protected branches page Then I should see "Shop" protected branches list Scenario: I create a branch - Given I click new branch link + Given I visit project branches page + And I click new branch link When I submit new branch form Then I should see new branch created diff --git a/features/steps/project/browse_branches.rb b/features/steps/project/browse_branches.rb index 5b5e8ba493..7a0625952d 100644 --- a/features/steps/project/browse_branches.rb +++ b/features/steps/project/browse_branches.rb @@ -3,11 +3,6 @@ class ProjectBrowseBranches < Spinach::FeatureSteps include SharedProject include SharedPaths - step 'I should see "Shop" recent branches list' do - page.should have_content "Branches" - page.should have_content "master" - end - step 'I click link "All"' do click_link "All" end diff --git a/features/steps/shared/paths.rb b/features/steps/shared/paths.rb index a0213815a7..d36ff7e388 100644 --- a/features/steps/shared/paths.rb +++ b/features/steps/shared/paths.rb @@ -240,6 +240,10 @@ module SharedPaths visit project_branches_path(@project) end + step 'I visit project protected branches page' do + visit project_protected_branches_path(@project) + end + step 'I visit compare refs page' do visit project_compare_index_path(@project) end From bbc4b2be8db5166ce54a81e6f25ffe48fa293a5f Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sat, 24 May 2014 14:26:15 +0300 Subject: [PATCH 055/360] Fix help tests Signed-off-by: Dmitriy Zaporozhets --- app/views/help/raketasks.html.haml | 15 ++------------- features/steps/help.rb | 2 +- 2 files changed, 3 insertions(+), 14 deletions(-) diff --git a/app/views/help/raketasks.html.haml b/app/views/help/raketasks.html.haml index 17a02e913e..61a3774a13 100644 --- a/app/views/help/raketasks.html.haml +++ b/app/views/help/raketasks.html.haml @@ -6,8 +6,6 @@ %ul.nav.nav-tabs.log-tabs %li.active - = link_to "Features", "#features", 'data-toggle' => 'tab' - %li = link_to "Maintenance", "#maintenance", 'data-toggle' => 'tab' %li = link_to "User Management", "#user_management", 'data-toggle' => 'tab' @@ -17,16 +15,7 @@ = link_to "Cleanup", "#cleanup", 'data-toggle' => 'tab' .tab-content - .tab-pane.active#features - .file-holder - .file-title - %i.icon-file - Features - .file-content.wiki - = preserve do - = markdown File.read(Rails.root.join("doc", "raketasks", "features.md")) - - .tab-pane#maintenance + .tab-pane.active#maintenance .file-holder .file-title %i.icon-file @@ -57,7 +46,7 @@ .file-holder .file-title %i.icon-file - Backup & Restore + Backup & Restore .file-content.wiki = preserve do = markdown File.read(Rails.root.join("doc", "raketasks", "backup_restore.md")) diff --git a/features/steps/help.rb b/features/steps/help.rb index aa147fd65c..5ea2c5daee 100644 --- a/features/steps/help.rb +++ b/features/steps/help.rb @@ -16,6 +16,6 @@ class Spinach::Features::Help < Spinach::FeatureSteps end step 'Header "Rebuild project satellites" should have correct ids and links' do - header_should_have_correct_id_and_link(3, 'Rebuild project satellites', 'rebuild-project-satellites') + header_should_have_correct_id_and_link(3, '(Re-)Create satellite repos', 're-create-satellite-repos') end end From ef933ae69bb48fd186c650927bff7d52a3956174 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sat, 24 May 2014 14:41:13 +0300 Subject: [PATCH 056/360] Even more tests fixed :) Signed-off-by: Dmitriy Zaporozhets --- features/steps/shared/diff_note.rb | 2 +- features/steps/shared/note.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/features/steps/shared/diff_note.rb b/features/steps/shared/diff_note.rb index f80d8d0647..f917d7bde0 100644 --- a/features/steps/shared/diff_note.rb +++ b/features/steps/shared/diff_note.rb @@ -138,7 +138,7 @@ module SharedDiffNote Then 'I should see the diff comment edit button' do within(".diff-file") do - page.should have_css(".js-note-edit-button", visible: true) + page.should have_css(".js-note-write-button", visible: true) end end diff --git a/features/steps/shared/note.rb b/features/steps/shared/note.rb index 36b81b7418..1c52d4c72d 100644 --- a/features/steps/shared/note.rb +++ b/features/steps/shared/note.rb @@ -81,7 +81,7 @@ module SharedNote Then 'I should see the comment edit button' do within(".js-main-target-form") do - page.should have_css(".js-note-edit-button", visible: true) + page.should have_css(".js-note-write-button", visible: true) end end From cc1dd324643db07bdb29f3673995a8ad0dffa2df Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Sat, 24 May 2014 20:05:02 +0300 Subject: [PATCH 057/360] Add pkgr.io to readme one-click installation methods --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index cbbfebc81e..283336b9e4 100644 --- a/README.md +++ b/README.md @@ -65,6 +65,8 @@ * [Cloud 66 deployment and management](http://blog.cloud66.com/installing-gitlab-ubuntu/) Use Cloud 66 to deploy GitLab to your own server or any cloud (eg. DigitalOcean, AWS, Rackspace, GCE) and then manage it with database backups, scaling and more. +* [Pkgr.io one-click installer](https://pkgr.io/apps/gitlabhq/gitlabhq) Currently supporting Ubuntu 14.04, Ubuntu 12.04 and Debian 7.4. For more information check the [README](https://gitlab.com/gitlab-org/gitlab-recipes/blob/master/install/pkgr/README.md) at gitlab-recipes repo. + #### Unofficial installation methods * [GitLab recipes](https://gitlab.com/gitlab-org/gitlab-recipes/) repository with unofficial guides for using GitLab with different software (operating systems, webservers, etc.) than the official version. From 23bcb9cb0d294611c3bcd1b453dd67ee73d50dff Mon Sep 17 00:00:00 2001 From: dosire Date: Mon, 26 May 2014 09:09:27 +0200 Subject: [PATCH 058/360] A regressions issue to improve communication. --- doc/release/monthly.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/doc/release/monthly.md b/doc/release/monthly.md index ed580f666a..667e3048a5 100644 --- a/doc/release/monthly.md +++ b/doc/release/monthly.md @@ -201,6 +201,15 @@ Include a link to the blog post and keep it short. Proposed email for CE: "We have released a new version of GitLab Community Edition and its packages. See our blog post() for more information." +### **10. Create a regressions issue** + +On [the GitLab CE issue tracker on GitLab.com](https://gitlab.com/gitlab-org/gitlab-ce/issues/) create and issue titled "GitLab X.X.X regressions", assign it to the release manager, /cc all the core-team members active on the issue tracker add the following text: + +This is a meta issue to discuss possible regressions in this release and any patch versions. +Please do not raise issues directly in this issue but link to issues that might warrant a patch release. +The decision to create a patch release or not is with the release manager who is assigned to this issue. +The release manager will comment here about the plans for patch releases. + # **23rd - Optional Patch Release** # **24th - Update GitLab.com** From 9f6709d8c4bcd72cfa7c52f7e3158da6d117b273 Mon Sep 17 00:00:00 2001 From: dosire Date: Mon, 26 May 2014 09:11:09 +0200 Subject: [PATCH 059/360] Have the issue for the entire monthly time. --- doc/release/monthly.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/release/monthly.md b/doc/release/monthly.md index 667e3048a5..e538baa375 100644 --- a/doc/release/monthly.md +++ b/doc/release/monthly.md @@ -203,9 +203,9 @@ Proposed email for CE: "We have released a new version of GitLab Community Editi ### **10. Create a regressions issue** -On [the GitLab CE issue tracker on GitLab.com](https://gitlab.com/gitlab-org/gitlab-ce/issues/) create and issue titled "GitLab X.X.X regressions", assign it to the release manager, /cc all the core-team members active on the issue tracker add the following text: +On [the GitLab CE issue tracker on GitLab.com](https://gitlab.com/gitlab-org/gitlab-ce/issues/) create and issue titled "GitLab X.X regressions", assign it to the release manager, /cc all the core-team members active on the issue tracker add the following text: -This is a meta issue to discuss possible regressions in this release and any patch versions. +This is a meta issue to discuss possible regressions in this monthly release and any patch versions. Please do not raise issues directly in this issue but link to issues that might warrant a patch release. The decision to create a patch release or not is with the release manager who is assigned to this issue. The release manager will comment here about the plans for patch releases. From f39d8a8a6006ab8d5e3aa747036be586684718aa Mon Sep 17 00:00:00 2001 From: dosire Date: Mon, 26 May 2014 09:12:57 +0200 Subject: [PATCH 060/360] Add any known bugs. --- doc/release/monthly.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/release/monthly.md b/doc/release/monthly.md index e538baa375..19c310ac3e 100644 --- a/doc/release/monthly.md +++ b/doc/release/monthly.md @@ -203,13 +203,15 @@ Proposed email for CE: "We have released a new version of GitLab Community Editi ### **10. Create a regressions issue** -On [the GitLab CE issue tracker on GitLab.com](https://gitlab.com/gitlab-org/gitlab-ce/issues/) create and issue titled "GitLab X.X regressions", assign it to the release manager, /cc all the core-team members active on the issue tracker add the following text: +On [the GitLab CE issue tracker on GitLab.com](https://gitlab.com/gitlab-org/gitlab-ce/issues/) create and issue titled "GitLab X.X regressions" add the following text: This is a meta issue to discuss possible regressions in this monthly release and any patch versions. Please do not raise issues directly in this issue but link to issues that might warrant a patch release. The decision to create a patch release or not is with the release manager who is assigned to this issue. The release manager will comment here about the plans for patch releases. +Assign the issue to the release manager and /cc all the core-team members active on the issue tracker. If there are any known bugs in the release add them immediately. + # **23rd - Optional Patch Release** # **24th - Update GitLab.com** From 1748073315e18a1211ca9502d5d227e95d844bcc Mon Sep 17 00:00:00 2001 From: dosire Date: Mon, 26 May 2014 09:14:44 +0200 Subject: [PATCH 061/360] Correct typo. --- doc/release/monthly.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/release/monthly.md b/doc/release/monthly.md index 19c310ac3e..390ec42260 100644 --- a/doc/release/monthly.md +++ b/doc/release/monthly.md @@ -203,7 +203,7 @@ Proposed email for CE: "We have released a new version of GitLab Community Editi ### **10. Create a regressions issue** -On [the GitLab CE issue tracker on GitLab.com](https://gitlab.com/gitlab-org/gitlab-ce/issues/) create and issue titled "GitLab X.X regressions" add the following text: +On [the GitLab CE issue tracker on GitLab.com](https://gitlab.com/gitlab-org/gitlab-ce/issues/) create an issue titled "GitLab X.X regressions" add the following text: This is a meta issue to discuss possible regressions in this monthly release and any patch versions. Please do not raise issues directly in this issue but link to issues that might warrant a patch release. From 8bec6b0bcb100b30a43fcd9c6649d1bee113b6a7 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Mon, 26 May 2014 14:17:46 +0200 Subject: [PATCH 062/360] Make existing tests test something, return correct errors. --- app/controllers/projects_controller.rb | 19 ++++++++++++++----- app/uploaders/file_uploader.rb | 2 +- spec/controllers/projects_controller_spec.rb | 17 +++++++++-------- 3 files changed, 24 insertions(+), 14 deletions(-) diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index c15205fb68..3144ece977 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -164,12 +164,21 @@ class ProjectsController < ApplicationController def upload_image uploader = FileUploader.new('uploads', upload_path, accepted_images) - alt = params['markdown_img'].original_filename - uploader.store!(params['markdown_img']) - link = { 'alt' => File.basename(alt, '.*'), - 'url' => File.join(root_url, uploader.url) } + image = params['markdown_img'] + + if image && accepted_images.map{ |format| image.content_type.include? format }.any? + alt = image.original_filename + uploader.store!(image) + link = { 'alt' => File.basename(alt, '.*'), + 'url' => File.join(root_url, uploader.url) } + end + respond_to do |format| - format.json { render json: { link: link } } + if link + format.json { render json: { link: link } } + else + format.json { render json: "Invalid file.", status: :unprocessable_entity } + end end end diff --git a/app/uploaders/file_uploader.rb b/app/uploaders/file_uploader.rb index cbc9271ac1..0fa987c93f 100644 --- a/app/uploaders/file_uploader.rb +++ b/app/uploaders/file_uploader.rb @@ -25,7 +25,7 @@ class FileUploader < CarrierWave::Uploader::Base end def store!(file) - file.original_filename = self.class.generate_filename(file) + @filename = self.class.generate_filename(file) super end diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb index 07ca8d2502..1d465d4996 100644 --- a/spec/controllers/projects_controller_spec.rb +++ b/spec/controllers/projects_controller_spec.rb @@ -11,34 +11,35 @@ describe ProjectsController do describe "POST #upload_image" do before do sign_in(user) + project.team << [user, :developer] end context "without params['markdown_img']" do it "returns an error" do - post :upload_image, id: project.to_param - expect(response.status).to eq(404) + post :upload_image, id: project.to_param, format: :json + expect(response.status).to eq(422) end end context "with invalid file" do before do - post :upload_image, id: project.to_param, markdown_img: @img + post :upload_image, id: project.to_param, markdown_img: txt, format: :json end it "returns an error" do - expect(response.status).to eq(404) + expect(response.status).to eq(422) end end context "with valid file" do before do - post :upload_image, id: project.to_param, markdown_img: @img + post :upload_image, id: project.to_param, markdown_img: jpg, format: :json end it "returns a content with original filename and new link." do - link = { alt: 'rails_sample', link: '' }.to_json - expect(response.body).to have_content link + expect(response.body).to match "\"alt\":\"rails_sample\"" + expect(response.body).to match "\"url\":\"http://test.host/uploads/#{project.path_with_namespace}" end end end -end \ No newline at end of file +end From 3b2b3cff04993c7247e953c10aa8c6fb5e8d6ddb Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Mon, 26 May 2014 14:53:34 +0200 Subject: [PATCH 063/360] Move logic to image_service. --- app/controllers/projects_controller.rb | 14 ++------ app/services/projects/image_service.rb | 39 +++++++++++++++++++++ spec/controllers/commits_controller_spec.rb | 2 +- 3 files changed, 43 insertions(+), 12 deletions(-) create mode 100644 app/services/projects/image_service.rb diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 3144ece977..07ccbd57fa 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -163,19 +163,11 @@ class ProjectsController < ApplicationController end def upload_image - uploader = FileUploader.new('uploads', upload_path, accepted_images) - image = params['markdown_img'] - - if image && accepted_images.map{ |format| image.content_type.include? format }.any? - alt = image.original_filename - uploader.store!(image) - link = { 'alt' => File.basename(alt, '.*'), - 'url' => File.join(root_url, uploader.url) } - end + link_to_image = ::Projects::ImageService.new(repository, params, root_url).execute respond_to do |format| - if link - format.json { render json: { link: link } } + if link_to_image + format.json { render json: { link: link_to_image } } else format.json { render json: "Invalid file.", status: :unprocessable_entity } end diff --git a/app/services/projects/image_service.rb b/app/services/projects/image_service.rb new file mode 100644 index 0000000000..c79ddddd97 --- /dev/null +++ b/app/services/projects/image_service.rb @@ -0,0 +1,39 @@ +module Projects + class ImageService < BaseService + include Rails.application.routes.url_helpers + def initialize(repository, params, root_url) + @repository, @params, @root_url = repository, params.dup, root_url + end + + def execute + uploader = FileUploader.new('uploads', upload_path, accepted_images) + image = @params['markdown_img'] + + if image && correct_mime_type?(image) + alt = image.original_filename + uploader.store!(image) + link = { + 'alt' => File.basename(alt, '.*'), + 'url' => File.join(@root_url, uploader.url) + } + else + link = nil + end + end + + protected + + def upload_path + base_dir = FileUploader.generate_dir + File.join(@repository.path_with_namespace, base_dir) + end + + def accepted_images + %w(png jpg jpeg gif) + end + + def correct_mime_type?(image) + accepted_images.map{ |format| image.content_type.include? format }.any? + end + end +end diff --git a/spec/controllers/commits_controller_spec.rb b/spec/controllers/commits_controller_spec.rb index 308cfa6921..0c19d755eb 100644 --- a/spec/controllers/commits_controller_spec.rb +++ b/spec/controllers/commits_controller_spec.rb @@ -6,7 +6,7 @@ describe Projects::CommitsController do before do sign_in(user) - project.creator = user + project.team << [user, :master] end describe "GET show" do From f441436e53377f207657ac0e0e518e5ee2b33a6c Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 26 May 2014 16:08:22 +0300 Subject: [PATCH 064/360] Add compare branches endpoint to API Signed-off-by: Dmitriy Zaporozhets --- doc/api/repositories.md | 66 +++++++++++++++++++++++++++++++++++++++++ lib/api/entities.rb | 17 +++++++++++ lib/api/repositories.rb | 16 ++++++++++ 3 files changed, 99 insertions(+) diff --git a/doc/api/repositories.md b/doc/api/repositories.md index 858fad0a0b..2cd387275e 100644 --- a/doc/api/repositories.md +++ b/doc/api/repositories.md @@ -131,3 +131,69 @@ GET /projects/:id/repository/archive Parameters: + `id` (required) - The ID of a project + `sha` (optional) - The commit sha to download defaults to the tip of the default branch + + +## Compare branches, tags or commits + +``` +GET /projects/:id/repository/compare +``` + +Parameters: ++ `id` (required) - The ID of a project ++ `from` (required) - the commit sha or branch name ++ `to` (required) - the commit sha or branch name + + +``` +GET /projects/:id/repository/compare?from=master&to=feature +``` + +Response: + +```json +{ + "commit": { + "id": "72e10ef47e770a95439255b2c49de722e8782106", + "short_id": "72e10ef47e7", + "title": "Add NEWFILE", + "author_name": "Dmitriy Zaporozhets", + "author_email": "dmitriy.zaporozhets@gmail.com", + "created_at": "2014-05-26T16:03:54+03:00" + }, + "commits": [{ + "id": "0b4bc9a49b562e85de7cc9e834518ea6828729b9", + "short_id": "0b4bc9a49b5", + "title": "Feature added", + "author_name": "Dmitriy Zaporozhets", + "author_email": "dmitriy.zaporozhets@gmail.com", + "created_at": "2014-02-27T10:26:01+02:00" + }, { + "id": "72e10ef47e770a95439255b2c49de722e8782106", + "short_id": "72e10ef47e7", + "title": "Add NEWFILE", + "author_name": "Dmitriy Zaporozhets", + "author_email": "dmitriy.zaporozhets@gmail.com", + "created_at": "2014-05-26T16:03:54+03:00" + }], + "diffs": [{ + "old_path": "NEWFILE", + "new_path": "NEWFILE", + "a_mode": null, + "b_mode": null, + "diff": "--- /dev/null\n+++ b/NEWFILE\n@@ -0,0 +1 @@\n+This is NEWFILE content\n\\ No newline at end of file", + "new_file": true, + "renamed_file": false, + "deleted_file": false + }, { + "old_path": "files/ruby/feature.rb", + "new_path": "files/ruby/feature.rb", + "a_mode": null, + "b_mode": null, + "diff": "--- /dev/null\n+++ b/files/ruby/feature.rb\n@@ -0,0 +1,5 @@\n+class Feature\n+ def foo\n+ puts 'bar'\n+ end\n+end", + "new_file": true, + "renamed_file": false, + "deleted_file": false + }] +} +``` diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 457af52fe9..eead8b18eb 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -194,5 +194,22 @@ module API class Label < Grape::Entity expose :name end + + class RepoDiff < Grape::Entity + expose :old_path, :new_path, :a_mode, :b_mode, :diff + expose :new_file, :renamed_file, :deleted_file + end + + class Compare < Grape::Entity + expose :commit, using: Entities::RepoCommit do |compare, options| + Commit.new compare.commit + end + expose :commits, using: Entities::RepoCommit do |compare, options| + Commit.decorate compare.commits + end + expose :diffs, using: Entities::RepoDiff do |compare, options| + compare.diffs + end + end end end diff --git a/lib/api/repositories.rb b/lib/api/repositories.rb index 076a9ceeb7..d59c25cf31 100644 --- a/lib/api/repositories.rb +++ b/lib/api/repositories.rb @@ -15,6 +15,7 @@ module API not_found! end end + # Get a project repository tags # # Parameters: @@ -118,6 +119,21 @@ module API not_found! end end + + # Compare two branches, tags or commits + # + # Parameters: + # id (required) - The ID of a project + # from (required) - the commit sha or branch name + # to (required) - the commit sha or branch name + # Example Request: + # GET /projects/:id/repository/compare?from=master&to=feature + get ':id/repository/compare' do + authorize! :download_code, user_project + compare = Gitlab::Git::Compare.new(user_project.repository.raw_repository, params[:from], params[:to], MergeRequestDiff::COMMITS_SAFE_SIZE) + + present compare, with: Entities::Compare + end end end end From 9c046fea676b65c4883707fad22ceb8dd0e7525e Mon Sep 17 00:00:00 2001 From: skv Date: Mon, 26 May 2014 16:40:10 +0400 Subject: [PATCH 065/360] links to issues on main dashboard --- app/helpers/gitlab_markdown_helper.rb | 2 +- app/helpers/issues_helper.rb | 82 ++++++++--------- app/views/events/_commit.html.haml | 2 +- lib/gitlab/markdown.rb | 97 +++++++++++++-------- lib/gitlab/reference_extractor.rb | 2 +- spec/helpers/gitlab_markdown_helper_spec.rb | 3 +- 6 files changed, 110 insertions(+), 78 deletions(-) diff --git a/app/helpers/gitlab_markdown_helper.rb b/app/helpers/gitlab_markdown_helper.rb index 69425bc171..39ec5672fc 100644 --- a/app/helpers/gitlab_markdown_helper.rb +++ b/app/helpers/gitlab_markdown_helper.rb @@ -19,7 +19,7 @@ module GitlabMarkdownHelper escape_once(body) end - gfm_body = gfm(escaped_body, html_options) + gfm_body = gfm(escaped_body, @project, html_options) gfm_body.gsub!(%r{.*?}m) do |match| "#{match}#{link_to("", url, html_options)[0..-5]}" # "".length +1 diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb index 7c58908165..2031519c32 100644 --- a/app/helpers/issues_helper.rb +++ b/app/helpers/issues_helper.rb @@ -13,76 +13,80 @@ module IssuesHelper OpenStruct.new(id: 0, title: 'None (backlog)', name: 'Unassigned') end - def url_for_project_issues - return "" if @project.nil? + def url_for_project_issues(project = @project) + return '' if project.nil? - if @project.used_default_issues_tracker? || !external_issues_tracker_enabled? - project_issues_path(@project) + if project.used_default_issues_tracker? || !external_issues_tracker_enabled? + project_issues_path(project) else - url = Gitlab.config.issues_tracker[@project.issues_tracker]["project_url"] - url.gsub(':project_id', @project.id.to_s) - .gsub(':issues_tracker_id', @project.issues_tracker_id.to_s) + url = Gitlab.config.issues_tracker[project.issues_tracker]['project_url'] + url.gsub(':project_id', project.id.to_s). + gsub(':issues_tracker_id', project.issues_tracker_id.to_s) end end - def url_for_new_issue - return "" if @project.nil? + def url_for_new_issue(project = @project) + return '' if project.nil? - if @project.used_default_issues_tracker? || !external_issues_tracker_enabled? - url = new_project_issue_path project_id: @project + if project.used_default_issues_tracker? || !external_issues_tracker_enabled? + url = new_project_issue_path project_id: project else - url = Gitlab.config.issues_tracker[@project.issues_tracker]["new_issue_url"] - url.gsub(':project_id', @project.id.to_s) - .gsub(':issues_tracker_id', @project.issues_tracker_id.to_s) + issues_tracker = Gitlab.config.issues_tracker[project.issues_tracker] + url = issues_tracker['new_issue_url'] + url.gsub(':project_id', project.id.to_s). + gsub(':issues_tracker_id', project.issues_tracker_id.to_s) end end - def url_for_issue(issue_iid) - return "" if @project.nil? + def url_for_issue(issue_iid, project = @project) + return '' if project.nil? - if @project.used_default_issues_tracker? || !external_issues_tracker_enabled? - url = project_issue_url project_id: @project, id: issue_iid + if project.used_default_issues_tracker? || !external_issues_tracker_enabled? + url = project_issue_url project_id: project, id: issue_iid else - url = Gitlab.config.issues_tracker[@project.issues_tracker]["issues_url"] - url.gsub(':id', issue_iid.to_s) - .gsub(':project_id', @project.id.to_s) - .gsub(':issues_tracker_id', @project.issues_tracker_id.to_s) + url = Gitlab.config.issues_tracker[project.issues_tracker]['issues_url'] + url.gsub(':id', issue_iid.to_s). + gsub(':project_id', project.id.to_s). + gsub(':issues_tracker_id', project.issues_tracker_id.to_s) end end - def title_for_issue(issue_iid) - return "" if @project.nil? + def title_for_issue(issue_iid, project = @project) + return '' if project.nil? - if @project.used_default_issues_tracker? && issue = @project.issues.where(iid: issue_iid).first - issue.title - else - "" + if project.used_default_issues_tracker? + issue = project.issues.where(iid: issue_iid).first + return issue.title if issue end + + '' end # Checks if issues_tracker setting exists in gitlab.yml def external_issues_tracker_enabled? - if Gitlab.config.issues_tracker && Gitlab.config.issues_tracker.values.any? - true - else - false - end + Gitlab.config.issues_tracker && Gitlab.config.issues_tracker.values.any? end def bulk_update_milestone_options - options_for_select(["None (backlog)"]) + options_from_collection_for_select(project_active_milestones, "id", "title", params[:milestone_id]) + options_for_select(['None (backlog)']) + + options_from_collection_for_select(project_active_milestones, 'id', + 'title', params[:milestone_id]) end - def bulk_update_assignee_options - options_for_select(["None (unassigned)"]) + options_from_collection_for_select(@project.team.members, "id", "name", params[:assignee_id]) + def bulk_update_assignee_options(project = @project) + options_for_select(['None (unassigned)']) + + options_from_collection_for_select(project.team.members, 'id', + 'name', params[:assignee_id]) end - def assignee_options object - options_from_collection_for_select(@project.team.members.sort_by(&:name), 'id', 'name', object.assignee_id) + def assignee_options(object, project = @project) + options_from_collection_for_select(project.team.members.sort_by(&:name), + 'id', 'name', object.assignee_id) end def milestone_options object - options_from_collection_for_select(object.project.milestones.active, 'id', 'title', object.milestone_id) + options_from_collection_for_select(object.project.milestones.active, + 'id', 'title', object.milestone_id) end def issue_box_class(item) diff --git a/app/views/events/_commit.html.haml b/app/views/events/_commit.html.haml index 135320da57..0e03e116e7 100644 --- a/app/views/events/_commit.html.haml +++ b/app/views/events/_commit.html.haml @@ -2,4 +2,4 @@ .commit-row-title = link_to commit[:id][0..8], project_commit_path(project, commit[:id]), class: "commit_short_id", alt: ''   - = gfm event_commit_title(commit[:message]) + = gfm event_commit_title(commit[:message]), project diff --git a/lib/gitlab/markdown.rb b/lib/gitlab/markdown.rb index dca3d7a7be..73a149621c 100644 --- a/lib/gitlab/markdown.rb +++ b/lib/gitlab/markdown.rb @@ -33,10 +33,9 @@ module Gitlab # Public: Parse the provided text with GitLab-Flavored Markdown # # text - the source text + # project - extra options for the reference links as given to link_to # html_options - extra options for the reference links as given to link_to - # - # Note: reference links will only be generated if @project is set - def gfm(text, html_options = {}) + def gfm(text, project = @project, html_options = {}) return text if text.nil? # Duplicate the string so we don't alter the original, then call to_str @@ -56,14 +55,19 @@ module Gitlab # TODO: add popups with additional information - text = parse(text) + text = parse(text, project) # Insert pre block extractions text.gsub!(/\{gfm-extraction-(\h{32})\}/) do insert_piece($1) end - sanitize text.html_safe, attributes: ActionView::Base.sanitized_allowed_attributes + %w(id class), tags: ActionView::Base.sanitized_allowed_tags + %w(table tr td th) + allowed_attributes = ActionView::Base.sanitized_allowed_attributes + allowed_tags = ActionView::Base.sanitized_allowed_tags + + sanitize text.html_safe, + attributes: allowed_attributes + %w(id class), + tags: allowed_tags + %w(table tr td th) end private @@ -84,11 +88,9 @@ module Gitlab # # text - Text to parse # - # Note: reference links will only be generated if @project is set - # # Returns parsed text - def parse(text) - parse_references(text) if @project + def parse(text, project = @project) + parse_references(text, project) if project parse_emoji(text) text @@ -110,7 +112,7 @@ module Gitlab TYPES = [:user, :issue, :merge_request, :snippet, :commit].freeze - def parse_references(text) + def parse_references(text, project = @project) # parse reference links text.gsub!(REFERENCE_PATTERN) do |match| prefix = $~[:prefix] @@ -123,7 +125,7 @@ module Gitlab # Avoid HTML entities if prefix && suffix && prefix[0] == '&' && suffix[-1] == ';' match - elsif ref_link = reference_link(type, identifier) + elsif ref_link = reference_link(type, identifier, project) "#{prefix}#{ref_link}#{suffix}" else match @@ -153,7 +155,7 @@ module Gitlab # # Returns boolean def valid_emoji?(emoji) - Emoji.find_by_name emoji + Emoji.find_by_name(emoji) end # Private: Dispatches to a dedicated processing method based on reference @@ -162,52 +164,77 @@ module Gitlab # identifier - Object identifier (Issue ID, SHA hash, etc.) # # Returns string rendered by the processing method - def reference_link(type, identifier) - send("reference_#{type}", identifier) + def reference_link(type, identifier, project = @project) + send("reference_#{type}", identifier, project) end - def reference_user(identifier) - if user = User.find_by_username(identifier) - link_to("@#{identifier}", user_url(identifier), html_options.merge(class: "gfm gfm-team_member #{html_options[:class]}")) + def reference_user(identifier, project = @project) + if user = User.find_by(username: identifier) + options = html_options.merge( + class: "gfm gfm-team_member #{html_options[:class]}" + ) + link_to("@#{identifier}", user_url(identifier), options) end end - def reference_issue(identifier) - if @project.used_default_issues_tracker? || !external_issues_tracker_enabled? - if @project.issue_exists? identifier - url = url_for_issue(identifier) + def reference_issue(identifier, project = @project) + if project.used_default_issues_tracker? || !external_issues_tracker_enabled? + if project.issue_exists? identifier + url = url_for_issue(identifier, project) title = title_for_issue(identifier) + options = html_options.merge( + title: "Issue: #{title}", + class: "gfm gfm-issue #{html_options[:class]}" + ) - link_to("##{identifier}", url, html_options.merge(title: "Issue: #{title}", class: "gfm gfm-issue #{html_options[:class]}")) + link_to("##{identifier}", url, options) end - else - reference_jira_issue(identifier) if @project.issues_tracker == "jira" + elsif project.issues_tracker == 'jira' + reference_jira_issue(identifier, project) end end - def reference_merge_request(identifier) - if merge_request = @project.merge_requests.where(iid: identifier).first - link_to("!#{identifier}", project_merge_request_url(@project, merge_request), html_options.merge(title: "Merge Request: #{merge_request.title}", class: "gfm gfm-merge_request #{html_options[:class]}")) + def reference_merge_request(identifier, project = @project) + if merge_request = project.merge_requests.find_by(iid: identifier) + options = html_options.merge( + title: "Merge Request: #{merge_request.title}", + class: "gfm gfm-merge_request #{html_options[:class]}" + ) + url = project_merge_request_url(project, merge_request) + link_to("!#{identifier}", url, options) end end - def reference_snippet(identifier) - if snippet = @project.snippets.where(id: identifier).first - link_to("$#{identifier}", project_snippet_url(@project, snippet), html_options.merge(title: "Snippet: #{snippet.title}", class: "gfm gfm-snippet #{html_options[:class]}")) + def reference_snippet(identifier, project = @project) + if snippet = project.snippets.find_by(id: identifier) + options = html_options.merge( + title: "Snippet: #{snippet.title}", + class: "gfm gfm-snippet #{html_options[:class]}" + ) + link_to("$#{identifier}", project_snippet_url(project, snippet), + options) end end - def reference_commit(identifier) - if @project.valid_repo? && commit = @project.repository.commit(identifier) - link_to(identifier, project_commit_url(@project, commit), html_options.merge(title: commit.link_title, class: "gfm gfm-commit #{html_options[:class]}")) + def reference_commit(identifier, project = @project) + if project.valid_repo? && commit = project.repository.commit(identifier) + options = html_options.merge( + title: commit.link_title, + class: "gfm gfm-commit #{html_options[:class]}" + ) + link_to(identifier, project_commit_url(project, commit), options) end end - def reference_jira_issue(identifier) + def reference_jira_issue(identifier, project = @project) url = url_for_issue(identifier) title = Gitlab.config.issues_tracker[@project.issues_tracker]["title"] - link_to("#{identifier}", url, html_options.merge(title: "Issue in #{title}", class: "gfm gfm-issue #{html_options[:class]}")) + options = html_options.merge( + title: "Issue in #{title}", + class: "gfm gfm-issue #{html_options[:class]}" + ) + link_to("#{identifier}", url, options) end end end diff --git a/lib/gitlab/reference_extractor.rb b/lib/gitlab/reference_extractor.rb index 94b01e808d..1eda614807 100644 --- a/lib/gitlab/reference_extractor.rb +++ b/lib/gitlab/reference_extractor.rb @@ -51,7 +51,7 @@ module Gitlab private - def reference_link type, identifier + def reference_link(type, identifier, project) # Append identifier to the appropriate collection. send("#{type}s") << identifier end diff --git a/spec/helpers/gitlab_markdown_helper_spec.rb b/spec/helpers/gitlab_markdown_helper_spec.rb index 49b48d26e2..fc9d1ac90c 100644 --- a/spec/helpers/gitlab_markdown_helper_spec.rb +++ b/spec/helpers/gitlab_markdown_helper_spec.rb @@ -41,7 +41,8 @@ describe GitlabMarkdownHelper do end it "should forward HTML options to links" do - gfm("Fixed in #{commit.id}", class: "foo").should have_selector("a.gfm.foo") + gfm("Fixed in #{commit.id}", @project, class: 'foo'). + should have_selector('a.gfm.foo') end describe "referencing a commit" do From 75e90cb45660bd9861a047d0cd4f630ca2e71dd3 Mon Sep 17 00:00:00 2001 From: dosire Date: Mon, 26 May 2014 15:38:18 +0200 Subject: [PATCH 066/360] Push to all remotes doc. --- doc/release/README.md | 8 ++++++-- doc/release/master.md | 29 +++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 doc/release/master.md diff --git a/doc/release/README.md b/doc/release/README.md index 22510be3f1..d53720acbd 100644 --- a/doc/release/README.md +++ b/doc/release/README.md @@ -1,2 +1,6 @@ -+ [Monthly](monthly.md) -+ [Security](security.md) +GitLab has the following updates: + ++ [Monthly release](monthly.md), every month on the 22nd. ++ [Patch release](patch.md), if there are serious regressions. ++ [Security](security.md), for security problems. ++ [Master](master.md), update process for the master branch. diff --git a/doc/release/master.md b/doc/release/master.md new file mode 100644 index 0000000000..aa7c854d07 --- /dev/null +++ b/doc/release/master.md @@ -0,0 +1,29 @@ +# How to push GitLab CE master branch to all remotes. + +Distribution to other repo's is done by Dmitriy if there is no rush. If a GitLab B.V. person wants to do it here are the instructions. + +## Add this to `.bashrc` + +```bash +gpa () +{ + git push origin $1 && git push gh $1 && git push public $1 +} +``` + +## Then add remotes to your local repo + +```bash +cd myrepo + +git remote add origin git@dev.gitlab.org:gitlab/gitlabhq.git +git remote add gh git@github.com:gitlabhq/gitlabhq.git +git remote add public git@gitlab.com:gitlab-org/gitlab-ce.git +``` + +## Pushto all remotes + +```bash +gpa master +``` + From c7a55309308aeffb65ac79dbe4696fa87a0e9f7c Mon Sep 17 00:00:00 2001 From: dosire Date: Mon, 26 May 2014 15:40:44 +0200 Subject: [PATCH 067/360] Small layout improvements. --- doc/release/master.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/doc/release/master.md b/doc/release/master.md index aa7c854d07..a3ad6e3886 100644 --- a/doc/release/master.md +++ b/doc/release/master.md @@ -1,6 +1,8 @@ # How to push GitLab CE master branch to all remotes. -Distribution to other repo's is done by Dmitriy if there is no rush. If a GitLab B.V. person wants to do it here are the instructions. +Distribution to other repo's is done by the lead developer if there is no rush. +This happens a few times per workday on average. +If a GitLab B.V. person wants to do it here are the instructions. ## Add this to `.bashrc` @@ -11,7 +13,7 @@ gpa () } ``` -## Then add remotes to your local repo +## Then add remotes to your local repo ```bash cd myrepo @@ -21,7 +23,7 @@ git remote add gh git@github.com:gitlabhq/gitlabhq.git git remote add public git@gitlab.com:gitlab-org/gitlab-ce.git ``` -## Pushto all remotes +## Push to all remotes ```bash gpa master From f8a6d3405ea3a25f5b0776241831deb037020fc6 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Mon, 26 May 2014 15:47:54 +0200 Subject: [PATCH 068/360] Add image_service spec. --- spec/controllers/projects_controller_spec.rb | 3 - spec/services/projects/image_service_spec.rb | 65 ++++++++++++++++++++ 2 files changed, 65 insertions(+), 3 deletions(-) create mode 100644 spec/services/projects/image_service_spec.rb diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb index 1d465d4996..7a772396e8 100644 --- a/spec/controllers/projects_controller_spec.rb +++ b/spec/controllers/projects_controller_spec.rb @@ -3,10 +3,7 @@ require('spec_helper') describe ProjectsController do let(:project) { create(:project) } let(:user) { create(:user) } - let(:png) { fixture_file_upload(Rails.root + 'spec/fixtures/dk.png', 'image/png') } let(:jpg) { fixture_file_upload(Rails.root + 'spec/fixtures/rails_sample.jpg', 'image/jpg') } - let(:gif) { fixture_file_upload(Rails.root + 'spec/fixtures/banana_sample.gif', 'image/gif') } - let(:txt) { fixture_file_upload(Rails.root + 'spec/fixtures/doc_sample.txt', 'text/plain') } describe "POST #upload_image" do before do diff --git a/spec/services/projects/image_service_spec.rb b/spec/services/projects/image_service_spec.rb new file mode 100644 index 0000000000..0311e312b5 --- /dev/null +++ b/spec/services/projects/image_service_spec.rb @@ -0,0 +1,65 @@ +require 'spec_helper' + +describe Projects::ImageService do + before(:each) { enable_observers } + after(:each) { disable_observers } + + describe 'Image service' do + before do + @user = create :user + @project = create :project, creator_id: @user.id, namespace: @user.namespace + end + + context 'for valid gif file' do + before do + gif = fixture_file_upload(Rails.root + 'spec/fixtures/banana_sample.gif', 'image/gif') + @link_to_image = upload_image(@project.repository, { 'markdown_img' => gif }, "http://test.example/") + end + + it { expect(@link_to_image).to have_key("alt") } + it { expect(@link_to_image).to have_key("url") } + it { expect(@link_to_image).to have_value("banana_sample") } + it { expect(@link_to_image["url"]).to match("http://test.example/uploads/#{@project.path_with_namespace}") } + it { expect(@link_to_image["url"]).to match("banana_sample.gif") } + end + + context 'for valid png file' do + before do + png = fixture_file_upload(Rails.root + 'spec/fixtures/dk.png', 'image/png') + @link_to_image = upload_image(@project.repository, { 'markdown_img' => png }, "http://test.example/") + end + + it { expect(@link_to_image).to have_key("alt") } + it { expect(@link_to_image).to have_key("url") } + it { expect(@link_to_image).to have_value("dk") } + it { expect(@link_to_image["url"]).to match("http://test.example/uploads/#{@project.path_with_namespace}") } + it { expect(@link_to_image["url"]).to match("dk.png") } + end + + context 'for valid jpg file' do + before do + jpg = fixture_file_upload(Rails.root + 'spec/fixtures/rails_sample.jpg', 'image/jpg') + @link_to_image = upload_image(@project.repository, { 'markdown_img' => jpg }, "http://test.example/") + end + + it { expect(@link_to_image).to have_key("alt") } + it { expect(@link_to_image).to have_key("url") } + it { expect(@link_to_image).to have_value("rails_sample") } + it { expect(@link_to_image["url"]).to match("http://test.example/uploads/#{@project.path_with_namespace}") } + it { expect(@link_to_image["url"]).to match("rails_sample.jpg") } + end + + context 'for txt file' do + before do + txt = fixture_file_upload(Rails.root + 'spec/fixtures/doc_sample.txt', 'text/plain') + @link_to_image = upload_image(@project.repository, { 'markdown_img' => txt }, "http://test.example/") + end + + it { expect(@link_to_image).to be_nil } + end + end + + def upload_image(repository, params, root_url) + Projects::ImageService.new(repository, params, root_url).execute + end +end From fe10f37199a04b92dd5bf2b713d49849491f9dfc Mon Sep 17 00:00:00 2001 From: dosire Date: Mon, 26 May 2014 15:54:06 +0200 Subject: [PATCH 069/360] Add default arguments, name gitlab repo gl, suggest dotfile repo. --- doc/release/master.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/release/master.md b/doc/release/master.md index a3ad6e3886..bed5692d0a 100644 --- a/doc/release/master.md +++ b/doc/release/master.md @@ -4,28 +4,28 @@ Distribution to other repo's is done by the lead developer if there is no rush. This happens a few times per workday on average. If a GitLab B.V. person wants to do it here are the instructions. -## Add this to `.bashrc` +## Add this to `.bashrc` or [your dotfiles](https://github.com/dosire/dotfiles/commit/52803ce3ac60d57632164b7713ff0041e86fa26c) ```bash gpa () { - git push origin $1 && git push gh $1 && git push public $1 + git push origin ${1:-master} && git push gh ${1:-master} && git push gl ${1:-master} } ``` ## Then add remotes to your local repo ```bash -cd myrepo +cd my-gitlab-ce-repo git remote add origin git@dev.gitlab.org:gitlab/gitlabhq.git -git remote add gh git@github.com:gitlabhq/gitlabhq.git -git remote add public git@gitlab.com:gitlab-org/gitlab-ce.git +git remote add gh git@github.com:gitlabhq/gitlabhq.git +git remote add gl git@gitlab.com:gitlab-org/gitlab-ce.git ``` ## Push to all remotes ```bash -gpa master +gpa ``` From 43e7b8fa075a2744b2debf11f52d1df731950aa8 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Mon, 26 May 2014 15:55:41 +0200 Subject: [PATCH 070/360] Remove empty space --- spec/services/projects/image_service_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/services/projects/image_service_spec.rb b/spec/services/projects/image_service_spec.rb index 0311e312b5..070c21698c 100644 --- a/spec/services/projects/image_service_spec.rb +++ b/spec/services/projects/image_service_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe Projects::ImageService do before(:each) { enable_observers } after(:each) { disable_observers } - + describe 'Image service' do before do @user = create :user From 9b2a13497dfc1fc97ac5d84f4074729cda040e2a Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Mon, 26 May 2014 15:58:03 +0200 Subject: [PATCH 071/360] Need txt file in test. --- spec/controllers/projects_controller_spec.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb index 7a772396e8..944df5314b 100644 --- a/spec/controllers/projects_controller_spec.rb +++ b/spec/controllers/projects_controller_spec.rb @@ -4,6 +4,7 @@ describe ProjectsController do let(:project) { create(:project) } let(:user) { create(:user) } let(:jpg) { fixture_file_upload(Rails.root + 'spec/fixtures/rails_sample.jpg', 'image/jpg') } + let(:txt) { fixture_file_upload(Rails.root + 'spec/fixtures/doc_sample.txt', 'text/plain') } describe "POST #upload_image" do before do From 040b3be5b1e1a0212c4c0073dfb252c26adbfc7d Mon Sep 17 00:00:00 2001 From: dosire Date: Mon, 26 May 2014 16:15:12 +0200 Subject: [PATCH 072/360] Give a hint where to find the email settings. --- config/gitlab.yml.example | 2 ++ 1 file changed, 2 insertions(+) diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example index 7b53a06553..04e85ed9a9 100644 --- a/config/gitlab.yml.example +++ b/config/gitlab.yml.example @@ -38,6 +38,8 @@ production: &base # Email address of your support contact (default: same as email_from) support_email: support@example.com + # Email server smtp settings are in [a separate file](initializers/smtp_settings.rb.sample). + ## User settings default_projects_limit: 10 # default_can_create_group: false # default: true From 242291850d7513731355c42e67c2f8c3cc727451 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 26 May 2014 18:05:55 +0300 Subject: [PATCH 073/360] Add some tests to compare api Signed-off-by: Dmitriy Zaporozhets --- spec/requests/api/repositories_spec.rb | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/spec/requests/api/repositories_spec.rb b/spec/requests/api/repositories_spec.rb index 5a5222ed3c..690a70b0b1 100644 --- a/spec/requests/api/repositories_spec.rb +++ b/spec/requests/api/repositories_spec.rb @@ -112,4 +112,24 @@ describe API::API, api: true do response.status.should == 404 end end + + describe 'GET /GET /projects/:id/repository/compare' do + it "should compare 2 branches" do + get api("/projects/#{project.id}/repository/compare", user), from: 'master', to: 'simple_merge_request' + response.status.should == 200 + json_response['commits'].size.should == 3 + end + + it "should compare 2 commits" do + get api("/projects/#{project.id}/repository/compare", user), from: 'b1e6a9dbf1c85', to: '1e689bfba395' + response.status.should == 200 + json_response['commits'].size.should == 0 + end + + it "should compare 2 commits" do + get api("/projects/#{project.id}/repository/compare", user), from: '1e689bfba395', to: 'b1e6a9dbf1c85' + response.status.should == 200 + json_response['commits'].size.should == 4 + end + end end From b2ec09e5d6e430eb4d4fd248364de9fe3bc9a116 Mon Sep 17 00:00:00 2001 From: dosire Date: Mon, 26 May 2014 17:09:27 +0200 Subject: [PATCH 074/360] Specify what version to test manually. --- doc/release/monthly.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/release/monthly.md b/doc/release/monthly.md index ed580f666a..d639c44a5e 100644 --- a/doc/release/monthly.md +++ b/doc/release/monthly.md @@ -120,7 +120,7 @@ It is important to do this as soon as possible, so we can catch any errors befor Create issue on dev.gitlab.org gitlab repository, named "GitLab X.X release" in order to keep track of the progress. -Use the omnibus packages or cookbook to test using [this guide](https://dev.gitlab.org/gitlab/gitlab-ee/blob/master/doc/release/manual_testing.md). +Use the omnibus packages of Enterprise Edition using [this guide](https://dev.gitlab.org/gitlab/gitlab-ee/blob/master/doc/release/manual_testing.md). **NOTE** Upgrader can only be tested when tags are pushed to all repositories. Do not forget to confirm it is working before releasing. Note that in the issue. From 446e920a1b0511eaf124b5c443d9f1c5a56b2667 Mon Sep 17 00:00:00 2001 From: Sean Edge Date: Mon, 26 May 2014 12:28:45 -0400 Subject: [PATCH 075/360] Add tests for creating tag with API. --- spec/requests/api/repositories_spec.rb | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/spec/requests/api/repositories_spec.rb b/spec/requests/api/repositories_spec.rb index 5a5222ed3c..f04775784b 100644 --- a/spec/requests/api/repositories_spec.rb +++ b/spec/requests/api/repositories_spec.rb @@ -23,6 +23,25 @@ describe API::API, api: true do end end + describe 'POST /projects/:id/repository/tags' do + it 'should create a new tag' do + post api("/projects/#{project.id}/repository/tags", user), + tag_name: 'v1.0.0', + ref: '621491c677087aa243f165eab467bfdfbee00be1' + + response.status.should == 201 + json_response.first['name'].should == 'v1.0.0' + json_response['commit']['id'].should == '621491c677087aa243f165eab467bfdfbee00be1' + end + it "should deny for user without push access" do + post api("/projects/#{project.id}/repository/tags", user2), + tag_name: 'v1.0.0', + ref: '621491c677087aa243f165eab467bfdfbee00be1' + + response.status.should == 403 + end + end + describe "GET /projects/:id/repository/tree" do context "authorized user" do before { project.team << [user2, :reporter] } From 435740b8a261e664ba021536690395b4313846f3 Mon Sep 17 00:00:00 2001 From: Sean Edge Date: Mon, 26 May 2014 12:32:01 -0400 Subject: [PATCH 076/360] Fixup for HoundCI. --- spec/requests/api/repositories_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/requests/api/repositories_spec.rb b/spec/requests/api/repositories_spec.rb index f04775784b..a61f6bbc8c 100644 --- a/spec/requests/api/repositories_spec.rb +++ b/spec/requests/api/repositories_spec.rb @@ -33,7 +33,7 @@ describe API::API, api: true do json_response.first['name'].should == 'v1.0.0' json_response['commit']['id'].should == '621491c677087aa243f165eab467bfdfbee00be1' end - it "should deny for user without push access" do + it 'should deny for user without push access' do post api("/projects/#{project.id}/repository/tags", user2), tag_name: 'v1.0.0', ref: '621491c677087aa243f165eab467bfdfbee00be1' From 52c3179be94e857ecb0de2cfa8ecbd484a36d213 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Tue, 20 May 2014 15:29:14 +0200 Subject: [PATCH 077/360] Do not replace links inside code blocks, less code for the same amount of work. --- app/helpers/gitlab_markdown_helper.rb | 109 ++++++++++---------------- lib/redcarpet/render/gitlab_html.rb | 17 +--- 2 files changed, 43 insertions(+), 83 deletions(-) diff --git a/app/helpers/gitlab_markdown_helper.rb b/app/helpers/gitlab_markdown_helper.rb index 69425bc171..2d226adb2a 100644 --- a/app/helpers/gitlab_markdown_helper.rb +++ b/app/helpers/gitlab_markdown_helper.rb @@ -59,90 +59,59 @@ module GitlabMarkdownHelper end end - # text - whole text from a markdown file - # project_path_with_namespace - namespace/projectname, eg. gitlabhq/gitlabhq - # ref - name of the branch or reference, eg. stable - # requested_path - path of request, eg. doc/api/README.md, used in special case when path is pointing to the .md file were the original request is coming from - def create_relative_links(text, project, ref, requested_path) - @path_to_satellite = project.satellite.path - project_path_with_namespace = project.path_with_namespace + def create_relative_links(text) paths = extract_paths(text) - paths.each do |file_path| - original_file_path = extract(file_path) - new_path = rebuild_path(project_path_with_namespace, original_file_path, requested_path, ref) - if reference_path?(file_path) - # Replacing old string with a new one that contains updated path - # eg. [some document]: document.md will be replaced with [some document] /namespace/project/master/blob/document.md - text.gsub!(file_path, file_path.gsub(original_file_path, "/#{new_path}")) - else - # Replacing old string with a new one with brackets ]() to prevent replacing occurence of a word - # e.g. If we have a markdown like [test](test) this will replace ](test) and not the word test - text.gsub!("](#{file_path})", "](/#{new_path})") - end + + paths.uniq.each do |file_path| + new_path = rebuild_path(file_path) + # Finds quoted path so we don't replace other mentions of the string + # eg. "doc/api" will be replaced and "/home/doc/api/text" won't + text.gsub!("\"#{file_path}\"", "\"/#{new_path}\"") end + text end - def extract_paths(markdown_text) - all_markdown_paths = pick_out_paths(markdown_text) - paths = remove_empty(all_markdown_paths) - select_relative(paths) + def extract_paths(text) + links = substitute_links(text) + image_links = substitute_image_links(text) + links + image_links end - # Split the markdown text to each line and find all paths, this will match anything with - ]("some_text") and [some text]: file.md - def pick_out_paths(markdown_text) - inline_paths = markdown_text.split("\n").map { |text| text.scan(/\]\(([^(]+)\)/) } - reference_paths = markdown_text.split("\n").map { |text| text.scan(/\[.*\]:.*/) } - inline_paths + reference_paths + def substitute_links(text) + links = text.scan(//) + relative_links = links.flatten.reject{ |link| link_to_ignore? link } + relative_links end - # Removes any empty result produced by not matching the regexp - def remove_empty(paths) - paths.reject{|l| l.empty? }.flatten + def substitute_image_links(text) + links = text.scan(/ Date: Tue, 20 May 2014 15:58:30 +0200 Subject: [PATCH 078/360] Make sure slashes are handled properly. --- app/helpers/gitlab_markdown_helper.rb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/app/helpers/gitlab_markdown_helper.rb b/app/helpers/gitlab_markdown_helper.rb index 2d226adb2a..b8891d801a 100644 --- a/app/helpers/gitlab_markdown_helper.rb +++ b/app/helpers/gitlab_markdown_helper.rb @@ -102,6 +102,8 @@ module GitlabMarkdownHelper path.gsub!(/(#.*)/, "") id = $1 || "" file_path = relative_file_path(path) + file_path = sanitize_slashes(file_path) + [ Gitlab.config.gitlab.relative_url_root, @project.path_with_namespace, @@ -110,6 +112,12 @@ module GitlabMarkdownHelper ].compact.join("/").gsub(/^\/*|\/*$/, '') + id end + def sanitize_slashes(path) + path[0] = "" if path.start_with?("/") + path.chop if path.end_with?("/") + path + end + def relative_file_path(path) requested_path = @path nested_path = build_nested_path(path, requested_path) From 281643a1bfd6f4da88a278bfce20133c80105de5 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Fri, 23 May 2014 12:58:34 +0200 Subject: [PATCH 079/360] Add feature spec. --- features/project/issues/issues.feature | 6 ++++++ features/steps/project/issues.rb | 12 ++++++++++++ lib/redcarpet/render/gitlab_html.rb | 6 +++--- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/features/project/issues/issues.feature b/features/project/issues/issues.feature index c5311544ef..191e8dcbe7 100644 --- a/features/project/issues/issues.feature +++ b/features/project/issues/issues.feature @@ -68,6 +68,12 @@ Feature: Project Issues And I leave a comment with a header containing "Comment with a header" Then The comment with the header should not have an ID + @javascript + Scenario: Blocks inside comments should not build relative links + Given I visit issue page "Release 0.4" + And I leave a comment with code block + Then The code block should be unchanged + Scenario: Issues on empty project Given empty project "Empty Project" When I visit empty project page diff --git a/features/steps/project/issues.rb b/features/steps/project/issues.rb index d1f3ba25a2..d0b4aa6e08 100644 --- a/features/steps/project/issues.rb +++ b/features/steps/project/issues.rb @@ -163,4 +163,16 @@ class ProjectIssues < Spinach::FeatureSteps project = Project.find_by(name: 'Empty Project') visit project_issues_path(project) end + + step 'I leave a comment with code block' do + within(".js-main-target-form") do + fill_in "note[note]", with: "```\nCommand [1]: /usr/local/bin/git , see [text](doc/text)\n```" + click_button "Add Comment" + sleep 0.05 + end + end + + step 'The code block should be unchanged' do + page.should have_content("```\nCommand [1]: /usr/local/bin/git , see [text](doc/text)\n```") + end end diff --git a/lib/redcarpet/render/gitlab_html.rb b/lib/redcarpet/render/gitlab_html.rb index 29bf42e762..bb225f1acd 100644 --- a/lib/redcarpet/render/gitlab_html.rb +++ b/lib/redcarpet/render/gitlab_html.rb @@ -6,8 +6,6 @@ class Redcarpet::Render::GitlabHTML < Redcarpet::Render::HTML def initialize(template, options = {}) @template = template @project = @template.instance_variable_get("@project") - @ref = @template.instance_variable_get("@ref") - @request_path = @template.instance_variable_get("@path") @options = options.dup super options end @@ -46,7 +44,9 @@ class Redcarpet::Render::GitlabHTML < Redcarpet::Render::HTML end def postprocess(full_document) - full_document = h.create_relative_links(full_document) + unless @template.instance_variable_get("@project_wiki") || @project.nil? + full_document = h.create_relative_links(full_document) + end h.gfm(full_document) end end From e426d43924be265d4834f47fd765895dde6017fb Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 26 May 2014 21:54:57 +0300 Subject: [PATCH 080/360] Check return system value for gitlab test rake tasks Signed-off-by: Dmitriy Zaporozhets --- lib/tasks/gitlab/test.rake | 5 ++--- lib/tasks/spec.rake | 4 ++-- lib/tasks/spinach.rake | 4 ++-- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/lib/tasks/gitlab/test.rake b/lib/tasks/gitlab/test.rake index 9516210e20..f38fe7810c 100644 --- a/lib/tasks/gitlab/test.rake +++ b/lib/tasks/gitlab/test.rake @@ -8,9 +8,8 @@ namespace :gitlab do ] cmds.each do |cmd| - result = system({'RAILS_ENV' => 'test', 'force' => 'yes'}, *cmd) - - raise "#{cmd} failed!" unless result + system({'RAILS_ENV' => 'test', 'force' => 'yes'}, *cmd) || + raise "#{cmd} failed!" end end end diff --git a/lib/tasks/spec.rake b/lib/tasks/spec.rake index 49fbe1bd47..a7cd7483be 100644 --- a/lib/tasks/spec.rake +++ b/lib/tasks/spec.rake @@ -40,7 +40,7 @@ end def run_commands(cmds) cmds.each do |cmd| - system({'RAILS_ENV' => 'test', 'force' => 'yes'}, *cmd) - raise "#{cmd} failed!" unless $?.exitstatus.zero? + system({'RAILS_ENV' => 'test', 'force' => 'yes'}, *cmd) || + raise "#{cmd} failed!" end end diff --git a/lib/tasks/spinach.rake b/lib/tasks/spinach.rake index c23d0e0e18..ebcce1e650 100644 --- a/lib/tasks/spinach.rake +++ b/lib/tasks/spinach.rake @@ -8,7 +8,7 @@ task :spinach do ] cmds.each do |cmd| - system({'RAILS_ENV' => 'test', 'force' => 'yes'}, *cmd) - raise "#{cmd} failed!" unless $?.exitstatus.zero? + system({'RAILS_ENV' => 'test', 'force' => 'yes'}, *cmd) || + raise "#{cmd} failed!" end end From c456231690c8fabeeefc844d46c9d5b0403df357 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 26 May 2014 23:26:41 +0300 Subject: [PATCH 081/360] Use css truncation on dashboard --- app/assets/stylesheets/generic/common.scss | 7 +------ app/assets/stylesheets/main/mixins.scss | 9 +++++++++ app/assets/stylesheets/sections/events.scss | 17 +++++++++++++++++ app/views/events/_event.html.haml | 2 +- app/views/events/_event_last_push.html.haml | 13 +++++++------ app/views/events/event/_push.html.haml | 2 +- 6 files changed, 36 insertions(+), 14 deletions(-) diff --git a/app/assets/stylesheets/generic/common.scss b/app/assets/stylesheets/generic/common.scss index 4e660d0b1e..6ab6458ea0 100644 --- a/app/assets/stylesheets/generic/common.scss +++ b/app/assets/stylesheets/generic/common.scss @@ -71,12 +71,7 @@ pre { } .str-truncated { - display: inline-block; - overflow: hidden; - text-overflow: ellipsis; - vertical-align: top; - white-space: nowrap; - max-width: 82%; + @include str-truncated; } /** FLASH message **/ diff --git a/app/assets/stylesheets/main/mixins.scss b/app/assets/stylesheets/main/mixins.scss index 8143cfa2c8..747676620b 100644 --- a/app/assets/stylesheets/main/mixins.scss +++ b/app/assets/stylesheets/main/mixins.scss @@ -123,3 +123,12 @@ margin-top: 0px; margin-bottom: 15px; } + +@mixin str-truncated($max_width: "82%") { + display: inline-block; + overflow: hidden; + text-overflow: ellipsis; + vertical-align: top; + white-space: nowrap; + max-width: $max_width; +} diff --git a/app/assets/stylesheets/sections/events.scss b/app/assets/stylesheets/sections/events.scss index b68f882220..05361976ef 100644 --- a/app/assets/stylesheets/sections/events.scss +++ b/app/assets/stylesheets/sections/events.scss @@ -45,6 +45,7 @@ padding: 12px 0px; border-bottom: 1px solid #eee; .event-title { + @include str-truncated(72%); color: #333; font-weight: normal; font-size: 14px; @@ -135,6 +136,12 @@ } } } + + .event-item-timestamp { + float: right; + color: #999; + line-height: 22px; + } } /** @@ -166,3 +173,13 @@ } } } + +/* + * Last push widget + */ +.event-last-push { + .event-last-push-text { + @include str-truncated(75%); + line-height: 24px; + } +} diff --git a/app/views/events/_event.html.haml b/app/views/events/_event.html.haml index 8cf26671e3..6138331537 100644 --- a/app/views/events/_event.html.haml +++ b/app/views/events/_event.html.haml @@ -1,6 +1,6 @@ - if event.proper? .event-item{class: "#{event.body? ? "event-block" : "event-inline" }"} - %span.cgray.pull-right + .event-item-timestamp #{time_ago_with_tooltip(event.created_at)} = cache event do diff --git a/app/views/events/_event_last_push.html.haml b/app/views/events/_event_last_push.html.haml index 6db05a1a5a..4c9a39bcc2 100644 --- a/app/views/events/_event_last_push.html.haml +++ b/app/views/events/_event_last_push.html.haml @@ -1,11 +1,12 @@ - if show_last_push_widget?(event) .event-last-push - %span You pushed to - = link_to project_commits_path(event.project, event.ref_name) do - %strong= truncate(event.ref_name, length: 28) - at - %strong= link_to_project event.project - #{time_ago_with_tooltip(event.created_at)} + .event-last-push-text + %span You pushed to + = link_to project_commits_path(event.project, event.ref_name) do + %strong= event.ref_name + at + %strong= link_to_project event.project + #{time_ago_with_tooltip(event.created_at)} .pull-right = link_to new_mr_path_from_push_event(event), title: "New Merge Request", class: "btn btn-create btn-small" do diff --git a/app/views/events/event/_push.html.haml b/app/views/events/event/_push.html.haml index f181df23eb..1bca64c7d5 100644 --- a/app/views/events/event/_push.html.haml +++ b/app/views/events/event/_push.html.haml @@ -5,7 +5,7 @@ %strong= event.ref_name - else = link_to project_commits_path(event.project, event.ref_name) do - %strong= truncate(event.ref_name, length: 30) + %strong= event.ref_name at = link_to_project event.project From c9020ae5866527f0642b00bea42b71ed0476d0e4 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 26 May 2014 20:30:45 +0000 Subject: [PATCH 082/360] Fix test.rake --- lib/tasks/gitlab/test.rake | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/tasks/gitlab/test.rake b/lib/tasks/gitlab/test.rake index f38fe7810c..5b937ce0a2 100644 --- a/lib/tasks/gitlab/test.rake +++ b/lib/tasks/gitlab/test.rake @@ -8,8 +8,7 @@ namespace :gitlab do ] cmds.each do |cmd| - system({'RAILS_ENV' => 'test', 'force' => 'yes'}, *cmd) || - raise "#{cmd} failed!" + system({'RAILS_ENV' => 'test', 'force' => 'yes'}, *cmd) or raise("#{cmd} failed!") end end -end +end \ No newline at end of file From 1e7fa8d99b52d89571b8e9581746561d00c383d5 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 27 May 2014 08:12:03 +0300 Subject: [PATCH 083/360] Fix syntax error Signed-off-by: Dmitriy Zaporozhets --- lib/tasks/spec.rake | 3 +-- lib/tasks/spinach.rake | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/tasks/spec.rake b/lib/tasks/spec.rake index a7cd7483be..bee2230029 100644 --- a/lib/tasks/spec.rake +++ b/lib/tasks/spec.rake @@ -40,7 +40,6 @@ end def run_commands(cmds) cmds.each do |cmd| - system({'RAILS_ENV' => 'test', 'force' => 'yes'}, *cmd) || - raise "#{cmd} failed!" + system({'RAILS_ENV' => 'test', 'force' => 'yes'}, *cmd) or raise("#{cmd} failed!") end end diff --git a/lib/tasks/spinach.rake b/lib/tasks/spinach.rake index ebcce1e650..dcc7d0fe01 100644 --- a/lib/tasks/spinach.rake +++ b/lib/tasks/spinach.rake @@ -8,7 +8,6 @@ task :spinach do ] cmds.each do |cmd| - system({'RAILS_ENV' => 'test', 'force' => 'yes'}, *cmd) || - raise "#{cmd} failed!" + system({'RAILS_ENV' => 'test', 'force' => 'yes'}, *cmd) or raise("#{cmd} failed!") end end From f4889f50fcd9ec8df9a1f44def25bb9ea384a3bf Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Tue, 27 May 2014 08:58:26 +0200 Subject: [PATCH 084/360] Add entry to changelog. --- CHANGELOG | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG b/CHANGELOG index d265d3a0b4..52ee3cc5d6 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -8,6 +8,7 @@ v 7.0.0 - Move protected branches page to Project settings area - Redirect to Files view when create new branch via UI - Drag and drop upload of image in every markdown-area (Earle Randolph Bunao and Neil Francis Calabroso) + - Refactor the markdown relative links processing v 6.9.0 - Store Rails cache data in the Redis `cache:gitlab` namespace From 10ee137e9c13271d49d7046723b1e473d62a578f Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 27 May 2014 11:16:50 +0300 Subject: [PATCH 085/360] Expose timeout and same_ref compare fields Signed-off-by: Dmitriy Zaporozhets --- doc/api/repositories.md | 47 ++++++++++---------------- lib/api/entities.rb | 6 ++++ lib/api/repositories.rb | 2 +- spec/requests/api/repositories_spec.rb | 3 ++ 4 files changed, 27 insertions(+), 31 deletions(-) diff --git a/doc/api/repositories.md b/doc/api/repositories.md index 2cd387275e..e9120e17bb 100644 --- a/doc/api/repositories.md +++ b/doc/api/repositories.md @@ -152,48 +152,35 @@ GET /projects/:id/repository/compare?from=master&to=feature Response: ```json + { "commit": { - "id": "72e10ef47e770a95439255b2c49de722e8782106", - "short_id": "72e10ef47e7", - "title": "Add NEWFILE", + "id": "12d65c8dd2b2676fa3ac47d955accc085a37a9c1", + "short_id": "12d65c8dd2b", + "title": "JS fix", "author_name": "Dmitriy Zaporozhets", "author_email": "dmitriy.zaporozhets@gmail.com", - "created_at": "2014-05-26T16:03:54+03:00" + "created_at": "2014-02-27T10:27:00+02:00" }, "commits": [{ - "id": "0b4bc9a49b562e85de7cc9e834518ea6828729b9", - "short_id": "0b4bc9a49b5", - "title": "Feature added", + "id": "12d65c8dd2b2676fa3ac47d955accc085a37a9c1", + "short_id": "12d65c8dd2b", + "title": "JS fix", "author_name": "Dmitriy Zaporozhets", "author_email": "dmitriy.zaporozhets@gmail.com", - "created_at": "2014-02-27T10:26:01+02:00" - }, { - "id": "72e10ef47e770a95439255b2c49de722e8782106", - "short_id": "72e10ef47e7", - "title": "Add NEWFILE", - "author_name": "Dmitriy Zaporozhets", - "author_email": "dmitriy.zaporozhets@gmail.com", - "created_at": "2014-05-26T16:03:54+03:00" + "created_at": "2014-02-27T10:27:00+02:00" }], "diffs": [{ - "old_path": "NEWFILE", - "new_path": "NEWFILE", + "old_path": "files/js/application.js", + "new_path": "files/js/application.js", "a_mode": null, - "b_mode": null, - "diff": "--- /dev/null\n+++ b/NEWFILE\n@@ -0,0 +1 @@\n+This is NEWFILE content\n\\ No newline at end of file", - "new_file": true, + "b_mode": "100644", + "diff": "--- a/files/js/application.js\n+++ b/files/js/application.js\n@@ -24,8 +24,10 @@\n //= require g.raphael-min\n //= require g.bar-min\n //= require branch-graph\n-//= require highlightjs.min\n-//= require ace/ace\n //= require_tree .\n //= require d3\n //= require underscore\n+\n+function fix() { \n+ alert(\"Fixed\")\n+}", + "new_file": false, "renamed_file": false, "deleted_file": false - }, { - "old_path": "files/ruby/feature.rb", - "new_path": "files/ruby/feature.rb", - "a_mode": null, - "b_mode": null, - "diff": "--- /dev/null\n+++ b/files/ruby/feature.rb\n@@ -0,0 +1,5 @@\n+class Feature\n+ def foo\n+ puts 'bar'\n+ end\n+end", - "new_file": true, - "renamed_file": false, - "deleted_file": false - }] + }], + "compare_timeout": false, + "compare_same_ref": false } ``` diff --git a/lib/api/entities.rb b/lib/api/entities.rb index eead8b18eb..4a9220a7f4 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -210,6 +210,12 @@ module API expose :diffs, using: Entities::RepoDiff do |compare, options| compare.diffs end + + expose :compare_timeout do |compare, options| + compare.timeout + end + + expose :same, as: :compare_same_ref end end end diff --git a/lib/api/repositories.rb b/lib/api/repositories.rb index d59c25cf31..a587d4a7bd 100644 --- a/lib/api/repositories.rb +++ b/lib/api/repositories.rb @@ -130,8 +130,8 @@ module API # GET /projects/:id/repository/compare?from=master&to=feature get ':id/repository/compare' do authorize! :download_code, user_project + required_attributes! [:from, :to] compare = Gitlab::Git::Compare.new(user_project.repository.raw_repository, params[:from], params[:to], MergeRequestDiff::COMMITS_SAFE_SIZE) - present compare, with: Entities::Compare end end diff --git a/spec/requests/api/repositories_spec.rb b/spec/requests/api/repositories_spec.rb index 690a70b0b1..eaf217f0af 100644 --- a/spec/requests/api/repositories_spec.rb +++ b/spec/requests/api/repositories_spec.rb @@ -118,18 +118,21 @@ describe API::API, api: true do get api("/projects/#{project.id}/repository/compare", user), from: 'master', to: 'simple_merge_request' response.status.should == 200 json_response['commits'].size.should == 3 + json_response['diffs'].size.should == 1 end it "should compare 2 commits" do get api("/projects/#{project.id}/repository/compare", user), from: 'b1e6a9dbf1c85', to: '1e689bfba395' response.status.should == 200 json_response['commits'].size.should == 0 + json_response['diffs'].size.should == 0 end it "should compare 2 commits" do get api("/projects/#{project.id}/repository/compare", user), from: '1e689bfba395', to: 'b1e6a9dbf1c85' response.status.should == 200 json_response['commits'].size.should == 4 + json_response['diffs'].size.should == 9 end end end From c7e00aca2d68a15c901506f1af4242df92670b6a Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 27 May 2014 11:27:42 +0300 Subject: [PATCH 086/360] Better specs for Compare API Signed-off-by: Dmitriy Zaporozhets --- lib/api/entities.rb | 4 ++- spec/requests/api/repositories_spec.rb | 34 +++++++++++++++++++------- 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 4a9220a7f4..6bad6c74bc 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -202,7 +202,9 @@ module API class Compare < Grape::Entity expose :commit, using: Entities::RepoCommit do |compare, options| - Commit.new compare.commit + if compare.commit + Commit.new compare.commit + end end expose :commits, using: Entities::RepoCommit do |compare, options| Commit.decorate compare.commits diff --git a/spec/requests/api/repositories_spec.rb b/spec/requests/api/repositories_spec.rb index eaf217f0af..a902a1542c 100644 --- a/spec/requests/api/repositories_spec.rb +++ b/spec/requests/api/repositories_spec.rb @@ -114,25 +114,41 @@ describe API::API, api: true do end describe 'GET /GET /projects/:id/repository/compare' do - it "should compare 2 branches" do + it "should compare branches" do get api("/projects/#{project.id}/repository/compare", user), from: 'master', to: 'simple_merge_request' response.status.should == 200 - json_response['commits'].size.should == 3 - json_response['diffs'].size.should == 1 + json_response['commits'].should be_present + json_response['diffs'].should be_present end - it "should compare 2 commits" do + it "should compare tags" do + get api("/projects/#{project.id}/repository/compare", user), from: 'v1.0.1', to: 'v1.0.2' + response.status.should == 200 + json_response['commits'].should be_present + json_response['diffs'].should be_present + end + + it "should compare commits" do get api("/projects/#{project.id}/repository/compare", user), from: 'b1e6a9dbf1c85', to: '1e689bfba395' response.status.should == 200 - json_response['commits'].size.should == 0 - json_response['diffs'].size.should == 0 + json_response['commits'].should be_empty + json_response['diffs'].should be_empty + json_response['compare_same_ref'].should be_false end - it "should compare 2 commits" do + it "should compare commits in reverse order" do get api("/projects/#{project.id}/repository/compare", user), from: '1e689bfba395', to: 'b1e6a9dbf1c85' response.status.should == 200 - json_response['commits'].size.should == 4 - json_response['diffs'].size.should == 9 + json_response['commits'].should be_present + json_response['diffs'].should be_present + end + + it "should compare same refs" do + get api("/projects/#{project.id}/repository/compare", user), from: 'master', to: 'master' + response.status.should == 200 + json_response['commits'].should be_empty + json_response['diffs'].should be_empty + json_response['compare_same_ref'].should be_true end end end From d7b3bbfc4ab9d128f0d9c4734b3a7bebbc5d6eef Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 27 May 2014 12:06:31 +0300 Subject: [PATCH 087/360] Make MR dicussion and changes tabs more noticable Signed-off-by: Dmitriy Zaporozhets --- .../stylesheets/sections/merge_requests.scss | 15 +++++++++++---- app/views/projects/merge_requests/_show.html.haml | 2 ++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/app/assets/stylesheets/sections/merge_requests.scss b/app/assets/stylesheets/sections/merge_requests.scss index 2d9a5e4bbe..cac4cb66aa 100644 --- a/app/assets/stylesheets/sections/merge_requests.scss +++ b/app/assets/stylesheets/sections/merge_requests.scss @@ -19,12 +19,19 @@ } } -.merge-request .nav-tabs{ +.merge-request .merge-request-tabs{ + border-color: #AAA; li { a { - font-weight: bold; - padding: 8px 20px; - text-align: center; + border-color: #AAA; + padding: 14px 40px; + font-size: 14px; + background-color: #F9F9F9; + } + &.active a { + border-color: #AAA; + border-bottom-color: #FFF; + background-color: #FFF; } } } diff --git a/app/views/projects/merge_requests/_show.html.haml b/app/views/projects/merge_requests/_show.html.haml index 0166b988e5..cbb8c83e4d 100644 --- a/app/views/projects/merge_requests/_show.html.haml +++ b/app/views/projects/merge_requests/_show.html.haml @@ -12,10 +12,12 @@ = link_to project_merge_request_path(@project, @merge_request) do %i.icon-comment Discussion + %span.badge= @merge_request.mr_and_commit_notes.count %li.diffs-tab{data: {action: 'diffs'}} = link_to diffs_project_merge_request_path(@project, @merge_request) do %i.icon-list-alt Changes + %span.badge= @merge_request.diffs.size - content_for :note_actions do - if can?(current_user, :modify_merge_request, @merge_request) From e10136999437bfcfd810ced0c629a84101e4a007 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Tue, 27 May 2014 13:06:20 +0200 Subject: [PATCH 088/360] Use newer version of git in installation doc. --- README.md | 2 +- doc/install/installation.md | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 283336b9e4..b32c4a9914 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ * Ubuntu/Debian/CentOS/RHEL** * ruby 1.9.3+ -* git 1.7.10+ +* git 1.9.3+ * redis 2.0+ * MySQL or PostgreSQL diff --git a/doc/install/installation.md b/doc/install/installation.md index 44f5a28fde..9a02f3af60 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -60,7 +60,7 @@ Make sure you have the right version of Git installed # Install Git sudo apt-get install -y git-core - # Make sure Git is version 1.7.10 or higher, for example 1.7.12 or 1.8.4 + # Make sure Git is version 1.9.3 or higher, for example 1.9.3 git --version Is the system packaged Git too old? Remove it and compile from source. @@ -73,8 +73,8 @@ Is the system packaged Git too old? Remove it and compile from source. # Download and compile from source cd /tmp - curl --progress https://git-core.googlecode.com/files/git-1.8.5.2.tar.gz | tar xz - cd git-1.8.5.2/ + curl --progress https://www.kernel.org/pub/software/scm/git/git-1.9.3.tar.gz | tar xz + cd git-1.9.3/ make prefix=/usr/local all # Install into /usr/local/bin From f22c709539d06be6fa76f148dedffdef1170936c Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Tue, 27 May 2014 14:12:15 +0200 Subject: [PATCH 089/360] Add titles to doc pages. --- doc/api/deploy_keys.md | 2 +- doc/api/groups.md | 2 ++ doc/api/issues.md | 2 ++ doc/api/merge_requests.md | 2 ++ doc/api/milestones.md | 2 ++ doc/api/notes.md | 2 ++ doc/api/project_snippets.md | 2 ++ doc/api/projects.md | 2 +- doc/api/repositories.md | 2 ++ doc/api/repository_files.md | 4 +++- doc/api/session.md | 2 ++ doc/api/system_hooks.md | 2 ++ doc/api/users.md | 2 ++ doc/install/database_mysql.md | 2 ++ doc/install/installation.md | 2 ++ doc/install/requirements.md | 4 +++- doc/legal/corporate_contributor_license_agreement.md | 2 ++ doc/legal/individual_contributor_license_agreement.md | 2 ++ doc/markdown/markdown.md | 2 ++ doc/permissions/permissions.md | 2 ++ doc/public_access/public_access.md | 2 ++ doc/raketasks/backup_restore.md | 2 ++ doc/raketasks/cleanup.md | 2 ++ doc/raketasks/import.md | 2 ++ doc/raketasks/maintenance.md | 2 ++ doc/raketasks/user_management.md | 2 ++ doc/raketasks/web_hooks.md | 2 ++ doc/release/monthly.md | 1 + doc/release/patch.md | 1 + doc/release/security.md | 1 + doc/security/rack_attack.md | 4 +++- doc/ssh/deploy_keys.md | 2 ++ doc/ssh/ssh.md | 2 ++ doc/system_hooks/system_hooks.md | 2 ++ doc/web_hooks/web_hooks.md | 2 ++ doc/workflow/authorization_for_merge_requests.md | 2 ++ doc/workflow/project_features.md | 2 ++ doc/workflow/workflow.md | 2 ++ 38 files changed, 74 insertions(+), 5 deletions(-) diff --git a/doc/api/deploy_keys.md b/doc/api/deploy_keys.md index d6c0e624df..6aa7be93c0 100644 --- a/doc/api/deploy_keys.md +++ b/doc/api/deploy_keys.md @@ -1,4 +1,4 @@ -## Deploy Keys +# Deploy Keys ### List deploy keys diff --git a/doc/api/groups.md b/doc/api/groups.md index f5f5d76905..1dbb93f908 100644 --- a/doc/api/groups.md +++ b/doc/api/groups.md @@ -1,3 +1,5 @@ +# Groups + ## List project groups Get a list of groups. (As user: my groups, as admin: all groups) diff --git a/doc/api/issues.md b/doc/api/issues.md index d18506f9ce..c769d7bb69 100644 --- a/doc/api/issues.md +++ b/doc/api/issues.md @@ -1,3 +1,5 @@ +# Issues + ## List issues Get all issues created by authenticated user. This function takes pagination parameters diff --git a/doc/api/merge_requests.md b/doc/api/merge_requests.md index d68f34971f..284c2befe6 100644 --- a/doc/api/merge_requests.md +++ b/doc/api/merge_requests.md @@ -1,3 +1,5 @@ +# Merge requests + ## List merge requests Get all merge requests for this project. diff --git a/doc/api/milestones.md b/doc/api/milestones.md index 2a2ef4b79b..b0f355b9a0 100644 --- a/doc/api/milestones.md +++ b/doc/api/milestones.md @@ -1,3 +1,5 @@ +# Milestones + ## List project milestones Returns a list of project milestones. diff --git a/doc/api/notes.md b/doc/api/notes.md index e9ad6e00c7..6d140643fc 100644 --- a/doc/api/notes.md +++ b/doc/api/notes.md @@ -1,3 +1,5 @@ +# Notes + Notes can be wall notes or comments on snippets, issues or merge requests. ## Wall diff --git a/doc/api/project_snippets.md b/doc/api/project_snippets.md index e16e1e8459..7a49827233 100644 --- a/doc/api/project_snippets.md +++ b/doc/api/project_snippets.md @@ -1,3 +1,5 @@ +# Project snippets + ## List snippets Get a list of project snippets. diff --git a/doc/api/projects.md b/doc/api/projects.md index ffaba0af7f..ae2b8365e8 100644 --- a/doc/api/projects.md +++ b/doc/api/projects.md @@ -1,4 +1,4 @@ -## Projects +# Projects ### List projects diff --git a/doc/api/repositories.md b/doc/api/repositories.md index e9120e17bb..ecb0fa3f6a 100644 --- a/doc/api/repositories.md +++ b/doc/api/repositories.md @@ -1,3 +1,5 @@ +# Repositories + ## List project repository tags Get a list of repository tags from a project, sorted by name in reverse alphabetical order. diff --git a/doc/api/repository_files.md b/doc/api/repository_files.md index b215cc2500..820ae71361 100644 --- a/doc/api/repository_files.md +++ b/doc/api/repository_files.md @@ -1,4 +1,6 @@ -# CRUD for repository files +# Repository files + +## CRUD for repository files ## Create, read, update and delete repository files using this API diff --git a/doc/api/session.md b/doc/api/session.md index 0be5af79da..2e717a2ea7 100644 --- a/doc/api/session.md +++ b/doc/api/session.md @@ -1,3 +1,5 @@ +# Session + Login to get private token ``` diff --git a/doc/api/system_hooks.md b/doc/api/system_hooks.md index d4c45ea9bb..0d33aee213 100644 --- a/doc/api/system_hooks.md +++ b/doc/api/system_hooks.md @@ -1,3 +1,5 @@ +# System hooks + All methods require admin authorization. The url endpoint of the system hooks can be configured in [the admin area under hooks](/admin/hooks). diff --git a/doc/api/users.md b/doc/api/users.md index 2b927c3077..c185cf6478 100644 --- a/doc/api/users.md +++ b/doc/api/users.md @@ -1,3 +1,5 @@ +# Users + ## List users Get a list of users. diff --git a/doc/install/database_mysql.md b/doc/install/database_mysql.md index bf8183729e..270ad3b0b8 100644 --- a/doc/install/database_mysql.md +++ b/doc/install/database_mysql.md @@ -1,3 +1,5 @@ +# Database Mysql + ## Note We do not recommend using MySQL due to various issues. For example, case [(in)sensitivity](https://dev.mysql.com/doc/refman/5.0/en/case-sensitivity.html) and [problems](http://bugs.mysql.com/bug.php?id=65830) that [suggested](http://bugs.mysql.com/bug.php?id=50909) [fixes](http://bugs.mysql.com/bug.php?id=65830) [have](http://bugs.mysql.com/bug.php?id=63164). diff --git a/doc/install/installation.md b/doc/install/installation.md index 44f5a28fde..73fef0dadf 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -1,3 +1,5 @@ +# Installation + # Select Version to Install Make sure you view [this installation guide](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/install/installation.md) from the branch (version) of GitLab you would like to install. In most cases this should be the highest numbered stable branch (example shown below). diff --git a/doc/install/requirements.md b/doc/install/requirements.md index fd2dd16cd8..2830a75df5 100644 --- a/doc/install/requirements.md +++ b/doc/install/requirements.md @@ -1,4 +1,6 @@ -# Operating Systems +# Requirements + +## Operating Systems GitLab is developed for the Linux operating system. For the installations options and instructions please see [the installation section of the readme](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/README.md#installation). diff --git a/doc/legal/corporate_contributor_license_agreement.md b/doc/legal/corporate_contributor_license_agreement.md index fb8d52e6bd..eb808d8a76 100644 --- a/doc/legal/corporate_contributor_license_agreement.md +++ b/doc/legal/corporate_contributor_license_agreement.md @@ -1,3 +1,5 @@ +# Corporate contributor license agreement + You accept and agree to the following terms and conditions for Your present and future Contributions submitted to GitLab B.V.. Except for the license granted herein to GitLab B.V. and recipients of software distributed by GitLab B.V., You reserve all right, title, and interest in and to Your Contributions. 1. Definitions. diff --git a/doc/legal/individual_contributor_license_agreement.md b/doc/legal/individual_contributor_license_agreement.md index 7ac9d6e4cd..95cbed7e75 100644 --- a/doc/legal/individual_contributor_license_agreement.md +++ b/doc/legal/individual_contributor_license_agreement.md @@ -1,3 +1,5 @@ +# Individual contributor license agreement + You accept and agree to the following terms and conditions for Your present and future Contributions submitted to GitLab B.V.. Except for the license granted herein to GitLab B.V. and recipients of software distributed by GitLab B.V., You reserve all right, title, and interest in and to Your Contributions. 1. Definitions. diff --git a/doc/markdown/markdown.md b/doc/markdown/markdown.md index e7ebc61343..47cb04cdb0 100644 --- a/doc/markdown/markdown.md +++ b/doc/markdown/markdown.md @@ -1,3 +1,5 @@ +# Markdown + ---------------------------------------------- Table of Contents diff --git a/doc/permissions/permissions.md b/doc/permissions/permissions.md index 9a3dcefe56..840bb90163 100644 --- a/doc/permissions/permissions.md +++ b/doc/permissions/permissions.md @@ -1,3 +1,5 @@ +# Permissions + Users have different abilities depending on the access level they have in a particular group or project. If a user is both in a project group and in the project itself, the highest permission level is used. If a user is a GitLab administrator they receive all permissions. diff --git a/doc/public_access/public_access.md b/doc/public_access/public_access.md index bb23a4bfd9..1714a7eeae 100644 --- a/doc/public_access/public_access.md +++ b/doc/public_access/public_access.md @@ -1,3 +1,5 @@ +# Public access + Gitlab allows you to open selected projects to be accessed **publicly** or **internally**. Projects with either of these visibility levels will be listen in the [public access directory](/public). Internal projects will only be available to authenticated users. diff --git a/doc/raketasks/backup_restore.md b/doc/raketasks/backup_restore.md index bdff6ad5da..f0be2b6a44 100644 --- a/doc/raketasks/backup_restore.md +++ b/doc/raketasks/backup_restore.md @@ -1,3 +1,5 @@ +# Backup restore + ### Create a backup of the GitLab system Creates a backup archive of the database and all repositories. This archive will be saved in backup_path (see `config/gitlab.yml`). diff --git a/doc/raketasks/cleanup.md b/doc/raketasks/cleanup.md index 99809ef434..b0b82754da 100644 --- a/doc/raketasks/cleanup.md +++ b/doc/raketasks/cleanup.md @@ -1,3 +1,5 @@ +# Cleanup + ### Remove garbage from filesystem. Important! Data loss! Remove namespaces(dirs) from `/home/git/repositories` if they don't exist in GitLab database. diff --git a/doc/raketasks/import.md b/doc/raketasks/import.md index e11328dc5c..628bd373b8 100644 --- a/doc/raketasks/import.md +++ b/doc/raketasks/import.md @@ -1,3 +1,5 @@ +# Import + ### Import bare repositories into GitLab project instance Notes: diff --git a/doc/raketasks/maintenance.md b/doc/raketasks/maintenance.md index 907c9352c5..da58962499 100644 --- a/doc/raketasks/maintenance.md +++ b/doc/raketasks/maintenance.md @@ -1,3 +1,5 @@ +# Maintenance + ### Gather information about GitLab and the system it runs on This command gathers information about your GitLab installation and the System diff --git a/doc/raketasks/user_management.md b/doc/raketasks/user_management.md index e823208291..d5b173fde6 100644 --- a/doc/raketasks/user_management.md +++ b/doc/raketasks/user_management.md @@ -1,3 +1,5 @@ +# User management + ### Add user as a developer to all projects ```bash diff --git a/doc/raketasks/web_hooks.md b/doc/raketasks/web_hooks.md index 1ca5bacb9d..4ffbf5f869 100644 --- a/doc/raketasks/web_hooks.md +++ b/doc/raketasks/web_hooks.md @@ -1,3 +1,5 @@ +# Web hooks + ### Add a web hook for **ALL** projects: RAILS_ENV=production bundle exec rake gitlab:web_hook:add URL="http://example.com/hook" diff --git a/doc/release/monthly.md b/doc/release/monthly.md index 5e85fe0825..71cd56a099 100644 --- a/doc/release/monthly.md +++ b/doc/release/monthly.md @@ -1,4 +1,5 @@ # Monthly Release + NOTE: This is a guide for GitLab developers. # **15th - Code Freeze & Release Manager** diff --git a/doc/release/patch.md b/doc/release/patch.md index 30bb39b4e4..6d8866a0cf 100644 --- a/doc/release/patch.md +++ b/doc/release/patch.md @@ -1,4 +1,5 @@ # Things to do when doing a patch release + NOTE: This is a guide for GitLab developers. If you are trying to install GitLab see the latest stable [installation guide](install/installation.md) and if you are trying to upgrade, see the [upgrade guides](update). ## When to do a patch release diff --git a/doc/release/security.md b/doc/release/security.md index 2fe0a948ad..ac2f79dfb9 100644 --- a/doc/release/security.md +++ b/doc/release/security.md @@ -1,4 +1,5 @@ # Things to do when doing an out-of-bound security release + NOTE: This is a guide for GitLab developers. If you are trying to install GitLab see the latest stable [installation guide](install/installation.md) and if you are trying to upgrade, see the [upgrade guides](update). ## When to do a security release diff --git a/doc/security/rack_attack.md b/doc/security/rack_attack.md index a0d02b1650..9e863bbd19 100644 --- a/doc/security/rack_attack.md +++ b/doc/security/rack_attack.md @@ -1,3 +1,5 @@ +# Rack attack + To prevent abusive clients doing damage GitLab uses rack-attack gem. If you installed or upgraded GitLab by following the official guides this should be enabled by default. If you are missing `config/initializers/rack_attack.rb` the following steps need to be taken in order to enable protection for your GitLab instance: @@ -16,4 +18,4 @@ If you want more restrictive/relaxed throttle rule change the `limit` or `period In case you find throttling is not enough to protect you against abusive clients, rack-attack gem offers IP whitelisting, blacklisting, Fail2ban style filter and tracking. -For more information on how to use these options check out [rack-attack README](https://github.com/kickstarter/rack-attack/blob/master/README.md). \ No newline at end of file +For more information on how to use these options check out [rack-attack README](https://github.com/kickstarter/rack-attack/blob/master/README.md). diff --git a/doc/ssh/deploy_keys.md b/doc/ssh/deploy_keys.md index c7125b7949..e113160c9b 100644 --- a/doc/ssh/deploy_keys.md +++ b/doc/ssh/deploy_keys.md @@ -1,3 +1,5 @@ +# Deploy keys + Deploy keys allow read-only access one or multiple projects with a single SSH key. This is really useful for cloning repositories to your Continuous Integration (CI) server. diff --git a/doc/ssh/ssh.md b/doc/ssh/ssh.md index 0a38bc16b4..f89b6a14ce 100644 --- a/doc/ssh/ssh.md +++ b/doc/ssh/ssh.md @@ -1,3 +1,5 @@ +# SSH keys + SSH key allows you to establish a secure connection between your computer and GitLab diff --git a/doc/system_hooks/system_hooks.md b/doc/system_hooks/system_hooks.md index 5c8daf466a..5a1a32c1ed 100644 --- a/doc/system_hooks/system_hooks.md +++ b/doc/system_hooks/system_hooks.md @@ -1,3 +1,5 @@ +# System hooks + Your GitLab instance can perform HTTP POST requests on the following events: `create_project`, `delete_project`, `create_user`, `delete_user` and `change_team_member`. System hooks can be used, e.g. for logging or changing information in a LDAP server. diff --git a/doc/web_hooks/web_hooks.md b/doc/web_hooks/web_hooks.md index 4c06bc4d44..19a60db00a 100644 --- a/doc/web_hooks/web_hooks.md +++ b/doc/web_hooks/web_hooks.md @@ -1,3 +1,5 @@ +# Web hooks + Project web hooks allow you to trigger an URL if new code is pushed or a new issue is created. --- diff --git a/doc/workflow/authorization_for_merge_requests.md b/doc/workflow/authorization_for_merge_requests.md index 4e07d7c04c..cc7031b11e 100644 --- a/doc/workflow/authorization_for_merge_requests.md +++ b/doc/workflow/authorization_for_merge_requests.md @@ -1,3 +1,5 @@ +# Authorization for Merge requests + There are two main ways to have a merge request flow with GitLab: working with protected branches in a single repository, or working with forks of an authoritative project. ## Protected branch flow diff --git a/doc/workflow/project_features.md b/doc/workflow/project_features.md index 64f4ddaa12..ec2c273db0 100644 --- a/doc/workflow/project_features.md +++ b/doc/workflow/project_features.md @@ -1,3 +1,5 @@ +# Project features + When in a Project -> Settings, you will find Features on the bottom of the page that you can toggle. Below you will find a more elaborate explanation of each of these. diff --git a/doc/workflow/workflow.md b/doc/workflow/workflow.md index bb232e9d5c..8186cd53b2 100644 --- a/doc/workflow/workflow.md +++ b/doc/workflow/workflow.md @@ -1,3 +1,5 @@ +# Workflow + 1. Clone project ```bash From a8f2977c6ac969e91180d06cd3c9ceffed48fd58 Mon Sep 17 00:00:00 2001 From: Sean Edge Date: Mon, 26 May 2014 12:32:52 -0400 Subject: [PATCH 090/360] More fixup for HoundCI. Fix up some small issues in docs. --- doc/api/repositories.md | 4 ++-- spec/requests/api/repositories_spec.rb | 11 ++++++----- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/doc/api/repositories.md b/doc/api/repositories.md index f71084c753..4633678e18 100644 --- a/doc/api/repositories.md +++ b/doc/api/repositories.md @@ -59,9 +59,9 @@ Parameters: "message": "Initial commit", "authored_date": "2012-05-28T04:42:42-07:00", "author_name": "John Smith", - "author email": "john@example.com" + "author email": "john@example.com", "committer_name": "Jack Smith", - "committed_date": "2012-05-28T04:42:42-07:00" + "committed_date": "2012-05-28T04:42:42-07:00", "committer_email": "jack@example.com" }, "protected": false diff --git a/spec/requests/api/repositories_spec.rb b/spec/requests/api/repositories_spec.rb index a61f6bbc8c..d8348be233 100644 --- a/spec/requests/api/repositories_spec.rb +++ b/spec/requests/api/repositories_spec.rb @@ -26,17 +26,18 @@ describe API::API, api: true do describe 'POST /projects/:id/repository/tags' do it 'should create a new tag' do post api("/projects/#{project.id}/repository/tags", user), - tag_name: 'v1.0.0', - ref: '621491c677087aa243f165eab467bfdfbee00be1' + tag_name: 'v1.0.0', + ref: '621491c677087aa243f165eab467bfdfbee00be1' response.status.should == 201 json_response.first['name'].should == 'v1.0.0' - json_response['commit']['id'].should == '621491c677087aa243f165eab467bfdfbee00be1' + json_response['commit']['id'].should == + '621491c677087aa243f165eab467bfdfbee00be1' end it 'should deny for user without push access' do post api("/projects/#{project.id}/repository/tags", user2), - tag_name: 'v1.0.0', - ref: '621491c677087aa243f165eab467bfdfbee00be1' + tag_name: 'v1.0.0', + ref: '621491c677087aa243f165eab467bfdfbee00be1' response.status.should == 403 end From 046647a74689f8bce86b119c63fa49dfc0756639 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Tue, 27 May 2014 14:25:34 +0200 Subject: [PATCH 091/360] Add directions on how to upgrade gitlab-shell in the upgrader guide. --- doc/update/upgrader.md | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/doc/update/upgrader.md b/doc/update/upgrader.md index 72a94f67b3..f8d2d9e749 100644 --- a/doc/update/upgrader.md +++ b/doc/update/upgrader.md @@ -34,13 +34,23 @@ __GitLab Upgrader is available only for GitLab version 6.4.2 or higher__ Check if GitLab and its environment are configured correctly: sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production - + To make sure you didn't miss anything run a more thorough check with: sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production - + If all items are green, then congratulations upgrade is complete! +### (optional) 5. Application status check fails + +If `gitlab:check` task reports old version of gitlab-shell and recommends upgrading, upgrade gitlab-shell by running: + +``` +cd /home/git/gitlab-shell +sudo -u git -H git fetch +sudo -u git -H git checkout v1.9.4 + +``` ### One line upgrade command From c8b58f0007ae81f39534e1de4f8958b9a7ed7590 Mon Sep 17 00:00:00 2001 From: dosire Date: Tue, 27 May 2014 14:56:52 +0200 Subject: [PATCH 092/360] Cherry-pick the changelog additions into master. --- doc/release/patch.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/doc/release/patch.md b/doc/release/patch.md index 30bb39b4e4..bd0f16d2b5 100644 --- a/doc/release/patch.md +++ b/doc/release/patch.md @@ -9,17 +9,20 @@ Otherwise include it in the monthly release and note there was a regression fix ## Release Procedure 1. Verify that the issue can be repoduced +1. Note in the 'GitLab X.X regressions' that you will create a patch 1. Create an issue on private GitLab development server 1. Name the issue "Release X.X.X CE and X.X.X EE", this will make searching easier 1. Fix the issue on a feature branch, do this on the private GitLab development server 1. Consider creating and testing workarounds 1. After the branch is merged into master, cherry pick the commit(s) into the current stable branch -1. In a separate commit in the stable branch, update the VERSION and CHANGELOG +1. In a separate commit in the stable branch update the VERSION +1. In a separate commit in the stable branch update the CHANGELOG 1. For EE, update the CHANGELOG-EE if it is EE specific fix. Otherwise, merge the stable CE branch and add to CHANGELOG-EE "Merge community edition changes for version X.X.X" 1. Create an annotated tag vX.X.X for CE and another patch release for EE -1. Make sure that the build has passed and no tests are failing +1. Make sure that the build has passed and all tests are passing 1. Push the code and the tags to all the CE and EE repositories 1. Apply the patch to GitLab Cloud and the private GitLab development server -1. Send tweets about the release from @gitlabhq, tweet should include the most important feature that the release is addressing as well as the link to the changelog 1. Build new packages with the latest version - +1. Cherry-pick the changelog update back into master +1. Send tweets about the release from @gitlabhq, tweet should include the most important feature that the release is addressing as well as the link to the changelog +1. Note in the 'GitLab X.X regressions' issue that the patch was published From 7dfb678df98b1b9ad420d9cbf4fe74f1553f34a7 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Tue, 27 May 2014 15:45:24 +0200 Subject: [PATCH 093/360] Revert "Actually use the 'user_filter' configuration option" This reverts commit e9d4587ff11c8510f01dfa184414f73d75b4550b, which is incompatible with GitLab's built in LDAP user filter: a GitLab LDAP filter is [added on top of the other filters used to find the user](https://gitlab.com/gitlab-org/gitlab-ce/blob/982d4d51e8110bec280eb00db0fb756b062103d9/lib/gitlab/ldap/adapter.rb#L61) Example GitLab LDAP filter: `(memberOf=cn=foo,dc=bar)`. In contrast, an omniauth-ldap filter [replaces the 'normal' filters](https://gitlab.com/gitlab-org/omniauth-ldap/blob/76d77543dec0c585bb4e974262f43675f9810953/lib/omniauth/strategies/ldap.rb#L55) Example omniauth-ldap user filter: `(&(uid=%{username})(memberOf=cn=foo,dc=bar))`. --- config/initializers/devise.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index d5cb110e88..50669ece7a 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -223,7 +223,6 @@ Devise.setup do |config| method: Gitlab.config.ldap['method'], bind_dn: Gitlab.config.ldap['bind_dn'], password: Gitlab.config.ldap['password'], - filter: Gitlab.config.ldap['user_filter'], name_proc: email_stripping_proc end @@ -245,4 +244,4 @@ Devise.setup do |config| config.omniauth provider['name'].to_sym, *provider_arguments end -end \ No newline at end of file +end From cee88509a382d93468982d33bee33a2dd08eb389 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Tue, 27 May 2014 16:30:00 +0200 Subject: [PATCH 094/360] Fix typo in text. --- doc/update/upgrader.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/doc/update/upgrader.md b/doc/update/upgrader.md index f8d2d9e749..0a1ad099da 100644 --- a/doc/update/upgrader.md +++ b/doc/update/upgrader.md @@ -43,13 +43,12 @@ If all items are green, then congratulations upgrade is complete! ### (optional) 5. Application status check fails -If `gitlab:check` task reports old version of gitlab-shell and recommends upgrading, upgrade gitlab-shell by running: +If the `gitlab:check` task reports an old version of gitlab-shell and recommends upgrading, upgrade gitlab-shell by running: ``` cd /home/git/gitlab-shell sudo -u git -H git fetch sudo -u git -H git checkout v1.9.4 - ``` ### One line upgrade command From 2341cefd6fa2811a1af41f2068554738d7eebfc4 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Tue, 27 May 2014 17:14:41 +0200 Subject: [PATCH 095/360] Move from script to bin directory. --- README.md | 2 +- {script => bin}/background_jobs | 0 {script => bin}/check | 0 {script => bin}/upgrade.rb | 0 {script => bin}/web | 0 doc/update/upgrader.md | 6 +++--- lib/support/init.d/gitlab | 12 ++++++------ lib/tasks/gitlab/check.rake | 2 +- lib/tasks/sidekiq.rake | 8 ++++---- script/rails | 6 ------ 10 files changed, 15 insertions(+), 21 deletions(-) rename {script => bin}/background_jobs (100%) rename {script => bin}/check (100%) rename {script => bin}/upgrade.rb (100%) rename {script => bin}/web (100%) delete mode 100755 script/rails diff --git a/README.md b/README.md index 283336b9e4..256f640454 100644 --- a/README.md +++ b/README.md @@ -108,7 +108,7 @@ Start it with [Foreman](https://github.com/ddollar/foreman) or start each component separately bundle exec rails s - script/background_jobs start + bin/background_jobs start And surf to [localhost:3000](http://localhost:3000/) and login with root / 5iveL!fe diff --git a/script/background_jobs b/bin/background_jobs similarity index 100% rename from script/background_jobs rename to bin/background_jobs diff --git a/script/check b/bin/check similarity index 100% rename from script/check rename to bin/check diff --git a/script/upgrade.rb b/bin/upgrade.rb similarity index 100% rename from script/upgrade.rb rename to bin/upgrade.rb diff --git a/script/web b/bin/web similarity index 100% rename from script/web rename to bin/web diff --git a/doc/update/upgrader.md b/doc/update/upgrader.md index 72a94f67b3..d08c8b85b5 100644 --- a/doc/update/upgrader.md +++ b/doc/update/upgrader.md @@ -19,10 +19,10 @@ __GitLab Upgrader is available only for GitLab version 6.4.2 or higher__ ### 2. Run gitlab upgrade tool cd /home/git/gitlab - sudo -u git -H ruby script/upgrade.rb + sudo -u git -H ruby bin/upgrade.rb # to perform a non-interactive install (no user input required) you can add -y - # sudo -u git -H ruby script/upgrade.rb -y + # sudo -u git -H ruby bin/upgrade.rb -y ### 3. Start application @@ -48,6 +48,6 @@ You've read through the entire guide, and probably did all the steps manually. H ```bash cd /home/git/gitlab; sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production; \ - sudo service gitlab stop; sudo -u git -H ruby script/upgrade.rb -y; sudo service gitlab start; \ + sudo service gitlab stop; sudo -u git -H ruby bin/upgrade.rb -y; sudo service gitlab start; \ sudo service nginx restart; sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production ``` diff --git a/lib/support/init.d/gitlab b/lib/support/init.d/gitlab index 3dd4465a6d..5c1ce2dada 100755 --- a/lib/support/init.d/gitlab +++ b/lib/support/init.d/gitlab @@ -167,14 +167,14 @@ start_gitlab() { # Remove old socket if it exists rm -f "$socket_path"/gitlab.socket 2>/dev/null # Start the web server - RAILS_ENV=$RAILS_ENV script/web start + RAILS_ENV=$RAILS_ENV bin/web start fi # If sidekiq is already running, don't start it again. if [ "$sidekiq_status" = "0" ]; then echo "The Sidekiq job dispatcher is already running with pid $spid, not restarting" else - RAILS_ENV=$RAILS_ENV script/background_jobs start & + RAILS_ENV=$RAILS_ENV bin/background_jobs start & fi # Wait for the pids to be planted @@ -197,11 +197,11 @@ stop_gitlab() { # If the Unicorn web server is running, tell it to stop; if [ "$web_status" = "0" ]; then - RAILS_ENV=$RAILS_ENV script/web stop + RAILS_ENV=$RAILS_ENV bin/web stop fi # And do the same thing for the Sidekiq. if [ "$sidekiq_status" = "0" ]; then - RAILS_ENV=$RAILS_ENV script/background_jobs stop + RAILS_ENV=$RAILS_ENV bin/background_jobs stop fi # If something needs to be stopped, lets wait for it to stop. Never use SIGKILL in a script. @@ -253,10 +253,10 @@ reload_gitlab(){ exit 1 fi printf "Reloading GitLab Unicorn configuration... " - RAILS_ENV=$RAILS_ENV script/web reload + RAILS_ENV=$RAILS_ENV bin/web reload echo "Done." echo "Restarting GitLab Sidekiq since it isn't capable of reloading its config..." - RAILS_ENV=$RAILS_ENV script/background_jobs restart + RAILS_ENV=$RAILS_ENV bin/background_jobs restart wait_for_pids print_status diff --git a/lib/tasks/gitlab/check.rake b/lib/tasks/gitlab/check.rake index 0387795fa4..ad5e04ecab 100644 --- a/lib/tasks/gitlab/check.rake +++ b/lib/tasks/gitlab/check.rake @@ -637,7 +637,7 @@ namespace :gitlab do else puts "no".red try_fixing_it( - sudo_gitlab("RAILS_ENV=production script/background_jobs start") + sudo_gitlab("RAILS_ENV=production bin/background_jobs start") ) for_more_information( see_installation_guide_section("Install Init Script"), diff --git a/lib/tasks/sidekiq.rake b/lib/tasks/sidekiq.rake index ba806e53cc..e4bd654575 100644 --- a/lib/tasks/sidekiq.rake +++ b/lib/tasks/sidekiq.rake @@ -1,21 +1,21 @@ namespace :sidekiq do desc "GITLAB | Stop sidekiq" task :stop do - system *%W(script/background_jobs stop) + system *%W(bin/background_jobs stop) end desc "GITLAB | Start sidekiq" task :start do - system *%W(script/background_jobs start) + system *%W(bin/background_jobs start) end desc 'GitLab | Restart sidekiq' task :restart do - system *%W(script/background_jobs restart) + system *%W(bin/background_jobs restart) end desc "GITLAB | Start sidekiq with launchd on Mac OS X" task :launchd do - system *%W(script/background_jobs start_no_deamonize) + system *%W(bin/background_jobs start_no_deamonize) end end diff --git a/script/rails b/script/rails deleted file mode 100755 index f8da2cffd4..0000000000 --- a/script/rails +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env ruby -# This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application. - -APP_PATH = File.expand_path('../../config/application', __FILE__) -require File.expand_path('../../config/boot', __FILE__) -require 'rails/commands' From affd376f7a36df4a80369bc1c7c8557dd4822b7d Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 27 May 2014 18:51:41 +0300 Subject: [PATCH 096/360] Dont show remove source branch ckecbox/button if you dont have such permissions for MR page Signed-off-by: Dmitriy Zaporozhets --- app/controllers/projects/merge_requests_controller.rb | 6 ------ app/models/merge_request.rb | 4 ---- app/views/projects/merge_requests/show/_mr_accept.html.haml | 2 +- .../merge_requests/show/_remove_source_branch.html.haml | 2 +- 4 files changed, 2 insertions(+), 12 deletions(-) diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index d8551db7b0..a0a8aa059e 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -225,7 +225,6 @@ class Projects::MergeRequestsController < Projects::ApplicationController @merge_request_diff = @merge_request.merge_request_diff @allowed_to_merge = allowed_to_merge? @show_merge_controls = @merge_request.open? && @commits.any? && @allowed_to_merge - @allowed_to_remove_source_branch = allowed_to_remove_source_branch? @source_branch = @merge_request.source_project.repository.find_branch(@merge_request.source_branch).try(:name) end @@ -238,11 +237,6 @@ class Projects::MergeRequestsController < Projects::ApplicationController render 'invalid' end - def allowed_to_remove_source_branch? - allowed_to_push_code?(@merge_request.source_project, @merge_request.source_branch) && - !@merge_request.disallow_source_branch_removal? - end - def allowed_to_push_code?(project, branch) action = if project.protected_branch?(branch) :push_code_to_protected_branches diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 061537132b..b7c4a2a923 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -212,10 +212,6 @@ class MergeRequest < ActiveRecord::Base target_project != source_project end - def disallow_source_branch_removal? - source_project.root_ref?(source_branch) || source_project.protected_branches.include?(source_branch) - end - def project target_project end diff --git a/app/views/projects/merge_requests/show/_mr_accept.html.haml b/app/views/projects/merge_requests/show/_mr_accept.html.haml index 1276489c2d..07e05f5501 100644 --- a/app/views/projects/merge_requests/show/_mr_accept.html.haml +++ b/app/views/projects/merge_requests/show/_mr_accept.html.haml @@ -38,7 +38,7 @@ .accept-group .pull-left = f.submit "Accept Merge Request", class: "btn btn-create accept_merge_request" - - unless @merge_request.disallow_source_branch_removal? + - if can_remove_branch?(@merge_request.source_project, @merge_request.source_branch) .remove_branch_holder.pull-left = label_tag :should_remove_source_branch, class: "checkbox" do = check_box_tag :should_remove_source_branch diff --git a/app/views/projects/merge_requests/show/_remove_source_branch.html.haml b/app/views/projects/merge_requests/show/_remove_source_branch.html.haml index f8f8b71f21..491360af1b 100644 --- a/app/views/projects/merge_requests/show/_remove_source_branch.html.haml +++ b/app/views/projects/merge_requests/show/_remove_source_branch.html.haml @@ -1,7 +1,7 @@ - if @source_branch.blank? Source branch has been removed -- elsif @allowed_to_remove_source_branch && @merge_request.merged? +- elsif can_remove_branch?(@merge_request.source_project, @merge_request.source_branch) && @merge_request.merged? .remove_source_branch_widget %p Changes merged into #{@merge_request.target_branch}. You can remove source branch now = link_to project_branch_path(@merge_request.source_project, @source_branch), remote: true, method: :delete, class: "btn btn-primary btn-small remove_source_branch" do From ca907e4f9f37acac51b60bd95fb495780e4c9a84 Mon Sep 17 00:00:00 2001 From: dosire Date: Wed, 28 May 2014 09:28:39 +0200 Subject: [PATCH 097/360] Make it more obvious that GitLab Shell should be upgraded. --- doc/update/upgrader.md | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/doc/update/upgrader.md b/doc/update/upgrader.md index 2875b1a823..b3947fa2de 100644 --- a/doc/update/upgrader.md +++ b/doc/update/upgrader.md @@ -31,19 +31,16 @@ __GitLab Upgrader is available only for GitLab version 6.4.2 or higher__ ### 4. Check application status -Check if GitLab and its environment are configured correctly: - - sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production - -To make sure you didn't miss anything run a more thorough check with: +Check if GitLab and its dependencies are configured correctly: sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production If all items are green, then congratulations upgrade is complete! -### (optional) 5. Application status check fails +### 5. Upgrade GitLab Shell (if needed) -If the `gitlab:check` task reports an old version of gitlab-shell and recommends upgrading, upgrade gitlab-shell by running: +If the `gitlab:check` task reports an outdated version of gitlab-shell you should upgrade it. +Upgrade it by running the commands below after replacing 1.9.4 with the correct version number: ``` cd /home/git/gitlab-shell @@ -53,7 +50,8 @@ sudo -u git -H git checkout v1.9.4 ### One line upgrade command -You've read through the entire guide, and probably did all the steps manually. Here is a one liner for convenience, the next time you upgrade: +You've read through the entire guide and probably already did all the steps one by one. +Here is a one line command with step 1 to 4 for the next time you upgrade: ```bash cd /home/git/gitlab; sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production; \ From a18ae13e985d07fe9ef8288794778d31e2435696 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 28 May 2014 11:35:43 +0300 Subject: [PATCH 098/360] Backport CI service refactoring from EE It allows easier contribution of different CI services Signed-off-by: Dmitriy Zaporozhets --- .../projects/merge_requests_controller.rb | 2 +- app/helpers/merge_requests_helper.rb | 2 +- app/models/project.rb | 11 ++++++ app/models/project_services/ci_service.rb | 34 +++++++++++++++++++ .../project_services/gitlab_ci_service.rb | 2 +- app/models/service.rb | 8 +++++ .../projects/merge_requests/_show.html.haml | 2 +- .../show/_state_widget.html.haml | 2 +- app/views/projects/services/_form.html.haml | 3 ++ 9 files changed, 61 insertions(+), 5 deletions(-) create mode 100644 app/models/project_services/ci_service.rb diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index a0a8aa059e..6ab353d222 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -160,7 +160,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController end def ci_status - status = @merge_request.source_project.gitlab_ci_service.commit_status(merge_request.last_commit.sha) + status = @merge_request.source_project.ci_service.commit_status(merge_request.last_commit.sha) response = {status: status} render json: response diff --git a/app/helpers/merge_requests_helper.rb b/app/helpers/merge_requests_helper.rb index 00ec34ae54..f3c3d43771 100644 --- a/app/helpers/merge_requests_helper.rb +++ b/app/helpers/merge_requests_helper.rb @@ -32,7 +32,7 @@ module MergeRequestsHelper end def ci_build_details_path merge_request - merge_request.source_project.gitlab_ci_service.build_page(merge_request.last_commit.sha) + merge_request.source_project.ci_service.build_page(merge_request.last_commit.sha) end def merge_path_description(merge_request, separator) diff --git a/app/models/project.rb b/app/models/project.rb index 45e950f480..fc7c7d042f 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -54,6 +54,9 @@ class Project < ActiveRecord::Base belongs_to :namespace has_one :last_event, -> {order 'events.created_at DESC'}, class_name: 'Event', foreign_key: 'project_id' + + # Project services + has_many :services has_one :gitlab_ci_service, dependent: :destroy has_one :campfire_service, dependent: :destroy has_one :emails_on_push_service, dependent: :destroy @@ -322,6 +325,14 @@ class Project < ActiveRecord::Base gitlab_ci_service && gitlab_ci_service.active end + def ci_services + services.select { |service| service.category == :ci } + end + + def ci_service + @ci_service ||= services.select(&:activated?).first + end + # For compatibility with old code def code path diff --git a/app/models/project_services/ci_service.rb b/app/models/project_services/ci_service.rb new file mode 100644 index 0000000000..fd34a2a35e --- /dev/null +++ b/app/models/project_services/ci_service.rb @@ -0,0 +1,34 @@ +# Base class for CI services +# List methods you need to implement to get your CI service +# working with GitLab Merge Requests +class CiService < Service + def category + :ci + end + + # Return complete url to build page + # + # Ex. + # http://jenkins.example.com:8888/job/test1/scm/bySHA1/12d65c + # + def build_page(sha) + # implement inside child + end + + # Return string with build status or :error symbol + # + # Allowed states: 'success', 'failed', 'running', 'pending' + # + # + # Ex. + # @service.commit_status('13be4ac') + # # => 'success' + # + # @service.commit_status('2abe4ac') + # # => 'running' + # + # + def commit_status(sha) + # implement inside child + end +end diff --git a/app/models/project_services/gitlab_ci_service.rb b/app/models/project_services/gitlab_ci_service.rb index ed1944f337..ef395e0ec6 100644 --- a/app/models/project_services/gitlab_ci_service.rb +++ b/app/models/project_services/gitlab_ci_service.rb @@ -17,7 +17,7 @@ # api_key :string(255) # -class GitlabCiService < Service +class GitlabCiService < CiService attr_accessible :project_url validates :project_url, presence: true, if: :activated? diff --git a/app/models/service.rb b/app/models/service.rb index ea00039521..d655937079 100644 --- a/app/models/service.rb +++ b/app/models/service.rb @@ -33,6 +33,10 @@ class Service < ActiveRecord::Base active end + def category + :common + end + def title # implement inside child end @@ -41,6 +45,10 @@ class Service < ActiveRecord::Base # implement inside child end + def help + # implement inside child + end + def to_param # implement inside child end diff --git a/app/views/projects/merge_requests/_show.html.haml b/app/views/projects/merge_requests/_show.html.haml index cbb8c83e4d..38a0ed567f 100644 --- a/app/views/projects/merge_requests/_show.html.haml +++ b/app/views/projects/merge_requests/_show.html.haml @@ -40,7 +40,7 @@ url_to_automerge_check: "#{automerge_check_project_merge_request_path(@project, @merge_request)}", check_enable: #{@merge_request.unchecked? ? "true" : "false"}, url_to_ci_check: "#{ci_status_project_merge_request_path(@project, @merge_request)}", - ci_enable: #{@project.gitlab_ci? ? "true" : "false"}, + ci_enable: #{@project.ci_service ? "true" : "false"}, current_status: "#{@merge_request.merge_status_name}", action: "#{controller.action_name}" }); diff --git a/app/views/projects/merge_requests/show/_state_widget.html.haml b/app/views/projects/merge_requests/show/_state_widget.html.haml index 80fe540489..bff5b36821 100644 --- a/app/views/projects/merge_requests/show/_state_widget.html.haml +++ b/app/views/projects/merge_requests/show/_state_widget.html.haml @@ -1,5 +1,5 @@ .panel.mr-state-widget.panel-default - - if @merge_request.source_project.gitlab_ci? && @commits.any? + - if @merge_request.source_project.ci_service && @commits.any? .panel-heading = render "projects/merge_requests/show/mr_ci" .panel-body diff --git a/app/views/projects/services/_form.html.haml b/app/views/projects/services/_form.html.haml index 70b4537fd3..f20efa76cb 100644 --- a/app/views/projects/services/_form.html.haml +++ b/app/views/projects/services/_form.html.haml @@ -17,6 +17,9 @@ - @service.errors.full_messages.each do |msg| %li= msg + - if @service.help.present? + .bs-callout + = @service.help .form-group = f.label :active, "Active", class: "control-label" From 8a3807c83880f71612b1e092c49e865d24e29704 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 28 May 2014 12:40:22 +0300 Subject: [PATCH 099/360] Fix tests Signed-off-by: Dmitriy Zaporozhets --- spec/models/merge_request_spec.rb | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index a10673fda9..81a48699cd 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -82,25 +82,6 @@ describe MergeRequest do end end - describe '#allow_source_branch_removal?' do - it 'should not allow removal when mr is a fork' do - - subject.disallow_source_branch_removal?.should be_true - end - it 'should not allow removal when the mr is not a fork, but the source branch is the root reference' do - subject.target_project = subject.source_project - subject.source_branch = subject.source_project.repository.root_ref - subject.disallow_source_branch_removal?.should be_true - end - - it 'should not disallow removal when the mr is not a fork, and but source branch is not the root reference' do - subject.target_project = subject.source_project - subject.source_branch = "Something Different #{subject.source_project.repository.root_ref}" - subject.for_fork?.should be_false - subject.disallow_source_branch_removal?.should be_false - end - end - describe 'detection of issues to be closed' do let(:issue0) { create :issue, project: subject.project } let(:issue1) { create :issue, project: subject.project } From a3db7631b84b9e41a2191cc2ac9659f921554da5 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 28 May 2014 12:52:02 +0300 Subject: [PATCH 100/360] Fix haml indent Signed-off-by: Dmitriy Zaporozhets --- app/views/projects/services/_form.html.haml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/views/projects/services/_form.html.haml b/app/views/projects/services/_form.html.haml index f20efa76cb..a5db7969a6 100644 --- a/app/views/projects/services/_form.html.haml +++ b/app/views/projects/services/_form.html.haml @@ -17,9 +17,9 @@ - @service.errors.full_messages.each do |msg| %li= msg - - if @service.help.present? - .bs-callout - = @service.help + - if @service.help.present? + .bs-callout + = @service.help .form-group = f.label :active, "Active", class: "control-label" From dc158af665a32a28e19ef7efd849fdb7f22e7b6c Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Wed, 28 May 2014 12:23:03 +0200 Subject: [PATCH 101/360] Add org-ruby for rendering .org files. --- Gemfile | 1 + Gemfile.lock | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/Gemfile b/Gemfile index 9775334a7c..eb4ca6569c 100644 --- a/Gemfile +++ b/Gemfile @@ -85,6 +85,7 @@ gem "seed-fu" # Markdown to HTML gem "redcarpet", "~> 2.2.2" gem "github-markup" +gem "org-ruby" # For rendering .org files # Diffs gem 'diffy', '~> 3.0.3' diff --git a/Gemfile.lock b/Gemfile.lock index 3d4a673af1..3def12c053 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -319,6 +319,8 @@ GEM omniauth-twitter (1.0.1) multi_json (~> 1.3) omniauth-oauth (~> 1.0) + org-ruby (0.9.6) + rubypants (>= 0.2.0) orm_adapter (0.5.0) pg (0.15.1) phantomjs (1.9.2.0) @@ -427,6 +429,7 @@ GEM rspec-mocks (~> 2.14.0) ruby-progressbar (1.2.0) rubyntlm (0.1.1) + rubypants (0.2.0) rugged (0.19.0) safe_yaml (0.9.7) sanitize (2.1.0) @@ -625,6 +628,7 @@ DEPENDENCIES omniauth-github omniauth-google-oauth2 omniauth-twitter + org-ruby pg poltergeist (~> 1.4.1) protected_attributes From 82855e078f7cfa55396522305d7f3408dad4019a Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Tue, 27 May 2014 16:36:14 +0200 Subject: [PATCH 102/360] Keep the lowest requirement for git in the documentation. --- README.md | 2 +- doc/install/installation.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b32c4a9914..283336b9e4 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ * Ubuntu/Debian/CentOS/RHEL** * ruby 1.9.3+ -* git 1.9.3+ +* git 1.7.10+ * redis 2.0+ * MySQL or PostgreSQL diff --git a/doc/install/installation.md b/doc/install/installation.md index 9a02f3af60..47adf17cdc 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -60,7 +60,7 @@ Make sure you have the right version of Git installed # Install Git sudo apt-get install -y git-core - # Make sure Git is version 1.9.3 or higher, for example 1.9.3 + # Make sure Git is version 1.7.10 or higher, for example 1.7.12 or 1.9.3 git --version Is the system packaged Git too old? Remove it and compile from source. From 666260bf6bff01011ba498dd8f38190b2d690725 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Tue, 27 May 2014 09:22:17 +0200 Subject: [PATCH 103/360] Add changelog for version to 6.9.1. Conflicts: CHANGELOG VERSION --- CHANGELOG | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 52ee3cc5d6..1410c96e04 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -10,6 +10,10 @@ v 7.0.0 - Drag and drop upload of image in every markdown-area (Earle Randolph Bunao and Neil Francis Calabroso) - Refactor the markdown relative links processing +v 6.9.1 + - Fix scroll to highlighted line + - Fix the pagination on load for commits page + v 6.9.0 - Store Rails cache data in the Redis `cache:gitlab` namespace - Adjust MySQL limits for existing installations From 2d4ba2679a3bb2a26adf6c013d5d4be19ed8da94 Mon Sep 17 00:00:00 2001 From: Sean Edge Date: Wed, 28 May 2014 07:59:02 -0400 Subject: [PATCH 104/360] Update tags_controller.rb to use CreateTagService. --- app/controllers/projects/tags_controller.rb | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/app/controllers/projects/tags_controller.rb b/app/controllers/projects/tags_controller.rb index 0b99165bf6..e03a9f4d66 100644 --- a/app/controllers/projects/tags_controller.rb +++ b/app/controllers/projects/tags_controller.rb @@ -13,11 +13,8 @@ class Projects::TagsController < Projects::ApplicationController end def create - @repository.add_tag(params[:tag_name], params[:ref]) - - if new_tag = @repository.find_tag(params[:tag_name]) - Event.create_ref_event(@project, current_user, new_tag, 'add', 'refs/tags') - end + @tag = CreateTagService.new.execute(@project, params[:tag_name], + params[:ref], current_user) redirect_to project_tags_path(@project) end From 7795a4b90c81de76e128227b7773ca6eb1abc80e Mon Sep 17 00:00:00 2001 From: dosire Date: Wed, 28 May 2014 15:08:27 +0200 Subject: [PATCH 105/360] The hard limit should be a lot more liberal, 10x seems reasonable. --- app/models/commit.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/models/commit.rb b/app/models/commit.rb index c313aeb757..81875e1be2 100644 --- a/app/models/commit.rb +++ b/app/models/commit.rb @@ -13,8 +13,8 @@ class Commit DIFF_SAFE_FILES = 100 DIFF_SAFE_LINES = 5000 # Commits above this size will not be rendered in HTML - DIFF_HARD_LIMIT_FILES = 500 - DIFF_HARD_LIMIT_LINES = 10000 + DIFF_HARD_LIMIT_FILES = 1000 + DIFF_HARD_LIMIT_LINES = 50000 class << self def decorate(commits) From 59f68b1b9fcf245ff8fe7344faa3f63983aad106 Mon Sep 17 00:00:00 2001 From: dosire Date: Wed, 28 May 2014 15:26:25 +0200 Subject: [PATCH 106/360] Link to installation page. --- README.md | 24 +----------------------- 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/README.md b/README.md index 256f640454..ef0b84c9bd 100644 --- a/README.md +++ b/README.md @@ -49,29 +49,7 @@ ### Installation -#### Official installation methods - -* [GitLab packages](https://www.gitlab.com/downloads/) **recommended** These packages contain GitLab and all its depencies (Ruby, PostgreSQL, Redis, Nginx, Unicorn, etc.). They are made with [omnibus-gitlab](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/README.md) that also contains the installation instructions. - -* [GitLab Chef Cookbook](https://gitlab.com/gitlab-org/cookbook-gitlab/blob/master/README.md) This cookbook can be used both for development installations and production installations. If you want to [contribute](CONTRIBUTE.md) to GitLab we suggest you follow the [development installation](https://gitlab.com/gitlab-org/cookbook-gitlab/blob/master/doc/development.md) instructions to install all testing dependencies. - -* [Manual installation guide](doc/install/installation.md) This guide to set up a production server on Ubuntu offers detailed and complete step-by-step instructions. - -#### Third party one-click installers - -* [Digital Ocean 1-Click Application Install](https://www.digitalocean.com/blog_posts/host-your-git-repositories-in-55-seconds-with-gitlab) Have a new server up in 55 seconds. Digital Ocean uses SSD disks which is great for an IO intensive app such as GitLab. We recommend selecting a droplet with [1GB of memory](https://github.com/gitlabhq/gitlabhq/blob/master/doc/install/requirements.md). - -* [BitNami one-click installers](http://bitnami.com/stack/gitlab) This package contains both GitLab and GitLab CI. It is available as installer, virtual machine or for cloud hosting providers (Amazon Web Services/Azure/etc.). - -* [Cloud 66 deployment and management](http://blog.cloud66.com/installing-gitlab-ubuntu/) Use Cloud 66 to deploy GitLab to your own server or any cloud (eg. DigitalOcean, AWS, Rackspace, GCE) and then manage it with database backups, scaling and more. - -* [Pkgr.io one-click installer](https://pkgr.io/apps/gitlabhq/gitlabhq) Currently supporting Ubuntu 14.04, Ubuntu 12.04 and Debian 7.4. For more information check the [README](https://gitlab.com/gitlab-org/gitlab-recipes/blob/master/install/pkgr/README.md) at gitlab-recipes repo. - -#### Unofficial installation methods - -* [GitLab recipes](https://gitlab.com/gitlab-org/gitlab-recipes/) repository with unofficial guides for using GitLab with different software (operating systems, webservers, etc.) than the official version. - -* [Installation guides](https://github.com/gitlabhq/gitlab-public-wiki/wiki/Unofficial-Installation-Guides) public wiki with unofficial guides to install GitLab on different operating systems. +Please see [the installation page on the GitLab website](https://www.gitlab.com/installation/). ### New versions and upgrading From 2273234653924b731f9ef01432e392481ee1d4e2 Mon Sep 17 00:00:00 2001 From: erbunao Date: Wed, 28 May 2014 11:47:00 +0800 Subject: [PATCH 107/360] Implements and refactors clipboard feature for markdown. --- .../javascripts/markdown_area.js.coffee | 120 +++++++++++++++--- .../stylesheets/generic/markdown_area.scss | 5 + app/controllers/projects_controller.rb | 6 + app/views/projects/issues/_form.html.haml | 2 +- .../projects/merge_requests/_form.html.haml | 3 +- .../merge_requests/_new_submit.html.haml | 3 +- app/views/projects/milestones/_form.html.haml | 2 +- app/views/projects/notes/_form.html.haml | 6 +- app/views/projects/wikis/_form.html.haml | 3 +- 9 files changed, 127 insertions(+), 23 deletions(-) diff --git a/app/assets/javascripts/markdown_area.js.coffee b/app/assets/javascripts/markdown_area.js.coffee index def5d12a82..67e8290bd5 100644 --- a/app/assets/javascripts/markdown_area.js.coffee +++ b/app/assets/javascripts/markdown_area.js.coffee @@ -1,6 +1,3 @@ -formatLink = (str) -> - "![" + str.alt + "](" + str.url + ")" - $(document).ready -> alertClass = "alert alert-danger alert-dismissable div-dropzone-alert" alertAttr = "class=\"close\" data-dismiss=\"alert\"" + "aria-hidden=\"true\"" @@ -13,15 +10,12 @@ $(document).ready -> project_image_path_upload = window.project_image_path_upload or null $("textarea.markdown-area").wrap "
" - $(".div-dropzone").parent().addClass "div-dropzone-wrapper" - $(".div-dropzone").append divHover $(".div-dropzone-hover").append iconPicture $(".div-dropzone").append divSpinner $(".div-dropzone-spinner").append iconSpinner - dropzone = $(".div-dropzone").dropzone( url: project_image_path_upload dictDefaultMessage: "" @@ -36,7 +30,7 @@ $(document).ready -> previewContainer: false processing: -> - $(".div-dropzone-alert").alert "close" + closeAlertMessage() dragover: -> $(".div-dropzone > textarea").addClass "div-dropzone-focus" @@ -55,31 +49,127 @@ $(document).ready -> return success: (header, response) -> - child = $(dropzone[0]).children("textarea") - $(child).val $(child).val() + formatLink(response.link) + "\n" + appendToTextArea(formatLink(response.link)) return error: (temp, errorMessage) -> - checkIfMsgExists = $(".error-alert").children().length - if checkIfMsgExists is 0 - $(".error-alert").append divAlert - $(".div-dropzone-alert").append btnAlert + errorMessage + showError(errorMessage) return sending: -> - $(".div-dropzone-spinner").css "opacity", 0.7 + showSpinner() return complete: -> $(".dz-preview").remove() $(".markdown-area").trigger "input" - $(".div-dropzone-spinner").css "opacity", 0 + closeSpinner() return ) + child = $(dropzone[0]).children("textarea") + + formatLink = (str) -> + "![" + str.alt + "](" + str.url + ")" + + handlePaste = (e) -> + e.preventDefault() + my_event = e.originalEvent + + if my_event.clipboardData and my_event.clipboardData.items + i = 0 + while i < my_event.clipboardData.items.length + item = my_event.clipboardData.items[i] + processItem(my_event, item) + i++ + + processItem = (e, item) -> + if isImage(item) + filename = getFilename(e) or "image.png" + text = "{{" + filename + "}}" + pasteText(text) + uploadFile item.getAsFile(), filename + else if e.clipboardData.items.length == 1 + text = e.clipboardData.getData("text/plain") + pasteText(text) + + isImage = (item) -> + if item + item.type.indexOf("image") isnt -1 + + pasteText = (text) -> + caretStart = $(child)[0].selectionStart + caretEnd = $(child)[0].selectionEnd + textEnd = $(child).val().length + + beforeSelection = $(child).val().substring 0, caretStart + afterSelection = $(child).val().substring caretEnd, textEnd + $(child).val beforeSelection + text + afterSelection + $(".markdown-area").trigger "input" + + getFilename = (e) -> + if window.clipboardData and window.clipboardData.getData + value = window.clipboardData.getData("Text") + else if e.clipboardData and e.clipboardData.getData + value = e.clipboardData.getData("text/plain") + + value = value.split("\r") + value.first() + + uploadFile = (item, filename) -> + formData = new FormData() + formData.append "markdown_img", item, filename + $.ajax + url: project_image_path_upload + type: "POST" + data: formData + dataType: "json" + processData: false + contentType: false + headers: + "X-CSRF-Token": $("meta[name=\"csrf-token\"]").attr("content") + + beforeSend: -> + showSpinner() + closeAlertMessage() + + success: (e, textStatus, response) -> + insertToTextArea(filename, formatLink(response.responseJSON.link)) + + error: (response) -> + showError(response.responseJSON.message) + + complete: -> + closeSpinner() + + insertToTextArea = (filename, url) -> + $(child).val (index, val) -> + val.replace("{{" + filename + "}}", url + "\n") + + appendToTextArea = (url) -> + $(child).val (index, val) -> + val + url + "\n" + + showSpinner = (e) -> + $(".div-dropzone-spinner").css "opacity", 0.7 + + closeSpinner = -> + $(".div-dropzone-spinner").css "opacity", 0 + + showError = (message) -> + checkIfMsgExists = $(".error-alert").children().length + if checkIfMsgExists is 0 + $(".error-alert").append divAlert + $(".div-dropzone-alert").append btnAlert + message + + closeAlertMessage = -> + $(".div-dropzone-alert").alert "close" + $(".markdown-selector").click (e) -> e.preventDefault() $(".div-dropzone").click() return + $(".div-dropzone").on "paste", handlePaste + return \ No newline at end of file diff --git a/app/assets/stylesheets/generic/markdown_area.scss b/app/assets/stylesheets/generic/markdown_area.scss index fbfa72c5e5..ae7ace61d4 100644 --- a/app/assets/stylesheets/generic/markdown_area.scss +++ b/app/assets/stylesheets/generic/markdown_area.scss @@ -43,6 +43,11 @@ display: none; } } + + .hint { + padding: 0; + margin: 0; + } } .div-dropzone-alert { diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 07ccbd57fa..bbd8f8dd88 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -11,6 +11,8 @@ class ProjectsController < ApplicationController layout 'navless', only: [:new, :create, :fork] before_filter :set_title, only: [:new, :create] + rescue_from CarrierWave::IntegrityError, with: :invalid_file + def new @project = Project.new end @@ -185,6 +187,10 @@ class ProjectsController < ApplicationController %w(png jpg jpeg gif) end + def invalid_file(error) + render json: { message: error.message }, status: :internal_server_error + end + def set_title @title = 'New Project' end diff --git a/app/views/projects/issues/_form.html.haml b/app/views/projects/issues/_form.html.haml index 49d1a87743..6e61fc8524 100644 --- a/app/views/projects/issues/_form.html.haml +++ b/app/views/projects/issues/_form.html.haml @@ -23,7 +23,7 @@ = f.text_area :description, class: 'form-control js-gfm-input markdown-area', rows: 14 .col-sm-12.hint .pull-left Issues are parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}. - .pull-right Attach images (JPG, PNG, GIF) by dragging & dropping or #{link_to "selecting them", '#', class: 'markdown-selector' }. + .pull-right Attach images (JPG, PNG, GIF) by dragging & dropping, #{link_to "selecting them", '#', class: 'markdown-selector' } or pasting from the clipboard. .clearfix .error-alert %hr diff --git a/app/views/projects/merge_requests/_form.html.haml b/app/views/projects/merge_requests/_form.html.haml index 3088f0cf86..facc6a63f3 100644 --- a/app/views/projects/merge_requests/_form.html.haml +++ b/app/views/projects/merge_requests/_form.html.haml @@ -25,7 +25,8 @@ = f.text_area :description, class: "form-control js-gfm-input markdown-area", rows: 14 .col-sm-12.hint .pull-left Description is parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}. - .pull-right Attach images (JPG, PNG, GIF) by dragging & dropping or #{link_to "selecting them", '#', class: 'markdown-selector' }. + .pull-right Attach images (JPG, PNG, GIF) by dragging & dropping, #{link_to "selecting them", '#', class: 'markdown-selector' } or pasting from the clipboard. + .clearfix .error-alert %hr diff --git a/app/views/projects/merge_requests/_new_submit.html.haml b/app/views/projects/merge_requests/_new_submit.html.haml index dc41ef8135..bf0e40f9a1 100644 --- a/app/views/projects/merge_requests/_new_submit.html.haml +++ b/app/views/projects/merge_requests/_new_submit.html.haml @@ -26,7 +26,8 @@ = f.text_area :description, class: "form-control js-gfm-input markdown-area", rows: 10 .col-sm-12.hint .pull-left Description is parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}. - .pull-right Attach images (JPG, PNG, GIF) by dragging & dropping or #{link_to "selecting them", '#', class: 'markdown-selector' }. + .pull-right Attach images (JPG, PNG, GIF) by dragging & dropping, #{link_to "selecting them", '#', class: 'markdown-selector' } or pasting from the clipboard. + .clearfix .error-alert .form-group diff --git a/app/views/projects/milestones/_form.html.haml b/app/views/projects/milestones/_form.html.haml index 7e0fd19d0a..2233a8838c 100644 --- a/app/views/projects/milestones/_form.html.haml +++ b/app/views/projects/milestones/_form.html.haml @@ -24,7 +24,7 @@ = f.text_area :description, maxlength: 2000, class: "form-control markdown-area", rows: 10 .hint .pull-left Milestones are parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}. - .pull-left Attach images (JPG, PNG, GIF) by dragging & dropping or #{link_to "selecting them", '#', class: 'markdown-selector' }. + .pull-left Attach images (JPG, PNG, GIF) by dragging & dropping, #{link_to "selecting them", '#', class: 'markdown-selector' } or pasting from the clipboard. .clearfix .error-alert .col-md-6 diff --git a/app/views/projects/notes/_form.html.haml b/app/views/projects/notes/_form.html.haml index 2e84dcea89..25ebaca930 100644 --- a/app/views/projects/notes/_form.html.haml +++ b/app/views/projects/notes/_form.html.haml @@ -16,10 +16,10 @@ .note-write-holder = f.text_area :note, size: 255, class: 'note_text js-note-text js-gfm-input markdown-area' - .light.clearfix + .light.clearfix.hint .pull-left Comments are parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}. - .pull-right Attach images (JPG, PNG, GIF) by dragging & dropping or #{link_to "selecting them", '#', class: 'markdown-selector' }. - + .pull-right Attach images (JPG, PNG, GIF) by dragging & dropping, #{link_to "selecting them", '#', class: 'markdown-selector' } or pasting from the clipboard. + .error-alert .note-preview-holder.hide .js-note-preview diff --git a/app/views/projects/wikis/_form.html.haml b/app/views/projects/wikis/_form.html.haml index a43e6f073e..303cec8e98 100644 --- a/app/views/projects/wikis/_form.html.haml +++ b/app/views/projects/wikis/_form.html.haml @@ -25,7 +25,8 @@ = f.text_area :content, class: 'form-control js-gfm-input markdown-area', rows: 18 .col-sm-12.hint .pull-left Wiki content is parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}. - .pull-right Attach images (JPG, PNG, GIF) by dragging & dropping or #{link_to "selecting them", '#', class: 'markdown-selector' }. + .pull-right Attach images (JPG, PNG, GIF) by dragging & dropping, #{link_to "selecting them", '#', class: 'markdown-selector' } or pasting from the clipboard. + .clearfix .error-alert .form-group From b7de9de4d2682a7af66e1fd8db5ec0a3fcf8980e Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Wed, 28 May 2014 17:09:20 +0200 Subject: [PATCH 108/360] Omnibus instructions for re-adding indexes --- doc/update/mysql_to_postgresql.md | 38 ++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/doc/update/mysql_to_postgresql.md b/doc/update/mysql_to_postgresql.md index acd1e33f59..c9b349b32e 100644 --- a/doc/update/mysql_to_postgresql.md +++ b/doc/update/mysql_to_postgresql.md @@ -34,21 +34,47 @@ The lanyrd database converter script does not preserve all indexes, so we have to recreate them ourselves after migrating from MySQL. It is not necessary to shut down GitLab for this process. + +### For source installations + +On source installations (distributed using Git) we retrieve the index +declarations from version control using `git stash`. + ``` # Clone the database converter on your Postgres-backed GitLab server cd /tmp git clone https://github.com/gitlabhq/mysql-postgresql-converter.git -# Stash changes to db/schema.rb to make sure we can find the right index statements cd /home/git/gitlab + +# Stash changes to db/schema.rb to make sure we can find the right index statements sudo -u git -H git stash -# Generate the `CREATE INDEX CONCURRENTLY` statements based on schema.rb -cd /tmp/mysql-to-postgresql-converter -ruby index_create_statements.rb /home/git/gitlab/db/schema.rb > index_create_statements.psql +# Generate add_index.rb +ruby /tmp/mysql-postgresql-converter/add_index_statements.rb db/schema.rb > /tmp/mysql-postgresql-converter/add_index.rb -# Execute the SQL statements against the GitLab database -sudo -u git psql -f index_create_statements.psql -d gitlabhq_production +# Create the indexes +sudo -u git -H bundle exec rails runner -e production 'eval $stdin.read' < /tmp/mysql-postgresql-converter/add_index.rb +``` + +### For omnibus-gitlab installations + +On omnibus-gitlab we need to get the index declarations from a file called +`schema.rb.bundled`. For older versions, we need to download the file. + +``` +# Clone the database converter on your Postgres-backed GitLab server +cd /tmp +/opt/gitlab/embedded/bin/git clone https://github.com/gitlabhq/mysql-postgresql-converter.git +cd /tmp/mysql-postgresql-converter + +# Generate add_index.rb +/opt/gitlab/embedded/bin/ruby add_index_statements.rb /opt/gitlab/embedded/service/gitlab-rails/db/schema.rb.bundled > add_index.rb + +# If schema.rb.bundled does not exist, download it as follows, then try generating add_index.rb again +sudo /opt/gitlab/embedded/bin/curl -o /opt/gitlab/embedded/service/gitlab-rails/db/schema.rb.bundled https://gitlab.com/gitlab-org/gitlab-ce/raw/v6.9.1/db/schema.rb + +/opt/gitlab/bin/gitlab-rails runner 'eval $stdin.read' < add_index.rb ``` ## Converting a GitLab backup file from MySQL to Postgres From 28de31f5200d908551d8372fed7511df80e284fd Mon Sep 17 00:00:00 2001 From: Sean Edge Date: Wed, 28 May 2014 11:14:51 -0400 Subject: [PATCH 109/360] Fix broken repositories_spec test for creating new tags. --- spec/requests/api/repositories_spec.rb | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/spec/requests/api/repositories_spec.rb b/spec/requests/api/repositories_spec.rb index d8348be233..173c4ef734 100644 --- a/spec/requests/api/repositories_spec.rb +++ b/spec/requests/api/repositories_spec.rb @@ -27,12 +27,10 @@ describe API::API, api: true do it 'should create a new tag' do post api("/projects/#{project.id}/repository/tags", user), tag_name: 'v1.0.0', - ref: '621491c677087aa243f165eab467bfdfbee00be1' + ref: 'master' response.status.should == 201 - json_response.first['name'].should == 'v1.0.0' - json_response['commit']['id'].should == - '621491c677087aa243f165eab467bfdfbee00be1' + json_response['name'].should == 'v1.0.0' end it 'should deny for user without push access' do post api("/projects/#{project.id}/repository/tags", user2), From 6ba4cb1d2b0bcfaf8459c8936513637acc92da5e Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 28 May 2014 19:01:19 +0300 Subject: [PATCH 110/360] Remove old rake task Signed-off-by: Dmitriy Zaporozhets --- lib/tasks/gitlab/enable_namespaces.rake | 111 ------------------------ 1 file changed, 111 deletions(-) delete mode 100644 lib/tasks/gitlab/enable_namespaces.rake diff --git a/lib/tasks/gitlab/enable_namespaces.rake b/lib/tasks/gitlab/enable_namespaces.rake deleted file mode 100644 index 201f34ab54..0000000000 --- a/lib/tasks/gitlab/enable_namespaces.rake +++ /dev/null @@ -1,111 +0,0 @@ -namespace :gitlab do - desc "GITLAB | Enable usernames and namespaces for user projects" - task enable_namespaces: :environment do - warn_user_is_not_gitlab - - migrate_user_namespaces - migrate_groups - migrate_projects - end - - def migrate_user_namespaces - puts "\nGenerate usernames for users without one: ".blue - User.find_each(batch_size: 500) do |user| - if user.namespace - print '-'.cyan - next - end - - username = if user.username.present? - # if user already has username filled - user.username - else - build_username(user) - end - - begin - User.transaction do - user.update_attributes!(username: username) - print '.'.green - end - rescue - print 'F'.red - end - end - puts "\nDone" - end - - def build_username(user) - username = nil - - # generate username - username = user.email.match(/^[^@]*/)[0] - username.gsub!("+", ".") - - # return username if no matches - return username unless User.find_by(username: username) - - # look for same username - (1..10).each do |i| - suffixed_username = "#{username}#{i}" - - return suffixed_username unless User.find_by(username: suffixed_username) - end - end - - def migrate_groups - puts "\nCreate directories for groups: ".blue - - Group.find_each(batch_size: 500) do |group| - begin - if group.dir_exists? - print '-'.cyan - else - if group.ensure_dir_exist - print '.'.green - else - print 'F'.red - end - end - rescue - print 'F'.red - end - end - puts "\nDone" - end - - def migrate_projects - git_path = Gitlab.config.gitlab_shell.repos_path - puts "\nMove projects in groups into respective directories ... ".blue - Project.where('namespace_id IS NOT NULL').find_each(batch_size: 500) do |project| - next unless project.group - - group = project.group - - print "#{project.name_with_namespace.yellow} ... " - - new_path = File.join(git_path, project.path_with_namespace + '.git') - - if File.exists?(new_path) - puts "already at #{new_path}".green - next - end - - old_path = File.join(git_path, project.path + '.git') - - unless File.exists?(old_path) - puts "couldn't find it at #{old_path}".red - next - end - - begin - project.transfer(group.path) - puts "moved to #{new_path}".green - rescue - puts "failed moving to #{new_path}".red - end - end - - puts "\nDone" - end -end From aca6be50d3dc1963491c9dcff61dac3b3ec937ca Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 28 May 2014 19:02:26 +0300 Subject: [PATCH 111/360] Refactor project transfer service. Add security check when create or transfer project into group Signed-off-by: Dmitriy Zaporozhets --- app/services/project_transfer_service.rb | 46 -------------- app/services/projects/create_service.rb | 2 +- app/services/projects/transfer_service.rb | 73 +++++++++++++++++++---- 3 files changed, 62 insertions(+), 59 deletions(-) delete mode 100644 app/services/project_transfer_service.rb diff --git a/app/services/project_transfer_service.rb b/app/services/project_transfer_service.rb deleted file mode 100644 index 7055ef32ae..0000000000 --- a/app/services/project_transfer_service.rb +++ /dev/null @@ -1,46 +0,0 @@ -# ProjectTransferService class -# -# Used for transfer project to another namespace -# -class ProjectTransferService - include Gitlab::ShellAdapter - - class TransferError < StandardError; end - - attr_accessor :project - - def transfer(project, new_namespace) - Project.transaction do - old_path = project.path_with_namespace - new_path = File.join(new_namespace.try(:path) || '', project.path) - - if Project.where(path: project.path, namespace_id: new_namespace.try(:id)).present? - raise TransferError.new("Project with same path in target namespace already exists") - end - - # Remove old satellite - project.satellite.destroy - - # Apply new namespace id - project.namespace = new_namespace - project.save! - - # Move main repository - unless gitlab_shell.mv_repository(old_path, new_path) - raise TransferError.new('Cannot move project') - end - - # Move wiki repo also if present - gitlab_shell.mv_repository("#{old_path}.wiki", "#{new_path}.wiki") - - # Create a new satellite (reload project from DB) - Project.find(project.id).ensure_satellite_exists - - # clear project cached events - project.reset_events_cache - - true - end - end -end - diff --git a/app/services/projects/create_service.rb b/app/services/projects/create_service.rb index 11b6525650..7d322f25e4 100644 --- a/app/services/projects/create_service.rb +++ b/app/services/projects/create_service.rb @@ -97,7 +97,7 @@ module Projects def allowed_namespace?(user, namespace_id) namespace = Namespace.find_by(id: namespace_id) - current_user.can?(:manage_namespace, namespace) + current_user.can?(:create_projects, namespace) end end end diff --git a/app/services/projects/transfer_service.rb b/app/services/projects/transfer_service.rb index f8e27f6f1c..d115e92a10 100644 --- a/app/services/projects/transfer_service.rb +++ b/app/services/projects/transfer_service.rb @@ -1,22 +1,71 @@ +# Projects::TransferService class +# +# Used for transfer project to another namespace +# +# Ex. +# # Move projects to namespace with ID 17 by user +# Projects::TransferService.new(project, user, namespace_id: 17).execute +# module Projects class TransferService < BaseService - def execute(role = :default) - namespace_id = params[:project].delete(:namespace_id) - allowed_transfer = can?(current_user, :change_namespace, project) || role == :admin + include Gitlab::ShellAdapter + class TransferError < StandardError; end - if allowed_transfer && namespace_id.present? - if namespace_id.to_i != project.namespace_id - # Transfer to someone namespace - namespace = Namespace.find(namespace_id) - project.transfer(namespace) - end + def execute + namespace_id = params.delete(:namespace_id) + namespace = Namespace.find_by(id: namespace_id) + + if allowed_transfer?(current_user, project, namespace) + transfer(project, namespace) + else + project.errors.add(:namespace, 'is invalid') + false end - - rescue ProjectTransferService::TransferError => ex + rescue Projects::TransferService::TransferError => ex project.reload project.errors.add(:namespace_id, ex.message) false end + + def transfer(project, new_namespace) + Project.transaction do + old_path = project.path_with_namespace + new_path = File.join(new_namespace.try(:path) || '', project.path) + + if Project.where(path: project.path, namespace_id: new_namespace.try(:id)).present? + raise TransferError.new("Project with same path in target namespace already exists") + end + + # Remove old satellite + project.satellite.destroy + + # Apply new namespace id + project.namespace = new_namespace + project.save! + + # Move main repository + unless gitlab_shell.mv_repository(old_path, new_path) + raise TransferError.new('Cannot move project') + end + + # Move wiki repo also if present + gitlab_shell.mv_repository("#{old_path}.wiki", "#{new_path}.wiki") + + # Create a new satellite (reload project from DB) + Project.find(project.id).ensure_satellite_exists + + # clear project cached events + project.reset_events_cache + + true + end + end + + def allowed_transfer?(current_user, project, namespace) + namespace && + can?(current_user, :change_namespace, project) && + namespace.id != project.namespace_id && + current_user.can?(:create_projects, namespace) + end end end - From aea79b80351109506bd089694df6f22785456f68 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 28 May 2014 19:03:01 +0300 Subject: [PATCH 112/360] Add ability rule for creating project in namespace Signed-off-by: Dmitriy Zaporozhets --- app/models/ability.rb | 8 ++++++++ app/models/group.rb | 6 +++++- app/models/project.rb | 4 ---- app/models/user.rb | 2 ++ 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/app/models/ability.rb b/app/models/ability.rb index 1afe8a4638..70c26caded 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -188,6 +188,13 @@ class Ability rules << :read_group end + # Only group masters and group owners can create new projects in group + if group.has_master?(user) || group.has_owner?(user) || user.admin? + rules += [ + :create_projects, + ] + end + # Only group owner and administrators can manage group if group.has_owner?(user) || user.admin? rules += [ @@ -205,6 +212,7 @@ class Ability # Only namespace owner and administrators can manage it if namespace.owner == user || user.admin? rules += [ + :create_projects, :manage_namespace ] end diff --git a/app/models/group.rb b/app/models/group.rb index 3cbf30a20d..2e68779d36 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -26,7 +26,7 @@ class Group < Namespace validates :avatar, file_size: { maximum: 100.kilobytes.to_i } mount_uploader :avatar, AttachmentUploader - + def self.accessible_to(user) accessible_ids = Project.accessible_to(user).pluck(:namespace_id) accessible_ids += user.groups.pluck(:id) if user @@ -60,6 +60,10 @@ class Group < Namespace owners.include?(user) end + def has_master?(user) + members.masters.where(user_id: user).any? + end + def last_owner?(user) has_owner?(user) && owners.size == 1 end diff --git a/app/models/project.rb b/app/models/project.rb index fc7c7d042f..1e74ae735b 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -387,10 +387,6 @@ class Project < ActiveRecord::Base end end - def transfer(new_namespace) - ProjectTransferService.new.transfer(self, new_namespace) - end - def execute_hooks(data, hooks_scope = :push_hooks) hooks.send(hooks_scope).each do |hook| hook.async_execute(data) diff --git a/app/models/user.rb b/app/models/user.rb index 16961e5413..f1b6139745 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -90,6 +90,8 @@ class User < ActiveRecord::Base has_many :users_groups, dependent: :destroy has_many :groups, through: :users_groups has_many :owned_groups, -> { where users_groups: { group_access: UsersGroup::OWNER } }, through: :users_groups, source: :group + has_many :masters_groups, -> { where users_groups: { group_access: UsersGroup::MASTER } }, through: :users_groups, source: :group + # Projects has_many :groups_projects, through: :groups, source: :projects has_many :personal_projects, through: :namespace, source: :projects From 900d30798b7eef1301978ff6f97b4cee7414b696 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 28 May 2014 19:03:45 +0300 Subject: [PATCH 113/360] Use new Projects::TransferService class Signed-off-by: Dmitriy Zaporozhets --- app/controllers/projects_controller.rb | 2 +- lib/api/groups.rb | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 07ccbd57fa..b9af36a0c7 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -44,7 +44,7 @@ class ProjectsController < ApplicationController end def transfer - ::Projects::TransferService.new(project, current_user, params).execute + ::Projects::TransferService.new(project, current_user, params[:project]).execute end def show diff --git a/lib/api/groups.rb b/lib/api/groups.rb index 03f027706d..caa2ca97a3 100644 --- a/lib/api/groups.rb +++ b/lib/api/groups.rb @@ -87,10 +87,12 @@ module API # POST /groups/:id/projects/:project_id post ":id/projects/:project_id" do authenticated_as_admin! - @group = Group.find(params[:id]) + group = Group.find(params[:id]) project = Project.find(params[:project_id]) - if project.transfer(@group) - present @group + result = ::Projects::TransferService.new(project, current_user, namespace_id: group.id).execute + + if result + present group else not_found! end From 14f78d067d703c20b788498cd90c40903ba9f84e Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 28 May 2014 19:04:18 +0300 Subject: [PATCH 114/360] Modify specs for new project transfer code Signed-off-by: Dmitriy Zaporozhets --- spec/requests/api/groups_spec.rb | 4 +- .../projects/transfer_service_spec.rb | 41 ++++++++++++------- 2 files changed, 29 insertions(+), 16 deletions(-) diff --git a/spec/requests/api/groups_spec.rb b/spec/requests/api/groups_spec.rb index 6fcab85335..f27a60e4bc 100644 --- a/spec/requests/api/groups_spec.rb +++ b/spec/requests/api/groups_spec.rb @@ -147,7 +147,7 @@ describe API::API, api: true do describe "POST /groups/:id/projects/:project_id" do let(:project) { create(:project) } before(:each) do - project.stub(:transfer).and_return(true) + Projects::TransferService.any_instance.stub(execute: true) Project.stub(:find).and_return(project) end @@ -160,8 +160,8 @@ describe API::API, api: true do context "when authenticated as admin" do it "should transfer project to group" do - project.should_receive(:transfer) post api("/groups/#{group1.id}/projects/#{project.id}", admin) + response.status.should == 201 end end end diff --git a/spec/services/projects/transfer_service_spec.rb b/spec/services/projects/transfer_service_spec.rb index 109b429967..563a8b0c01 100644 --- a/spec/services/projects/transfer_service_spec.rb +++ b/spec/services/projects/transfer_service_spec.rb @@ -1,16 +1,20 @@ require 'spec_helper' -describe ProjectTransferService do +describe Projects::TransferService do before(:each) { enable_observers } after(:each) {disable_observers} - context 'namespace -> namespace' do - let(:user) { create(:user) } - let(:group) { create(:group) } - let(:project) { create(:project, namespace: user.namespace) } + let(:user) { create(:user) } + let(:group) { create(:group) } + let(:group2) { create(:group) } + let(:project) { create(:project, namespace: user.namespace) } + context 'namespace -> namespace' do before do - @result = service.transfer(project, group) + group.add_owner(user) + @service = Projects::TransferService.new(project, user, namespace_id: group.id) + @service.gitlab_shell.stub(mv_repository: true) + @result = @service.execute end it { @result.should be_true } @@ -18,16 +22,25 @@ describe ProjectTransferService do end context 'namespace -> no namespace' do - let(:user) { create(:user) } - let(:project) { create(:project, namespace: user.namespace) } + before do + group.add_owner(user) + @service = Projects::TransferService.new(project, user, namespace_id: nil) + @service.gitlab_shell.stub(mv_repository: true) + @result = @service.execute + end - it { lambda{service.transfer(project, nil)}.should raise_error(ActiveRecord::RecordInvalid) } + it { @result.should be_false } + it { project.namespace.should == user.namespace } end - def service - service = ProjectTransferService.new - service.gitlab_shell.stub(mv_repository: true) - service + context 'namespace -> not allowed namespace' do + before do + @service = Projects::TransferService.new(project, user, namespace_id: group2.id) + @service.gitlab_shell.stub(mv_repository: true) + @result = @service.execute + end + + it { @result.should be_false } + it { project.namespace.should == user.namespace } end end - From 1932f902d51d17ff4eb4ebfd15a16fac55cf9eb4 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 28 May 2014 19:04:42 +0300 Subject: [PATCH 115/360] Allow masters to create projects in groups Signed-off-by: Dmitriy Zaporozhets --- app/helpers/namespaces_helper.rb | 2 +- app/views/groups/_projects.html.haml | 2 +- doc/permissions/permissions.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/helpers/namespaces_helper.rb b/app/helpers/namespaces_helper.rb index c363c7ffd7..bf25dce230 100644 --- a/app/helpers/namespaces_helper.rb +++ b/app/helpers/namespaces_helper.rb @@ -1,6 +1,6 @@ module NamespacesHelper def namespaces_options(selected = :current_user, scope = :default) - groups = current_user.owned_groups + groups = current_user.owned_groups + current_user.masters_groups users = [current_user.namespace] group_opts = ["Groups", groups.sort_by(&:human_name).map {|g| [g.human_name, g.id]} ] diff --git a/app/views/groups/_projects.html.haml b/app/views/groups/_projects.html.haml index 41f8cb9da4..4ded28058e 100644 --- a/app/views/groups/_projects.html.haml +++ b/app/views/groups/_projects.html.haml @@ -1,7 +1,7 @@ .ui-box .title Projects (#{projects.count}) - - if can? current_user, :manage_group, @group + - if can? current_user, :create_projects, @group %span.pull-right = link_to new_project_path(namespace_id: @group.id), class: "btn btn-new" do %i.icon-plus diff --git a/doc/permissions/permissions.md b/doc/permissions/permissions.md index 840bb90163..95b47a8612 100644 --- a/doc/permissions/permissions.md +++ b/doc/permissions/permissions.md @@ -40,7 +40,7 @@ If a user is a GitLab administrator they receive all permissions. |------|-----|--------|---------|------|-----| |Browse group|✓|✓|✓|✓|✓| |Edit group|||||✓| -|Create project in group|||||✓| +|Create project in group||||✓|✓| |Manage group members|||||✓| |Remove group|||||✓| From cea0fc1de80242a5849cff343148328028b81914 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 28 May 2014 19:33:49 +0300 Subject: [PATCH 116/360] Fix tests Signed-off-by: Dmitriy Zaporozhets --- spec/models/project_spec.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index b42d7bfe60..a2519fbd68 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -84,7 +84,6 @@ describe Project do it { should respond_to(:satellite) } it { should respond_to(:update_merge_requests) } it { should respond_to(:execute_hooks) } - it { should respond_to(:transfer) } it { should respond_to(:name_with_namespace) } it { should respond_to(:owner) } it { should respond_to(:path_with_namespace) } From e52c4a62f23ebc53f65b1acdbbe3e7c055e8a9d7 Mon Sep 17 00:00:00 2001 From: William Karavites Date: Wed, 28 May 2014 13:08:00 -0400 Subject: [PATCH 117/360] Too many zeros in CPU req listing There were too many zeros in the listing of users for CPU's. --- doc/install/requirements.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/install/requirements.md b/doc/install/requirements.md index 2830a75df5..5e08458ec8 100644 --- a/doc/install/requirements.md +++ b/doc/install/requirements.md @@ -49,9 +49,9 @@ We love [JRuby](http://jruby.org/) and [Rubinius](http://rubini.us/)) but GitLab - **2 cores** is the **recommended** number of cores and supports up to 500 users - 4 cores supports up to 2,000 users - 8 cores supports up to 5,000 users -- 16 cores supports up to 10,0000 users -- 32 cores supports up to 20,0000 users -- 64 cores supports up to 40,0000 users +- 16 cores supports up to 10,000 users +- 32 cores supports up to 20,000 users +- 64 cores supports up to 40,000 users ## Memory From ce498eed9a2f394ce8c3110d0e233e873152c931 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 28 May 2014 20:18:25 +0300 Subject: [PATCH 118/360] Add stuff to CHANGELOG Signed-off-by: Dmitriy Zaporozhets --- CHANGELOG | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 1410c96e04..163e46975a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -9,6 +9,8 @@ v 7.0.0 - Redirect to Files view when create new branch via UI - Drag and drop upload of image in every markdown-area (Earle Randolph Bunao and Neil Francis Calabroso) - Refactor the markdown relative links processing + - Make it easier to implement other CI services for GitLab + - Group masters can create projects in group v 6.9.1 - Fix scroll to highlighted line From e61e3eaadb7f0c7c106b72d1325437e7743a2027 Mon Sep 17 00:00:00 2001 From: Job van der Voort Date: Tue, 15 Apr 2014 18:01:54 +0200 Subject: [PATCH 119/360] render readme in help --- app/assets/stylesheets/application.scss | 1 + app/assets/stylesheets/sections/help.scss | 11 +++++ app/views/help/index.html.haml | 54 +++-------------------- 3 files changed, 17 insertions(+), 49 deletions(-) create mode 100644 app/assets/stylesheets/sections/help.scss diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index 0b372a87a1..630d2aa429 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -34,6 +34,7 @@ /** * Page specific styles (issues, projects etc): */ + @import "sections/*"; /** diff --git a/app/assets/stylesheets/sections/help.scss b/app/assets/stylesheets/sections/help.scss new file mode 100644 index 0000000000..c888185370 --- /dev/null +++ b/app/assets/stylesheets/sections/help.scss @@ -0,0 +1,11 @@ +.documentation { + padding-bottom: 10px; + p { + padding: 10px; + margin: 0; + } + li { + list-style-type: none; + padding-left: 10px; + } +} \ No newline at end of file diff --git a/app/views/help/index.html.haml b/app/views/help/index.html.haml index 724fe1d6b3..8f0db82d47 100644 --- a/app/views/help/index.html.haml +++ b/app/views/help/index.html.haml @@ -33,53 +33,9 @@ Use = link_to "shortcuts", '#', onclick: "new Shortcuts()" - .col-md-4 - .ui-box - .title - User documentation - %ul.well-list - %li - %strong= link_to "Workflow", help_workflow_path - %p Learn how to use Git and GitLab together. + .col-md-8 + .ui-box.documentation + .title Documentation - %li - %strong= link_to "SSH keys", help_ssh_path - %p Setup secure access to your projects. - - %li - %strong= link_to "GitLab Markdown", help_markdown_path - %p Learn what you can do with GitLab's advanced formatting system. - - %li - %strong= link_to "Permissions", help_permissions_path - %p Get familiar with GitLab's permission levels. - - %li - %strong= link_to "API", help_api_file_path(category: 'README') - %p Explore how you can access GitLab via a simple and powerful API. - - %li - %strong= link_to "Web Hooks", help_web_hooks_path - %p Let GitLab notify you when new code has been pushed to your project. - - .col-md-4 - .ui-box - .title - Admin documentation - %ul.well-list - - %li - %strong= link_to "Rake Tasks", help_raketasks_path - %p Explore what GitLab has in store for you to make administration easier. - - %li - %strong= link_to "System Hooks", help_system_hooks_path - %p Let GitLab notify you when certain management tasks need to be carried out. - - %li - %strong= link_to "Public Access", help_public_access_path - %p Learn how you can allow public access to a project. - - %li - %strong= link_to "Security", help_security_path - %p Learn what you can do to secure your GitLab instance. + = preserve do + = markdown File.read(Rails.root.join("doc", "README.md")) \ No newline at end of file From fd476cf62013e49acf23a301b841e7c09197e9ae Mon Sep 17 00:00:00 2001 From: Job van der Voort Date: Fri, 18 Apr 2014 17:21:21 +0200 Subject: [PATCH 120/360] render items from doc --- app/assets/stylesheets/sections/help.scss | 20 ++++++++++---------- app/controllers/help_controller.rb | 11 +++++++++++ app/views/help/_layout.html.haml | 10 +++++----- app/views/help/index.html.haml | 2 +- app/views/help/show.html.haml | 1 + config/routes.rb | 16 +++------------- 6 files changed, 31 insertions(+), 29 deletions(-) create mode 100644 app/views/help/show.html.haml diff --git a/app/assets/stylesheets/sections/help.scss b/app/assets/stylesheets/sections/help.scss index c888185370..6488e7c1e8 100644 --- a/app/assets/stylesheets/sections/help.scss +++ b/app/assets/stylesheets/sections/help.scss @@ -1,11 +1,11 @@ .documentation { - padding-bottom: 10px; - p { - padding: 10px; - margin: 0; - } - li { - list-style-type: none; - padding-left: 10px; - } -} \ No newline at end of file + padding-bottom: 10px; + p { + padding: 10px; + margin: 0; + } + li { + list-style-type: none; + padding-left: 10px; + } +} diff --git a/app/controllers/help_controller.rb b/app/controllers/help_controller.rb index 051cbdfaf0..a4fcd4b29e 100644 --- a/app/controllers/help_controller.rb +++ b/app/controllers/help_controller.rb @@ -13,6 +13,17 @@ class HelpController < ApplicationController end end + def show + @category = params[:category] + @file = params[:file] + + if File.exists?(Rails.root.join('doc', @category, @file + '.md')) + render 'show' + else + not_found! + end + end + def shortcuts end end diff --git a/app/views/help/_layout.html.haml b/app/views/help/_layout.html.haml index 201d63ca24..72547ed014 100644 --- a/app/views/help/_layout.html.haml +++ b/app/views/help/_layout.html.haml @@ -1,11 +1,11 @@ .row .col-md-3 %h3.page-title Help - %ul.nav.nav-pills.nav-stacked - - links = {:"Workflow" => help_workflow_path, :"SSH Keys" => help_ssh_path, :"GitLab Markdown" => help_markdown_path, :"Permissions" => help_permissions_path, :"API" => help_api_path, :"Web Hooks" => help_web_hooks_path, :"Rake Tasks" => help_raketasks_path, :"System Hooks" => help_system_hooks_path, :"Public Access" => help_public_access_path, :"Security" => help_security_path} - - links.each do |title,path| - %li{class: current_page?(path) ? 'active' : nil} - = link_to title, path + / %ul.nav.nav-pills.nav-stacked + / - links = {:"Workflow" => help_workflow_path, :"SSH Keys" => help_ssh_path, :"GitLab Markdown" => help_markdown_path, :"Permissions" => help_permissions_path, :"API" => help_api_path, :"Web Hooks" => help_web_hooks_path, :"Rake Tasks" => help_raketasks_path, :"System Hooks" => help_system_hooks_path, :"Public Access" => help_public_access_path, :"Security" => help_security_path} + / - links.each do |title,path| + / %li{class: current_page?(path) ? 'active' : nil} + / = link_to title, path .col-md-9 .wiki diff --git a/app/views/help/index.html.haml b/app/views/help/index.html.haml index 8f0db82d47..ca8e17d152 100644 --- a/app/views/help/index.html.haml +++ b/app/views/help/index.html.haml @@ -38,4 +38,4 @@ .title Documentation = preserve do - = markdown File.read(Rails.root.join("doc", "README.md")) \ No newline at end of file + = markdown File.read(Rails.root.join("doc", "README.md")) diff --git a/app/views/help/show.html.haml b/app/views/help/show.html.haml new file mode 100644 index 0000000000..d7785d307e --- /dev/null +++ b/app/views/help/show.html.haml @@ -0,0 +1 @@ += markdown File.read(Rails.root.join('doc', @category, @file + '.md')) diff --git a/config/routes.rb b/config/routes.rb index ada9bb1d77..bab8fb1d21 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -31,19 +31,9 @@ Gitlab::Application.routes.draw do # # Help # - get 'help' => 'help#index' - get 'help/api' => 'help#api' - get 'help/api/:category' => 'help#api', as: 'help_api_file' - get 'help/markdown' => 'help#markdown' - get 'help/permissions' => 'help#permissions' - get 'help/public_access' => 'help#public_access' - get 'help/raketasks' => 'help#raketasks' - get 'help/ssh' => 'help#ssh' - get 'help/system_hooks' => 'help#system_hooks' - get 'help/web_hooks' => 'help#web_hooks' - get 'help/workflow' => 'help#workflow' - get 'help/shortcuts' - get 'help/security' + + get 'help' => 'help#index' + get 'help/:category/:file' => 'help#show' # # Global snippets From 54ff9d90adc66f88c608b2157789d71b0944590e Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Wed, 28 May 2014 14:37:08 +0200 Subject: [PATCH 121/360] Scan the text and add the help path. --- app/views/help/index.html.haml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/views/help/index.html.haml b/app/views/help/index.html.haml index ca8e17d152..87fa5ef57d 100644 --- a/app/views/help/index.html.haml +++ b/app/views/help/index.html.haml @@ -38,4 +38,7 @@ .title Documentation = preserve do - = markdown File.read(Rails.root.join("doc", "README.md")) + - readme_text = File.read(Rails.root.join("doc", "README.md")) + - text = readme_text.dup + - readme_text.scan(/\]\(([^(]+)\)/) { |match| text.gsub!(match.first, "help/#{match.first}") } + = markdown text From 59797b2f2eef559397b53b6a3763c62d40363902 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Wed, 28 May 2014 15:18:23 +0200 Subject: [PATCH 122/360] Remove list items styling in show render. --- app/views/help/show.html.haml | 4 +++- doc/workflow/README.md | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/app/views/help/show.html.haml b/app/views/help/show.html.haml index d7785d307e..e9fc6163c7 100644 --- a/app/views/help/show.html.haml +++ b/app/views/help/show.html.haml @@ -1 +1,3 @@ -= markdown File.read(Rails.root.join('doc', @category, @file + '.md')) +.col-md-12 + .documentation + = markdown File.read(Rails.root.join('doc', @category, @file + '.md')) diff --git a/doc/workflow/README.md b/doc/workflow/README.md index efc28d06e7..39b3059e07 100644 --- a/doc/workflow/README.md +++ b/doc/workflow/README.md @@ -1,2 +1,2 @@ -+ [Workflow](workflow/workflow.md) -+ [Project Features](workflow/project_features.md) ++ [Workflow](workflow.md) ++ [Project Features](project_features.md) From a9580a157a39bd6d7bc046f1bada88eb5d698b9c Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Wed, 28 May 2014 15:47:03 +0200 Subject: [PATCH 123/360] Use the correct links, replace in search. --- app/helpers/search_helper.rb | 18 +++++++++--------- app/views/help/_layout.html.haml | 6 ------ app/views/projects/_visibility_level.html.haml | 2 +- config/routes.rb | 2 +- 4 files changed, 11 insertions(+), 17 deletions(-) diff --git a/app/helpers/search_helper.rb b/app/helpers/search_helper.rb index d7f3da7e53..01c3120569 100644 --- a/app/helpers/search_helper.rb +++ b/app/helpers/search_helper.rb @@ -33,15 +33,15 @@ module SearchHelper # Autocomplete results for internal help pages def help_autocomplete [ - { label: "help: API Help", url: help_api_path }, - { label: "help: Markdown Help", url: help_markdown_path }, - { label: "help: Permissions Help", url: help_permissions_path }, - { label: "help: Public Access Help", url: help_public_access_path }, - { label: "help: Rake Tasks Help", url: help_raketasks_path }, - { label: "help: SSH Keys Help", url: help_ssh_path }, - { label: "help: System Hooks Help", url: help_system_hooks_path }, - { label: "help: Web Hooks Help", url: help_web_hooks_path }, - { label: "help: Workflow Help", url: help_workflow_path }, + { label: "help: API Help", url: help_page_path("api", "README") }, + { label: "help: Markdown Help", url: help_page_path("markdown", "markdown") }, + { label: "help: Permissions Help", url: help_page_path("permissions", "permissions") }, + { label: "help: Public Access Help", url: help_page_path("public_access", "public_access") }, + { label: "help: Rake Tasks Help", url: help_page_path("raketasks", "README") }, + { label: "help: SSH Keys Help", url: help_page_path("ssh", "README") }, + { label: "help: System Hooks Help", url: help_page_path("system_hooks", "system_hooks") }, + { label: "help: Web Hooks Help", url: help_page_path("web_hooks", "web_hooks") }, + { label: "help: Workflow Help", url: help_page_path("workflow", "README") }, ] end diff --git a/app/views/help/_layout.html.haml b/app/views/help/_layout.html.haml index 72547ed014..93a746c60e 100644 --- a/app/views/help/_layout.html.haml +++ b/app/views/help/_layout.html.haml @@ -1,12 +1,6 @@ .row .col-md-3 %h3.page-title Help - / %ul.nav.nav-pills.nav-stacked - / - links = {:"Workflow" => help_workflow_path, :"SSH Keys" => help_ssh_path, :"GitLab Markdown" => help_markdown_path, :"Permissions" => help_permissions_path, :"API" => help_api_path, :"Web Hooks" => help_web_hooks_path, :"Rake Tasks" => help_raketasks_path, :"System Hooks" => help_system_hooks_path, :"Public Access" => help_public_access_path, :"Security" => help_security_path} - / - links.each do |title,path| - / %li{class: current_page?(path) ? 'active' : nil} - / = link_to title, path - .col-md-9 .wiki = yield diff --git a/app/views/projects/_visibility_level.html.haml b/app/views/projects/_visibility_level.html.haml index eb38fce0ec..5f34e66b3e 100644 --- a/app/views/projects/_visibility_level.html.haml +++ b/app/views/projects/_visibility_level.html.haml @@ -1,7 +1,7 @@ .form-group.project-visibility-level-holder = f.label :visibility_level, class: 'control-label' do Visibility Level - = link_to "(?)", help_public_access_path + = link_to "(?)", help_page_path("public_access", "public_access") .col-sm-10 - if can_change_visibility_level - Gitlab::VisibilityLevel.values.each do |level| diff --git a/config/routes.rb b/config/routes.rb index bab8fb1d21..38e6727b19 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -33,7 +33,7 @@ Gitlab::Application.routes.draw do # get 'help' => 'help#index' - get 'help/:category/:file' => 'help#show' + get 'help/:category/:file' => 'help#show', as: :help_page # # Global snippets From f79a300417120bb2bdd5d5b22c8ced42e5c3dab7 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Wed, 28 May 2014 15:58:02 +0200 Subject: [PATCH 124/360] Replace existing links to help pages with the new ones. --- app/views/admin/groups/show.html.haml | 2 +- app/views/admin/hooks/index.html.haml | 2 +- app/views/errors/access_denied.html.haml | 2 +- app/views/groups/members.html.haml | 2 +- app/views/profiles/keys/index.html.haml | 2 +- app/views/profiles/keys/new.html.haml | 2 +- app/views/projects/deploy_keys/_form.html.haml | 2 +- app/views/projects/hooks/index.html.haml | 2 +- app/views/projects/issues/_form.html.haml | 2 +- app/views/projects/merge_requests/_form.html.haml | 3 +-- app/views/projects/merge_requests/_new_submit.html.haml | 3 +-- app/views/projects/milestones/_form.html.haml | 2 +- app/views/projects/notes/_form.html.haml | 2 +- app/views/projects/protected_branches/index.html.haml | 4 ++-- app/views/projects/team_members/index.html.haml | 2 +- app/views/projects/wikis/_form.html.haml | 3 +-- features/steps/help.rb | 2 +- 17 files changed, 18 insertions(+), 21 deletions(-) diff --git a/app/views/admin/groups/show.html.haml b/app/views/admin/groups/show.html.haml index 6055865b4c..594762f495 100644 --- a/app/views/admin/groups/show.html.haml +++ b/app/views/admin/groups/show.html.haml @@ -51,7 +51,7 @@ .body.form-holder %p.light Read more about project permissions - %strong= link_to "here", help_permissions_path, class: "vlink" + %strong= link_to "here", help_page_path("permissions", "permissions"), class: "vlink" = form_tag project_teams_update_admin_group_path(@group), id: "new_team_member", class: "bulk_import", method: :put do %div diff --git a/app/views/admin/hooks/index.html.haml b/app/views/admin/hooks/index.html.haml index 60773c2009..b27523cbf2 100644 --- a/app/views/admin/hooks/index.html.haml +++ b/app/views/admin/hooks/index.html.haml @@ -2,7 +2,7 @@ System hooks %p.light - #{link_to "System hooks ", help_system_hooks_path, class: "vlink"} can be + #{link_to "System hooks ", help_page_path("system_hooks", "system_hooks"), class: "vlink"} can be used for binding events when GitLab creates a User or Project. %hr diff --git a/app/views/errors/access_denied.html.haml b/app/views/errors/access_denied.html.haml index 6aa78f0c2a..e005a7c440 100644 --- a/app/views/errors/access_denied.html.haml +++ b/app/views/errors/access_denied.html.haml @@ -2,4 +2,4 @@ %h3.page-title Access Denied %hr %p You are not allowed to access this page. -%p Read more about project permissions #{link_to "here", help_permissions_path, class: "vlink"} +%p Read more about project permissions #{link_to "here", help_page_path("permissions", "permissions"), class: "vlink"} diff --git a/app/views/groups/members.html.haml b/app/views/groups/members.html.haml index fa44ee2ae1..cc5eba6437 100644 --- a/app/views/groups/members.html.haml +++ b/app/views/groups/members.html.haml @@ -5,7 +5,7 @@ %p.light Members of group have access to all group projects. Read more about permissions - %strong= link_to "here", help_permissions_path, class: "vlink" + %strong= link_to "here", help_page_path("permissions", "permissions"), class: "vlink" %hr diff --git a/app/views/profiles/keys/index.html.haml b/app/views/profiles/keys/index.html.haml index 71a4ca91d4..2e10fa8be8 100644 --- a/app/views/profiles/keys/index.html.haml +++ b/app/views/profiles/keys/index.html.haml @@ -6,7 +6,7 @@ SSH keys allow you to establish a secure connection between your computer and GitLab %br Before you can add an SSH key you need to - = link_to "generate it", help_ssh_path + = link_to "generate it", help_page_path("ssh", "README") %hr diff --git a/app/views/profiles/keys/new.html.haml b/app/views/profiles/keys/new.html.haml index 3d5a947948..126afa5554 100644 --- a/app/views/profiles/keys/new.html.haml +++ b/app/views/profiles/keys/new.html.haml @@ -1,6 +1,6 @@ %h3.page-title Add an SSH Key %p.light - Paste your public key here. Read more about how to generate a key on #{link_to "the SSH help page", help_ssh_path}. + Paste your public key here. Read more about how to generate a key on #{link_to "the SSH help page", help_page_path("ssh", "README")}. %hr = render 'form' diff --git a/app/views/projects/deploy_keys/_form.html.haml b/app/views/projects/deploy_keys/_form.html.haml index ebb92b36b4..162ef05b36 100644 --- a/app/views/projects/deploy_keys/_form.html.haml +++ b/app/views/projects/deploy_keys/_form.html.haml @@ -14,7 +14,7 @@ .col-sm-10 %p.light Paste a machine public key here. Read more about how to generate it - = link_to "here", help_ssh_path + = link_to "here", help_page_path("ssh", "README") = f.text_area :key, class: "form-control thin_area", rows: 5 .form-actions diff --git a/app/views/projects/hooks/index.html.haml b/app/views/projects/hooks/index.html.haml index 866fd6f606..73171fbe99 100644 --- a/app/views/projects/hooks/index.html.haml +++ b/app/views/projects/hooks/index.html.haml @@ -2,7 +2,7 @@ Web hooks %p.light - #{link_to "Web hooks ", help_web_hooks_path, class: "vlink"} can be + #{link_to "Web hooks ", help_page_path("web_hooks", "web_hooks"), class: "vlink"} can be used for binding events when something is happening within the project. %hr.clearfix diff --git a/app/views/projects/issues/_form.html.haml b/app/views/projects/issues/_form.html.haml index 6e61fc8524..120d70eaa6 100644 --- a/app/views/projects/issues/_form.html.haml +++ b/app/views/projects/issues/_form.html.haml @@ -22,7 +22,7 @@ .col-sm-10 = f.text_area :description, class: 'form-control js-gfm-input markdown-area', rows: 14 .col-sm-12.hint - .pull-left Issues are parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}. + .pull-left Issues are parsed with #{link_to "GitLab Flavored Markdown", help_page_path("markdown", "markdown"), target: '_blank'}. .pull-right Attach images (JPG, PNG, GIF) by dragging & dropping, #{link_to "selecting them", '#', class: 'markdown-selector' } or pasting from the clipboard. .clearfix .error-alert diff --git a/app/views/projects/merge_requests/_form.html.haml b/app/views/projects/merge_requests/_form.html.haml index facc6a63f3..27ea53c006 100644 --- a/app/views/projects/merge_requests/_form.html.haml +++ b/app/views/projects/merge_requests/_form.html.haml @@ -24,9 +24,8 @@ .col-sm-10 = f.text_area :description, class: "form-control js-gfm-input markdown-area", rows: 14 .col-sm-12.hint - .pull-left Description is parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}. + .pull-left Description is parsed with #{link_to "GitLab Flavored Markdown", help_page_path("markdown", "markdown"), target: '_blank'}. .pull-right Attach images (JPG, PNG, GIF) by dragging & dropping, #{link_to "selecting them", '#', class: 'markdown-selector' } or pasting from the clipboard. - .clearfix .error-alert %hr diff --git a/app/views/projects/merge_requests/_new_submit.html.haml b/app/views/projects/merge_requests/_new_submit.html.haml index bf0e40f9a1..bdfa4444ab 100644 --- a/app/views/projects/merge_requests/_new_submit.html.haml +++ b/app/views/projects/merge_requests/_new_submit.html.haml @@ -25,9 +25,8 @@ = f.label :description, "Description" = f.text_area :description, class: "form-control js-gfm-input markdown-area", rows: 10 .col-sm-12.hint - .pull-left Description is parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}. + .pull-left Description is parsed with #{link_to "GitLab Flavored Markdown", help_page_path("markdown", "markdown"), target: '_blank'}. .pull-right Attach images (JPG, PNG, GIF) by dragging & dropping, #{link_to "selecting them", '#', class: 'markdown-selector' } or pasting from the clipboard. - .clearfix .error-alert .form-group diff --git a/app/views/projects/milestones/_form.html.haml b/app/views/projects/milestones/_form.html.haml index 2233a8838c..9f3e0c44b2 100644 --- a/app/views/projects/milestones/_form.html.haml +++ b/app/views/projects/milestones/_form.html.haml @@ -23,7 +23,7 @@ .col-sm-10 = f.text_area :description, maxlength: 2000, class: "form-control markdown-area", rows: 10 .hint - .pull-left Milestones are parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}. + .pull-left Milestones are parsed with #{link_to "GitLab Flavored Markdown", help_page_path("markdown", "markdown"), target: '_blank'}. .pull-left Attach images (JPG, PNG, GIF) by dragging & dropping, #{link_to "selecting them", '#', class: 'markdown-selector' } or pasting from the clipboard. .clearfix .error-alert diff --git a/app/views/projects/notes/_form.html.haml b/app/views/projects/notes/_form.html.haml index 25ebaca930..f6a21f7995 100644 --- a/app/views/projects/notes/_form.html.haml +++ b/app/views/projects/notes/_form.html.haml @@ -17,7 +17,7 @@ = f.text_area :note, size: 255, class: 'note_text js-note-text js-gfm-input markdown-area' .light.clearfix.hint - .pull-left Comments are parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}. + .pull-left Comments are parsed with #{link_to "GitLab Flavored Markdown", help_page_path("markdown", "markdown"), target: '_blank'} .pull-right Attach images (JPG, PNG, GIF) by dragging & dropping, #{link_to "selecting them", '#', class: 'markdown-selector' } or pasting from the clipboard. .error-alert .note-preview-holder.hide diff --git a/app/views/projects/protected_branches/index.html.haml b/app/views/projects/protected_branches/index.html.haml index e51bf1d3a8..a51a4cc224 100644 --- a/app/views/projects/protected_branches/index.html.haml +++ b/app/views/projects/protected_branches/index.html.haml @@ -5,10 +5,10 @@ .bs-callout.bs-callout-info %p Protected branches designed to %ul - %li prevent push for all except #{link_to "masters", help_permissions_path, class: "vlink"}. + %li prevent push for all except #{link_to "masters", help_page_path("permissions", "permissions"), class: "vlink"}. %li prevent branch from force push %li prevent branch from removal - %p Read more about project permissions #{link_to "here", help_permissions_path, class: "underlined-link"} + %p Read more about project permissions #{link_to "here", help_page_path("permissions", "permissions"), class: "underlined-link"} - if can? current_user, :admin_project, @project = form_for [@project, @protected_branch], html: { class: 'form-horizontal' } do |f| diff --git a/app/views/projects/team_members/index.html.haml b/app/views/projects/team_members/index.html.haml index 6eccaafe3d..ddb3b9d4a9 100644 --- a/app/views/projects/team_members/index.html.haml +++ b/app/views/projects/team_members/index.html.haml @@ -10,7 +10,7 @@ %p.light Read more about project permissions - %strong= link_to "here", help_permissions_path, class: "vlink" + %strong= link_to "here", help_page_path("permissions", "permissions"), class: "vlink" = render "team", members: @users_projects - if @group = render "group_members" diff --git a/app/views/projects/wikis/_form.html.haml b/app/views/projects/wikis/_form.html.haml index 303cec8e98..a0a56b84a1 100644 --- a/app/views/projects/wikis/_form.html.haml +++ b/app/views/projects/wikis/_form.html.haml @@ -24,9 +24,8 @@ .col-sm-10 = f.text_area :content, class: 'form-control js-gfm-input markdown-area', rows: 18 .col-sm-12.hint - .pull-left Wiki content is parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}. + .pull-left Wiki content is parsed with #{link_to "GitLab Flavored Markdown", help_page_path("markdown", "markdown"), target: '_blank'} .pull-right Attach images (JPG, PNG, GIF) by dragging & dropping, #{link_to "selecting them", '#', class: 'markdown-selector' } or pasting from the clipboard. - .clearfix .error-alert .form-group diff --git a/features/steps/help.rb b/features/steps/help.rb index 5ea2c5daee..770aceadb8 100644 --- a/features/steps/help.rb +++ b/features/steps/help.rb @@ -8,7 +8,7 @@ class Spinach::Features::Help < Spinach::FeatureSteps end step 'I visit the "Rake Tasks" help page' do - visit help_raketasks_path + visit help_page_path("raketasks", "README") end step 'I should see "Rake Tasks" page markdown rendered' do From c1551c6ed077a00731e692edc1a7ddb0b1f29ad1 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Thu, 29 May 2014 08:36:32 +0200 Subject: [PATCH 125/360] Fix routing tests. --- spec/routing/routing_spec.rb | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/spec/routing/routing_spec.rb b/spec/routing/routing_spec.rb index a2d2a35140..7bfd5d0b99 100644 --- a/spec/routing/routing_spec.rb +++ b/spec/routing/routing_spec.rb @@ -79,35 +79,35 @@ describe HelpController, "routing" do end it "to #permissions" do - get("/help/permissions").should route_to('help#permissions') + get("/help/permissions/permissions").should route_to('help#show', category: "permissions", file: "permissions") end it "to #workflow" do - get("/help/workflow").should route_to('help#workflow') + get("/help/workflow/README").should route_to('help#show', category: "workflow", file: "README") end it "to #api" do - get("/help/api").should route_to('help#api') + get("/help/api/README").should route_to('help#show', category: "api", file: "README") end it "to #web_hooks" do - get("/help/web_hooks").should route_to('help#web_hooks') + get("/help/web_hooks/web_hooks").should route_to('help#show', category: "web_hooks", file: "web_hooks") end it "to #system_hooks" do - get("/help/system_hooks").should route_to('help#system_hooks') + get("/help/system_hooks/system_hooks").should route_to('help#show', category: "system_hooks", file: "system_hooks") end it "to #markdown" do - get("/help/markdown").should route_to('help#markdown') + get("/help/markdown/markdown").should route_to('help#show',category: "markdown", file: "markdown") end it "to #ssh" do - get("/help/ssh").should route_to('help#ssh') + get("/help/ssh/README").should route_to('help#show', category: "ssh", file: "README") end it "to #raketasks" do - get("/help/raketasks").should route_to('help#raketasks') + get("/help/raketasks/README").should route_to('help#show', category: "raketasks", file: "README") end end From 321130de7aa2c98eb8298c4e1caf2e2f468cd514 Mon Sep 17 00:00:00 2001 From: dosire Date: Thu, 29 May 2014 09:12:35 +0200 Subject: [PATCH 126/360] Make the updating documetation better for Omnibus users. --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index ef0b84c9bd..d6b959ba54 100644 --- a/README.md +++ b/README.md @@ -51,13 +51,13 @@ Please see [the installation page on the GitLab website](https://www.gitlab.com/installation/). -### New versions and upgrading +### New versions -Since 2011 GitLab is released on the 22nd of every month. Every new release includes an [upgrade guide](doc/update) and new features are detailed in the [Changelog](CHANGELOG). +Since 2011 a minor or major version of GitLab is released on the 22nd of every month. Patch and security releases come out when needed. New features are detailed on the [blog](https://www.gitlab.com/blog/) and in the [changelog](CHANGELOG). For more information about the release process see the release [documentation](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/release). Features that will likely be in the next releases can be found on the [feature request forum](http://feedback.gitlab.com/forums/176466-general) with the status [started](http://feedback.gitlab.com/forums/176466-general/status/796456) and [completed](http://feedback.gitlab.com/forums/176466-general/status/796457). -It is recommended to follow a monthly upgrade schedule. Security releases come out when needed. For more information about the release process see the documentation for [monthly](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/release/monthly.md) and [security](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/release/security.md) releases. +### Upgrading -* Features that will be in the next releases are listed on the [feature request forum](http://feedback.gitlab.com/forums/176466-general) with the status [started](http://feedback.gitlab.com/forums/176466-general/status/796456) and [completed](http://feedback.gitlab.com/forums/176466-general/status/796457). +For updating the the Omnibus installation please see the [update documentation](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/update.md). For manual installations there is an [upgrader script](doc/update/upgrader.md) and there are [upgrade guides](doc/update). ### Run in production mode From 0879babfd1224626d0523a66caca0cac44ee9ee8 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Thu, 29 May 2014 10:13:30 +0200 Subject: [PATCH 127/360] Fix feature. --- features/steps/help.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/features/steps/help.rb b/features/steps/help.rb index 770aceadb8..bfb3a38a29 100644 --- a/features/steps/help.rb +++ b/features/steps/help.rb @@ -8,14 +8,14 @@ class Spinach::Features::Help < Spinach::FeatureSteps end step 'I visit the "Rake Tasks" help page' do - visit help_page_path("raketasks", "README") + visit help_page_path("raketasks", "maintenance") end step 'I should see "Rake Tasks" page markdown rendered' do - page.should have_content "GitLab provides some specific rake tasks to enable special features or perform maintenance tasks" + page.should have_content "Gather information about GitLab and the system it runs on" end step 'Header "Rebuild project satellites" should have correct ids and links' do - header_should_have_correct_id_and_link(3, '(Re-)Create satellite repos', 're-create-satellite-repos') + header_should_have_correct_id_and_link(3, '(Re-)Create satellite repos', 're-create-satellite-repos', '.documentation') end end From 2dbf1a00a91b98f639212b46efdcbe60484e4483 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Tue, 27 May 2014 12:47:09 +0200 Subject: [PATCH 128/360] Ruby 2.0+ is a requirement. --- README.md | 2 +- doc/install/requirements.md | 2 +- doc/raketasks/maintenance.md | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index ef0b84c9bd..10b3c9a828 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ ### Requirements * Ubuntu/Debian/CentOS/RHEL** -* ruby 1.9.3+ +* ruby 2.0+ * git 1.7.10+ * redis 2.0+ * MySQL or PostgreSQL diff --git a/doc/install/requirements.md b/doc/install/requirements.md index 2830a75df5..3b8335e272 100644 --- a/doc/install/requirements.md +++ b/doc/install/requirements.md @@ -36,7 +36,7 @@ Please consider using a virtual machine to run GitLab. # Ruby versions -GitLab requires Ruby (MRI) 1.9.3 or 2.0+. +GitLab requires Ruby (MRI) 2.0+. You will have to use the standard MRI implementation of Ruby. We love [JRuby](http://jruby.org/) and [Rubinius](http://rubini.us/)) but GitLab needs several Gems that have native extensions. diff --git a/doc/raketasks/maintenance.md b/doc/raketasks/maintenance.md index da58962499..e9ae3fb300 100644 --- a/doc/raketasks/maintenance.md +++ b/doc/raketasks/maintenance.md @@ -16,8 +16,8 @@ System information System: Debian 6.0.7 Current User: git Using RVM: no -Ruby Version: 1.9.3p392 -Gem Version: 1.8.23 +Ruby Version: 2.0.0-p481 +Gem Version: 1.8.23 Bundler Version:1.3.5 Rake Version: 10.0.4 From dfaf1a09924407df3b08d8796bc00ad2a0f56723 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Tue, 27 May 2014 13:04:14 +0200 Subject: [PATCH 129/360] Add deprecation to changelog. --- CHANGELOG | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG b/CHANGELOG index 163e46975a..c8a969912e 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -11,6 +11,7 @@ v 7.0.0 - Refactor the markdown relative links processing - Make it easier to implement other CI services for GitLab - Group masters can create projects in group + - Deprecate ruby 1.9.3 support v 6.9.1 - Fix scroll to highlighted line From 17a696a98b8f7a8bbdbcd4bdc3d1500e08ddceaa Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Thu, 29 May 2014 12:01:34 +0200 Subject: [PATCH 130/360] We need shortcuts route. --- config/routes.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/config/routes.rb b/config/routes.rb index 38e6727b19..6581aeef11 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -34,6 +34,7 @@ Gitlab::Application.routes.draw do get 'help' => 'help#index' get 'help/:category/:file' => 'help#show', as: :help_page + get 'help/shortcuts' # # Global snippets From 631eb0420c03da8ada8edb2e94f7474952fbd070 Mon Sep 17 00:00:00 2001 From: GitLab Date: Thu, 29 May 2014 12:33:14 +0200 Subject: [PATCH 131/360] No need to copy the unicorn file if you use the cookbook. --- README.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 10b3c9a828..ba653940e2 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ ### Resources -* [GitLab.com](https://www.gitlab.com/) includes information about [subscriptions](https://www.gitlab.com/subscription/), [consultancy](https://www.gitlab.com/consultancy/), the [community](https://www.gitlab.com/community/) and the [hosted GitLab Cloud](https://www.gitlab.com/cloud/). +* [www.gitlab.com](https://www.gitlab.com/) includes information about [subscriptions](https://www.gitlab.com/subscription/), [consultancy](https://www.gitlab.com/consultancy/), the [community](https://www.gitlab.com/community/) and the [hosted GitLab.com](https://www.gitlab.com/gitlab-com/). * [GitLab Enterprise Edition](https://www.gitlab.com/gitlab-ee/) offers additional features aimed at larger organizations. @@ -71,14 +71,15 @@ or by directly calling the script Please login with root / 5iveL!fe -### Run in development mode +### Install a development environment -Consider setting up the development environment with [the cookbook](https://gitlab.com/gitlab-org/cookbook-gitlab/blob/master/README.md#installation). - -Copy the example development unicorn configuration file +We recommend setting up your development environment with [the cookbook](https://gitlab.com/gitlab-org/cookbook-gitlab/blob/master/README.md#installation). +If you do not use the cookbook you might need to copy the example development unicorn configuration file cp config/unicorn.rb.example.development config/unicorn.rb +### Run in development mode + Start it with [Foreman](https://github.com/ddollar/foreman) bundle exec foreman start -p 3000 From 3910b5917c84875f94f8b15594e4c506a3de39cc Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Thu, 29 May 2014 12:49:15 +0200 Subject: [PATCH 132/360] Extend default link_to helper to add noreferrer html_option. --- app/helpers/application_helper.rb | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 5f07cdf448..4a3b345bdf 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -231,4 +231,18 @@ module ApplicationHelper content_tag(:i, nil, class: 'icon-spinner icon-spin') + text end end + + def link_to(name = nil, options = nil, html_options = nil, &block) + if html_options + if html_options[:rel] + html_options[:rel] << " noreferrer" + else + html_options.merge(rel: "noreferrer") + end + else + html_options = Hash.new + html_options[:rel] = "noreferrer" + end + super + end end From bc62c283c6f769a8f82842d13e909209296c4d3b Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Thu, 29 May 2014 15:42:20 +0200 Subject: [PATCH 133/360] Download schema.rb.bundled if necessary --- doc/update/mysql_to_postgresql.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/doc/update/mysql_to_postgresql.md b/doc/update/mysql_to_postgresql.md index c9b349b32e..5083bef1e2 100644 --- a/doc/update/mysql_to_postgresql.md +++ b/doc/update/mysql_to_postgresql.md @@ -35,9 +35,9 @@ to recreate them ourselves after migrating from MySQL. It is not necessary to shut down GitLab for this process. -### For source installations +### For non-omnibus installations -On source installations (distributed using Git) we retrieve the index +On non-omnibus installations (distributed using Git) we retrieve the index declarations from version control using `git stash`. ``` @@ -60,7 +60,7 @@ sudo -u git -H bundle exec rails runner -e production 'eval $stdin.read' < /tmp/ ### For omnibus-gitlab installations On omnibus-gitlab we need to get the index declarations from a file called -`schema.rb.bundled`. For older versions, we need to download the file. +`schema.rb.bundled`. For versions older than 6.9, we need to download the file. ``` # Clone the database converter on your Postgres-backed GitLab server @@ -68,12 +68,13 @@ cd /tmp /opt/gitlab/embedded/bin/git clone https://github.com/gitlabhq/mysql-postgresql-converter.git cd /tmp/mysql-postgresql-converter +# Download schema.rb.bundled if necessary +test -e /opt/gitlab/embedded/service/gitlab-rails/db/schema.rb.bundled || sudo /opt/gitlab/embedded/bin/curl -o /opt/gitlab/embedded/service/gitlab-rails/db/schema.rb.bundled https://gitlab.com/gitlab-org/gitlab-ce/raw/v6.9.1/db/schema.rb + # Generate add_index.rb /opt/gitlab/embedded/bin/ruby add_index_statements.rb /opt/gitlab/embedded/service/gitlab-rails/db/schema.rb.bundled > add_index.rb -# If schema.rb.bundled does not exist, download it as follows, then try generating add_index.rb again -sudo /opt/gitlab/embedded/bin/curl -o /opt/gitlab/embedded/service/gitlab-rails/db/schema.rb.bundled https://gitlab.com/gitlab-org/gitlab-ce/raw/v6.9.1/db/schema.rb - +# Create the indexes /opt/gitlab/bin/gitlab-rails runner 'eval $stdin.read' < add_index.rb ``` From 6dcbe1b43c50229fd0dff69eba2c6ab658d91ad2 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 29 May 2014 18:42:44 +0300 Subject: [PATCH 134/360] Replace ui-box with panel.panel-default Signed-off-by: Dmitriy Zaporozhets --- app/views/admin/background_jobs/show.html.haml | 4 ++-- app/views/admin/groups/show.html.haml | 8 ++++---- app/views/admin/hooks/index.html.haml | 2 +- app/views/admin/projects/index.html.haml | 2 +- app/views/admin/projects/show.html.haml | 8 ++++---- app/views/admin/users/index.html.haml | 2 +- app/views/admin/users/show.html.haml | 6 +++--- app/views/dashboard/_groups.html.haml | 2 +- app/views/dashboard/_projects.html.haml | 2 +- app/views/groups/_projects.html.haml | 2 +- app/views/groups/edit.html.haml | 6 +++--- app/views/groups/members.html.haml | 2 +- app/views/help/index.html.haml | 4 ++-- app/views/profiles/emails/index.html.haml | 2 +- app/views/profiles/groups/index.html.haml | 2 +- app/views/profiles/keys/index.html.haml | 2 +- app/views/profiles/keys/show.html.haml | 2 +- app/views/projects/compare/show.html.haml | 2 +- app/views/projects/edit.html.haml | 8 ++++---- app/views/projects/hooks/index.html.haml | 2 +- app/views/projects/issues/_issues.html.haml | 2 +- app/views/projects/merge_requests/_new_submit.html.haml | 2 +- app/views/projects/merge_requests/index.html.haml | 2 +- app/views/projects/merge_requests/show/_commits.html.haml | 2 +- app/views/projects/milestones/_issues.html.haml | 2 +- app/views/projects/milestones/index.html.haml | 2 +- app/views/projects/milestones/show.html.haml | 4 ++-- app/views/projects/team_members/_group_members.html.haml | 2 +- app/views/projects/team_members/_team.html.haml | 2 +- app/views/shared/_issues.html.haml | 2 +- app/views/shared/_merge_requests.html.haml | 2 +- app/views/users/_profile.html.haml | 2 +- app/views/users/_projects.html.haml | 2 +- 33 files changed, 49 insertions(+), 49 deletions(-) diff --git a/app/views/admin/background_jobs/show.html.haml b/app/views/admin/background_jobs/show.html.haml index 32f77cc1a7..5833eaf5f3 100644 --- a/app/views/admin/background_jobs/show.html.haml +++ b/app/views/admin/background_jobs/show.html.haml @@ -3,7 +3,7 @@ %hr -.ui-box +.panel.panel-default .title Sidekiq running processes .body - if @sidekiq_processes.empty? @@ -40,5 +40,5 @@ -.ui-box +.panel.panel-default %iframe{src: sidekiq_path, width: '100%', height: 900, style: "border: none"} diff --git a/app/views/admin/groups/show.html.haml b/app/views/admin/groups/show.html.haml index 594762f495..1bc7328509 100644 --- a/app/views/admin/groups/show.html.haml +++ b/app/views/admin/groups/show.html.haml @@ -7,7 +7,7 @@ %hr .row .col-md-6 - .ui-box + .panel.panel-default .title Group info: %ul.well-list @@ -29,7 +29,7 @@ %strong = @group.created_at.stamp("March 1, 1999") - .ui-box + .panel.panel-default .title Projects %small @@ -45,7 +45,7 @@ %span.monospace= project.path_with_namespace + ".git" .col-md-6 - .ui-box + .panel.panel-default .title Add user(s) to the group: .body.form-holder @@ -60,7 +60,7 @@ = select_tag :group_access, options_for_select(UsersGroup.group_access_roles), class: "project-access-select select2" %hr = submit_tag 'Add users into group', class: "btn btn-create" - .ui-box + .panel.panel-default .title %strong #{@group.name} Group Members diff --git a/app/views/admin/hooks/index.html.haml b/app/views/admin/hooks/index.html.haml index b27523cbf2..67f0c5d3dc 100644 --- a/app/views/admin/hooks/index.html.haml +++ b/app/views/admin/hooks/index.html.haml @@ -22,7 +22,7 @@ %hr -if @hooks.any? - .ui-box + .panel.panel-default .title System hooks (#{@hooks.count}) %ul.well-list diff --git a/app/views/admin/projects/index.html.haml b/app/views/admin/projects/index.html.haml index 51ad702154..0fef5e9404 100644 --- a/app/views/admin/projects/index.html.haml +++ b/app/views/admin/projects/index.html.haml @@ -37,7 +37,7 @@ = link_to "Reset", admin_projects_path, class: "btn" .col-md-8 - .ui-box + .panel.panel-default .title Projects (#{@projects.total_count}) .pull-right diff --git a/app/views/admin/projects/show.html.haml b/app/views/admin/projects/show.html.haml index 11f07743ac..b4c01bb9bf 100644 --- a/app/views/admin/projects/show.html.haml +++ b/app/views/admin/projects/show.html.haml @@ -6,7 +6,7 @@ %hr .row .col-md-6 - .ui-box + .panel.panel-default .title Project info: %ul.well-list @@ -75,7 +75,7 @@ = visibility_level_icon(@project.visibility_level) = visibility_level_label(@project.visibility_level) - .ui-box + .panel.panel-default .title Transfer project .body @@ -92,7 +92,7 @@ .col-md-6 - if @group - .ui-box + .panel.panel-default .title %strong #{@group.name} group members (#{@group.users_groups.count}) @@ -103,7 +103,7 @@ - @group.users_groups.order('group_access DESC').each do |member| = render 'users_groups/users_group', member: member, show_controls: false - .ui-box + .panel.panel-default .title Project members %small diff --git a/app/views/admin/users/index.html.haml b/app/views/admin/users/index.html.haml index f42ae7c6a0..37070a216d 100644 --- a/app/views/admin/users/index.html.haml +++ b/app/views/admin/users/index.html.haml @@ -28,7 +28,7 @@ = link_to 'Reset', admin_users_path, class: "btn btn-cancel" .col-md-9 - .ui-box + .panel.panel-default .title Users (#{@users.total_count}) .pull-right diff --git a/app/views/admin/users/show.html.haml b/app/views/admin/users/show.html.haml index 764b34499a..1cc1ff0c43 100644 --- a/app/views/admin/users/show.html.haml +++ b/app/views/admin/users/show.html.haml @@ -14,7 +14,7 @@ .row .col-md-6 - .ui-box + .panel.panel-default .title Account: .pull-right @@ -118,7 +118,7 @@ .col-md-6 - if @user.users_groups.present? - .ui-box + .panel.panel-default .title Groups: %ul.well-list - @user.users_groups.each do |user_group| @@ -132,7 +132,7 @@ = link_to group_users_group_path(group, user_group), data: { confirm: remove_user_from_group_message(group, @user) }, method: :delete, remote: true, class: "btn-tiny btn btn-remove", title: 'Remove user from group' do %i.icon-remove.icon-white - .ui-box + .panel.panel-default .title Projects (#{@projects.count}) %ul.well-list - @projects.sort_by(&:name_with_namespace).each do |project| diff --git a/app/views/dashboard/_groups.html.haml b/app/views/dashboard/_groups.html.haml index a6bc946bed..b3254d2d9e 100644 --- a/app/views/dashboard/_groups.html.haml +++ b/app/views/dashboard/_groups.html.haml @@ -1,4 +1,4 @@ -.ui-box +.panel.panel-default .title.clearfix = search_field_tag :filter_group, nil, placeholder: 'Filter by name', class: 'dash-filter form-control' - if current_user.can_create_group? diff --git a/app/views/dashboard/_projects.html.haml b/app/views/dashboard/_projects.html.haml index 44c7a4b8c8..e22eea32dd 100644 --- a/app/views/dashboard/_projects.html.haml +++ b/app/views/dashboard/_projects.html.haml @@ -1,4 +1,4 @@ -.ui-box +.panel.panel-default .title.clearfix = search_field_tag :filter_projects, nil, placeholder: 'Filter by name', class: 'dash-filter form-control' - if current_user.can_create_project? diff --git a/app/views/groups/_projects.html.haml b/app/views/groups/_projects.html.haml index 4ded28058e..44c1b30aa8 100644 --- a/app/views/groups/_projects.html.haml +++ b/app/views/groups/_projects.html.haml @@ -1,4 +1,4 @@ -.ui-box +.panel.panel-default .title Projects (#{projects.count}) - if can? current_user, :create_projects, @group diff --git a/app/views/groups/edit.html.haml b/app/views/groups/edit.html.haml index 2a5614cff6..f3e2638d35 100644 --- a/app/views/groups/edit.html.haml +++ b/app/views/groups/edit.html.haml @@ -17,7 +17,7 @@ .col-md-10 .tab-content .tab-pane.active#tab-edit - .ui-box + .panel.panel-default .title %strong= @group.name group settings: @@ -61,7 +61,7 @@ = f.submit 'Save group', class: "btn btn-save" .tab-pane#tab-projects - .ui-box + .panel.panel-default .title %strong= @group.name projects: @@ -84,7 +84,7 @@ .nothing-here-block This group has no projects yet .tab-pane#tab-remove - .ui-box.ui-box-danger + .panel.panel-default.panel.panel-default-danger .title Remove group .body %p diff --git a/app/views/groups/members.html.haml b/app/views/groups/members.html.haml index cc5eba6437..ee5f9244bb 100644 --- a/app/views/groups/members.html.haml +++ b/app/views/groups/members.html.haml @@ -24,7 +24,7 @@ .js-toggle-content.hide.new-group-member-holder = render "new_group_member" -.ui-box.prepend-top-20 +.panel.panel-default.prepend-top-20 .title %strong #{@group.name} group members diff --git a/app/views/help/index.html.haml b/app/views/help/index.html.haml index 87fa5ef57d..5a684e1e56 100644 --- a/app/views/help/index.html.haml +++ b/app/views/help/index.html.haml @@ -18,7 +18,7 @@ .row .col-md-4 - .ui-box + .panel.panel-default .title Quick help %ul.well-list @@ -34,7 +34,7 @@ = link_to "shortcuts", '#', onclick: "new Shortcuts()" .col-md-8 - .ui-box.documentation + .panel.panel-default.documentation .title Documentation = preserve do diff --git a/app/views/profiles/emails/index.html.haml b/app/views/profiles/emails/index.html.haml index b5f1e438cc..5192c62dd4 100644 --- a/app/views/profiles/emails/index.html.haml +++ b/app/views/profiles/emails/index.html.haml @@ -9,7 +9,7 @@ %hr -.ui-box +.panel.panel-default .title Emails (#{@emails.count + 1}) %ul.well-list#emails-table diff --git a/app/views/profiles/groups/index.html.haml b/app/views/profiles/groups/index.html.haml index cebc0b6bcc..6367e04737 100644 --- a/app/views/profiles/groups/index.html.haml +++ b/app/views/profiles/groups/index.html.haml @@ -8,7 +8,7 @@ %p.light Group members have access to all a group's projects %hr -.ui-box +.panel.panel-default .title %strong Groups (#{@user_groups.count}) diff --git a/app/views/profiles/keys/index.html.haml b/app/views/profiles/keys/index.html.haml index 2e10fa8be8..42fd547494 100644 --- a/app/views/profiles/keys/index.html.haml +++ b/app/views/profiles/keys/index.html.haml @@ -10,7 +10,7 @@ %hr -.ui-box +.panel.panel-default .title SSH Keys (#{@keys.count}) %ul.well-list#keys-table diff --git a/app/views/profiles/keys/show.html.haml b/app/views/profiles/keys/show.html.haml index b6724a7cb5..38ca570640 100644 --- a/app/views/profiles/keys/show.html.haml +++ b/app/views/profiles/keys/show.html.haml @@ -1,6 +1,6 @@ .row .col-md-4 - .ui-box + .panel.panel-default .title SSH Key %ul.well-list diff --git a/app/views/projects/compare/show.html.haml b/app/views/projects/compare/show.html.haml index 57331bff31..7ae05b19ef 100644 --- a/app/views/projects/compare/show.html.haml +++ b/app/views/projects/compare/show.html.haml @@ -6,7 +6,7 @@ = render "form" - if @commits.present? - %div.ui-box + %div.panel.panel-default .title Commits (#{@commits.count}) - if @commits.size > MergeRequestDiff::COMMITS_SAFE_SIZE diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml index 10674ccae4..51eb27aa95 100644 --- a/app/views/projects/edit.html.haml +++ b/app/views/projects/edit.html.haml @@ -106,7 +106,7 @@ .js-toggle-content.hide - if can? current_user, :archive_project, @project - .ui-box.ui-box-danger + .panel.panel-default.panel.panel-default-danger .title - if @project.archived? Unarchive project @@ -137,7 +137,7 @@ .nothing-here-block Only the project owner can archive a project - if can?(current_user, :change_namespace, @project) - .ui-box.ui-box-danger + .panel.panel-default.panel.panel-default-danger .title Transfer project .errors-holder .form-holder @@ -157,7 +157,7 @@ - else .nothing-here-block Only the project owner can transfer a project - .ui-box.ui-box-danger + .panel.panel-default.panel.panel-default-danger .title Rename repository .errors-holder .form-holder @@ -177,7 +177,7 @@ = f.submit 'Rename', class: "btn btn-remove" - if can?(current_user, :remove_project, @project) - .ui-box.ui-box-danger + .panel.panel-default.panel.panel-default-danger .title Remove project .body %p diff --git a/app/views/projects/hooks/index.html.haml b/app/views/projects/hooks/index.html.haml index 73171fbe99..8bc8f26453 100644 --- a/app/views/projects/hooks/index.html.haml +++ b/app/views/projects/hooks/index.html.haml @@ -51,7 +51,7 @@ = f.submit "Add Web Hook", class: "btn btn-create" -if @hooks.any? - .ui-box + .panel.panel-default .title Web hooks (#{@hooks.count}) %ul.well-list diff --git a/app/views/projects/issues/_issues.html.haml b/app/views/projects/issues/_issues.html.haml index e85ff3a786..1d0dcd7f07 100644 --- a/app/views/projects/issues/_issues.html.haml +++ b/app/views/projects/issues/_issues.html.haml @@ -61,7 +61,7 @@ = hidden_field_tag :status, params[:status] = button_tag "Update issues", class: "btn update_selected_issues btn-save" -.ui-box +.panel.panel-default %ul.well-list.issues-list = render @issues - if @issues.blank? diff --git a/app/views/projects/merge_requests/_new_submit.html.haml b/app/views/projects/merge_requests/_new_submit.html.haml index bdfa4444ab..46a3d98ea2 100644 --- a/app/views/projects/merge_requests/_new_submit.html.haml +++ b/app/views/projects/merge_requests/_new_submit.html.haml @@ -58,7 +58,7 @@ = f.submit 'Submit merge request', class: "btn btn-create" .mr-compare - %div.ui-box + %div.panel.panel-default .title Commits (#{@commits.count}) - if @commits.size > MergeRequestDiff::COMMITS_SAFE_SIZE diff --git a/app/views/projects/merge_requests/index.html.haml b/app/views/projects/merge_requests/index.html.haml index 12a72edb22..232d398c53 100644 --- a/app/views/projects/merge_requests/index.html.haml +++ b/app/views/projects/merge_requests/index.html.haml @@ -61,7 +61,7 @@ .pull-right = render 'shared/sort_dropdown' - .ui-box + .panel.panel-default %ul.well-list.mr-list = render @merge_requests - if @merge_requests.blank? diff --git a/app/views/projects/merge_requests/show/_commits.html.haml b/app/views/projects/merge_requests/show/_commits.html.haml index f69146e1a3..e37c6f4f3e 100644 --- a/app/views/projects/merge_requests/show/_commits.html.haml +++ b/app/views/projects/merge_requests/show/_commits.html.haml @@ -1,5 +1,5 @@ - if @commits.present? - .ui-box + .panel.panel-default .title %i.icon-list Commits (#{@commits.count}) diff --git a/app/views/projects/milestones/_issues.html.haml b/app/views/projects/milestones/_issues.html.haml index c277dcc536..16b412b3d8 100644 --- a/app/views/projects/milestones/_issues.html.haml +++ b/app/views/projects/milestones/_issues.html.haml @@ -1,4 +1,4 @@ -.ui-box +.panel.panel-default .title= title %ul.well-list - issues.each do |issue| diff --git a/app/views/projects/milestones/index.html.haml b/app/views/projects/milestones/index.html.haml index 3537650ad4..15635b299f 100644 --- a/app/views/projects/milestones/index.html.haml +++ b/app/views/projects/milestones/index.html.haml @@ -20,7 +20,7 @@ = link_to project_milestones_path(@project, f: "all") do All .col-md-9 - .ui-box + .panel.panel-default %ul.well-list = render @milestones diff --git a/app/views/projects/milestones/show.html.haml b/app/views/projects/milestones/show.html.haml index 0fe5ac25b5..f1eb2c7c9c 100644 --- a/app/views/projects/milestones/show.html.haml +++ b/app/views/projects/milestones/show.html.haml @@ -84,13 +84,13 @@ .tab-pane#tab-merge-requests .row .col-md-6 - .ui-box + .panel.panel-default .title Open %ul.well-list - @merge_requests.opened.each do |merge_request| = render 'merge_request', merge_request: merge_request .col-md-6 - .ui-box + .panel.panel-default .title Closed %ul.well-list - @merge_requests.closed.each do |merge_request| diff --git a/app/views/projects/team_members/_group_members.html.haml b/app/views/projects/team_members/_group_members.html.haml index eceec6627b..52be9d1f2d 100644 --- a/app/views/projects/team_members/_group_members.html.haml +++ b/app/views/projects/team_members/_group_members.html.haml @@ -1,5 +1,5 @@ - group_users_count = @group.users_groups.count -.ui-box +.panel.panel-default .title %strong #{@group.name} group members (#{group_users_count}) diff --git a/app/views/projects/team_members/_team.html.haml b/app/views/projects/team_members/_team.html.haml index 2daf684766..fae0b3c406 100644 --- a/app/views/projects/team_members/_team.html.haml +++ b/app/views/projects/team_members/_team.html.haml @@ -1,6 +1,6 @@ .team-table - can_admin_project = (can? current_user, :admin_project, @project) - .ui-box + .panel.panel-default .title %strong #{@project.name} project members (#{members.count}) diff --git a/app/views/shared/_issues.html.haml b/app/views/shared/_issues.html.haml index 087b6632e8..ad31984951 100644 --- a/app/views/shared/_issues.html.haml +++ b/app/views/shared/_issues.html.haml @@ -1,6 +1,6 @@ - if @issues.any? - @issues.group_by(&:project).each do |group| - .ui-box.ui-box-small + .panel.panel-default.panel.panel-default-small - project = group[0] .title = link_to_project project diff --git a/app/views/shared/_merge_requests.html.haml b/app/views/shared/_merge_requests.html.haml index f40b7be486..cb461cd713 100644 --- a/app/views/shared/_merge_requests.html.haml +++ b/app/views/shared/_merge_requests.html.haml @@ -1,6 +1,6 @@ - if @merge_requests.any? - @merge_requests.group_by(&:target_project).each do |group| - .ui-box.ui-box-small + .panel.panel-default.panel.panel-default-small - project = group[0] .title = link_to_project project diff --git a/app/views/users/_profile.html.haml b/app/views/users/_profile.html.haml index 7ffd43e837..5c008ac8fe 100644 --- a/app/views/users/_profile.html.haml +++ b/app/views/users/_profile.html.haml @@ -1,4 +1,4 @@ -.ui-box +.panel.panel-default .title Profile %ul.well-list diff --git a/app/views/users/_projects.html.haml b/app/views/users/_projects.html.haml index a61c6ba5b8..7fc7aeb6b0 100644 --- a/app/views/users/_projects.html.haml +++ b/app/views/users/_projects.html.haml @@ -1,4 +1,4 @@ -.ui-box +.panel.panel-default .title Projects %ul.well-list - @projects.each do |project| From 38ff5d1ab9d9eb5d09bbc8498410b770445b698e Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 29 May 2014 18:43:21 +0300 Subject: [PATCH 135/360] Replace ui-box title with panel-heading Signed-off-by: Dmitriy Zaporozhets --- app/views/admin/background_jobs/show.html.haml | 2 +- app/views/admin/groups/show.html.haml | 8 ++++---- app/views/admin/hooks/index.html.haml | 2 +- app/views/admin/projects/index.html.haml | 2 +- app/views/admin/projects/show.html.haml | 8 ++++---- app/views/admin/users/index.html.haml | 2 +- app/views/admin/users/show.html.haml | 6 +++--- app/views/dashboard/_groups.html.haml | 2 +- app/views/dashboard/_projects.html.haml | 2 +- app/views/groups/_projects.html.haml | 2 +- app/views/groups/edit.html.haml | 6 +++--- app/views/groups/members.html.haml | 2 +- app/views/help/index.html.haml | 4 ++-- app/views/profiles/emails/index.html.haml | 2 +- app/views/profiles/groups/index.html.haml | 2 +- app/views/profiles/keys/index.html.haml | 2 +- app/views/profiles/keys/show.html.haml | 2 +- app/views/projects/compare/show.html.haml | 2 +- app/views/projects/edit.html.haml | 8 ++++---- app/views/projects/hooks/index.html.haml | 2 +- app/views/projects/merge_requests/_new_submit.html.haml | 2 +- app/views/projects/merge_requests/show/_commits.html.haml | 2 +- app/views/projects/milestones/_issues.html.haml | 2 +- app/views/projects/milestones/show.html.haml | 4 ++-- app/views/projects/team_members/_group_members.html.haml | 2 +- app/views/projects/team_members/_team.html.haml | 2 +- app/views/shared/_issues.html.haml | 2 +- app/views/shared/_merge_requests.html.haml | 2 +- app/views/users/_profile.html.haml | 2 +- app/views/users/_projects.html.haml | 2 +- 30 files changed, 45 insertions(+), 45 deletions(-) diff --git a/app/views/admin/background_jobs/show.html.haml b/app/views/admin/background_jobs/show.html.haml index 5833eaf5f3..dcb3bfcda6 100644 --- a/app/views/admin/background_jobs/show.html.haml +++ b/app/views/admin/background_jobs/show.html.haml @@ -4,7 +4,7 @@ %hr .panel.panel-default - .title Sidekiq running processes + .panel-heading Sidekiq running processes .body - if @sidekiq_processes.empty? %h4.cred diff --git a/app/views/admin/groups/show.html.haml b/app/views/admin/groups/show.html.haml index 1bc7328509..2b7dbfad59 100644 --- a/app/views/admin/groups/show.html.haml +++ b/app/views/admin/groups/show.html.haml @@ -8,7 +8,7 @@ .row .col-md-6 .panel.panel-default - .title + .panel-heading Group info: %ul.well-list %li @@ -30,7 +30,7 @@ = @group.created_at.stamp("March 1, 1999") .panel.panel-default - .title + .panel-heading Projects %small (#{@group.projects.count}) @@ -46,7 +46,7 @@ .col-md-6 .panel.panel-default - .title + .panel-heading Add user(s) to the group: .body.form-holder %p.light @@ -61,7 +61,7 @@ %hr = submit_tag 'Add users into group', class: "btn btn-create" .panel.panel-default - .title + .panel-heading %strong #{@group.name} Group Members %small diff --git a/app/views/admin/hooks/index.html.haml b/app/views/admin/hooks/index.html.haml index 67f0c5d3dc..0c5db0805f 100644 --- a/app/views/admin/hooks/index.html.haml +++ b/app/views/admin/hooks/index.html.haml @@ -23,7 +23,7 @@ -if @hooks.any? .panel.panel-default - .title + .panel-heading System hooks (#{@hooks.count}) %ul.well-list - @hooks.each do |hook| diff --git a/app/views/admin/projects/index.html.haml b/app/views/admin/projects/index.html.haml index 0fef5e9404..fb462840ba 100644 --- a/app/views/admin/projects/index.html.haml +++ b/app/views/admin/projects/index.html.haml @@ -38,7 +38,7 @@ .col-md-8 .panel.panel-default - .title + .panel-heading Projects (#{@projects.total_count}) .pull-right .dropdown.inline diff --git a/app/views/admin/projects/show.html.haml b/app/views/admin/projects/show.html.haml index b4c01bb9bf..3fe188a57e 100644 --- a/app/views/admin/projects/show.html.haml +++ b/app/views/admin/projects/show.html.haml @@ -7,7 +7,7 @@ .row .col-md-6 .panel.panel-default - .title + .panel-heading Project info: %ul.well-list %li @@ -76,7 +76,7 @@ = visibility_level_label(@project.visibility_level) .panel.panel-default - .title + .panel-heading Transfer project .body = form_for @project, url: transfer_admin_project_path(@project), method: :put, html: { class: 'form-horizontal' } do |f| @@ -93,7 +93,7 @@ .col-md-6 - if @group .panel.panel-default - .title + .panel-heading %strong #{@group.name} group members (#{@group.users_groups.count}) .pull-right @@ -104,7 +104,7 @@ = render 'users_groups/users_group', member: member, show_controls: false .panel.panel-default - .title + .panel-heading Project members %small (#{@project.users.count}) diff --git a/app/views/admin/users/index.html.haml b/app/views/admin/users/index.html.haml index 37070a216d..4bfdcbc4de 100644 --- a/app/views/admin/users/index.html.haml +++ b/app/views/admin/users/index.html.haml @@ -29,7 +29,7 @@ .col-md-9 .panel.panel-default - .title + .panel-heading Users (#{@users.total_count}) .pull-right = link_to 'New User', new_admin_user_path, class: "btn btn-new" diff --git a/app/views/admin/users/show.html.haml b/app/views/admin/users/show.html.haml index 1cc1ff0c43..28c91c2c3e 100644 --- a/app/views/admin/users/show.html.haml +++ b/app/views/admin/users/show.html.haml @@ -15,7 +15,7 @@ .row .col-md-6 .panel.panel-default - .title + .panel-heading Account: .pull-right = image_tag avatar_icon(@user.email, 32), class: "avatar s32" @@ -119,7 +119,7 @@ .col-md-6 - if @user.users_groups.present? .panel.panel-default - .title Groups: + .panel-heading Groups: %ul.well-list - @user.users_groups.each do |user_group| - group = user_group.group @@ -133,7 +133,7 @@ %i.icon-remove.icon-white .panel.panel-default - .title Projects (#{@projects.count}) + .panel-heading Projects (#{@projects.count}) %ul.well-list - @projects.sort_by(&:name_with_namespace).each do |project| - tm = project.team.find_tm(@user.id) diff --git a/app/views/dashboard/_groups.html.haml b/app/views/dashboard/_groups.html.haml index b3254d2d9e..cb9c18b796 100644 --- a/app/views/dashboard/_groups.html.haml +++ b/app/views/dashboard/_groups.html.haml @@ -1,5 +1,5 @@ .panel.panel-default - .title.clearfix + .panel-heading.clearfix = search_field_tag :filter_group, nil, placeholder: 'Filter by name', class: 'dash-filter form-control' - if current_user.can_create_group? %span.pull-right diff --git a/app/views/dashboard/_projects.html.haml b/app/views/dashboard/_projects.html.haml index e22eea32dd..f2cd57504c 100644 --- a/app/views/dashboard/_projects.html.haml +++ b/app/views/dashboard/_projects.html.haml @@ -1,5 +1,5 @@ .panel.panel-default - .title.clearfix + .panel-heading.clearfix = search_field_tag :filter_projects, nil, placeholder: 'Filter by name', class: 'dash-filter form-control' - if current_user.can_create_project? %span.pull-right diff --git a/app/views/groups/_projects.html.haml b/app/views/groups/_projects.html.haml index 44c1b30aa8..520310bc43 100644 --- a/app/views/groups/_projects.html.haml +++ b/app/views/groups/_projects.html.haml @@ -1,5 +1,5 @@ .panel.panel-default - .title + .panel-heading Projects (#{projects.count}) - if can? current_user, :create_projects, @group %span.pull-right diff --git a/app/views/groups/edit.html.haml b/app/views/groups/edit.html.haml index f3e2638d35..e04b5ba7ef 100644 --- a/app/views/groups/edit.html.haml +++ b/app/views/groups/edit.html.haml @@ -18,7 +18,7 @@ .tab-content .tab-pane.active#tab-edit .panel.panel-default - .title + .panel-heading %strong= @group.name group settings: %div.form-holder @@ -62,7 +62,7 @@ .tab-pane#tab-projects .panel.panel-default - .title + .panel-heading %strong= @group.name projects: - if can? current_user, :manage_group, @group @@ -85,7 +85,7 @@ .tab-pane#tab-remove .panel.panel-default.panel.panel-default-danger - .title Remove group + .panel-heading Remove group .body %p Removing group will cause all child projects and resources to be removed. diff --git a/app/views/groups/members.html.haml b/app/views/groups/members.html.haml index ee5f9244bb..19819c9612 100644 --- a/app/views/groups/members.html.haml +++ b/app/views/groups/members.html.haml @@ -25,7 +25,7 @@ = render "new_group_member" .panel.panel-default.prepend-top-20 - .title + .panel-heading %strong #{@group.name} group members %small diff --git a/app/views/help/index.html.haml b/app/views/help/index.html.haml index 5a684e1e56..1b714429f1 100644 --- a/app/views/help/index.html.haml +++ b/app/views/help/index.html.haml @@ -19,7 +19,7 @@ .row .col-md-4 .panel.panel-default - .title + .panel-heading Quick help %ul.well-list %li @@ -35,7 +35,7 @@ .col-md-8 .panel.panel-default.documentation - .title Documentation + .panel-heading Documentation = preserve do - readme_text = File.read(Rails.root.join("doc", "README.md")) diff --git a/app/views/profiles/emails/index.html.haml b/app/views/profiles/emails/index.html.haml index 5192c62dd4..ca980db2f3 100644 --- a/app/views/profiles/emails/index.html.haml +++ b/app/views/profiles/emails/index.html.haml @@ -10,7 +10,7 @@ %hr .panel.panel-default - .title + .panel-heading Emails (#{@emails.count + 1}) %ul.well-list#emails-table %li diff --git a/app/views/profiles/groups/index.html.haml b/app/views/profiles/groups/index.html.haml index 6367e04737..2efe72b1bb 100644 --- a/app/views/profiles/groups/index.html.haml +++ b/app/views/profiles/groups/index.html.haml @@ -9,7 +9,7 @@ Group members have access to all a group's projects %hr .panel.panel-default - .title + .panel-heading %strong Groups (#{@user_groups.count}) %ul.well-list diff --git a/app/views/profiles/keys/index.html.haml b/app/views/profiles/keys/index.html.haml index 42fd547494..aabfd57c28 100644 --- a/app/views/profiles/keys/index.html.haml +++ b/app/views/profiles/keys/index.html.haml @@ -11,7 +11,7 @@ .panel.panel-default - .title + .panel-heading SSH Keys (#{@keys.count}) %ul.well-list#keys-table = render @keys diff --git a/app/views/profiles/keys/show.html.haml b/app/views/profiles/keys/show.html.haml index 38ca570640..c4fc1bb269 100644 --- a/app/views/profiles/keys/show.html.haml +++ b/app/views/profiles/keys/show.html.haml @@ -1,7 +1,7 @@ .row .col-md-4 .panel.panel-default - .title + .panel-heading SSH Key %ul.well-list %li diff --git a/app/views/projects/compare/show.html.haml b/app/views/projects/compare/show.html.haml index 7ae05b19ef..88122a73bb 100644 --- a/app/views/projects/compare/show.html.haml +++ b/app/views/projects/compare/show.html.haml @@ -7,7 +7,7 @@ - if @commits.present? %div.panel.panel-default - .title + .panel-heading Commits (#{@commits.count}) - if @commits.size > MergeRequestDiff::COMMITS_SAFE_SIZE %ul.well-list diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml index 51eb27aa95..0a45f7e130 100644 --- a/app/views/projects/edit.html.haml +++ b/app/views/projects/edit.html.haml @@ -107,7 +107,7 @@ .js-toggle-content.hide - if can? current_user, :archive_project, @project .panel.panel-default.panel.panel-default-danger - .title + .panel-heading - if @project.archived? Unarchive project - else @@ -138,7 +138,7 @@ - if can?(current_user, :change_namespace, @project) .panel.panel-default.panel.panel-default-danger - .title Transfer project + .panel-heading Transfer project .errors-holder .form-holder = form_for(@project, url: transfer_project_path(@project), method: :put, remote: true, html: { class: 'transfer-project form-horizontal' }) do |f| @@ -158,7 +158,7 @@ .nothing-here-block Only the project owner can transfer a project .panel.panel-default.panel.panel-default-danger - .title Rename repository + .panel-heading Rename repository .errors-holder .form-holder = form_for(@project, html: { class: 'form-horizontal' }) do |f| @@ -178,7 +178,7 @@ - if can?(current_user, :remove_project, @project) .panel.panel-default.panel.panel-default-danger - .title Remove project + .panel-heading Remove project .body %p Removing the project will delete its repository and all related resources including issues, merge requests etc. diff --git a/app/views/projects/hooks/index.html.haml b/app/views/projects/hooks/index.html.haml index 8bc8f26453..9a003c87f6 100644 --- a/app/views/projects/hooks/index.html.haml +++ b/app/views/projects/hooks/index.html.haml @@ -52,7 +52,7 @@ -if @hooks.any? .panel.panel-default - .title + .panel-heading Web hooks (#{@hooks.count}) %ul.well-list - @hooks.each do |hook| diff --git a/app/views/projects/merge_requests/_new_submit.html.haml b/app/views/projects/merge_requests/_new_submit.html.haml index 46a3d98ea2..553bc30ee0 100644 --- a/app/views/projects/merge_requests/_new_submit.html.haml +++ b/app/views/projects/merge_requests/_new_submit.html.haml @@ -59,7 +59,7 @@ .mr-compare %div.panel.panel-default - .title + .panel-heading Commits (#{@commits.count}) - if @commits.size > MergeRequestDiff::COMMITS_SAFE_SIZE %ul.well-list diff --git a/app/views/projects/merge_requests/show/_commits.html.haml b/app/views/projects/merge_requests/show/_commits.html.haml index e37c6f4f3e..e62ab9d9d3 100644 --- a/app/views/projects/merge_requests/show/_commits.html.haml +++ b/app/views/projects/merge_requests/show/_commits.html.haml @@ -1,6 +1,6 @@ - if @commits.present? .panel.panel-default - .title + .panel-heading %i.icon-list Commits (#{@commits.count}) .commits diff --git a/app/views/projects/milestones/_issues.html.haml b/app/views/projects/milestones/_issues.html.haml index 16b412b3d8..83eb327975 100644 --- a/app/views/projects/milestones/_issues.html.haml +++ b/app/views/projects/milestones/_issues.html.haml @@ -1,5 +1,5 @@ .panel.panel-default - .title= title + .panel-heading= title %ul.well-list - issues.each do |issue| %li diff --git a/app/views/projects/milestones/show.html.haml b/app/views/projects/milestones/show.html.haml index f1eb2c7c9c..e33f4e5273 100644 --- a/app/views/projects/milestones/show.html.haml +++ b/app/views/projects/milestones/show.html.haml @@ -85,13 +85,13 @@ .row .col-md-6 .panel.panel-default - .title Open + .panel-heading Open %ul.well-list - @merge_requests.opened.each do |merge_request| = render 'merge_request', merge_request: merge_request .col-md-6 .panel.panel-default - .title Closed + .panel-heading Closed %ul.well-list - @merge_requests.closed.each do |merge_request| = render 'merge_request', merge_request: merge_request diff --git a/app/views/projects/team_members/_group_members.html.haml b/app/views/projects/team_members/_group_members.html.haml index 52be9d1f2d..83c4b6f87d 100644 --- a/app/views/projects/team_members/_group_members.html.haml +++ b/app/views/projects/team_members/_group_members.html.haml @@ -1,6 +1,6 @@ - group_users_count = @group.users_groups.count .panel.panel-default - .title + .panel-heading %strong #{@group.name} group members (#{group_users_count}) .pull-right diff --git a/app/views/projects/team_members/_team.html.haml b/app/views/projects/team_members/_team.html.haml index fae0b3c406..0e5b817613 100644 --- a/app/views/projects/team_members/_team.html.haml +++ b/app/views/projects/team_members/_team.html.haml @@ -1,7 +1,7 @@ .team-table - can_admin_project = (can? current_user, :admin_project, @project) .panel.panel-default - .title + .panel-heading %strong #{@project.name} project members (#{members.count}) %ul.well-list diff --git a/app/views/shared/_issues.html.haml b/app/views/shared/_issues.html.haml index ad31984951..d36e96dc49 100644 --- a/app/views/shared/_issues.html.haml +++ b/app/views/shared/_issues.html.haml @@ -2,7 +2,7 @@ - @issues.group_by(&:project).each do |group| .panel.panel-default.panel.panel-default-small - project = group[0] - .title + .panel-heading = link_to_project project = link_to 'show all', project_issues_path(project), class: 'pull-right' diff --git a/app/views/shared/_merge_requests.html.haml b/app/views/shared/_merge_requests.html.haml index cb461cd713..954b16cfdb 100644 --- a/app/views/shared/_merge_requests.html.haml +++ b/app/views/shared/_merge_requests.html.haml @@ -2,7 +2,7 @@ - @merge_requests.group_by(&:target_project).each do |group| .panel.panel-default.panel.panel-default-small - project = group[0] - .title + .panel-heading = link_to_project project = link_to 'show all', project_merge_requests_path(project), class: 'pull-right' %ul.well-list.mr-list diff --git a/app/views/users/_profile.html.haml b/app/views/users/_profile.html.haml index 5c008ac8fe..3b44959baa 100644 --- a/app/views/users/_profile.html.haml +++ b/app/views/users/_profile.html.haml @@ -1,5 +1,5 @@ .panel.panel-default - .title + .panel-heading Profile %ul.well-list %li diff --git a/app/views/users/_projects.html.haml b/app/views/users/_projects.html.haml index 7fc7aeb6b0..2d97c4545b 100644 --- a/app/views/users/_projects.html.haml +++ b/app/views/users/_projects.html.haml @@ -1,5 +1,5 @@ .panel.panel-default - .title Projects + .panel-heading Projects %ul.well-list - @projects.each do |project| %li From a2b3eb134a5549bf9c80a8ee0f950a4c67777413 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 29 May 2014 18:57:27 +0300 Subject: [PATCH 136/360] Move from ui-box to panels Signed-off-by: Dmitriy Zaporozhets --- app/assets/javascripts/dashboard.js.coffee | 2 +- app/assets/stylesheets/generic/lists.scss | 9 +++++++++ app/assets/stylesheets/generic/ui_box.scss | 9 --------- app/assets/stylesheets/gl_bootstrap.scss | 8 ++++++++ app/views/admin/background_jobs/show.html.haml | 2 +- app/views/admin/groups/show.html.haml | 2 +- app/views/admin/projects/show.html.haml | 2 +- app/views/groups/edit.html.haml | 4 ++-- app/views/projects/edit.html.haml | 18 +++++++++--------- 9 files changed, 32 insertions(+), 24 deletions(-) diff --git a/app/assets/javascripts/dashboard.js.coffee b/app/assets/javascripts/dashboard.js.coffee index d2bd9e7362..c4a0ccd9c2 100644 --- a/app/assets/javascripts/dashboard.js.coffee +++ b/app/assets/javascripts/dashboard.js.coffee @@ -4,7 +4,7 @@ class Dashboard $(".dash-filter").keyup -> terms = $(this).val() - uiBox = $(this).parents('.ui-box').first() + uiBox = $(this).parents('.panel').first() if terms == "" || terms == undefined uiBox.find(".dash-list li").show() else diff --git a/app/assets/stylesheets/generic/lists.scss b/app/assets/stylesheets/generic/lists.scss index 963768044d..2e3559f3c8 100644 --- a/app/assets/stylesheets/generic/lists.scss +++ b/app/assets/stylesheets/generic/lists.scss @@ -72,6 +72,15 @@ font-size: 14px; line-height: 18px; } + + .row_title { + font-weight: 500; + color: #444; + &:hover { + color: #444; + text-decoration: underline; + } + } } } diff --git a/app/assets/stylesheets/generic/ui_box.scss b/app/assets/stylesheets/generic/ui_box.scss index 7a977eae70..461e8e2ba5 100644 --- a/app/assets/stylesheets/generic/ui_box.scss +++ b/app/assets/stylesheets/generic/ui_box.scss @@ -106,15 +106,6 @@ } } - .row_title { - font-weight: 500; - color: #444; - &:hover { - color: #444; - text-decoration: underline; - } - } - .form-holder { padding-top: 20px; form { diff --git a/app/assets/stylesheets/gl_bootstrap.scss b/app/assets/stylesheets/gl_bootstrap.scss index 8676f07b1a..15f08ccc10 100644 --- a/app/assets/stylesheets/gl_bootstrap.scss +++ b/app/assets/stylesheets/gl_bootstrap.scss @@ -221,3 +221,11 @@ ul.breadcrumb { position: relative; white-space: nowrap; } + +/** + * Add some extra stuff to panels + * + */ +.panel { + +} diff --git a/app/views/admin/background_jobs/show.html.haml b/app/views/admin/background_jobs/show.html.haml index dcb3bfcda6..c79d1280dd 100644 --- a/app/views/admin/background_jobs/show.html.haml +++ b/app/views/admin/background_jobs/show.html.haml @@ -5,7 +5,7 @@ .panel.panel-default .panel-heading Sidekiq running processes - .body + .panel-body - if @sidekiq_processes.empty? %h4.cred %i.icon-warning-sign diff --git a/app/views/admin/groups/show.html.haml b/app/views/admin/groups/show.html.haml index 2b7dbfad59..183203aac7 100644 --- a/app/views/admin/groups/show.html.haml +++ b/app/views/admin/groups/show.html.haml @@ -48,7 +48,7 @@ .panel.panel-default .panel-heading Add user(s) to the group: - .body.form-holder + .panel-body.form-holder %p.light Read more about project permissions %strong= link_to "here", help_page_path("permissions", "permissions"), class: "vlink" diff --git a/app/views/admin/projects/show.html.haml b/app/views/admin/projects/show.html.haml index 3fe188a57e..3f25eb7fdb 100644 --- a/app/views/admin/projects/show.html.haml +++ b/app/views/admin/projects/show.html.haml @@ -78,7 +78,7 @@ .panel.panel-default .panel-heading Transfer project - .body + .panel-body = form_for @project, url: transfer_admin_project_path(@project), method: :put, html: { class: 'form-horizontal' } do |f| .form-group = f.label :namespace_id, "Namespace", class: 'control-label' diff --git a/app/views/groups/edit.html.haml b/app/views/groups/edit.html.haml index e04b5ba7ef..315da0370f 100644 --- a/app/views/groups/edit.html.haml +++ b/app/views/groups/edit.html.haml @@ -84,9 +84,9 @@ .nothing-here-block This group has no projects yet .tab-pane#tab-remove - .panel.panel-default.panel.panel-default-danger + .panel.panel-default.panel.panel-danger .panel-heading Remove group - .body + .panel-body %p Removing group will cause all child projects and resources to be removed. %p diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml index 0a45f7e130..43775026f7 100644 --- a/app/views/projects/edit.html.haml +++ b/app/views/projects/edit.html.haml @@ -6,7 +6,7 @@ Project settings: %p.light Some settings, such as "Transfer Project", are hidden inside the danger area below %hr - .form-holder + .panel-body = form_for @project, remote: true, html: { class: "edit_project form-horizontal" } do |f| %fieldset .form-group.project_name_holder @@ -106,13 +106,13 @@ .js-toggle-content.hide - if can? current_user, :archive_project, @project - .panel.panel-default.panel.panel-default-danger + .panel.panel-default.panel.panel-danger .panel-heading - if @project.archived? Unarchive project - else Archive project - .body + .panel-body - if @project.archived? %p Unarchiving the project will mark its repository as active. @@ -137,10 +137,10 @@ .nothing-here-block Only the project owner can archive a project - if can?(current_user, :change_namespace, @project) - .panel.panel-default.panel.panel-default-danger + .panel.panel-default.panel.panel-danger .panel-heading Transfer project .errors-holder - .form-holder + .panel-body = form_for(@project, url: transfer_project_path(@project), method: :put, remote: true, html: { class: 'transfer-project form-horizontal' }) do |f| .form-group = f.label :namespace_id, class: 'control-label' do @@ -157,10 +157,10 @@ - else .nothing-here-block Only the project owner can transfer a project - .panel.panel-default.panel.panel-default-danger + .panel.panel-default.panel.panel-danger .panel-heading Rename repository .errors-holder - .form-holder + .panel-body = form_for(@project, html: { class: 'form-horizontal' }) do |f| .form-group = f.label :path, class: 'control-label' do @@ -177,9 +177,9 @@ = f.submit 'Rename', class: "btn btn-remove" - if can?(current_user, :remove_project, @project) - .panel.panel-default.panel.panel-default-danger + .panel.panel-default.panel.panel-danger .panel-heading Remove project - .body + .panel-body %p Removing the project will delete its repository and all related resources including issues, merge requests etc. %br From b66d9c4f28168be13616696a20e252c7adae3e49 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 29 May 2014 19:32:19 +0300 Subject: [PATCH 137/360] Remove ui-box css Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/generic/ui_box.scss | 164 ------------------ app/assets/stylesheets/gl_bootstrap.scss | 9 + .../stylesheets/sections/dashboard.scss | 17 +- app/views/groups/_projects.html.haml | 2 +- 4 files changed, 18 insertions(+), 174 deletions(-) delete mode 100644 app/assets/stylesheets/generic/ui_box.scss diff --git a/app/assets/stylesheets/generic/ui_box.scss b/app/assets/stylesheets/generic/ui_box.scss deleted file mode 100644 index 461e8e2ba5..0000000000 --- a/app/assets/stylesheets/generic/ui_box.scss +++ /dev/null @@ -1,164 +0,0 @@ -/** - * UI box: - * Block element for separating information on page. - * Used for storing issues lists, grouped data. - * You can have multiple ui boxes on one page - * - * Classes: - * .ui-box - for any block & widgets - * .ui-box.ui-box-small - same but with smaller title - * .ui-box.ui-box-danger - with red title - * - * Ex. 1: List - * .ui-box - * .title - * # title here - * %ul - * # content here - * - * Ex. 2: Block data - * .ui-box - * .title - * # title here - * .body - * # content here - * - */ - -.ui-box { - background: #FFF; - margin-bottom: 20px; - border: 1px solid #DDD; - word-wrap: break-word; - - img { - max-width: 100%; - } - - pre { - code { - background: none !important; - } - } - - ul { - margin: 0; - padding: 0; - } - - .title { - background-color: #EEE; - border-bottom: 1px solid #DDD; - color: #666; - font-size: 16px; - text-shadow: 0 1px 1px #fff; - padding: 0 10px; - font-size: 14px; - line-height: 40px; - font-weight: normal; - margin: 0; - - > a { - text-shadow: 0 1px 1px #fff; - } - - form { - margin-bottom: 0; - margin-top: 0; - } - - .btn { - vertical-align: middle; - padding: 4px 12px; - @include box-shadow(0 0px 1px 1px #f2f2f2); - } - - .nav-pills { - > li { - > a { - padding: 13px; - margin: 0; - font-size: 13px; - } - &.active { - > a { - background: #D5D5D5; - color: $style_color; - @include border-radius(0); - border-radius: 0; - border-left: 1px solid #CCC; - border-right: 1px solid #CCC; - } - } - } - } - } - - .body { - padding: 10px; - } - - &.padded { - h5, .title { - margin: -20px; - margin-bottom: 0; - padding: 5px 20px; - } - } - - .form-holder { - padding-top: 20px; - form { - margin-bottom: 0; - legend { - text-indent: 10px; - } - .form-actions { - margin-bottom: 0; - } - } - } -} - -/* - * Small box - */ -.ui-box.ui-box-small { - margin-bottom: 10px; - - .title { - font-size: 13px; - line-height: 30px; - - a { - color: #666; - &:hover { - text-decoration: underline; - } - } - } -} - -/* - * Danger box - */ -.ui-box.ui-box-danger { - background: #f7f7f7; - border: none; - - .title { - background: #D65; - color: #fff; - text-shadow: none; - font-weight: 500; - } -} - -/* - * Block under tw-bootstrap tabs - */ -.tab-pane { - .ui-box { - margin: 3px 3px 25px 3px; - } -} diff --git a/app/assets/stylesheets/gl_bootstrap.scss b/app/assets/stylesheets/gl_bootstrap.scss index 15f08ccc10..55a1d50a09 100644 --- a/app/assets/stylesheets/gl_bootstrap.scss +++ b/app/assets/stylesheets/gl_bootstrap.scss @@ -227,5 +227,14 @@ ul.breadcrumb { * */ .panel { + .panel-heading { + font-size: 14px; + line-height: 18px; + .panel-head-actions { + position: relative; + top: -7px; + float: right; + } + } } diff --git a/app/assets/stylesheets/sections/dashboard.scss b/app/assets/stylesheets/sections/dashboard.scss index e70757e040..0ec21ff50f 100644 --- a/app/assets/stylesheets/sections/dashboard.scss +++ b/app/assets/stylesheets/sections/dashboard.scss @@ -1,10 +1,11 @@ .dashboard { .side { - .ui-box { - margin: 0px; - box-shadow: none; - - .nav-projects-tabs li { padding: 0; } + .panel { + .panel-heading { + background: #EEE; + border-top-left-radius: 0; + } + border-top-left-radius: 0; } } } @@ -24,9 +25,7 @@ .dashboard { .dash-filter { - margin: 7px 0; - padding: 4px 6px; - width: 220px; + width: 205px; float: left; height: inherit; } @@ -34,7 +33,7 @@ @media (max-width: 1200px) { .dashboard .dash-filter { - width: 150px; + width: 140px; } } diff --git a/app/views/groups/_projects.html.haml b/app/views/groups/_projects.html.haml index 520310bc43..a6ca41877a 100644 --- a/app/views/groups/_projects.html.haml +++ b/app/views/groups/_projects.html.haml @@ -2,7 +2,7 @@ .panel-heading Projects (#{projects.count}) - if can? current_user, :create_projects, @group - %span.pull-right + .panel-head-actions = link_to new_project_path(namespace_id: @group.id), class: "btn btn-new" do %i.icon-plus New project From 4c51619de3a0443ee25d19ee5ba0d7ab77bedc07 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 29 May 2014 19:42:49 +0300 Subject: [PATCH 138/360] Use more logic class names for buttons in panel headings Signed-off-by: Dmitriy Zaporozhets --- app/views/admin/projects/index.html.haml | 2 +- app/views/admin/users/index.html.haml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/admin/projects/index.html.haml b/app/views/admin/projects/index.html.haml index fb462840ba..7a23b7020c 100644 --- a/app/views/admin/projects/index.html.haml +++ b/app/views/admin/projects/index.html.haml @@ -40,7 +40,7 @@ .panel.panel-default .panel-heading Projects (#{@projects.total_count}) - .pull-right + .panel-head-actions .dropdown.inline %a.dropdown-toggle.btn{href: '#', "data-toggle" => "dropdown"} %span.light sort: diff --git a/app/views/admin/users/index.html.haml b/app/views/admin/users/index.html.haml index 4bfdcbc4de..b8a1822444 100644 --- a/app/views/admin/users/index.html.haml +++ b/app/views/admin/users/index.html.haml @@ -31,7 +31,7 @@ .panel.panel-default .panel-heading Users (#{@users.total_count}) - .pull-right + .panel-head-actions = link_to 'New User', new_admin_user_path, class: "btn btn-new" %ul.well-list - @users.each do |user| From 4f9669cd9f35a72dd9c950decccbe012d1a3d957 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 29 May 2014 20:35:43 +0300 Subject: [PATCH 139/360] Improve help page content Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/sections/help.scss | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/app/assets/stylesheets/sections/help.scss b/app/assets/stylesheets/sections/help.scss index 6488e7c1e8..178a735941 100644 --- a/app/assets/stylesheets/sections/help.scss +++ b/app/assets/stylesheets/sections/help.scss @@ -1,11 +1,17 @@ .documentation { padding-bottom: 10px; p { - padding: 10px; + padding: 10px 14px; margin: 0; } + li { - list-style-type: none; - padding-left: 10px; + line-height: 24px; + color: #888; + + a { + font-size: 14px; + margin-right: 3px; + } } } From e6f1eef47858e21dad9526a45586c609f8dea5e8 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 29 May 2014 21:30:07 +0300 Subject: [PATCH 140/360] Fix group tests Signed-off-by: Dmitriy Zaporozhets --- features/steps/group/group.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/features/steps/group/group.rb b/features/steps/group/group.rb index 5e0c71581f..f321428592 100644 --- a/features/steps/group/group.rb +++ b/features/steps/group/group.rb @@ -38,22 +38,22 @@ class Groups < Spinach::FeatureSteps end Then 'I should see user "John Doe" in team list' do - projects_with_access = find(".ui-box .well-list") + projects_with_access = find(".panel .well-list") projects_with_access.should have_content("John Doe") end Then 'I should not see user "John Doe" in team list' do - projects_with_access = find(".ui-box .well-list") + projects_with_access = find(".panel .well-list") projects_with_access.should_not have_content("John Doe") end Then 'I should see user "Mary Jane" in team list' do - projects_with_access = find(".ui-box .well-list") + projects_with_access = find(".panel .well-list") projects_with_access.should have_content("Mary Jane") end Then 'I should not see user "Mary Jane" in team list' do - projects_with_access = find(".ui-box .well-list") + projects_with_access = find(".panel .well-list") projects_with_access.should_not have_content("Mary Jane") end From 5b26b45dcbba8ee11177eef348502bd2ea3b037f Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 29 May 2014 21:30:20 +0300 Subject: [PATCH 141/360] Improve group settings UI Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/gl_bootstrap.scss | 11 ++ app/controllers/groups_controller.rb | 10 +- app/views/groups/_settings_nav.html.haml | 10 ++ app/views/groups/edit.html.haml | 135 ++++++++--------------- app/views/groups/projects.html.haml | 29 +++++ config/routes.rb | 1 + 6 files changed, 106 insertions(+), 90 deletions(-) create mode 100644 app/views/groups/_settings_nav.html.haml create mode 100644 app/views/groups/projects.html.haml diff --git a/app/assets/stylesheets/gl_bootstrap.scss b/app/assets/stylesheets/gl_bootstrap.scss index 55a1d50a09..f46dfbf112 100644 --- a/app/assets/stylesheets/gl_bootstrap.scss +++ b/app/assets/stylesheets/gl_bootstrap.scss @@ -237,4 +237,15 @@ ul.breadcrumb { float: right; } } + + .panel-body { + form { + margin: 0; + } + + .form-actions { + margin-bottom: 0; + background: #FFF; + } + } } diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index ddaae6f0e8..c8e13879b1 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -9,7 +9,7 @@ class GroupsController < ApplicationController before_filter :authorize_create_group!, only: [:new, :create] # Load group projects - before_filter :projects, except: [:new, :create] + before_filter :load_projects, except: [:new, :create, :projects, :edit, :update] before_filter :default_filter, only: [:issues, :merge_requests] @@ -79,9 +79,13 @@ class GroupsController < ApplicationController def edit end + def projects + @projects = @group.projects.page(params[:page]) + end + def update if @group.update_attributes(params[:group]) - redirect_to @group, notice: 'Group was successfully updated.' + redirect_to edit_group_path(@group), notice: 'Group was successfully updated.' else render action: "edit" end @@ -99,7 +103,7 @@ class GroupsController < ApplicationController @group ||= Group.find_by(path: params[:id]) end - def projects + def load_projects @projects ||= ProjectsFinder.new.execute(current_user, group: group).sorted_by_activity.non_archived end diff --git a/app/views/groups/_settings_nav.html.haml b/app/views/groups/_settings_nav.html.haml new file mode 100644 index 0000000000..32eae31a47 --- /dev/null +++ b/app/views/groups/_settings_nav.html.haml @@ -0,0 +1,10 @@ +%ul.nav.nav-pills.nav-stacked.nav-stacked-menu + = nav_link(path: 'groups#edit') do + = link_to edit_group_path(@group) do + %i.icon-edit + Group + = nav_link(path: 'groups#projects') do + = link_to projects_group_path(@group) do + %i.icon-folder-close + Projects + diff --git a/app/views/groups/edit.html.haml b/app/views/groups/edit.html.haml index 315da0370f..97f22df044 100644 --- a/app/views/groups/edit.html.haml +++ b/app/views/groups/edit.html.haml @@ -1,95 +1,56 @@ .row .col-md-2 - %ul.nav.nav-pills.nav-stacked.nav-stacked-menu - %li.active - = link_to '#tab-edit', 'data-toggle' => 'tab' do - %i.icon-edit - Group - %li - = link_to '#tab-projects', 'data-toggle' => 'tab' do - %i.icon-folder-close - Projects - %li - = link_to '#tab-remove', 'data-toggle' => 'tab' do - %i.icon-remove-sign - Remove - + = render 'settings_nav' .col-md-10 - .tab-content - .tab-pane.active#tab-edit - .panel.panel-default - .panel-heading - %strong= @group.name - group settings: - %div.form-holder - = form_for @group, html: { multipart: true, class: "form-horizontal" }, authenticity_token: true do |f| - - if @group.errors.any? - .alert.alert-danger - %span= @group.errors.full_messages.first - .form-group - = f.label :name, class: 'control-label' do - Group name - .col-sm-10 - = f.text_field :name, placeholder: "Ex. OpenSource", class: "form-control left" + .panel.panel-default + .panel-heading + %strong= @group.name + group settings: + .panel-body + = form_for @group, html: { multipart: true, class: "form-horizontal" }, authenticity_token: true do |f| + - if @group.errors.any? + .alert.alert-danger + %span= @group.errors.full_messages.first + .form-group + = f.label :name, class: 'control-label' do + Group name + .col-sm-10 + = f.text_field :name, placeholder: "Ex. OpenSource", class: "form-control left" - .form-group.group-description-holder - = f.label :description, "Details", class: 'control-label' - .col-sm-10 - = f.text_area :description, maxlength: 250, class: "form-control js-gfm-input", rows: 4 + .form-group.group-description-holder + = f.label :description, "Details", class: 'control-label' + .col-sm-10 + = f.text_area :description, maxlength: 250, class: "form-control js-gfm-input", rows: 4 - .form-group - .col-sm-2 - .col-sm-10 - = image_tag group_icon(@group.to_param), alt: '', class: 'avatar s160' - %p.light - - if @group.avatar? - You can change your group avatar here - - else - You can upload a group avatar here - %a.choose-btn.btn.btn-small.js-choose-group-avatar-button - %i.icon-paper-clip - %span Choose File ... -   - %span.file_name.js-avatar-filename File name... - = f.file_field :avatar, class: "js-group-avatar-input hidden" - .light The maximum file size allowed is 100KB. - - if @group.avatar? - %hr - = link_to 'Remove avatar', group_avatar_path(@group.to_param), data: { confirm: "Group avatar will be removed. Are you sure?"}, method: :delete, class: "btn btn-remove btn-small remove-avatar" + .form-group + .col-sm-2 + .col-sm-10 + = image_tag group_icon(@group.to_param), alt: '', class: 'avatar s160' + %p.light + - if @group.avatar? + You can change your group avatar here + - else + You can upload a group avatar here + %a.choose-btn.btn.btn-small.js-choose-group-avatar-button + %i.icon-paper-clip + %span Choose File ... +   + %span.file_name.js-avatar-filename File name... + = f.file_field :avatar, class: "js-group-avatar-input hidden" + .light The maximum file size allowed is 100KB. + - if @group.avatar? + %hr + = link_to 'Remove avatar', group_avatar_path(@group.to_param), data: { confirm: "Group avatar will be removed. Are you sure?"}, method: :delete, class: "btn btn-remove btn-small remove-avatar" - .form-actions - = f.submit 'Save group', class: "btn btn-save" + .form-actions + = f.submit 'Save group', class: "btn btn-save" - .tab-pane#tab-projects - .panel.panel-default - .panel-heading - %strong= @group.name - projects: - - if can? current_user, :manage_group, @group - %span.pull-right - = link_to new_project_path(namespace_id: @group.id), class: "btn btn-tiny" do - %i.icon-plus - New Project - %ul.well-list - - @group.projects.each do |project| - %li - .list-item-name - = visibility_level_icon(project.visibility_level) - = link_to project.name_with_namespace, project - .pull-right - = link_to 'Members', project_team_index_path(project), id: "edit_#{dom_id(project)}", class: "btn btn-small" - = link_to 'Edit', edit_project_path(project), id: "edit_#{dom_id(project)}", class: "btn btn-small" - = link_to 'Remove', project, data: { confirm: remove_project_message(project)}, method: :delete, class: "btn btn-small btn-remove" - - if @group.projects.blank? - .nothing-here-block This group has no projects yet + .panel.panel-danger + .panel-heading Remove group + .panel-body + %p + Removing group will cause all child projects and resources to be removed. + %br + %strong Removed group can not be restored! - .tab-pane#tab-remove - .panel.panel-default.panel.panel-danger - .panel-heading Remove group - .panel-body - %p - Removing group will cause all child projects and resources to be removed. - %p - %strong Removed group can not be restored! - - = link_to 'Remove Group', @group, data: {confirm: 'Removed group can not be restored! Are you sure?'}, method: :delete, class: "btn btn-remove" + = link_to 'Remove Group', @group, data: {confirm: 'Removed group can not be restored! Are you sure?'}, method: :delete, class: "btn btn-remove" diff --git a/app/views/groups/projects.html.haml b/app/views/groups/projects.html.haml new file mode 100644 index 0000000000..a5e752d776 --- /dev/null +++ b/app/views/groups/projects.html.haml @@ -0,0 +1,29 @@ +.row + .col-md-2 + = render 'settings_nav' + .col-md-10 + .panel.panel-default + .panel-heading + %strong= @group.name + projects: + - if can? current_user, :manage_group, @group + .panel-head-actions + = link_to new_project_path(namespace_id: @group.id), class: "btn btn-new" do + %i.icon-plus + New Project + %ul.well-list + - @projects.each do |project| + %li + .list-item-name + = visibility_level_icon(project.visibility_level) + %strong= link_to project.name_with_namespace, project + %span.label.label-gray + = repository_size(project) + .pull-right + = link_to 'Members', project_team_index_path(project), id: "edit_#{dom_id(project)}", class: "btn btn-small" + = link_to 'Edit', edit_project_path(project), id: "edit_#{dom_id(project)}", class: "btn btn-small" + = link_to 'Remove', project, data: { confirm: remove_project_message(project)}, method: :delete, class: "btn btn-small btn-remove" + - if @projects.blank? + .nothing-here-block This group has no projects yet + + = paginate @projects, theme: "gitlab" diff --git a/config/routes.rb b/config/routes.rb index 6581aeef11..7c2ab6bd1d 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -146,6 +146,7 @@ Gitlab::Application.routes.draw do get :issues get :merge_requests get :members + get :projects end resources :users_groups, only: [:create, :update, :destroy] From f329d34ff339f0d0da150b262465a654bfe445a5 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 29 May 2014 22:03:42 +0300 Subject: [PATCH 142/360] Fix group projects fetch Signed-off-by: Dmitriy Zaporozhets --- app/controllers/groups_controller.rb | 6 +++--- spec/features/security/group/group_access_spec.rb | 12 ++++++++++++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index c8e13879b1..a2629c5138 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -5,7 +5,7 @@ class GroupsController < ApplicationController # Authorize before_filter :authorize_read_group!, except: [:new, :create] - before_filter :authorize_admin_group!, only: [:edit, :update, :destroy] + before_filter :authorize_admin_group!, only: [:edit, :update, :destroy, :projects] before_filter :authorize_create_group!, only: [:new, :create] # Load group projects @@ -108,12 +108,12 @@ class GroupsController < ApplicationController end def project_ids - projects.pluck(:id) + @projects.pluck(:id) end # Dont allow unauthorized access to group def authorize_read_group! - unless @group and (projects.present? or can?(current_user, :read_group, @group)) + unless @group and (@projects.present? or can?(current_user, :read_group, @group)) if current_user.nil? return authenticate_user! else diff --git a/spec/features/security/group/group_access_spec.rb b/spec/features/security/group/group_access_spec.rb index b65e1d2dbf..44de499e6d 100644 --- a/spec/features/security/group/group_access_spec.rb +++ b/spec/features/security/group/group_access_spec.rb @@ -82,5 +82,17 @@ describe "Group access", feature: true do it { should be_denied_for :user } it { should be_denied_for :visitor } end + + describe "GET /groups/:path/projects" do + subject { projects_group_path(group) } + + it { should be_allowed_for owner } + it { should be_denied_for master } + it { should be_denied_for reporter } + it { should be_allowed_for :admin } + it { should be_denied_for guest } + it { should be_denied_for :user } + it { should be_denied_for :visitor } + end end end From 7ba1853660e09bc997d829fc596ea576c122086b Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Fri, 30 May 2014 10:57:13 +0200 Subject: [PATCH 143/360] Add to changelog v6.9.2 Conflicts: CHANGELOG --- CHANGELOG | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index c8a969912e..151db5dd30 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -13,6 +13,9 @@ v 7.0.0 - Group masters can create projects in group - Deprecate ruby 1.9.3 support +v 6.9.2 + - Revert the commit that broke the LDAP user filter + v 6.9.1 - Fix scroll to highlighted line - Fix the pagination on load for commits page From d8c7efa626ba925aa9c1bf1efaf6289cd5db4f0b Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 30 May 2014 16:26:45 +0300 Subject: [PATCH 144/360] Dont allow git tag rewrite/removal unless you are master Signed-off-by: Dmitriy Zaporozhets --- CHANGELOG | 1 + app/views/projects/tags/_tag.html.haml | 2 +- doc/permissions/permissions.md | 1 + lib/gitlab/git_access.rb | 3 +++ 4 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 151db5dd30..97d1299bae 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -12,6 +12,7 @@ v 7.0.0 - Make it easier to implement other CI services for GitLab - Group masters can create projects in group - Deprecate ruby 1.9.3 support + - Only masters can rewrite/remove git tags v 6.9.2 - Revert the commit that broke the LDAP user filter diff --git a/app/views/projects/tags/_tag.html.haml b/app/views/projects/tags/_tag.html.haml index 6629e47ad3..67d771c970 100644 --- a/app/views/projects/tags/_tag.html.haml +++ b/app/views/projects/tags/_tag.html.haml @@ -17,6 +17,6 @@ - if can? current_user, :download_code, @project = render 'projects/repositories/download_archive', ref: tag.name, btn_class: 'btn-grouped btn-group-small' - if can?(current_user, :admin_project, @project) - = link_to project_tag_path(@project, tag.name), class: 'btn btn-small remove-row grouped', method: :delete, data: { confirm: 'Removed tag cannot be restored. Are you sure?'}, remote: true do + = link_to project_tag_path(@project, tag.name), class: 'btn btn-small btn-remove remove-row grouped', method: :delete, data: { confirm: 'Removed tag cannot be restored. Are you sure?'}, remote: true do %i.icon-trash diff --git a/doc/permissions/permissions.md b/doc/permissions/permissions.md index 95b47a8612..40d748c057 100644 --- a/doc/permissions/permissions.md +++ b/doc/permissions/permissions.md @@ -27,6 +27,7 @@ If a user is a GitLab administrator they receive all permissions. |Add new team members| |||✓|✓| |Push to protected branches| |||✓|✓| |Enable/Disable branch protection| |||✓|✓| +|Rewrite/remove git tags| |||✓|✓| |Edit project| |||✓|✓| |Add Deploy Keys to project| |||✓|✓| |Configure Project Hooks| |||✓|✓| diff --git a/lib/gitlab/git_access.rb b/lib/gitlab/git_access.rb index 2f8b55aaca..38b3d82e2f 100644 --- a/lib/gitlab/git_access.rb +++ b/lib/gitlab/git_access.rb @@ -53,6 +53,9 @@ module Gitlab else :push_code_to_protected_branches end + elsif project.repository && project.repository.tag_names.include?(ref) + # Prevent any changes to existing git tag unless user has permissions + :admin_project else :push_code end From 4a03bbe4831399381a45cde7fd19ecfb67895bd4 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Fri, 30 May 2014 17:09:31 +0200 Subject: [PATCH 145/360] Add nofollow to all internal links. --- app/helpers/application_helper.rb | 31 ++++++++++++++++++------- spec/helpers/application_helper_spec.rb | 23 ++++++++++++++++++ 2 files changed, 45 insertions(+), 9 deletions(-) diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 4a3b345bdf..198ca76545 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -233,16 +233,29 @@ module ApplicationHelper end def link_to(name = nil, options = nil, html_options = nil, &block) - if html_options - if html_options[:rel] - html_options[:rel] << " noreferrer" - else - html_options.merge(rel: "noreferrer") - end - else - html_options = Hash.new - html_options[:rel] = "noreferrer" + begin + uri = URI(options) + host = uri.host + absolute_uri = uri.absolute? + rescue URI::InvalidURIError, ArgumentError + host = nil + absolute_uri = nil end + + # Add "nofollow" only to external links + if host && host != Gitlab.config.gitlab.host && absolute_uri + if html_options + if html_options[:rel] + html_options[:rel] << " nofollow" + else + html_options.merge!(rel: "nofollow") + end + else + html_options = Hash.new + html_options[:rel] = "nofollow" + end + end + super end end diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb index 0376e0aadf..10c5617d24 100644 --- a/spec/helpers/application_helper_spec.rb +++ b/spec/helpers/application_helper_spec.rb @@ -195,4 +195,27 @@ describe ApplicationHelper do simple_sanitize(input).should == a_tag end end + + describe "link_to" do + + it "should not include rel=nofollow for internal links" do + expect(link_to("Home", root_path)).to eq("
Home") + end + + it "should include rel=nofollow for external links" do + expect(link_to("Example", "http://www.example.com")).to eq("Example") + end + + it "should include re=nofollow for external links and honor existing html_options" do + expect( + link_to("Example", "http://www.example.com", class: "toggle", data: {toggle: "dropdown"}) + ).to eq("Example") + end + + it "should include rel=nofollow for external links and preserver other rel values" do + expect( + link_to("Example", "http://www.example.com", rel: "noreferrer") + ).to eq("Example") + end + end end From 72b295259ed8565e166a7f2a466ca33d183f6108 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 30 May 2014 18:22:59 +0300 Subject: [PATCH 146/360] Show only personal projects on profile page Signed-off-by: Dmitriy Zaporozhets --- app/controllers/users_controller.rb | 4 +++- app/views/users/_projects.html.haml | 2 +- app/views/users/show.html.haml | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 9461174b95..2d227ae201 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -4,10 +4,12 @@ class UsersController < ApplicationController def show @user = User.find_by_username!(params[:username]) - @projects = @user.authorized_projects.accessible_to(current_user) + @projects = Project.personal(@user).accessible_to(current_user) + if !current_user && @projects.empty? return authenticate_user! end + @groups = @user.groups.accessible_to(current_user) @events = @user.recent_events.where(project_id: @projects.pluck(:id)).limit(20) @title = @user.name diff --git a/app/views/users/_projects.html.haml b/app/views/users/_projects.html.haml index 2d97c4545b..bcaec4a27e 100644 --- a/app/views/users/_projects.html.haml +++ b/app/views/users/_projects.html.haml @@ -1,5 +1,5 @@ .panel.panel-default - .panel-heading Projects + .panel-heading Personal projects %ul.well-list - @projects.each do |project| %li diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml index edcaf3acf9..948b59fead 100644 --- a/app/views/users/show.html.haml +++ b/app/views/users/show.html.haml @@ -20,4 +20,5 @@ = render @events .col-md-4 = render 'profile', user: @user - = render 'projects' + - if @projects.present? + = render 'projects' From 65cf5957deec1816f867f0285b34f314599c905a Mon Sep 17 00:00:00 2001 From: Jeroen van Baarsen Date: Fri, 30 May 2014 20:11:07 +0200 Subject: [PATCH 147/360] Removed the Support Email setting This setting was not longer used in GitLab, so i think it can be removed. Signed-off-by: Jeroen van Baarsen --- config/gitlab.yml.example | 3 --- config/initializers/1_settings.rb | 1 - 2 files changed, 4 deletions(-) diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example index 04e85ed9a9..6f33256a2b 100644 --- a/config/gitlab.yml.example +++ b/config/gitlab.yml.example @@ -35,9 +35,6 @@ production: &base # Email address used in the "From" field in mails sent by GitLab email_from: example@example.com - # Email address of your support contact (default: same as email_from) - support_email: support@example.com - # Email server smtp settings are in [a separate file](initializers/smtp_settings.rb.sample). ## User settings diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb index 97f2954640..18c628223a 100644 --- a/config/initializers/1_settings.rb +++ b/config/initializers/1_settings.rb @@ -79,7 +79,6 @@ Settings.gitlab['port'] ||= Settings.gitlab.https ? 443 : 80 Settings.gitlab['relative_url_root'] ||= ENV['RAILS_RELATIVE_URL_ROOT'] || '' Settings.gitlab['protocol'] ||= Settings.gitlab.https ? "https" : "http" Settings.gitlab['email_from'] ||= "gitlab@#{Settings.gitlab.host}" -Settings.gitlab['support_email'] ||= Settings.gitlab.email_from Settings.gitlab['url'] ||= Settings.send(:build_gitlab_url) Settings.gitlab['user'] ||= 'git' Settings.gitlab['user_home'] ||= begin From 5ba00d950bb15fde71f58ac08ec22e04cc9437d6 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 30 May 2014 23:43:53 +0300 Subject: [PATCH 148/360] Add old ui-box style to panels Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/gl_bootstrap.scss | 15 +++++++++++++++ .../stylesheets/sections/merge_requests.scss | 6 ------ app/views/shared/_issues.html.haml | 2 +- app/views/shared/_merge_requests.html.haml | 2 +- 4 files changed, 17 insertions(+), 8 deletions(-) diff --git a/app/assets/stylesheets/gl_bootstrap.scss b/app/assets/stylesheets/gl_bootstrap.scss index f46dfbf112..e4256a5324 100644 --- a/app/assets/stylesheets/gl_bootstrap.scss +++ b/app/assets/stylesheets/gl_bootstrap.scss @@ -227,7 +227,10 @@ ul.breadcrumb { * */ .panel { + @include border-radius(0px); + .panel-heading { + @include border-radius(0px); font-size: 14px; line-height: 18px; @@ -248,4 +251,16 @@ ul.breadcrumb { background: #FFF; } } + + &.panel-small { + .panel-heading { + padding: 6px 15px; + } + } + + &.panel-default { + .panel-heading { + background-color: #EEE; + } + } } diff --git a/app/assets/stylesheets/sections/merge_requests.scss b/app/assets/stylesheets/sections/merge_requests.scss index cac4cb66aa..5d716ddec3 100644 --- a/app/assets/stylesheets/sections/merge_requests.scss +++ b/app/assets/stylesheets/sections/merge_requests.scss @@ -106,12 +106,6 @@ } .mr-state-widget { - @include border-radius(0px); - - .panel-heading { - @include border-radius(0px); - } - .panel-body { h4 { margin-top: 0px; diff --git a/app/views/shared/_issues.html.haml b/app/views/shared/_issues.html.haml index d36e96dc49..e976f897dc 100644 --- a/app/views/shared/_issues.html.haml +++ b/app/views/shared/_issues.html.haml @@ -1,6 +1,6 @@ - if @issues.any? - @issues.group_by(&:project).each do |group| - .panel.panel-default.panel.panel-default-small + .panel.panel-default.panel-small - project = group[0] .panel-heading = link_to_project project diff --git a/app/views/shared/_merge_requests.html.haml b/app/views/shared/_merge_requests.html.haml index 954b16cfdb..39a1ee38f8 100644 --- a/app/views/shared/_merge_requests.html.haml +++ b/app/views/shared/_merge_requests.html.haml @@ -1,6 +1,6 @@ - if @merge_requests.any? - @merge_requests.group_by(&:target_project).each do |group| - .panel.panel-default.panel.panel-default-small + .panel.panel-default.panel-small - project = group[0] .panel-heading = link_to_project project From e02aec662751d545b70fe014c757d7061c577016 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sat, 31 May 2014 00:13:15 +0300 Subject: [PATCH 149/360] Use var colors for panels --- app/assets/stylesheets/gl_bootstrap.scss | 44 ++++++++++++++++++++-- app/assets/stylesheets/main/variables.scss | 5 +++ 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/app/assets/stylesheets/gl_bootstrap.scss b/app/assets/stylesheets/gl_bootstrap.scss index e4256a5324..69053eae52 100644 --- a/app/assets/stylesheets/gl_bootstrap.scss +++ b/app/assets/stylesheets/gl_bootstrap.scss @@ -257,10 +257,46 @@ ul.breadcrumb { padding: 6px 15px; } } +} - &.panel-default { - .panel-heading { - background-color: #EEE; - } +.panel-default { + .panel-heading { + background-color: #EEE; + } +} + +.panel-danger { + border-color: $border_danger; + .panel-heading { + color: #ffffff; + background-color: $bg_danger; + border-color: $border_danger; + } +} + +.panel-success { + border-color: $border_success; + .panel-heading { + color: #ffffff; + background-color: $bg_success; + border-color: $border_success; + } +} + +.panel-primary { + border-color: $border_primary; + .panel-heading { + color: #ffffff; + background-color: $bg_primary; + border-color: $border_primary; + } +} + +.panel-warning { + border-color: $border_warning; + .panel-heading { + color: #ffffff; + background-color: $bg_warning; + border-color: $border_warning; } } diff --git a/app/assets/stylesheets/main/variables.scss b/app/assets/stylesheets/main/variables.scss index f133777de5..ddfcdef836 100644 --- a/app/assets/stylesheets/main/variables.scss +++ b/app/assets/stylesheets/main/variables.scss @@ -32,6 +32,11 @@ $bg_primary: #429bca; $bg_light_primary: #d9edf7; $color_primary: #31708f; +/* + * Warning colors (yellow) + */ +$bg_warning: #f39c12; +$border_warning: #f39c12; /** * Commit Diff Colors From 2314438925af827b694fbaaf59c31c49dd2c0c31 Mon Sep 17 00:00:00 2001 From: Jeroen van Baarsen Date: Thu, 8 May 2014 19:15:58 +0200 Subject: [PATCH 150/360] Fix for failing specs --- .travis.yml | 3 --- Gemfile | 4 ++-- Gemfile.lock | 24 ++++++++++++------------ features/support/env.rb | 2 +- spec/support/db_cleaner.rb | 33 ++++++++++++++++----------------- 5 files changed, 31 insertions(+), 35 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9bab337f33..055a521711 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,9 +15,6 @@ env: - TASK=jasmine:ci DB=postgresql before_install: - sudo apt-get install libicu-dev -y -branches: - only: - - 'master' rvm: - 2.0.0 services: diff --git a/Gemfile b/Gemfile index eb4ca6569c..c74d2f54c2 100644 --- a/Gemfile +++ b/Gemfile @@ -199,7 +199,7 @@ group :development, :test do # gem 'rails-dev-tweaks' gem 'spinach-rails' gem "rspec-rails" - gem "capybara" + gem "capybara", '~> 2.2.1' gem "pry" gem "awesome_print" gem "database_cleaner" @@ -222,7 +222,7 @@ group :development, :test do gem 'rb-inotify', require: linux_only('rb-inotify') # PhantomJS driver for Capybara - gem 'poltergeist', '~> 1.4.1' + gem 'poltergeist', '~> 1.5.1' gem 'jasmine', '2.0.0.rc5' diff --git a/Gemfile.lock b/Gemfile.lock index 3def12c053..7a72d3c3e8 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -47,7 +47,7 @@ GEM bootstrap-sass (3.0.3.0) sass (~> 3.2) builder (3.1.4) - capybara (2.1.0) + capybara (2.2.1) mime-types (>= 1.16) nokogiri (>= 1.3.3) rack (>= 1.0.0) @@ -60,7 +60,7 @@ GEM celluloid (0.15.2) timers (~> 1.1.0) charlock_holmes (0.6.9.4) - cliver (0.2.2) + cliver (0.3.2) code_analyzer (0.4.3) sexp_processor coderay (1.1.0) @@ -281,9 +281,9 @@ GEM treetop (~> 1.4.8) method_source (0.8.2) mime-types (1.25.1) - mini_portile (0.5.3) + mini_portile (0.6.0) minitest (4.7.5) - multi_json (1.10.0) + multi_json (1.10.1) multi_xml (0.5.5) multipart-post (1.2.0) mysql2 (0.3.11) @@ -291,8 +291,8 @@ GEM net-scp (1.1.2) net-ssh (>= 2.6.5) net-ssh (2.8.0) - nokogiri (1.6.1) - mini_portile (~> 0.5.0) + nokogiri (1.6.2.1) + mini_portile (= 0.6.0) nprogress-rails (0.1.2.3) oauth (0.4.7) oauth2 (0.8.1) @@ -324,9 +324,9 @@ GEM orm_adapter (0.5.0) pg (0.15.1) phantomjs (1.9.2.0) - poltergeist (1.4.1) - capybara (~> 2.1.0) - cliver (~> 0.2.1) + poltergeist (1.5.1) + capybara (~> 2.1) + cliver (~> 0.3.1) multi_json (~> 1.0) websocket-driver (>= 0.2.0) polyglot (0.3.4) @@ -557,7 +557,7 @@ GEM webmock (1.16.0) addressable (>= 2.2.7) crack (>= 0.3.2) - websocket-driver (0.3.1) + websocket-driver (0.3.3) xpath (2.0.0) nokogiri (~> 1.3) @@ -573,7 +573,7 @@ DEPENDENCIES better_errors binding_of_caller bootstrap-sass (~> 3.0) - capybara + capybara (~> 2.2.1) carrierwave coffee-rails colored @@ -630,7 +630,7 @@ DEPENDENCIES omniauth-twitter org-ruby pg - poltergeist (~> 1.4.1) + poltergeist (~> 1.5.1) protected_attributes pry quiet_assets (~> 1.0.1) diff --git a/features/support/env.rb b/features/support/env.rb index a5b297775d..3ab2ce0a3e 100644 --- a/features/support/env.rb +++ b/features/support/env.rb @@ -28,7 +28,7 @@ WebMock.allow_net_connect! require 'capybara/poltergeist' Capybara.javascript_driver = :poltergeist Capybara.register_driver :poltergeist do |app| - Capybara::Poltergeist::Driver.new(app, :js_errors => false, :timeout => 60) + Capybara::Poltergeist::Driver.new(app, js_errors: false, timeout: 90) end Spinach.hooks.on_tag("javascript") do ::Capybara.current_driver = ::Capybara.javascript_driver diff --git a/spec/support/db_cleaner.rb b/spec/support/db_cleaner.rb index 8c9c74f14b..f2b310245b 100644 --- a/spec/support/db_cleaner.rb +++ b/spec/support/db_cleaner.rb @@ -1,22 +1,21 @@ -require 'database_cleaner' - RSpec.configure do |config| - config.before do - if example.metadata[:js] - DatabaseCleaner.strategy = :truncation - Capybara::Selenium::Driver::DEFAULT_OPTIONS[:resynchronize] = true - else - DatabaseCleaner.strategy = :transaction - end - - unless example.metadata[:no_db] - DatabaseCleaner.start - end + config.around(:each) do + DatabaseCleaner.clean_with(:truncation) end - config.after do - unless example.metadata[:no_db] - DatabaseCleaner.clean - end + config.around(:each) do + DatabaseCleaner.strategy = :transaction + end + + config.around(:each, js: true) do + DatabaseCleaner.strategy = :truncation + end + + config.before(:each) do + DatabaseCleaner.start + end + + config.after(:each) do + DatabaseCleaner.clean end end From 3351f15af63929caec03c8dd0d62f52b8f7704eb Mon Sep 17 00:00:00 2001 From: Jeroen van Baarsen Date: Fri, 30 May 2014 23:34:52 +0200 Subject: [PATCH 151/360] Put back the travis information Signed-off-by: Jeroen van Baarsen --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index 055a521711..9bab337f33 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,6 +15,9 @@ env: - TASK=jasmine:ci DB=postgresql before_install: - sudo apt-get install libicu-dev -y +branches: + only: + - 'master' rvm: - 2.0.0 services: From 1a97db413b03881f0ce4307811181776e3d6e408 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sat, 31 May 2014 00:41:11 +0300 Subject: [PATCH 152/360] Simplify issue-box style --- app/assets/stylesheets/generic/issue_box.scss | 47 +++++++------------ app/views/projects/issues/show.html.haml | 6 +-- .../merge_requests/show/_mr_box.html.haml | 4 +- app/views/projects/milestones/show.html.haml | 4 +- 4 files changed, 23 insertions(+), 38 deletions(-) diff --git a/app/assets/stylesheets/generic/issue_box.scss b/app/assets/stylesheets/generic/issue_box.scss index bd69241798..9847e80f8e 100644 --- a/app/assets/stylesheets/generic/issue_box.scss +++ b/app/assets/stylesheets/generic/issue_box.scss @@ -17,52 +17,36 @@ &.issue-box-closed { border-color: $border_danger; .state { - background-color: $bg_light_danger; + background-color: $bg_danger; + color: #FFF; border-color: $border_danger; - color: $color_danger; - .state-label { - background-color: $bg_danger; - color: #FFF; - } } } &.issue-box-merged { border-color: $border_primary; .state { - background-color: $bg_light_primary; + background-color: $bg_primary; + color: #FFF; border-color: $border_primary; - color: $color_primary; - .state-label { - background-color: $bg_primary; - color: #FFF; - } } } &.issue-box-open { border-color: $border_success; .state { - background-color: $bg_light_success; border-color: $border_success; - color: $color_success; - .state-label { - background-color: $bg_success; - color: #FFF; - } + background-color: $bg_success; + color: #FFF; } } &.issue-box-expired { border-color: #cea61b; .state { - background-color: #fcf8e3; border-color: #faebcc; - color: #8a6d3b; - .state-label { - background: #cea61b; - color: #FFF; - } + background: #cea61b; + color: #FFF; } } @@ -72,7 +56,7 @@ .state { border-bottom: 1px solid #DDD; - line-height: 32px; + padding: 10px 25px; } .title { @@ -115,14 +99,15 @@ .state-label { font-size: 14px; - padding: 1px 25px; - text-align: center; - text-shadow: none; - display: inline-block; - line-height: 34px; + float: left; + font-weight: bold; } .creator { - padding: 2px 15px; + float: right; + a { + color: #FFF; + text-decoration: underline; + } } } diff --git a/app/views/projects/issues/show.html.haml b/app/views/projects/issues/show.html.haml index 2c816e788d..695eb22575 100644 --- a/app/views/projects/issues/show.html.haml +++ b/app/views/projects/issues/show.html.haml @@ -32,13 +32,13 @@ .issue-box{ class: issue_box_class(@issue) } .state.clearfix - .state-label.col-sm-2.col-xs-12 + .state-label - if @issue.closed? Closed - else Open - %span.creator.col-sm-9.col-xs-12 + .creator Created by #{link_to_member(@project, @issue.author)} #{time_ago_with_tooltip(@issue.created_at)} %h4.title @@ -73,4 +73,4 @@ = label.name   -.voting_notes#notes= render "projects/notes/notes_with_form" \ No newline at end of file +.voting_notes#notes= render "projects/notes/notes_with_form" 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 435e916c6d..f1aaba2010 100644 --- a/app/views/projects/merge_requests/show/_mr_box.html.haml +++ b/app/views/projects/merge_requests/show/_mr_box.html.haml @@ -1,6 +1,6 @@ .issue-box{ class: issue_box_class(@merge_request) } .state.clearfix - %span.state-label.col-sm-2.col-xs-12 + .state-label - if @merge_request.merged? Merged - elsif @merge_request.closed? @@ -8,7 +8,7 @@ - else Open - %span.creator.col-sm-9.col-xs-12 + .creator Created by #{link_to_member(@project, @merge_request.author)} #{time_ago_with_tooltip(@merge_request.created_at)} %h4.title diff --git a/app/views/projects/milestones/show.html.haml b/app/views/projects/milestones/show.html.haml index e33f4e5273..d355f25882 100644 --- a/app/views/projects/milestones/show.html.haml +++ b/app/views/projects/milestones/show.html.haml @@ -22,14 +22,14 @@ .issue-box{ class: issue_box_class(@milestone) } .state.clearfix - .state-label.col-sm-2.col-xs-12 + .state-label - if @milestone.closed? Closed - elsif @milestone.expired? Expired - else Open - %span.creator.col-sm-9.col-xs-12 + .creator = @milestone.expires_at %h4.title From c2c43e6aa1f9dc43d16f3d3c03ef247f73156db2 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sat, 31 May 2014 14:00:23 +0300 Subject: [PATCH 153/360] Small ui improvements Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/generic/issue_box.scss | 4 ++-- app/assets/stylesheets/gl_bootstrap.scss | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/app/assets/stylesheets/generic/issue_box.scss b/app/assets/stylesheets/generic/issue_box.scss index 9847e80f8e..3cb64d69a9 100644 --- a/app/assets/stylesheets/generic/issue_box.scss +++ b/app/assets/stylesheets/generic/issue_box.scss @@ -60,8 +60,8 @@ } .title { - font-size: 22px; - font-weight: 500; + font-size: 26px; + font-weight: normal; line-height: 1.5; margin: 0; color: #333; diff --git a/app/assets/stylesheets/gl_bootstrap.scss b/app/assets/stylesheets/gl_bootstrap.scss index 69053eae52..874c4f5b76 100644 --- a/app/assets/stylesheets/gl_bootstrap.scss +++ b/app/assets/stylesheets/gl_bootstrap.scss @@ -271,6 +271,10 @@ ul.breadcrumb { color: #ffffff; background-color: $bg_danger; border-color: $border_danger; + a { + color: #FFF; + text-decoration: underline; + } } } @@ -280,6 +284,10 @@ ul.breadcrumb { color: #ffffff; background-color: $bg_success; border-color: $border_success; + a { + color: #FFF; + text-decoration: underline; + } } } @@ -289,6 +297,10 @@ ul.breadcrumb { color: #ffffff; background-color: $bg_primary; border-color: $border_primary; + a { + color: #FFF; + text-decoration: underline; + } } } @@ -298,5 +310,9 @@ ul.breadcrumb { color: #ffffff; background-color: $bg_warning; border-color: $border_warning; + a { + color: #FFF; + text-decoration: underline; + } } } From 8beb7c886e3bb9706bfa6760325453e749b84231 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sat, 31 May 2014 14:21:13 +0300 Subject: [PATCH 154/360] Different UI colors for archive project and remove project Since remove is more danger in compare to archive it good to have them in different colors Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/generic/buttons.scss | 16 ++++++++ app/views/projects/edit.html.haml | 42 ++++++++++----------- 2 files changed, 37 insertions(+), 21 deletions(-) diff --git a/app/assets/stylesheets/generic/buttons.scss b/app/assets/stylesheets/generic/buttons.scss index dd0a2938cf..1c74bd2de0 100644 --- a/app/assets/stylesheets/generic/buttons.scss +++ b/app/assets/stylesheets/generic/buttons.scss @@ -104,6 +104,22 @@ } } + &.btn-warning { + color: #ffffff; + background-color: $bg_warning; + border-color: $border_warning; + + + &.hover, + &:hover, + &.disabled, + &[disabled] { + color: #ffffff; + background-color: #e38c02; + border-color: #e38c02; + } + } + &.btn-new { @extend .btn-success; } diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml index 43775026f7..59dcf3a6ff 100644 --- a/app/views/projects/edit.html.haml +++ b/app/views/projects/edit.html.haml @@ -106,7 +106,7 @@ .js-toggle-content.hide - if can? current_user, :archive_project, @project - .panel.panel-default.panel.panel-danger + .panel.panel-default.panel.panel-warning .panel-heading - if @project.archived? Unarchive project @@ -132,10 +132,29 @@ %strong Archived projects cannot be committed to! = link_to 'Archive', archive_project_path(@project), data: { confirm: "Are you sure that you want to archive this project?\nAn archived project cannot be committed to." }, - method: :post, class: "btn btn-remove" + method: :post, class: "btn btn-warning" - else .nothing-here-block Only the project owner can archive a project + .panel.panel-default.panel.panel-warning + .panel-heading Rename repository + .errors-holder + .panel-body + = form_for(@project, html: { class: 'form-horizontal' }) do |f| + .form-group + = f.label :path, class: 'control-label' do + %span Path + .col-sm-9 + .form-group + .input-group + = f.text_field :path, class: 'form-control' + %span.input-group-addon .git + %ul + %li Be careful. Renaming a project's repository can have unintended side effects. + %li You will need to update your local repositories to point to the new location. + .form-actions + = f.submit 'Rename', class: "btn btn-warning" + - if can?(current_user, :change_namespace, @project) .panel.panel-default.panel.panel-danger .panel-heading Transfer project @@ -157,25 +176,6 @@ - else .nothing-here-block Only the project owner can transfer a project - .panel.panel-default.panel.panel-danger - .panel-heading Rename repository - .errors-holder - .panel-body - = form_for(@project, html: { class: 'form-horizontal' }) do |f| - .form-group - = f.label :path, class: 'control-label' do - %span Path - .col-sm-9 - .form-group - .input-group - = f.text_field :path, class: 'form-control' - %span.input-group-addon .git - %ul - %li Be careful. Renaming a project's repository can have unintended side effects. - %li You will need to update your local repositories to point to the new location. - .form-actions - = f.submit 'Rename', class: "btn btn-remove" - - if can?(current_user, :remove_project, @project) .panel.panel-default.panel.panel-danger .panel-heading Remove project From e53f4a4ea541f3f7fd845fe395662ab86d196d55 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sat, 31 May 2014 14:24:04 +0300 Subject: [PATCH 155/360] Use same color vars for primary/warning styles Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/generic/buttons.scss | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/app/assets/stylesheets/generic/buttons.scss b/app/assets/stylesheets/generic/buttons.scss index 1c74bd2de0..a9849aa487 100644 --- a/app/assets/stylesheets/generic/buttons.scss +++ b/app/assets/stylesheets/generic/buttons.scss @@ -59,8 +59,8 @@ &.btn-primary { color: #ffffff; - background-color: #429bca; - border-color: #358ebd; + background-color: $bg_primary; + border-color: $border_primary; &.hover, &:hover, @@ -74,8 +74,8 @@ &.btn-success { color: #ffffff; - background-color: #5cb85c; - border-color: #4cae4c; + background-color: $bg_success; + border-color: $border_success; &.hover, @@ -90,8 +90,8 @@ &.btn-danger { color: #ffffff; - background-color: #d9534f; - border-color: #d43f3a; + background-color: $bg_danger; + border-color: $border_danger; &.hover, From 5d6f5be0603e51514705976e35c2a6f2fff74c84 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sat, 31 May 2014 14:48:33 +0300 Subject: [PATCH 156/360] New colors for success/warning/primary Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/gl_bootstrap.scss | 4 ++-- app/assets/stylesheets/main/variables.scss | 18 ++++++------------ 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/app/assets/stylesheets/gl_bootstrap.scss b/app/assets/stylesheets/gl_bootstrap.scss index 874c4f5b76..3312c762ed 100644 --- a/app/assets/stylesheets/gl_bootstrap.scss +++ b/app/assets/stylesheets/gl_bootstrap.scss @@ -7,8 +7,8 @@ */ $font-size-base: 13px !default; -$nav-pills-active-link-hover-bg: $bg_style_color; -$pagination-active-bg: $bg_style_color; +$nav-pills-active-link-hover-bg: $bg_primary; +$pagination-active-bg: $bg_primary; // Core variables and mixins @import "bootstrap/variables"; diff --git a/app/assets/stylesheets/main/variables.scss b/app/assets/stylesheets/main/variables.scss index ddfcdef836..6ea6a8303f 100644 --- a/app/assets/stylesheets/main/variables.scss +++ b/app/assets/stylesheets/main/variables.scss @@ -11,32 +11,26 @@ $hover: #D9EDF7; /* * Success colors (green) */ -$border_success: #4cae4c; -$bg_success: #5cb85c; -$bg_light_success: #dff0d8; -$color_success: #3c763d; +$border_success: #469408; +$bg_success: #469408; /* * Danger colors (red) */ $border_danger: #d43f3a; $bg_danger: #d9534f; -$bg_light_danger: #f2dede; -$color_danger: #a94442; /* * Primary colors (blue) */ -$border_primary: #358ebd; -$bg_primary: #429bca; -$bg_light_primary: #d9edf7; -$color_primary: #31708f; +$border_primary: #446e9b; +$bg_primary: #446e9b; /* * Warning colors (yellow) */ -$bg_warning: #f39c12; -$border_warning: #f39c12; +$bg_warning: #d9831f; +$border_warning: #d9831f; /** * Commit Diff Colors From 94b0f1b2bb691928ce0db0fba2ccfe02d1a5d11e Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sat, 31 May 2014 15:57:22 +0300 Subject: [PATCH 157/360] Bump gitlab-shell version Signed-off-by: Dmitriy Zaporozhets --- doc/install/installation.md | 2 +- lib/tasks/gitlab/check.rake | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/install/installation.md b/doc/install/installation.md index 9973113062..0dc28d8da8 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -254,7 +254,7 @@ GitLab Shell is an ssh access and repository management software developed speci cd /home/git/gitlab # Run the installation task for gitlab-shell (replace `REDIS_URL` if needed): - sudo -u git -H bundle exec rake gitlab:shell:install[v1.9.4] REDIS_URL=redis://localhost:6379 RAILS_ENV=production + sudo -u git -H bundle exec rake gitlab:shell:install[v1.9.5] REDIS_URL=redis://localhost:6379 RAILS_ENV=production # By default, the gitlab-shell config is generated from your main gitlab config. You can review (and modify) it as follows: sudo -u git -H editor /home/git/gitlab-shell/config.yml diff --git a/lib/tasks/gitlab/check.rake b/lib/tasks/gitlab/check.rake index 8a7f39599a..362693b060 100644 --- a/lib/tasks/gitlab/check.rake +++ b/lib/tasks/gitlab/check.rake @@ -779,7 +779,7 @@ namespace :gitlab do end def check_gitlab_shell - required_version = Gitlab::VersionInfo.new(1, 9, 4) + required_version = Gitlab::VersionInfo.new(1, 9, 5) current_version = Gitlab::VersionInfo.parse(gitlab_shell_version) print "GitLab Shell version >= #{required_version} ? ... " From 379299ad18c28bb8b6f0ea52c5086193bb1d0e96 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Mon, 2 Jun 2014 09:39:43 +0200 Subject: [PATCH 158/360] Add bash one liner in updater doc due to change of updater location. --- doc/update/upgrader.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/update/upgrader.md b/doc/update/upgrader.md index b3947fa2de..c8cfd4f92b 100644 --- a/doc/update/upgrader.md +++ b/doc/update/upgrader.md @@ -18,11 +18,12 @@ __GitLab Upgrader is available only for GitLab version 6.4.2 or higher__ ### 2. Run gitlab upgrade tool + # Starting with GitLab version 7.0 upgrader script has been moved to bin directory cd /home/git/gitlab - sudo -u git -H ruby bin/upgrade.rb + if [ -f bin/upgrade.rb ]; then sudo -u git -H ruby bin/upgrade.rb; else sudo -u git -H ruby script/upgrade.rb; fi # to perform a non-interactive install (no user input required) you can add -y - # sudo -u git -H ruby bin/upgrade.rb -y + # if [ -f bin/upgrade.rb ]; then sudo -u git -H ruby bin/upgrade.rb -y; else sudo -u git -H ruby script/upgrade.rb -y; fi ### 3. Start application From c8460c4731fe73cf3ca4cb45d098f21636c71df3 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Mon, 2 Jun 2014 09:48:55 +0200 Subject: [PATCH 159/360] Update the one-liner. --- doc/update/upgrader.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/update/upgrader.md b/doc/update/upgrader.md index c8cfd4f92b..19faca4ec4 100644 --- a/doc/update/upgrader.md +++ b/doc/update/upgrader.md @@ -56,6 +56,8 @@ Here is a one line command with step 1 to 4 for the next time you upgrade: ```bash cd /home/git/gitlab; sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production; \ - sudo service gitlab stop; sudo -u git -H ruby bin/upgrade.rb -y; sudo service gitlab start; \ + sudo service gitlab stop; \ + if [ -f bin/upgrade.rb ]; then sudo -u git -H ruby bin/upgrade.rb -y; else sudo -u git -H ruby script/upgrade.rb -y; fi; \ + sudo service gitlab start; \ sudo service nginx restart; sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production ``` From e9de569458b55b43a0d09dceef07c3c5d583af24 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 2 Jun 2014 13:43:07 +0300 Subject: [PATCH 160/360] Fix tests for user page Signed-off-by: Dmitriy Zaporozhets --- app/controllers/users_controller.rb | 2 +- app/models/user.rb | 4 ++++ features/steps/shared/project.rb | 12 ++++++------ features/user.feature | 22 +++++++++++----------- 4 files changed, 22 insertions(+), 18 deletions(-) diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 2d227ae201..d42c2db9e5 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -6,7 +6,7 @@ class UsersController < ApplicationController @user = User.find_by_username!(params[:username]) @projects = Project.personal(@user).accessible_to(current_user) - if !current_user && @projects.empty? + unless current_user || @user.public_profile? return authenticate_user! end diff --git a/app/models/user.rb b/app/models/user.rb index f1b6139745..0fbc9284dd 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -478,4 +478,8 @@ class User < ActiveRecord::Base def generate_tmp_oauth_email self.email = "temp-email-for-oauth-#{username}@gitlab.localhost" end + + def public_profile? + authorized_projects.public_only.any? + end end diff --git a/features/steps/shared/project.rb b/features/steps/shared/project.rb index f8cb753b78..40362fee0b 100644 --- a/features/steps/shared/project.rb +++ b/features/steps/shared/project.rb @@ -102,24 +102,24 @@ module SharedProject page.should_not have_content "Community" end - step '"John Doe" is authorized to private project "Enterprise"' do + step '"John Doe" owns private project "Enterprise"' do user = user_exists("John Doe", username: "john_doe") project = Project.find_by(name: "Enterprise") - project ||= create(:project, name: "Enterprise", namespace: user.namespace) + project ||= create(:empty_project, name: "Enterprise", namespace: user.namespace) project.team << [user, :master] end - step '"John Doe" is authorized to internal project "Internal"' do + step '"John Doe" owns internal project "Internal"' do user = user_exists("John Doe", username: "john_doe") project = Project.find_by(name: "Internal") - project ||= create :project, :internal, name: 'Internal' + project ||= create :empty_project, :internal, name: 'Internal', namespace: user.namespace project.team << [user, :master] end - step '"John Doe" is authorized to public project "Community"' do + step '"John Doe" owns public project "Community"' do user = user_exists("John Doe", username: "john_doe") project = Project.find_by(name: "Community") - project ||= create :project, :public, name: 'Community' + project ||= create :empty_project, :public, name: 'Community', namespace: user.namespace project.team << [user, :master] end end diff --git a/features/user.feature b/features/user.feature index d4198c08de..a2167935fd 100644 --- a/features/user.feature +++ b/features/user.feature @@ -1,13 +1,13 @@ Feature: User Background: Given User "John Doe" exists - And "John Doe" is authorized to private project "Enterprise" + And "John Doe" owns private project "Enterprise" # Signed out - Scenario: I visit user "John Doe" page while not signed in when he is authorized to a public project - Given "John Doe" is authorized to internal project "Internal" - And "John Doe" is authorized to public project "Community" + Scenario: I visit user "John Doe" page while not signed in when he owns a public project + Given "John Doe" owns internal project "Internal" + And "John Doe" owns public project "Community" When I visit user "John Doe" page Then I should see user "John Doe" page And I should not see project "Enterprise" @@ -15,15 +15,15 @@ Feature: User And I should see project "Community" Scenario: I visit user "John Doe" page while not signed in when he is not authorized to a public project - Given "John Doe" is authorized to internal project "Internal" + Given "John Doe" owns internal project "Internal" When I visit user "John Doe" page Then I should be redirected to sign in page # Signed in as someone else - Scenario: I visit user "John Doe" page while signed in as someone else when he is authorized to a public project - Given "John Doe" is authorized to public project "Community" - And "John Doe" is authorized to internal project "Internal" + Scenario: I visit user "John Doe" page while signed in as someone else when he owns a public project + Given "John Doe" owns public project "Community" + And "John Doe" owns internal project "Internal" And I sign in as a user When I visit user "John Doe" page Then I should see user "John Doe" page @@ -32,7 +32,7 @@ Feature: User And I should see project "Community" Scenario: I visit user "John Doe" page while signed in as someone else when he is not authorized to a public project - Given "John Doe" is authorized to internal project "Internal" + Given "John Doe" owns internal project "Internal" And I sign in as a user When I visit user "John Doe" page Then I should see user "John Doe" page @@ -51,8 +51,8 @@ Feature: User # Signed in as the user himself Scenario: I visit user "John Doe" page while signed in as "John Doe" when he has a public project - Given "John Doe" is authorized to internal project "Internal" - And "John Doe" is authorized to public project "Community" + Given "John Doe" owns internal project "Internal" + And "John Doe" owns public project "Community" And I sign in as "John Doe" When I visit user "John Doe" page Then I should see user "John Doe" page From 6854be80a85ae8bc8203a3ae768e2bab7d5daa34 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 2 Jun 2014 14:12:46 +0300 Subject: [PATCH 161/360] Refactor scss variables. Use darker color for links Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/generic/typography.scss | 2 +- app/assets/stylesheets/gl_bootstrap.scss | 1 + app/assets/stylesheets/main/variables.scss | 11 +++++++---- app/assets/stylesheets/sections/nav.scss | 2 +- app/assets/stylesheets/sections/notes.scss | 4 ++-- app/assets/stylesheets/sections/tree.scss | 2 +- 6 files changed, 13 insertions(+), 9 deletions(-) diff --git a/app/assets/stylesheets/generic/typography.scss b/app/assets/stylesheets/generic/typography.scss index 8cc72d7f07..412c25f438 100644 --- a/app/assets/stylesheets/generic/typography.scss +++ b/app/assets/stylesheets/generic/typography.scss @@ -40,7 +40,7 @@ a { color: $link_color; &:hover { text-decoration: none; - color: $primary_color; + color: $link_hover_colory; } &:focus { diff --git a/app/assets/stylesheets/gl_bootstrap.scss b/app/assets/stylesheets/gl_bootstrap.scss index 3312c762ed..3bff2156c3 100644 --- a/app/assets/stylesheets/gl_bootstrap.scss +++ b/app/assets/stylesheets/gl_bootstrap.scss @@ -9,6 +9,7 @@ $font-size-base: 13px !default; $nav-pills-active-link-hover-bg: $bg_primary; $pagination-active-bg: $bg_primary; +$list-group-active-bg: $bg_style_color; // Core variables and mixins @import "bootstrap/variables"; diff --git a/app/assets/stylesheets/main/variables.scss b/app/assets/stylesheets/main/variables.scss index 6ea6a8303f..8bcdad3579 100644 --- a/app/assets/stylesheets/main/variables.scss +++ b/app/assets/stylesheets/main/variables.scss @@ -1,13 +1,16 @@ -/** +/* * General Colors */ -$primary_color: #2FA0BB; -$link_color: #3A89A3; $style_color: #474D57; $bg_style_color: #2299BB; -$list-group-active-bg: $bg_style_color; $hover: #D9EDF7; +/* + * Link colors + */ +$link_color: #446e9b; +$link_hover_color: #2FA0BB; + /* * Success colors (green) */ diff --git a/app/assets/stylesheets/sections/nav.scss b/app/assets/stylesheets/sections/nav.scss index 88f16a2159..69a97cac01 100644 --- a/app/assets/stylesheets/sections/nav.scss +++ b/app/assets/stylesheets/sections/nav.scss @@ -116,7 +116,7 @@ padding: 5px 0; &.active { - background-color: $primary_color; + background-color: $link_hover_colory; a { color: #fff; diff --git a/app/assets/stylesheets/sections/notes.scss b/app/assets/stylesheets/sections/notes.scss index 2758f57bd5..ca16076644 100644 --- a/app/assets/stylesheets/sections/notes.scss +++ b/app/assets/stylesheets/sections/notes.scss @@ -37,7 +37,7 @@ ul.notes { font-weight: bold; font-size: 14px; &:hover { - color: $primary_color; + color: $link_hover_colory; } } } @@ -172,7 +172,7 @@ ul.notes { @extend .cgray; &:hover { - color: $primary_color; + color: $link_hover_colory; &.danger { @extend .cred; } } } diff --git a/app/assets/stylesheets/sections/tree.scss b/app/assets/stylesheets/sections/tree.scss index 86e2a51641..fa9456d745 100644 --- a/app/assets/stylesheets/sections/tree.scss +++ b/app/assets/stylesheets/sections/tree.scss @@ -53,7 +53,7 @@ vertical-align: middle; a { &:hover { - color: $primary_color; + color: $link_hover_colory; } } From 33ff53d91560f15f80347c4f5774ba8b9791f133 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 2 Jun 2014 14:13:35 +0300 Subject: [PATCH 162/360] Fix syntax error Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/generic/typography.scss | 2 +- app/assets/stylesheets/sections/nav.scss | 2 +- app/assets/stylesheets/sections/notes.scss | 4 ++-- app/assets/stylesheets/sections/tree.scss | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/assets/stylesheets/generic/typography.scss b/app/assets/stylesheets/generic/typography.scss index 412c25f438..4ab83786b5 100644 --- a/app/assets/stylesheets/generic/typography.scss +++ b/app/assets/stylesheets/generic/typography.scss @@ -40,7 +40,7 @@ a { color: $link_color; &:hover { text-decoration: none; - color: $link_hover_colory; + color: $link_hover_color; } &:focus { diff --git a/app/assets/stylesheets/sections/nav.scss b/app/assets/stylesheets/sections/nav.scss index 69a97cac01..c82da5fce3 100644 --- a/app/assets/stylesheets/sections/nav.scss +++ b/app/assets/stylesheets/sections/nav.scss @@ -116,7 +116,7 @@ padding: 5px 0; &.active { - background-color: $link_hover_colory; + background-color: $link_hover_color; a { color: #fff; diff --git a/app/assets/stylesheets/sections/notes.scss b/app/assets/stylesheets/sections/notes.scss index ca16076644..e8d6ec3e29 100644 --- a/app/assets/stylesheets/sections/notes.scss +++ b/app/assets/stylesheets/sections/notes.scss @@ -37,7 +37,7 @@ ul.notes { font-weight: bold; font-size: 14px; &:hover { - color: $link_hover_colory; + color: $link_hover_color; } } } @@ -172,7 +172,7 @@ ul.notes { @extend .cgray; &:hover { - color: $link_hover_colory; + color: $link_hover_color; &.danger { @extend .cred; } } } diff --git a/app/assets/stylesheets/sections/tree.scss b/app/assets/stylesheets/sections/tree.scss index fa9456d745..db177a0083 100644 --- a/app/assets/stylesheets/sections/tree.scss +++ b/app/assets/stylesheets/sections/tree.scss @@ -53,7 +53,7 @@ vertical-align: middle; a { &:hover { - color: $link_hover_colory; + color: $link_hover_color; } } From 133d231f87fdeb4a920051833750d4865b492b39 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 2 Jun 2014 14:21:12 +0300 Subject: [PATCH 163/360] Use link_color var more often Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/generic/common.scss | 2 +- app/assets/stylesheets/sections/nav.scss | 2 +- app/assets/stylesheets/sections/projects.scss | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/assets/stylesheets/generic/common.scss b/app/assets/stylesheets/generic/common.scss index 6ab6458ea0..0cb2090f53 100644 --- a/app/assets/stylesheets/generic/common.scss +++ b/app/assets/stylesheets/generic/common.scss @@ -60,7 +60,7 @@ pre { .dropdown-menu > li > a:hover, .dropdown-menu > li > a:focus { - background: #29b; + background: $bg_style_color; color: #FFF } diff --git a/app/assets/stylesheets/sections/nav.scss b/app/assets/stylesheets/sections/nav.scss index c82da5fce3..59eaaec949 100644 --- a/app/assets/stylesheets/sections/nav.scss +++ b/app/assets/stylesheets/sections/nav.scss @@ -64,7 +64,7 @@ left: 50%; width: 0; height: 0; - border-color: transparent transparent #29b transparent; + border-color: transparent transparent $link_color transparent; border-style: solid; border-width: 6px; margin-left: -6px; diff --git a/app/assets/stylesheets/sections/projects.scss b/app/assets/stylesheets/sections/projects.scss index 5757858a1c..949d646afc 100644 --- a/app/assets/stylesheets/sections/projects.scss +++ b/app/assets/stylesheets/sections/projects.scss @@ -85,7 +85,7 @@ .btn { background: none; - color: #29b; + color: $link_color; &.active { color: #333; From d514833a1579d50070fc687acc2af4f135b25a56 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 2 Jun 2014 16:18:16 +0300 Subject: [PATCH 164/360] Dont show new file link on protected branch for developers Signed-off-by: Dmitriy Zaporozhets --- app/helpers/branches_helper.rb | 25 ++++++++++++++++++------- app/views/projects/tree/_tree.html.haml | 2 +- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/app/helpers/branches_helper.rb b/app/helpers/branches_helper.rb index e08ffccb94..2ec2cc9615 100644 --- a/app/helpers/branches_helper.rb +++ b/app/helpers/branches_helper.rb @@ -1,11 +1,22 @@ module BranchesHelper def can_remove_branch?(project, branch_name) - if project.protected_branch? branch_name - false - elsif branch_name == project.repository.root_ref - false - else - can?(current_user, :push_code, project) - end + if project.protected_branch? branch_name + false + elsif branch_name == project.repository.root_ref + false + else + can?(current_user, :push_code, project) + end + end + + def can_push_branch?(project, branch_name) + return false unless project.repository.branch_names.include?(branch_name) + action = if project.protected_branch?(branch_name) + :push_code_to_protected_branches + else + :push_code + end + + current_user.can?(action, project) end end diff --git a/app/views/projects/tree/_tree.html.haml b/app/views/projects/tree/_tree.html.haml index ee850e2bc1..1fc06928bc 100644 --- a/app/views/projects/tree/_tree.html.haml +++ b/app/views/projects/tree/_tree.html.haml @@ -9,7 +9,7 @@ = link_to truncate(title, length: 40), project_tree_path(@project, path) - else = link_to title, '#' - - if current_user && @repository.branch_names.include?(@ref) && current_user.can?(:push_code, @project) + - if current_user && can_push_branch?(@project, @ref) %li = link_to project_new_tree_path(@project, @id), title: 'New file', id: 'new-file-link' do %small From 9a4c8f7e41eaec63d98431f5ff776240e2dc7604 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 2 Jun 2014 18:58:00 +0300 Subject: [PATCH 165/360] Improve admin group page performance Add pagination for projects and members to /admin/groups/:group page Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/gl_bootstrap.scss | 6 ++++++ app/controllers/admin/groups_controller.rb | 2 ++ app/views/admin/groups/show.html.haml | 23 +++++++++++++--------- 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/app/assets/stylesheets/gl_bootstrap.scss b/app/assets/stylesheets/gl_bootstrap.scss index 3bff2156c3..514ab8cdfa 100644 --- a/app/assets/stylesheets/gl_bootstrap.scss +++ b/app/assets/stylesheets/gl_bootstrap.scss @@ -253,6 +253,12 @@ ul.breadcrumb { } } + .panel-footer { + .pagination { + margin: 0; + } + } + &.panel-small { .panel-heading { padding: 6px 15px; diff --git a/app/controllers/admin/groups_controller.rb b/app/controllers/admin/groups_controller.rb index 4bb3cf07da..1a523d081d 100644 --- a/app/controllers/admin/groups_controller.rb +++ b/app/controllers/admin/groups_controller.rb @@ -8,6 +8,8 @@ class Admin::GroupsController < Admin::ApplicationController end def show + @members = @group.members.order("group_access DESC").page(params[:members_page]).per(30) + @projects = @group.projects.page(params[:projects_page]).per(30) end def new diff --git a/app/views/admin/groups/show.html.haml b/app/views/admin/groups/show.html.haml index 183203aac7..b8068886be 100644 --- a/app/views/admin/groups/show.html.haml +++ b/app/views/admin/groups/show.html.haml @@ -31,11 +31,12 @@ .panel.panel-default .panel-heading - Projects - %small - (#{@group.projects.count}) + %h3.panel-title + Projects + %span.badge + #{@group.projects.count} %ul.well-list - - @group.projects.sort_by(&:name).each do |project| + - @projects.each do |project| %li %strong = link_to project.name_with_namespace, [:admin, project] @@ -43,6 +44,8 @@ = repository_size(project) %span.pull-right.light %span.monospace= project.path_with_namespace + ".git" + .panel-footer + = paginate @projects, param_name: 'projects_page', theme: 'gitlab' .col-md-6 .panel.panel-default @@ -62,12 +65,12 @@ = submit_tag 'Add users into group', class: "btn btn-create" .panel.panel-default .panel-heading - %strong #{@group.name} - Group Members - %small - (#{@group.users_groups.count}) + %h3.panel-title + Members + %span.badge + #{@group.users_groups.count} %ul.well-list.group-users-list - - @group.users_groups.order('group_access DESC').each do |member| + - @members.each do |member| - user = member.user %li{class: dom_class(user)} .list-item-name @@ -77,3 +80,5 @@ = member.human_access = link_to group_users_group_path(@group, member), data: { confirm: remove_user_from_group_message(@group, user) }, method: :delete, remote: true, class: "btn-tiny btn btn-remove", title: 'Remove user from group' do %i.icon-minus.icon-white + .panel-footer + = paginate @members, param_name: 'members_page', theme: 'gitlab' From 144212fba27b688d0e3a12ea6092c4f4c7b89da9 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 2 Jun 2014 19:31:43 +0300 Subject: [PATCH 166/360] Add members paginations to admin/project page Signed-off-by: Dmitriy Zaporozhets --- app/controllers/admin/projects_controller.rb | 2 ++ app/views/admin/projects/show.html.haml | 8 ++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/app/controllers/admin/projects_controller.rb b/app/controllers/admin/projects_controller.rb index 92ef596337..097d208f31 100644 --- a/app/controllers/admin/projects_controller.rb +++ b/app/controllers/admin/projects_controller.rb @@ -17,6 +17,8 @@ class Admin::ProjectsController < Admin::ApplicationController end def show + @group_members = @group.members.order("group_access DESC").page(params[:group_members_page]).per(30) + @project_members = @project.users_projects.page(params[:project_members_page]).per(30) end def transfer diff --git a/app/views/admin/projects/show.html.haml b/app/views/admin/projects/show.html.haml index 3f25eb7fdb..66a72449f4 100644 --- a/app/views/admin/projects/show.html.haml +++ b/app/views/admin/projects/show.html.haml @@ -100,8 +100,10 @@ = link_to admin_group_path(@group), class: 'btn btn-small' do %i.icon-edit %ul.well-list - - @group.users_groups.order('group_access DESC').each do |member| + - @group_members.each do |member| = render 'users_groups/users_group', member: member, show_controls: false + .panel-footer + = paginate @group_members, param_name: 'group_members_page', theme: 'gitlab' .panel.panel-default .panel-heading @@ -113,7 +115,7 @@ %i.icon-edit Manage Access %ul.well-list.team_members - - @project.users_projects.each do |users_project| + - @project_members.each do |users_project| - user = users_project.user %li.users_project .list-item-name @@ -126,3 +128,5 @@ %span.light= users_project.human_access = link_to project_team_member_path(@project, user), data: { confirm: remove_from_project_team_message(@project, user)}, method: :delete, remote: true, class: "btn btn-small btn-remove" do %i.icon-remove + .panel-footer + = paginate @project_members, param_name: 'project_members_page', theme: 'gitlab' From 3410aaf950bb8a36415c9246195709b652d1d75c Mon Sep 17 00:00:00 2001 From: William Herry Date: Tue, 3 Jun 2014 01:05:07 +0800 Subject: [PATCH 167/360] add smtp_settings.rb to gitignore file --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index d151849b71..92ca729dc1 100644 --- a/.gitignore +++ b/.gitignore @@ -21,6 +21,7 @@ config/gitlab.yml config/database.yml config/initializers/omniauth.rb config/initializers/rack_attack.rb +config/initializers/smtp_settings.rb config/unicorn.rb config/resque.yml config/aws.yml From 5a064b0249922c4d82fb44ae9f3bcf230a3cbbd0 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 2 Jun 2014 21:25:01 +0300 Subject: [PATCH 168/360] Get group members only if group not nil Signed-off-by: Dmitriy Zaporozhets --- app/controllers/admin/projects_controller.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/controllers/admin/projects_controller.rb b/app/controllers/admin/projects_controller.rb index 097d208f31..8c1f45ac01 100644 --- a/app/controllers/admin/projects_controller.rb +++ b/app/controllers/admin/projects_controller.rb @@ -17,7 +17,10 @@ class Admin::ProjectsController < Admin::ApplicationController end def show - @group_members = @group.members.order("group_access DESC").page(params[:group_members_page]).per(30) + if @group + @group_members = @group.members.order("group_access DESC").page(params[:group_members_page]).per(30) + end + @project_members = @project.users_projects.page(params[:project_members_page]).per(30) end From 636718adf00e71bfd3a2bf96df86c1b3b0c931bc Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 3 Jun 2014 10:01:15 +0300 Subject: [PATCH 169/360] Use padding like most of other bootstrap elements Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/generic/lists.scss | 2 +- app/assets/stylesheets/sections/dashboard.scss | 3 +-- app/assets/stylesheets/sections/issues.scss | 4 ++-- app/assets/stylesheets/sections/merge_requests.scss | 2 +- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/app/assets/stylesheets/generic/lists.scss b/app/assets/stylesheets/generic/lists.scss index 2e3559f3c8..0cab6c44c9 100644 --- a/app/assets/stylesheets/generic/lists.scss +++ b/app/assets/stylesheets/generic/lists.scss @@ -8,7 +8,7 @@ list-style: none; li { - padding: 10px; + padding: 10px 15px; min-height: 20px; border-bottom: 1px solid #eee; border-bottom: 1px solid rgba(0, 0, 0, 0.05); diff --git a/app/assets/stylesheets/sections/dashboard.scss b/app/assets/stylesheets/sections/dashboard.scss index 0ec21ff50f..abc9e57f2a 100644 --- a/app/assets/stylesheets/sections/dashboard.scss +++ b/app/assets/stylesheets/sections/dashboard.scss @@ -60,7 +60,7 @@ } .project-row, .group-row { - padding: 8px 12px !important; + padding: 8px 15px !important; font-size: 14px; line-height: 24px; @@ -74,7 +74,6 @@ .arrow { float: right; - padding: 0px 5px; margin: 0; font-size: 20px; color: #666; diff --git a/app/assets/stylesheets/sections/issues.scss b/app/assets/stylesheets/sections/issues.scss index 02c9123178..949c528bdb 100644 --- a/app/assets/stylesheets/sections/issues.scss +++ b/app/assets/stylesheets/sections/issues.scss @@ -1,6 +1,6 @@ .issues-list { .issue { - padding: 10px; + padding: 10px 15px; position: relative; .issue-title { @@ -42,7 +42,7 @@ height: 32px; float: left; margin-right: 12px; - padding: 6px 10px; + padding: 6px 15px; border: 1px solid #ccc; @include border-radius(4px); } diff --git a/app/assets/stylesheets/sections/merge_requests.scss b/app/assets/stylesheets/sections/merge_requests.scss index 5d716ddec3..7255b3ab23 100644 --- a/app/assets/stylesheets/sections/merge_requests.scss +++ b/app/assets/stylesheets/sections/merge_requests.scss @@ -70,7 +70,7 @@ .mr-list { .merge-request { - padding: 10px; + padding: 10px 15px; position: relative; .merge-request-title { From 7bb0551fd9f703674f2126ca316d8a097ef9d1ed Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 3 Jun 2014 10:04:31 +0300 Subject: [PATCH 170/360] Improve small panels Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/gl_bootstrap.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/assets/stylesheets/gl_bootstrap.scss b/app/assets/stylesheets/gl_bootstrap.scss index 514ab8cdfa..8ab305695f 100644 --- a/app/assets/stylesheets/gl_bootstrap.scss +++ b/app/assets/stylesheets/gl_bootstrap.scss @@ -262,6 +262,10 @@ ul.breadcrumb { &.panel-small { .panel-heading { padding: 6px 15px; + font-size: 13px; + a { + color: #777; + } } } } From 87e0fe6f76fa8829abb99dd90a8af65ed11bc3a3 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 3 Jun 2014 10:27:50 +0300 Subject: [PATCH 171/360] Use big colorful pills for switch between MR tabs Signed-off-by: Dmitriy Zaporozhets --- .../stylesheets/sections/merge_requests.scss | 14 +++++--------- app/views/projects/merge_requests/_show.html.haml | 2 +- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/app/assets/stylesheets/sections/merge_requests.scss b/app/assets/stylesheets/sections/merge_requests.scss index 7255b3ab23..c1eaae82e5 100644 --- a/app/assets/stylesheets/sections/merge_requests.scss +++ b/app/assets/stylesheets/sections/merge_requests.scss @@ -20,18 +20,14 @@ } .merge-request .merge-request-tabs{ - border-color: #AAA; + border-bottom: 2px solid $border_primary; + padding-bottom: 10px; + margin-bottom: 20px; + li { a { - border-color: #AAA; - padding: 14px 40px; + padding: 20px 40px; font-size: 14px; - background-color: #F9F9F9; - } - &.active a { - border-color: #AAA; - border-bottom-color: #FFF; - background-color: #FFF; } } } diff --git a/app/views/projects/merge_requests/_show.html.haml b/app/views/projects/merge_requests/_show.html.haml index 38a0ed567f..1072728af2 100644 --- a/app/views/projects/merge_requests/_show.html.haml +++ b/app/views/projects/merge_requests/_show.html.haml @@ -7,7 +7,7 @@ = render "projects/merge_requests/show/participants" - if @commits.present? - %ul.nav.nav-tabs.merge-request-tabs + %ul.nav.nav-pills.merge-request-tabs %li.notes-tab{data: {action: 'notes'}} = link_to project_merge_request_path(@project, @merge_request) do %i.icon-comment From 3398e0a3d7a1bed8efb7e700dee92f95173d8334 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 3 Jun 2014 10:56:40 +0300 Subject: [PATCH 172/360] Revert "Implements and refactors clipboard feature for markdown." This reverts commit 2273234653924b731f9ef01432e392481ee1d4e2. Signed-off-by: Dmitriy Zaporozhets Conflicts: app/views/projects/issues/_form.html.haml app/views/projects/merge_requests/_form.html.haml app/views/projects/merge_requests/_new_submit.html.haml app/views/projects/milestones/_form.html.haml app/views/projects/notes/_form.html.haml app/views/projects/wikis/_form.html.haml --- .../javascripts/markdown_area.js.coffee | 120 +++--------------- .../stylesheets/generic/markdown_area.scss | 5 - app/controllers/projects_controller.rb | 6 - app/views/projects/issues/_form.html.haml | 2 +- .../projects/merge_requests/_form.html.haml | 2 +- .../merge_requests/_new_submit.html.haml | 4 +- app/views/projects/milestones/_form.html.haml | 2 +- app/views/projects/notes/_form.html.haml | 6 +- app/views/projects/wikis/_form.html.haml | 4 +- 9 files changed, 25 insertions(+), 126 deletions(-) diff --git a/app/assets/javascripts/markdown_area.js.coffee b/app/assets/javascripts/markdown_area.js.coffee index 67e8290bd5..def5d12a82 100644 --- a/app/assets/javascripts/markdown_area.js.coffee +++ b/app/assets/javascripts/markdown_area.js.coffee @@ -1,3 +1,6 @@ +formatLink = (str) -> + "![" + str.alt + "](" + str.url + ")" + $(document).ready -> alertClass = "alert alert-danger alert-dismissable div-dropzone-alert" alertAttr = "class=\"close\" data-dismiss=\"alert\"" + "aria-hidden=\"true\"" @@ -10,12 +13,15 @@ $(document).ready -> project_image_path_upload = window.project_image_path_upload or null $("textarea.markdown-area").wrap "
" + $(".div-dropzone").parent().addClass "div-dropzone-wrapper" + $(".div-dropzone").append divHover $(".div-dropzone-hover").append iconPicture $(".div-dropzone").append divSpinner $(".div-dropzone-spinner").append iconSpinner + dropzone = $(".div-dropzone").dropzone( url: project_image_path_upload dictDefaultMessage: "" @@ -30,7 +36,7 @@ $(document).ready -> previewContainer: false processing: -> - closeAlertMessage() + $(".div-dropzone-alert").alert "close" dragover: -> $(".div-dropzone > textarea").addClass "div-dropzone-focus" @@ -49,127 +55,31 @@ $(document).ready -> return success: (header, response) -> - appendToTextArea(formatLink(response.link)) + child = $(dropzone[0]).children("textarea") + $(child).val $(child).val() + formatLink(response.link) + "\n" return error: (temp, errorMessage) -> - showError(errorMessage) + checkIfMsgExists = $(".error-alert").children().length + if checkIfMsgExists is 0 + $(".error-alert").append divAlert + $(".div-dropzone-alert").append btnAlert + errorMessage return sending: -> - showSpinner() + $(".div-dropzone-spinner").css "opacity", 0.7 return complete: -> $(".dz-preview").remove() $(".markdown-area").trigger "input" - closeSpinner() + $(".div-dropzone-spinner").css "opacity", 0 return ) - child = $(dropzone[0]).children("textarea") - - formatLink = (str) -> - "![" + str.alt + "](" + str.url + ")" - - handlePaste = (e) -> - e.preventDefault() - my_event = e.originalEvent - - if my_event.clipboardData and my_event.clipboardData.items - i = 0 - while i < my_event.clipboardData.items.length - item = my_event.clipboardData.items[i] - processItem(my_event, item) - i++ - - processItem = (e, item) -> - if isImage(item) - filename = getFilename(e) or "image.png" - text = "{{" + filename + "}}" - pasteText(text) - uploadFile item.getAsFile(), filename - else if e.clipboardData.items.length == 1 - text = e.clipboardData.getData("text/plain") - pasteText(text) - - isImage = (item) -> - if item - item.type.indexOf("image") isnt -1 - - pasteText = (text) -> - caretStart = $(child)[0].selectionStart - caretEnd = $(child)[0].selectionEnd - textEnd = $(child).val().length - - beforeSelection = $(child).val().substring 0, caretStart - afterSelection = $(child).val().substring caretEnd, textEnd - $(child).val beforeSelection + text + afterSelection - $(".markdown-area").trigger "input" - - getFilename = (e) -> - if window.clipboardData and window.clipboardData.getData - value = window.clipboardData.getData("Text") - else if e.clipboardData and e.clipboardData.getData - value = e.clipboardData.getData("text/plain") - - value = value.split("\r") - value.first() - - uploadFile = (item, filename) -> - formData = new FormData() - formData.append "markdown_img", item, filename - $.ajax - url: project_image_path_upload - type: "POST" - data: formData - dataType: "json" - processData: false - contentType: false - headers: - "X-CSRF-Token": $("meta[name=\"csrf-token\"]").attr("content") - - beforeSend: -> - showSpinner() - closeAlertMessage() - - success: (e, textStatus, response) -> - insertToTextArea(filename, formatLink(response.responseJSON.link)) - - error: (response) -> - showError(response.responseJSON.message) - - complete: -> - closeSpinner() - - insertToTextArea = (filename, url) -> - $(child).val (index, val) -> - val.replace("{{" + filename + "}}", url + "\n") - - appendToTextArea = (url) -> - $(child).val (index, val) -> - val + url + "\n" - - showSpinner = (e) -> - $(".div-dropzone-spinner").css "opacity", 0.7 - - closeSpinner = -> - $(".div-dropzone-spinner").css "opacity", 0 - - showError = (message) -> - checkIfMsgExists = $(".error-alert").children().length - if checkIfMsgExists is 0 - $(".error-alert").append divAlert - $(".div-dropzone-alert").append btnAlert + message - - closeAlertMessage = -> - $(".div-dropzone-alert").alert "close" - $(".markdown-selector").click (e) -> e.preventDefault() $(".div-dropzone").click() return - $(".div-dropzone").on "paste", handlePaste - return \ No newline at end of file diff --git a/app/assets/stylesheets/generic/markdown_area.scss b/app/assets/stylesheets/generic/markdown_area.scss index ae7ace61d4..fbfa72c5e5 100644 --- a/app/assets/stylesheets/generic/markdown_area.scss +++ b/app/assets/stylesheets/generic/markdown_area.scss @@ -43,11 +43,6 @@ display: none; } } - - .hint { - padding: 0; - margin: 0; - } } .div-dropzone-alert { diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 6ea9b2cf27..b9af36a0c7 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -11,8 +11,6 @@ class ProjectsController < ApplicationController layout 'navless', only: [:new, :create, :fork] before_filter :set_title, only: [:new, :create] - rescue_from CarrierWave::IntegrityError, with: :invalid_file - def new @project = Project.new end @@ -187,10 +185,6 @@ class ProjectsController < ApplicationController %w(png jpg jpeg gif) end - def invalid_file(error) - render json: { message: error.message }, status: :internal_server_error - end - def set_title @title = 'New Project' end diff --git a/app/views/projects/issues/_form.html.haml b/app/views/projects/issues/_form.html.haml index 120d70eaa6..73cbb79665 100644 --- a/app/views/projects/issues/_form.html.haml +++ b/app/views/projects/issues/_form.html.haml @@ -23,7 +23,7 @@ = f.text_area :description, class: 'form-control js-gfm-input markdown-area', rows: 14 .col-sm-12.hint .pull-left Issues are parsed with #{link_to "GitLab Flavored Markdown", help_page_path("markdown", "markdown"), target: '_blank'}. - .pull-right Attach images (JPG, PNG, GIF) by dragging & dropping, #{link_to "selecting them", '#', class: 'markdown-selector' } or pasting from the clipboard. + .pull-right Attach images (JPG, PNG, GIF) by dragging & dropping or #{link_to "selecting them", '#', class: 'markdown-selector' }. .clearfix .error-alert %hr diff --git a/app/views/projects/merge_requests/_form.html.haml b/app/views/projects/merge_requests/_form.html.haml index 27ea53c006..b0e7aa6084 100644 --- a/app/views/projects/merge_requests/_form.html.haml +++ b/app/views/projects/merge_requests/_form.html.haml @@ -25,7 +25,7 @@ = f.text_area :description, class: "form-control js-gfm-input markdown-area", rows: 14 .col-sm-12.hint .pull-left Description is parsed with #{link_to "GitLab Flavored Markdown", help_page_path("markdown", "markdown"), target: '_blank'}. - .pull-right Attach images (JPG, PNG, GIF) by dragging & dropping, #{link_to "selecting them", '#', class: 'markdown-selector' } or pasting from the clipboard. + .pull-right Attach images (JPG, PNG, GIF) by dragging & dropping or #{link_to "selecting them", '#', class: 'markdown-selector' }. .clearfix .error-alert %hr diff --git a/app/views/projects/merge_requests/_new_submit.html.haml b/app/views/projects/merge_requests/_new_submit.html.haml index 553bc30ee0..01bc10421b 100644 --- a/app/views/projects/merge_requests/_new_submit.html.haml +++ b/app/views/projects/merge_requests/_new_submit.html.haml @@ -26,7 +26,7 @@ = f.text_area :description, class: "form-control js-gfm-input markdown-area", rows: 10 .col-sm-12.hint .pull-left Description is parsed with #{link_to "GitLab Flavored Markdown", help_page_path("markdown", "markdown"), target: '_blank'}. - .pull-right Attach images (JPG, PNG, GIF) by dragging & dropping, #{link_to "selecting them", '#', class: 'markdown-selector' } or pasting from the clipboard. + .pull-right Attach images (JPG, PNG, GIF) by dragging & dropping or #{link_to "selecting them", '#', class: 'markdown-selector' }. .clearfix .error-alert .form-group @@ -84,5 +84,5 @@ $('#merge_request_assignee_id').val("#{current_user.id}").trigger("change"); e.preventDefault(); }); - + window.project_image_path_upload = "#{upload_image_project_path @project}"; diff --git a/app/views/projects/milestones/_form.html.haml b/app/views/projects/milestones/_form.html.haml index 9f3e0c44b2..979c27daa2 100644 --- a/app/views/projects/milestones/_form.html.haml +++ b/app/views/projects/milestones/_form.html.haml @@ -24,7 +24,7 @@ = f.text_area :description, maxlength: 2000, class: "form-control markdown-area", rows: 10 .hint .pull-left Milestones are parsed with #{link_to "GitLab Flavored Markdown", help_page_path("markdown", "markdown"), target: '_blank'}. - .pull-left Attach images (JPG, PNG, GIF) by dragging & dropping, #{link_to "selecting them", '#', class: 'markdown-selector' } or pasting from the clipboard. + .pull-left Attach images (JPG, PNG, GIF) by dragging & dropping or #{link_to "selecting them", '#', class: 'markdown-selector' }. .clearfix .error-alert .col-md-6 diff --git a/app/views/projects/notes/_form.html.haml b/app/views/projects/notes/_form.html.haml index f6a21f7995..b62aada3a9 100644 --- a/app/views/projects/notes/_form.html.haml +++ b/app/views/projects/notes/_form.html.haml @@ -16,10 +16,10 @@ .note-write-holder = f.text_area :note, size: 255, class: 'note_text js-note-text js-gfm-input markdown-area' - .light.clearfix.hint + .light.clearfix .pull-left Comments are parsed with #{link_to "GitLab Flavored Markdown", help_page_path("markdown", "markdown"), target: '_blank'} - .pull-right Attach images (JPG, PNG, GIF) by dragging & dropping, #{link_to "selecting them", '#', class: 'markdown-selector' } or pasting from the clipboard. - .error-alert + .pull-right Attach images (JPG, PNG, GIF) by dragging & dropping or #{link_to "selecting them", '#', class: 'markdown-selector' }. + .note-preview-holder.hide .js-note-preview diff --git a/app/views/projects/wikis/_form.html.haml b/app/views/projects/wikis/_form.html.haml index a0a56b84a1..0a24e36ae8 100644 --- a/app/views/projects/wikis/_form.html.haml +++ b/app/views/projects/wikis/_form.html.haml @@ -25,7 +25,7 @@ = f.text_area :content, class: 'form-control js-gfm-input markdown-area', rows: 18 .col-sm-12.hint .pull-left Wiki content is parsed with #{link_to "GitLab Flavored Markdown", help_page_path("markdown", "markdown"), target: '_blank'} - .pull-right Attach images (JPG, PNG, GIF) by dragging & dropping, #{link_to "selecting them", '#', class: 'markdown-selector' } or pasting from the clipboard. + .pull-right Attach images (JPG, PNG, GIF) by dragging & dropping or #{link_to "selecting them", '#', class: 'markdown-selector' }. .clearfix .error-alert .form-group @@ -39,7 +39,7 @@ - else = f.submit 'Create page', class: "btn-create btn" = link_to "Cancel", project_wiki_path(@project, :home), class: "btn btn-cancel" - + :javascript window.project_image_path_upload = "#{upload_image_project_path @project}"; From d2851b088313cd4c343acb28d61bd517740932b6 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Tue, 3 Jun 2014 10:36:27 +0200 Subject: [PATCH 173/360] Do not show a 72 times. --- app/views/shared/_commit_message_container.html.haml | 1 - 1 file changed, 1 deletion(-) diff --git a/app/views/shared/_commit_message_container.html.haml b/app/views/shared/_commit_message_container.html.haml index cca7a0efc9..3be01478cb 100644 --- a/app/views/shared/_commit_message_container.html.haml +++ b/app/views/shared/_commit_message_container.html.haml @@ -1,5 +1,4 @@ .commit-message-container .max-width-marker -# When the `ch` CSS length unit becomes widely supported `http://www.quirksmode.org/css/units-values` remove this workaround. - = 'a' * 72 = textarea From 51d5e4cd6e109d2e0972f36b5f73d2af9966f827 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Thu, 29 May 2014 14:13:01 +0200 Subject: [PATCH 174/360] Bump to Rails 4.1. --- Gemfile | 4 +-- Gemfile.lock | 97 +++++++++++++++++++++++++++------------------------- 2 files changed, 53 insertions(+), 48 deletions(-) diff --git a/Gemfile b/Gemfile index c74d2f54c2..f3791e9598 100644 --- a/Gemfile +++ b/Gemfile @@ -8,7 +8,7 @@ def linux_only(require_as) RUBY_PLATFORM.include?('linux') && require_as end -gem "rails", "~> 4.0.0" +gem "rails", "~> 4.1.0" gem "protected_attributes" gem 'rails-observers' @@ -207,7 +207,7 @@ group :development, :test do gem 'factory_girl_rails' # Prevent occasions where minitest is not bundled in packaged versions of ruby (see #3826) - gem 'minitest', '~> 4.7.0' + gem 'minitest', '~> 5.3.0' # Generate Fake data gem "ffaker" diff --git a/Gemfile.lock b/Gemfile.lock index 7a72d3c3e8..60f1dd0a21 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -2,37 +2,39 @@ GEM remote: https://rubygems.org/ specs: ace-rails-ap (2.0.1) - actionmailer (4.0.5) - actionpack (= 4.0.5) + actionmailer (4.1.1) + actionpack (= 4.1.1) + actionview (= 4.1.1) mail (~> 2.5.4) - actionpack (4.0.5) - activesupport (= 4.0.5) - builder (~> 3.1.0) - erubis (~> 2.7.0) + actionpack (4.1.1) + actionview (= 4.1.1) + activesupport (= 4.1.1) rack (~> 1.5.2) rack-test (~> 0.6.2) - activemodel (4.0.5) - activesupport (= 4.0.5) - builder (~> 3.1.0) - activerecord (4.0.5) - activemodel (= 4.0.5) - activerecord-deprecated_finders (~> 1.0.2) - activesupport (= 4.0.5) - arel (~> 4.0.0) - activerecord-deprecated_finders (1.0.3) - activesupport (4.0.5) + actionview (4.1.1) + activesupport (= 4.1.1) + builder (~> 3.1) + erubis (~> 2.7.0) + activemodel (4.1.1) + activesupport (= 4.1.1) + builder (~> 3.1) + activerecord (4.1.1) + activemodel (= 4.1.1) + activesupport (= 4.1.1) + arel (~> 5.0.0) + activesupport (4.1.1) i18n (~> 0.6, >= 0.6.9) - minitest (~> 4.2) - multi_json (~> 1.3) + json (~> 1.7, >= 1.7.7) + minitest (~> 5.1) thread_safe (~> 0.1) - tzinfo (~> 0.3.37) + tzinfo (~> 1.1) acts-as-taggable-on (2.4.1) rails (>= 3, < 5) addressable (2.3.5) annotate (2.6.0) activerecord (>= 2.3.0) rake (>= 0.8.7) - arel (4.0.2) + arel (5.0.1.20140414130214) asciidoctor (0.1.4) awesome_print (1.2.0) axiom-types (0.0.5) @@ -46,7 +48,7 @@ GEM debug_inspector (>= 0.0.1) bootstrap-sass (3.0.3.0) sass (~> 3.2) - builder (3.1.4) + builder (3.2.2) capybara (2.2.1) mime-types (>= 1.16) nokogiri (>= 1.3.3) @@ -223,13 +225,13 @@ GEM guard-spinach (0.0.2) guard (>= 1.1) spinach - haml (4.0.4) + haml (4.0.5) tilt - haml-rails (0.5.1) - actionpack (~> 4.0.0) - activesupport (~> 4.0.0) + haml-rails (0.5.3) + actionpack (>= 4.0.1) + activesupport (>= 4.0.1) haml (>= 3.1, < 5.0) - railties (~> 4.0.0) + railties (>= 4.0.1) hashie (2.0.5) hike (1.2.3) hipchat (0.14.0) @@ -282,7 +284,7 @@ GEM method_source (0.8.2) mime-types (1.25.1) mini_portile (0.6.0) - minitest (4.7.5) + minitest (5.3.4) multi_json (1.10.1) multi_xml (0.5.5) multipart-post (1.2.0) @@ -355,14 +357,16 @@ GEM rack rack-test (0.6.2) rack (>= 1.0) - rails (4.0.5) - actionmailer (= 4.0.5) - actionpack (= 4.0.5) - activerecord (= 4.0.5) - activesupport (= 4.0.5) + rails (4.1.1) + actionmailer (= 4.1.1) + actionpack (= 4.1.1) + actionview (= 4.1.1) + activemodel (= 4.1.1) + activerecord (= 4.1.1) + activesupport (= 4.1.1) bundler (>= 1.3.0, < 2.0) - railties (= 4.0.5) - sprockets-rails (~> 2.0.0) + railties (= 4.1.1) + sprockets-rails (~> 2.0) rails-observers (0.1.2) activemodel (~> 4.0) rails_best_practices (1.14.4) @@ -374,13 +378,13 @@ GEM i18n require_all ruby-progressbar - railties (4.0.5) - actionpack (= 4.0.5) - activesupport (= 4.0.5) + railties (4.1.1) + actionpack (= 4.1.1) + activesupport (= 4.1.1) rake (>= 0.8.7) thor (>= 0.18.1, < 2.0) raindrops (0.12.0) - rake (10.3.1) + rake (10.3.2) raphael-rails (2.1.2) rb-fsevent (0.9.3) rb-inotify (0.9.2) @@ -443,9 +447,9 @@ GEM sdoc (0.3.20) json (>= 1.1.3) rdoc (~> 3.10) - seed-fu (2.3.0) - activerecord (>= 3.1, < 4.1) - activesupport (>= 3.1, < 4.1) + seed-fu (2.3.1) + activerecord (>= 3.1, < 4.2) + activesupport (>= 3.1, < 4.2) select2-rails (3.5.2) thor (~> 0.14) settingslogic (2.0.9) @@ -491,7 +495,7 @@ GEM multi_json (~> 1.0) rack (~> 1.0) tilt (~> 1.1, != 1.3.0) - sprockets-rails (2.0.1) + sprockets-rails (2.1.3) actionpack (>= 3.0) activesupport (>= 3.0) sprockets (~> 2.8) @@ -510,7 +514,7 @@ GEM eventmachine (>= 1.0.0) rack (>= 1.0.0) thor (0.19.1) - thread_safe (0.3.3) + thread_safe (0.3.4) tilt (1.4.1) timers (1.1.0) tinder (1.9.3) @@ -532,7 +536,8 @@ GEM eventmachine (>= 0.12.8) http_parser.rb (~> 0.5.1) simple_oauth (~> 0.1.4) - tzinfo (0.3.39) + tzinfo (1.2.0) + thread_safe (~> 0.1) uglifier (2.3.2) execjs (>= 0.3.0) json (>= 1.8.0) @@ -621,7 +626,7 @@ DEPENDENCIES kaminari (~> 0.15.1) launchy letter_opener - minitest (~> 4.7.0) + minitest (~> 5.3.0) mysql2 nprogress-rails omniauth (~> 1.1.3) @@ -637,7 +642,7 @@ DEPENDENCIES rack-attack rack-cors rack-mini-profiler - rails (~> 4.0.0) + rails (~> 4.1.0) rails-observers rails_best_practices raphael-rails (~> 2.1.2) From 90c2e0d971b5c105224196b8509012f943c9ea9b Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Fri, 30 May 2014 17:21:14 +0200 Subject: [PATCH 175/360] Replace now forbidden keywords public and private for snippets scope --- app/controllers/snippets_controller.rb | 2 +- app/models/snippet.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/controllers/snippets_controller.rb b/app/controllers/snippets_controller.rb index 0dd941a48e..59ad8ff907 100644 --- a/app/controllers/snippets_controller.rb +++ b/app/controllers/snippets_controller.rb @@ -14,7 +14,7 @@ class SnippetsController < ApplicationController layout 'navless' def index - @snippets = Snippet.public.fresh.non_expired.page(params[:page]).per(20) + @snippets = Snippet.is_public.fresh.non_expired.page(params[:page]).per(20) end def user_index diff --git a/app/models/snippet.rb b/app/models/snippet.rb index 720accd73d..0727bb1639 100644 --- a/app/models/snippet.rb +++ b/app/models/snippet.rb @@ -34,8 +34,8 @@ class Snippet < ActiveRecord::Base validates :content, presence: true # Scopes - scope :public, -> { where(private: false) } - scope :private, -> { where(private: true) } + scope :is_public, -> { where(private: false) } + scope :is_private, -> { where(private: true) } scope :fresh, -> { order("created_at DESC") } scope :expired, -> { where(["expires_at IS NOT NULL AND expires_at < ?", Time.current]) } scope :non_expired, -> { where(["expires_at IS NULL OR expires_at > ?", Time.current]) } From 79f8abc51fa876e12de4150ab3ec489208aaed84 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Mon, 2 Jun 2014 10:20:37 +0200 Subject: [PATCH 176/360] Replace snippets scopes in view and controller. --- app/controllers/snippets_controller.rb | 10 +++++----- app/views/snippets/current_user_index.html.haml | 12 ++++++------ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/app/controllers/snippets_controller.rb b/app/controllers/snippets_controller.rb index 59ad8ff907..89edd9fd7e 100644 --- a/app/controllers/snippets_controller.rb +++ b/app/controllers/snippets_controller.rb @@ -26,15 +26,15 @@ class SnippetsController < ApplicationController if @user == current_user @snippets = case params[:scope] - when 'public' then - @snippets.public - when 'private' then - @snippets.private + when 'is_public' then + @snippets.is_public + when 'is_private' then + @snippets.is_private else @snippets end else - @snippets = @snippets.public + @snippets = @snippets.is_public end @snippets = @snippets.page(params[:page]).per(20) diff --git a/app/views/snippets/current_user_index.html.haml b/app/views/snippets/current_user_index.html.haml index 90ddc7198f..3e03042870 100644 --- a/app/views/snippets/current_user_index.html.haml +++ b/app/views/snippets/current_user_index.html.haml @@ -18,16 +18,16 @@ All %span.pull-right = @user.snippets.count - = nav_tab :scope, 'private' do - = link_to user_snippets_path(@user, scope: 'private') do + = nav_tab :scope, 'is_private' do + = link_to user_snippets_path(@user, scope: 'is_private') do Private %span.pull-right - = @user.snippets.private.count - = nav_tab :scope, 'public' do - = link_to user_snippets_path(@user, scope: 'public') do + = @user.snippets.is_private.count + = nav_tab :scope, 'is_public' do + = link_to user_snippets_path(@user, scope: 'is_public') do Public %span.pull-right - = @user.snippets.public.count + = @user.snippets.is_public.count .col-md-9.my-snippets = render 'snippets' From 9abee4eac80852be502f1cc35cedae063d314e45 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Mon, 2 Jun 2014 10:20:56 +0200 Subject: [PATCH 177/360] Add a state_machine patch for rails 4.1. --- config/initializers/state_machine_patch.rb | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 config/initializers/state_machine_patch.rb diff --git a/config/initializers/state_machine_patch.rb b/config/initializers/state_machine_patch.rb new file mode 100644 index 0000000000..a446b6275c --- /dev/null +++ b/config/initializers/state_machine_patch.rb @@ -0,0 +1,9 @@ +# This is a patch to address the issue in https://github.com/pluginaweek/state_machine/issues/251 +# where gem 'state_machine' was not working for Rails 4.1 +module StateMachine + module Integrations + module ActiveModel + public :around_validation + end + end +end From 1dca950c2831bbe37c7d421ae2033aca4cfc4334 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Mon, 2 Jun 2014 10:51:22 +0200 Subject: [PATCH 178/360] Fix failing submodule test. --- spec/helpers/submodule_helper_spec.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spec/helpers/submodule_helper_spec.rb b/spec/helpers/submodule_helper_spec.rb index 20378b1b17..41c9f038c2 100644 --- a/spec/helpers/submodule_helper_spec.rb +++ b/spec/helpers/submodule_helper_spec.rb @@ -16,7 +16,8 @@ describe SubmoduleHelper do end it 'should detect ssh on standard port' do - Gitlab.config.gitlab.stub(ssh_port: 22) # set this just to be sure + Gitlab.config.gitlab_shell.stub(ssh_port: 22) # set this just to be sure + Gitlab.config.gitlab_shell.stub(ssh_path_prefix: Settings.send(:build_gitlab_shell_ssh_path_prefix)) stub_url([ config.user, '@', config.host, ':gitlab-org/gitlab-ce.git' ].join('')) submodule_links(submodule_item).should == [ project_path('gitlab-org/gitlab-ce'), project_tree_path('gitlab-org/gitlab-ce', 'hash') ] end From 7bf64b2648f4d23ad6850641d52b06b1fc447b81 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Mon, 2 Jun 2014 11:28:32 +0200 Subject: [PATCH 179/360] Convert to array since Relation no longer returns an array. --- app/controllers/projects_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 6ea9b2cf27..7401b28ea1 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -217,6 +217,6 @@ class ProjectsController < ApplicationController end def sorted(users) - users.uniq.compact.sort_by(&:username).map { |user| { username: user.username, name: user.name } } + users.uniq.to_a.compact.sort_by(&:username).map { |user| { username: user.username, name: user.name } } end end From e18d5be55af9eab1cfeb7ebae90e3799fb4f7a53 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Mon, 2 Jun 2014 11:35:39 +0200 Subject: [PATCH 180/360] Remove active_record.auto_explain_treshold_in_seconds, rails 4.0 deprecation --- config/environments/production.rb | 4 ---- 1 file changed, 4 deletions(-) diff --git a/config/environments/production.rb b/config/environments/production.rb index 47f7e17aeb..2450d5719e 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -74,10 +74,6 @@ Gitlab::Application.configure do # Send deprecation notices to registered listeners config.active_support.deprecation = :notify - # Log the query plan for queries taking more than this (works - # with SQLite, MySQL, and PostgreSQL) - # config.active_record.auto_explain_threshold_in_seconds = 0.5 - config.action_mailer.delivery_method = :sendmail # Defaults to: # # config.action_mailer.sendmail_settings = { From ecfd33c12f0d008d4b09b9dab486e3d0100239c3 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Mon, 2 Jun 2014 14:13:35 +0200 Subject: [PATCH 181/360] Add acts-as-taggable-on-patch for gem version 2.4.1 and Rails 4.1. --- .../initializers/acts_as_taggable_on_patch.rb | 130 ++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 config/initializers/acts_as_taggable_on_patch.rb diff --git a/config/initializers/acts_as_taggable_on_patch.rb b/config/initializers/acts_as_taggable_on_patch.rb new file mode 100644 index 0000000000..baa77fde39 --- /dev/null +++ b/config/initializers/acts_as_taggable_on_patch.rb @@ -0,0 +1,130 @@ +# This is a patch to address the issue in https://github.com/mbleigh/acts-as-taggable-on/issues/427 caused by +# https://github.com/rails/rails/commit/31a43ebc107fbd50e7e62567e5208a05909ec76c +# gem 'acts-as-taggable-on' has the fix included https://github.com/mbleigh/acts-as-taggable-on/commit/89bbed3864a9252276fb8dd7d535fce280454b90 +# but not in the currently used version of gem ('2.4.1') +# With replacement of 'acts-as-taggable-on' gem this file will become obsolete + +module ActsAsTaggableOn::Taggable + module Core + module ClassMethods + def tagged_with(tags, options = {}) + tag_list = ActsAsTaggableOn::TagList.from(tags) + empty_result = where("1 = 0") + + return empty_result if tag_list.empty? + + joins = [] + conditions = [] + having = [] + select_clause = [] + + context = options.delete(:on) + owned_by = options.delete(:owned_by) + alias_base_name = undecorated_table_name.gsub('.','_') + quote = ActsAsTaggableOn::Tag.using_postgresql? ? '"' : '' + + if options.delete(:exclude) + if options.delete(:wild) + tags_conditions = tag_list.map { |t| sanitize_sql(["#{ActsAsTaggableOn::Tag.table_name}.name #{like_operator} ? ESCAPE '!'", "%#{escape_like(t)}%"]) }.join(" OR ") + else + tags_conditions = tag_list.map { |t| sanitize_sql(["#{ActsAsTaggableOn::Tag.table_name}.name #{like_operator} ?", t]) }.join(" OR ") + end + + conditions << "#{table_name}.#{primary_key} NOT IN (SELECT #{ActsAsTaggableOn::Tagging.table_name}.taggable_id FROM #{ActsAsTaggableOn::Tagging.table_name} JOIN #{ActsAsTaggableOn::Tag.table_name} ON #{ActsAsTaggableOn::Tagging.table_name}.tag_id = #{ActsAsTaggableOn::Tag.table_name}.#{ActsAsTaggableOn::Tag.primary_key} AND (#{tags_conditions}) WHERE #{ActsAsTaggableOn::Tagging.table_name}.taggable_type = #{quote_value(base_class.name, nil)})" + + if owned_by + joins << "JOIN #{ActsAsTaggableOn::Tagging.table_name}" + + " ON #{ActsAsTaggableOn::Tagging.table_name}.taggable_id = #{quote}#{table_name}#{quote}.#{primary_key}" + + " AND #{ActsAsTaggableOn::Tagging.table_name}.taggable_type = #{quote_value(base_class.name, nil)}" + + " AND #{ActsAsTaggableOn::Tagging.table_name}.tagger_id = #{owned_by.id}" + + " AND #{ActsAsTaggableOn::Tagging.table_name}.tagger_type = #{quote_value(owned_by.class.base_class.to_s, nil)}" + end + + elsif options.delete(:any) + # get tags, drop out if nothing returned (we need at least one) + tags = if options.delete(:wild) + ActsAsTaggableOn::Tag.named_like_any(tag_list) + else + ActsAsTaggableOn::Tag.named_any(tag_list) + end + + return empty_result unless tags.length > 0 + + # setup taggings alias so we can chain, ex: items_locations_taggings_awesome_cool_123 + # avoid ambiguous column name + taggings_context = context ? "_#{context}" : '' + + taggings_alias = adjust_taggings_alias( + "#{alias_base_name[0..4]}#{taggings_context[0..6]}_taggings_#{sha_prefix(tags.map(&:name).join('_'))}" + ) + + tagging_join = "JOIN #{ActsAsTaggableOn::Tagging.table_name} #{taggings_alias}" + + " ON #{taggings_alias}.taggable_id = #{quote}#{table_name}#{quote}.#{primary_key}" + + " AND #{taggings_alias}.taggable_type = #{quote_value(base_class.name, nil)}" + tagging_join << " AND " + sanitize_sql(["#{taggings_alias}.context = ?", context.to_s]) if context + + # don't need to sanitize sql, map all ids and join with OR logic + conditions << tags.map { |t| "#{taggings_alias}.tag_id = #{t.id}" }.join(" OR ") + select_clause = "DISTINCT #{table_name}.*" unless context and tag_types.one? + + if owned_by + tagging_join << " AND " + + sanitize_sql([ + "#{taggings_alias}.tagger_id = ? AND #{taggings_alias}.tagger_type = ?", + owned_by.id, + owned_by.class.base_class.to_s + ]) + end + + joins << tagging_join + else + tags = ActsAsTaggableOn::Tag.named_any(tag_list) + + return empty_result unless tags.length == tag_list.length + + tags.each do |tag| + taggings_alias = adjust_taggings_alias("#{alias_base_name[0..11]}_taggings_#{sha_prefix(tag.name)}") + tagging_join = "JOIN #{ActsAsTaggableOn::Tagging.table_name} #{taggings_alias}" + + " ON #{taggings_alias}.taggable_id = #{quote}#{table_name}#{quote}.#{primary_key}" + + " AND #{taggings_alias}.taggable_type = #{quote_value(base_class.name, nil)}" + + " AND #{taggings_alias}.tag_id = #{tag.id}" + + tagging_join << " AND " + sanitize_sql(["#{taggings_alias}.context = ?", context.to_s]) if context + + if owned_by + tagging_join << " AND " + + sanitize_sql([ + "#{taggings_alias}.tagger_id = ? AND #{taggings_alias}.tagger_type = ?", + owned_by.id, + owned_by.class.base_class.to_s + ]) + end + + joins << tagging_join + end + end + + taggings_alias, tags_alias = adjust_taggings_alias("#{alias_base_name}_taggings_group"), "#{alias_base_name}_tags_group" + + if options.delete(:match_all) + joins << "LEFT OUTER JOIN #{ActsAsTaggableOn::Tagging.table_name} #{taggings_alias}" + + " ON #{taggings_alias}.taggable_id = #{quote}#{table_name}#{quote}.#{primary_key}" + + " AND #{taggings_alias}.taggable_type = #{quote_value(base_class.name, nil)}" + + + group_columns = ActsAsTaggableOn::Tag.using_postgresql? ? grouped_column_names_for(self) : "#{table_name}.#{primary_key}" + group = group_columns + having = "COUNT(#{taggings_alias}.taggable_id) = #{tags.size}" + end + + select(select_clause) \ + .joins(joins.join(" ")) \ + .where(conditions.join(" AND ")) \ + .group(group) \ + .having(having) \ + .order(options[:order]) \ + .readonly(false) + end + end + end +end From 209726917b1231e02bf77f1f5ee71cbc95f94853 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Mon, 2 Jun 2014 16:22:51 +0200 Subject: [PATCH 182/360] Fix the system_hook test. --- spec/models/system_hook_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/models/system_hook_spec.rb b/spec/models/system_hook_spec.rb index 7314439730..47d6d861d7 100644 --- a/spec/models/system_hook_spec.rb +++ b/spec/models/system_hook_spec.rb @@ -59,7 +59,7 @@ describe SystemHook do user = create(:user) project = create(:project) project.team << [user, :master] - project.users_projects.clear + project.users_projects.destroy_all WebMock.should have_requested(:post, @system_hook.url).with(body: /user_remove_from_team/).once end end From ef7cfdceea0355c0e9c434ec3fc2b9915979da5e Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Mon, 2 Jun 2014 17:04:59 +0200 Subject: [PATCH 183/360] Update jasmine. --- Gemfile | 2 +- Gemfile.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Gemfile b/Gemfile index f3791e9598..5b45b8bdcc 100644 --- a/Gemfile +++ b/Gemfile @@ -224,7 +224,7 @@ group :development, :test do # PhantomJS driver for Capybara gem 'poltergeist', '~> 1.5.1' - gem 'jasmine', '2.0.0.rc5' + gem 'jasmine', '2.0.2' gem "spring", '1.1.1' gem "spring-commands-rspec", '1.0.1' diff --git a/Gemfile.lock b/Gemfile.lock index 60f1dd0a21..416c4985f9 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -244,12 +244,12 @@ GEM httpauth (0.2.0) i18n (0.6.9) ice_nine (0.10.0) - jasmine (2.0.0.rc5) - jasmine-core (~> 2.0.0.rc5) + jasmine (2.0.2) + jasmine-core (~> 2.0.0) phantomjs rack (>= 1.2.1) rake - jasmine-core (2.0.0.rc5) + jasmine-core (2.0.0) jquery-atwho-rails (0.3.3) jquery-rails (3.1.0) railties (>= 3.0, < 5.0) @@ -617,7 +617,7 @@ DEPENDENCIES haml-rails hipchat (~> 0.14.0) httparty - jasmine (= 2.0.0.rc5) + jasmine (= 2.0.2) jquery-atwho-rails (~> 0.3.3) jquery-rails jquery-scrollto-rails From 84dc9cd6926ea8bc4db533e658463b4e60f68e6b Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Tue, 3 Jun 2014 12:06:13 +0200 Subject: [PATCH 184/360] Update mysql2 gem. --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 416c4985f9..5124863692 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -288,7 +288,7 @@ GEM multi_json (1.10.1) multi_xml (0.5.5) multipart-post (1.2.0) - mysql2 (0.3.11) + mysql2 (0.3.16) net-ldap (0.3.1) net-scp (1.1.2) net-ssh (>= 2.6.5) From fc43c4e7fad0b958f4ba36a48ccecee82343ec2a Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 3 Jun 2014 12:44:22 +0300 Subject: [PATCH 185/360] Restyle admin/user page Signed-off-by: Dmitriy Zaporozhets --- app/controllers/admin/users_controller.rb | 3 +- app/views/admin/users/show.html.haml | 293 +++++++++++++--------- app/views/users/_projects.html.haml | 2 +- app/views/users/show.html.haml | 10 +- 4 files changed, 181 insertions(+), 127 deletions(-) diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb index 5b06af79d5..5ecdfbd807 100644 --- a/app/controllers/admin/users_controller.rb +++ b/app/controllers/admin/users_controller.rb @@ -8,7 +8,8 @@ class Admin::UsersController < Admin::ApplicationController end def show - @projects = user.authorized_projects + @personal_projects = user.personal_projects + @joined_projects = user.projects.joined(@user) end def new diff --git a/app/views/admin/users/show.html.haml b/app/views/admin/users/show.html.haml index 28c91c2c3e..a255c64fc2 100644 --- a/app/views/admin/users/show.html.haml +++ b/app/views/admin/users/show.html.haml @@ -1,5 +1,5 @@ %h3.page-title - %span.cgray User: + User: = @user.name - if @user.blocked? %span.cred (Blocked) @@ -11,112 +11,144 @@ %i.icon-edit Edit %hr +%ul.nav.nav-tabs + %li.active + %a{"data-toggle" => "tab", href: "#account"} Account + %li + %a{"data-toggle" => "tab", href: "#profile"} Profile + %li + %a{"data-toggle" => "tab", href: "#groups"} Groups + %li + %a{"data-toggle" => "tab", href: "#projects"} Projects -.row - .col-md-6 - .panel.panel-default - .panel-heading - Account: - .pull-right - = image_tag avatar_icon(@user.email, 32), class: "avatar s32" - %ul.well-list - %li - %span.light Name: - %strong= @user.name - %li - %span.light Username: - %strong - = @user.username - %li - %span.light Email: - %strong - = mail_to @user.email - %li - %span.light Can create groups: - %strong - = @user.can_create_group ? "Yes" : "No" - %li - %span.light Personal projects limit: - %strong - = @user.projects_limit - %li - %span.light Member since: - %strong - = @user.created_at.stamp("Nov 12, 2031") - - if @user.confirmed_at - %li - %span.light Confirmed at: - %strong - = @user.confirmed_at.stamp("Nov 12, 2031") - - else - %li - %span.light Confirmed: - %strong.cred - No - - %li - %span.light Last sign-in at: - %strong - - if @user.last_sign_in_at - = @user.last_sign_in_at.stamp("Nov 12, 2031") - - else - never - - - if @user.ldap_user? - %li - %span.light LDAP uid: - %strong - = @user.extern_uid - - - if @user.created_by - %li - %span.light Created by: - %strong - = link_to @user.created_by.name, [:admin, @user.created_by] - - - unless @user == current_user - - if @user.blocked? - .alert.alert-info - %h4 This user is blocked - %p Blocking user has the following effects: - %ul - %li User will not be able to login - %li User will not be able to access git repositories - %li User will be removed from joined projects and groups - %li Personal projects will be left - %li Owned groups will be left - %br - = link_to 'Unblock user', unblock_admin_user_path(@user), method: :put, class: "btn btn-new", data: { confirm: 'Are you sure?' } - - else - .alert.alert-warning - %h4 Block this user - %p Blocking user has the following effects: - %ul - %li User will not be able to login - %li User will not be able to access git repositories - %li User will be removed from joined projects and groups - %li Personal projects will be left - %li Owned groups will be left - %br - = link_to 'Block user', block_admin_user_path(@user), data: { confirm: 'USER WILL BE BLOCKED! Are you sure?' }, method: :put, class: "btn btn-remove" - - .alert.alert-danger - %h4 - Remove user - %p Deleting a user has the following effects: - %ul - %li All user content like authored issues, snippets, comments will be removed - - rp = @user.personal_projects.count - - unless rp.zero? - %li #{pluralize rp, 'personal project'} will be removed and cannot be restored - - if @user.solo_owned_groups.present? +.tab-content + #account.tab-pane.active + .row + .col-md-6 + .panel.panel-default + .panel-heading + Account: + %ul.well-list %li - Next groups with all content will be removed: - %strong #{@user.solo_owned_groups.map(&:name).join(', ')} - %br - = link_to 'Remove user', [:admin, @user], data: { confirm: "USER #{@user.name} WILL BE REMOVED! Are you sure?" }, method: :delete, class: "btn btn-remove" + %span.light Name: + %strong= @user.name + %li + %span.light Username: + %strong + = @user.username + %li + %span.light Email: + %strong + = mail_to @user.email + - @user.emails.each do |email| + %li + %span.light Secondary email: + %strong= email.email - .col-md-6 + %li + %span.light Can create groups: + %strong + = @user.can_create_group ? "Yes" : "No" + %li + %span.light Personal projects limit: + %strong + = @user.projects_limit + %li + %span.light Member since: + %strong + = @user.created_at.stamp("Nov 12, 2031") + - if @user.confirmed_at + %li + %span.light Confirmed at: + %strong + = @user.confirmed_at.stamp("Nov 12, 2031") + - else + %li + %span.light Confirmed: + %strong.cred + No + + %li + %span.light Last sign-in at: + %strong + - if @user.last_sign_in_at + = @user.last_sign_in_at.stamp("Nov 12, 2031") + - else + never + + - if @user.ldap_user? + %li + %span.light LDAP uid: + %strong + = @user.extern_uid + + - if @user.created_by + %li + %span.light Created by: + %strong + = link_to @user.created_by.name, [:admin, @user.created_by] + + .col-md-6 + - unless @user == current_user + - if @user.blocked? + .alert.alert-info + %h4 This user is blocked + %p Blocking user has the following effects: + %ul + %li User will not be able to login + %li User will not be able to access git repositories + %li User will be removed from joined projects and groups + %li Personal projects will be left + %li Owned groups will be left + %br + = link_to 'Unblock user', unblock_admin_user_path(@user), method: :put, class: "btn btn-new", data: { confirm: 'Are you sure?' } + - else + .alert.alert-warning + %h4 Block this user + %p Blocking user has the following effects: + %ul + %li User will not be able to login + %li User will not be able to access git repositories + %li User will be removed from joined projects and groups + %li Personal projects will be left + %li Owned groups will be left + %br + = link_to 'Block user', block_admin_user_path(@user), data: { confirm: 'USER WILL BE BLOCKED! Are you sure?' }, method: :put, class: "btn btn-remove" + + .alert.alert-danger + %h4 + Remove user + %p Deleting a user has the following effects: + %ul + %li All user content like authored issues, snippets, comments will be removed + - rp = @user.personal_projects.count + - unless rp.zero? + %li #{pluralize rp, 'personal project'} will be removed and cannot be restored + - if @user.solo_owned_groups.present? + %li + Next groups with all content will be removed: + %strong #{@user.solo_owned_groups.map(&:name).join(', ')} + %br + = link_to 'Remove user', [:admin, @user], data: { confirm: "USER #{@user.name} WILL BE REMOVED! Are you sure?" }, method: :delete, class: "btn btn-remove" + + #profile.tab-pane + .row + .col-md-6 + .panel.panel-default + .panel-heading + = @user.name + %ul.well-list + %li + = image_tag avatar_icon(@user.email, 60), class: "avatar s60" + %li + %span.light Profile page: + %strong + = link_to user_path(@user) do + = @user.username + .col-md-6 + = render 'users/profile', user: @user + + #groups.tab-pane - if @user.users_groups.present? .panel.panel-default .panel-heading Groups: @@ -131,23 +163,42 @@ - unless user_group.owner? = link_to group_users_group_path(group, user_group), data: { confirm: remove_user_from_group_message(group, @user) }, method: :delete, remote: true, class: "btn-tiny btn btn-remove", title: 'Remove user from group' do %i.icon-remove.icon-white + - else + .nothing-here-block This user has no groups. - .panel.panel-default - .panel-heading Projects (#{@projects.count}) - %ul.well-list - - @projects.sort_by(&:name_with_namespace).each do |project| - - tm = project.team.find_tm(@user.id) - %li.users_project - = link_to admin_project_path(project), class: dom_class(project) do - = project.name_with_namespace + #projects.tab-pane + - if @user.groups.any? + .panel.panel-default + .panel-heading Group projects + %ul.well-list + - @user.groups.each do |group| + %li + %strong= group.name + – access to + #{pluralize(group.projects.count, 'project')} - - if tm - .pull-right - - if tm.owner? - %span.light Owner - - else - %span.light= tm.human_access + .row + .col-md-6 + = render 'users/projects', projects: @personal_projects - - if tm.respond_to? :project - = link_to project_team_member_path(project, @user), data: { confirm: remove_from_project_team_message(project, @user) }, remote: true, method: :delete, class: "btn-tiny btn btn-remove", title: 'Remove user from project' do - %i.icon-remove + .col-md-6 + .panel.panel-default + .panel-heading Joined projects (#{@joined_projects.count}) + %ul.well-list + - @joined_projects.sort_by(&:name_with_namespace).each do |project| + - tm = project.team.find_tm(@user.id) + %li.users_project + .list-item-name + = link_to admin_project_path(project), class: dom_class(project) do + = project.name_with_namespace + + - if tm + .pull-right + - if tm.owner? + %span.light Owner + - else + %span.light= tm.human_access + + - if tm.respond_to? :project + = link_to project_team_member_path(project, @user), data: { confirm: remove_from_project_team_message(project, @user) }, remote: true, method: :delete, class: "btn-tiny btn btn-remove", title: 'Remove user from project' do + %i.icon-remove diff --git a/app/views/users/_projects.html.haml b/app/views/users/_projects.html.haml index bcaec4a27e..1d38f8e8ab 100644 --- a/app/views/users/_projects.html.haml +++ b/app/views/users/_projects.html.haml @@ -1,6 +1,6 @@ .panel.panel-default .panel-heading Personal projects %ul.well-list - - @projects.each do |project| + - projects.each do |project| %li = link_to_project project diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml index 948b59fead..60159a29b9 100644 --- a/app/views/users/show.html.haml +++ b/app/views/users/show.html.haml @@ -13,12 +13,14 @@ %br %small member since #{@user.created_at.stamp("Nov 12, 2031")} .clearfix - %h4 Groups: - = render 'groups', groups: @groups - %hr + + - if @groups.any? + %h4 Groups: + = render 'groups', groups: @groups + %hr %h4 User Activity: = render @events .col-md-4 = render 'profile', user: @user - if @projects.present? - = render 'projects' + = render 'projects', projects: @projects From 31c963edb137055c1fe7a67c31b63fabbfd8c0bd Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 3 Jun 2014 13:05:06 +0300 Subject: [PATCH 186/360] Improve admin/user form Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/generic/forms.scss | 4 ++++ app/views/admin/users/_form.html.haml | 15 ++++++--------- app/views/admin/users/edit.html.haml | 7 ++++--- app/views/admin/users/new.html.haml | 1 - 4 files changed, 14 insertions(+), 13 deletions(-) diff --git a/app/assets/stylesheets/generic/forms.scss b/app/assets/stylesheets/generic/forms.scss index 36551f85b6..bd9d4bceb8 100644 --- a/app/assets/stylesheets/generic/forms.scss +++ b/app/assets/stylesheets/generic/forms.scss @@ -98,3 +98,7 @@ label { z-index: 2; } } + +.fieldset-form fieldset { + margin-bottom: 20px; +} diff --git a/app/views/admin/users/_form.html.haml b/app/views/admin/users/_form.html.haml index b9e6382ea8..d00772d4df 100644 --- a/app/views/admin/users/_form.html.haml +++ b/app/views/admin/users/_form.html.haml @@ -1,5 +1,5 @@ .user_new - = form_for [:admin, @user], html: { class: 'form-horizontal' } do |f| + = form_for [:admin, @user], html: { class: 'form-horizontal fieldset-form' } do |f| -if @user.errors.any? #error_explanation .alert.alert-danger @@ -61,16 +61,13 @@ .col-sm-10 You cannot remove your own admin rights - else .col-sm-10= f.check_box :admin - - unless @user.new_record? || current_user == @user - .alert.alert-danger - - if @user.blocked? - %p This user is blocked and is not able to login to GitLab - = link_to 'Unblock User', unblock_admin_user_path(@user), method: :put, class: "btn btn-small" - - else - %p Blocked users will be removed from all projects & will not be able to login to GitLab. - = link_to 'Block User', block_admin_user_path(@user), data: {confirm: 'USER WILL BE BLOCKED! Are you sure?'}, method: :put, class: "btn btn-small btn-remove" %fieldset %legend Profile + .form-group + = f.label :avatar, class: 'control-label' + .col-sm-10 + = f.file_field :avatar + .form-group = f.label :skype, class: 'control-label' .col-sm-10= f.text_field :skype, class: 'form-control' diff --git a/app/views/admin/users/edit.html.haml b/app/views/admin/users/edit.html.haml index 2a4f8c6054..d71d8189c5 100644 --- a/app/views/admin/users/edit.html.haml +++ b/app/views/admin/users/edit.html.haml @@ -1,6 +1,7 @@ %h3.page-title - #{@user.name} → - %i.icon-edit - Edit user + Edit user: #{@user.name} +.back-link + = link_to admin_user_path(@user) do + ← Back to user page %hr = render 'form' diff --git a/app/views/admin/users/new.html.haml b/app/views/admin/users/new.html.haml index a1c90c4894..8fbb757f42 100644 --- a/app/views/admin/users/new.html.haml +++ b/app/views/admin/users/new.html.haml @@ -1,5 +1,4 @@ %h3.page-title - %i.icon-plus New user %hr = render 'form' From da37a251f9f6a794c696cbc6afc8b2b04443fbeb Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Tue, 3 Jun 2014 12:33:43 +0200 Subject: [PATCH 187/360] Add ch width. --- app/assets/stylesheets/generic/forms.scss | 1 + app/views/shared/_commit_message_container.html.haml | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/stylesheets/generic/forms.scss b/app/assets/stylesheets/generic/forms.scss index 36551f85b6..baa1133616 100644 --- a/app/assets/stylesheets/generic/forms.scss +++ b/app/assets/stylesheets/generic/forms.scss @@ -82,6 +82,7 @@ label { font-family: $monospace_font; $left: 12px; .max-width-marker { + width: 72ch; color: rgba(0, 0, 0, 0.0); font-family: inherit; left: $left; diff --git a/app/views/shared/_commit_message_container.html.haml b/app/views/shared/_commit_message_container.html.haml index 3be01478cb..4365947e70 100644 --- a/app/views/shared/_commit_message_container.html.haml +++ b/app/views/shared/_commit_message_container.html.haml @@ -1,4 +1,3 @@ .commit-message-container .max-width-marker - -# When the `ch` CSS length unit becomes widely supported `http://www.quirksmode.org/css/units-values` remove this workaround. = textarea From 4656ef957a59a76b050badf60577c30bbf758535 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 3 Jun 2014 13:40:07 +0300 Subject: [PATCH 188/360] Replace files icons with fontawesome Signed-off-by: Dmitriy Zaporozhets --- app/assets/images/Storage-UI.PNG | Bin 737 -> 0 bytes app/assets/images/file_bin.png | Bin 219 -> 0 bytes app/assets/images/file_dir.png | Bin 1648 -> 0 bytes app/assets/images/file_empty.png | Bin 319 -> 0 bytes app/assets/images/file_img.png | Bin 536 -> 0 bytes app/assets/images/file_txt.png | Bin 463 -> 0 bytes app/assets/images/rss_ui.png | Bin 812 -> 0 bytes app/assets/images/submodule.png | Bin 641 -> 0 bytes app/assets/stylesheets/sections/tree.scss | 4 ++++ app/helpers/tree_helper.rb | 9 +++++++-- .../projects/tree/_submodule_item.html.haml | 2 +- app/views/projects/tree/_tree.html.haml | 3 +-- 12 files changed, 13 insertions(+), 5 deletions(-) delete mode 100644 app/assets/images/Storage-UI.PNG delete mode 100644 app/assets/images/file_bin.png delete mode 100644 app/assets/images/file_dir.png delete mode 100644 app/assets/images/file_empty.png delete mode 100644 app/assets/images/file_img.png delete mode 100644 app/assets/images/file_txt.png delete mode 100644 app/assets/images/rss_ui.png delete mode 100644 app/assets/images/submodule.png diff --git a/app/assets/images/Storage-UI.PNG b/app/assets/images/Storage-UI.PNG deleted file mode 100644 index 8ab6678de325550c5c504ee383df323f80b5c5d6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 737 zcmV<70v`Q|P)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iyS@ z4Gku_pU>6+00Lo2L_t(Y$FoVK)2g9H#hef9ydN&!oAE~>~_045D`z}BfMd}@;*My%-&>myjYMg z@aLEyoAE9_!;J>Crk>y8oih7jWC9=KO{|50 z8`Z?dvdcJ|nJ+D~Py@b>FRT69+T>8!@9trm0( z&zH_ZW?qVj8C<}Hh0?`nfX;6<$=t+8WH=jp>%%2 z^r&&vmW|ki^Eil;5pgUtFIL9iiw`h`Pw+%-ZdIVhMNe0NzJQ%L9}x?sGga+J951gl zs(b&7#a3FG!X>;`yIzN;-Wj35 zt-4Iy9#bjrwKvi(6R-;x$CM0q%D@00000NkvXXu0mjf+y!5X diff --git a/app/assets/images/file_bin.png b/app/assets/images/file_bin.png deleted file mode 100644 index b3feafcce0befa79ffbaa68ac6dda0c549cba911..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 219 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!60wlNoGJgf67>k44ofy`glX(f`FeQ1ryDG3<=WYfJK_+NC3#FSU={}?9Cim-pjEt_{Y^K+(QF+1zO9IfM#B|Si^7(8A5 KT-G@yGywqaXh%Z; diff --git a/app/assets/images/file_dir.png b/app/assets/images/file_dir.png deleted file mode 100644 index ea277bb14dba38fa633a32675ee58b88b88f80a4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1648 zcmV-$29NoPP)4Tx05}naRo`#hR1`jmZ&IWdKOk5~hl<6oRa0BJ8yc;~21%2p?MfD<>DVeH z9(p*dx19w`~g7O0}n_%Aq@s%d)fBDv`JHkDym6Hd+5XuAtvnwRpGmK zVkc9?T=n|PIo~X-eVh__(Z?q}P9Z-Dj?gOW6|D%o20XmjW-qs4UjrD(li^iv8@eK9k+ZFm zVRFymFOPAzG5-%Pn|1W;U4vNroTa&AxDScmEA~{ri9gr1^c?U@uwSpaNnw8l_>cP1 zd;)kMQS_;jeRSUEM_*s96y65j1$)tOrwdK{YIQMt92l|D^(E_=$Rjw{b!QT@q!)ni zR`|5oW9X5n$Wv+HVc@|^eX5yXnsHX8PF3UX~a6)MwxDE0HaPjyrlI!;jX{6Kvuh*8ej?;85ekN$?5uuCiS zBTvvVG+XTxAO{m@bvM#Jr)z6J><&E22D|vq?Y?Vkbo_DijopiF$2PET#mZ8eu=y$(ArYkv7@Ex`GL?QCc!_*KFrd&;n1r7 zqW-CFs9&fT)ZaU5gc&=gBz-DaCw(vdOp0__x+47~U6sC(E(JNe@4cTT*n6*E zVH4eoU1-&7pEV~_PRe`a7v+@vy!^5}8?Y3)UmlaER00009a7bBm000XU000XU0RWnu7ytkP@<~KNR5%f( zQn6}PK@gqYyDzB|Nkoevf+=Dtq7On8Ldt-p*k~n!MLrK0m!pqy;+3}p+`{FAE5f|p}&d!`UXJ)T6Gx?tt2p(Kr-B`J`_Gr4$mruJp>FbBL z(|3P5*8&7Tet7=@6R5|*UegizYXP@>@9DFJ`Ng~IcWz(tj?lK=?SA~m)9)L4BED@> zuqQql}bCJC~lWhvRDSgE_X8F}&QWvne69v_Qk z?Q3)IYGNuX9#k0?MWqxJP!q-OQGj}a=A3_?Dx{_+51I`u;Hv-}QA}~?U{nB~#S~x7 zDWF=3xau%Xox*Gs-L!r2nwN*UoS2#&-?;(lO*~KF&BaW0000k diff --git a/app/assets/images/file_empty.png b/app/assets/images/file_empty.png deleted file mode 100644 index 2e85bb487378a9b3139dd95c8836d691d884891d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 319 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!60wlNoGJgf67>k44ofy`glX(f`FeQ1ryDErwR-il26 z%CVt&@tQNAGW_Lb9-LV@-PL$kfqLbHBPu$4etdj(wH4ttzdvxEUh``IrnJP?&3OoR;=-YK%45r z&`=X!*W$fy9s8O6-QxuAZJ9UuN!IPd^*o34ns(h<_j&oPnxFh!DQSV{wig1u%D~|1 L>gTe~DWM4f3;1?( diff --git a/app/assets/images/file_img.png b/app/assets/images/file_img.png deleted file mode 100644 index ca554c5aefe554beec3745e0c194ed5f1b1fe34f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 536 zcmV+z0_XjSP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iyY; z6(}U%?U;N300EduL_t(I%cYaciW5N;hQGfqU0r=kkbxQSvK8DWFc09u2kT`W7Lko$3Qz`R+$Y%!Tn;n=(*zjgs0pYJC|=O&;*0oK!Bf299BrT;po|1={#e*u?I4+TE6sK`(e zP?g>@^1UMw5YNuGvEYPV1(7N1dCg` ztGAf@C4@kVIf@y{2yRv|Tamu4NMC+p7t6!3Y}+=S%5HxQ|A_xlAL?_S# acfSA*Ae7X{f4cqv0000(;GXzkdD3jT^UY*|KBDj$ONU?b)+u@7}%p z_U$`x;J~3nhYlY;eC*h<}^;r@H7%ptzJ$bc>lcVCKZV!=JkGcN;mpa)M=DavCW6E)J z<9pnvjhKzPH{?vSl{i1eK>xeDTkqxF=2~jM_wPJoYk70;zp#Wl`OurYdzT;PIJ4cV z_)p0^!5Ma&+{(X-F-Dh!nK9WJ?_TwrjWPVfQo#>XV`E=QF^WeqGws{GdzLqgKL2xu n)qU?`gU}Zocra4ei%_Kyl*f>gTe~DWM4f8l?II diff --git a/app/assets/images/rss_ui.png b/app/assets/images/rss_ui.png deleted file mode 100644 index c45afbab519ad7582f5c4558b28a95424aefdea5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 812 zcmV+{1JnG8P)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iyf3 z6&nTw)Im!C00OK@L_t(Y$Gz51h*eb_2k_6mzR?ORv$?u0&>(2hB8rG8D3~EmP~xIO zp-p6qn-UBOM&L?=pyDDe4JL3EMBK%^phZD#+LRHAh1H@UuV{q?jc?|)=v+Bn-kZ76 z*bg3@_dDnQzUTYJjzkA2ba#mFJX1s<&u8q8jm-EQvP;!Hf zWFy+%nkViWuj9J$zr0A6oX-ZG4OqbfZiwq$xEFUK?-m(|-lhy+M!>^3whq{AKE>b}oQ+0*!taTZUHGD?>KBTt&YLnE z$I(vq_KMMRQ-&=`Ja*!K?7@?T$C@&%7FE57eN&iCWb_Yd%J555hWGI-9*-sh>3&t>P1G!_OGvL{o;9$Z#7zk1m8iv9l?|Z$(uv#CFz;QI3akHy*=V zxKvd2-pKG*+?QN#3*L_F_i)Y>qkXdNMw}|D`njd0C5yWU7jZB-^HfpQw>M=thtrc> zm#@(byFF`w6Z^j%-7`Nw4MO7D3cRF?s*j`lij;0LX_jTQPx#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iyV< z6(c3wcaRzY00IF?L_t(I%cYaCPE0%i)SCIa@5_UdA0R*uix+9e)|3*VB_)fTbCEBWC3yR+$bRqhPe6^qoTYq zJlOyK;PvJyVExIxM~&w6%VF=3tTBVAB3@A^h$>K>ql0}D6IYX90PRHpg1fs42uS4m5tdkurjkE5sxMe+U@ofaIM__u#n0G-XKLlFcHKA z?D!rlJByJQAN%t+yBoi~hy>tP8D^FM3ayiC0|^cd4h Date: Tue, 3 Jun 2014 13:57:26 +0300 Subject: [PATCH 189/360] Change page-title font/color Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/generic/typography.scss | 1 + app/assets/stylesheets/main/mixins.scss | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/app/assets/stylesheets/generic/typography.scss b/app/assets/stylesheets/generic/typography.scss index 4ab83786b5..9aa819d40f 100644 --- a/app/assets/stylesheets/generic/typography.scss +++ b/app/assets/stylesheets/generic/typography.scss @@ -14,6 +14,7 @@ h2.page-title { h3.page-title { @include page-title; + font-size: 22px; } h6 { diff --git a/app/assets/stylesheets/main/mixins.scss b/app/assets/stylesheets/main/mixins.scss index 747676620b..289490712b 100644 --- a/app/assets/stylesheets/main/mixins.scss +++ b/app/assets/stylesheets/main/mixins.scss @@ -117,11 +117,11 @@ } @mixin page-title { - color: #333; - font-size: 20px; + color: #555; line-height: 1.5; + font-weight: normal; margin-top: 0px; - margin-bottom: 15px; + margin-bottom: 10px; } @mixin str-truncated($max_width: "82%") { From 95d61a094d4d69fc332b40923ba08bbb57776f39 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 3 Jun 2014 14:19:11 +0300 Subject: [PATCH 190/360] Improve admin/projects page Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/sections/admin.scss | 22 ++++++++--- app/controllers/admin/projects_controller.rb | 6 +-- app/views/admin/projects/index.html.haml | 40 ++++++++++---------- 3 files changed, 39 insertions(+), 29 deletions(-) diff --git a/app/assets/stylesheets/sections/admin.scss b/app/assets/stylesheets/sections/admin.scss index a558633d11..a51deee797 100644 --- a/app/assets/stylesheets/sections/admin.scss +++ b/app/assets/stylesheets/sections/admin.scss @@ -21,12 +21,22 @@ } .admin-filter form { - label { width: 110px; } - .controls { margin-left: 130px; } - .form-actions { padding-left: 130px; background: #fff } - .visibility-levels { - .controls { - margin-bottom: 9px; + .select2-container { + width: 100% + } + + .controls { + margin-left: 130px; + } + + .form-actions { + padding-left: 130px; + background: #fff + } + + .visibility-levels { + .controls { + margin-bottom: 9px; } i { diff --git a/app/controllers/admin/projects_controller.rb b/app/controllers/admin/projects_controller.rb index 8c1f45ac01..d2f86369b5 100644 --- a/app/controllers/admin/projects_controller.rb +++ b/app/controllers/admin/projects_controller.rb @@ -4,10 +4,8 @@ class Admin::ProjectsController < Admin::ApplicationController before_filter :repository, only: [:show, :transfer] def index - owner_id = params[:owner_id] - user = User.find_by(id: owner_id) - - @projects = user ? user.owned_projects : Project.all + @projects = Project.all + @projects = @projects.where(namespace_id: params[:namespace_id]) if params[:namespace_id].present? @projects = @projects.where("visibility_level IN (?)", params[:visibility_levels]) if params[:visibility_levels].present? @projects = @projects.with_push if params[:with_push].present? @projects = @projects.abandoned if params[:abandoned].present? diff --git a/app/views/admin/projects/index.html.haml b/app/views/admin/projects/index.html.haml index 7a23b7020c..5ca6090f8d 100644 --- a/app/views/admin/projects/index.html.haml +++ b/app/views/admin/projects/index.html.haml @@ -1,5 +1,5 @@ .row - .col-md-4 + .col-md-3 .admin-filter = form_tag admin_projects_path, method: :get, class: '' do .form-group @@ -7,19 +7,21 @@ = text_field_tag :name, params[:name], class: "form-control" .form-group - = label_tag :owner_id, 'Owner:' - %div - = users_select_tag :owner_id, selected: params[:owner_id], class: 'input-large input-clamp' - .checkbox - = label_tag :with_push, 'Not empty' - = check_box_tag :with_push, 1, params[:with_push] -   - %span.light Projects with push events - .checkbox - = label_tag :abandoned, 'Abandoned' - = check_box_tag :abandoned, 1, params[:abandoned] -   - %span.light No activity over 6 month + = label_tag :namespace_id, "Namespace" + = namespace_select_tag :namespace_id, selected: params[:namespace_id], class: 'input-large' + + .form-group + %strong Activity + .checkbox + = label_tag :with_push, 'Not empty' + = check_box_tag :with_push, 1, params[:with_push] +   + %span.light Projects with push events + .checkbox + = label_tag :abandoned, 'Abandoned' + = check_box_tag :abandoned, 1, params[:abandoned] +   + %span.light No activity over 6 month %fieldset %strong Visibility level: @@ -31,12 +33,12 @@ %span.descr = visibility_level_icon(level) = label - .form-actions - = hidden_field_tag :sort, params[:sort] - = submit_tag "Search", class: "btn submit btn-primary" - = link_to "Reset", admin_projects_path, class: "btn" + %hr + = hidden_field_tag :sort, params[:sort] + = submit_tag "Search", class: "btn submit btn-primary" + = link_to "Reset", admin_projects_path, class: "btn btn-cancel" - .col-md-8 + .col-md-9 .panel.panel-default .panel-heading Projects (#{@projects.total_count}) From 55ab7a2a958c99332f71d8b0e94ccae2b5b54c13 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 3 Jun 2014 14:49:50 +0300 Subject: [PATCH 191/360] Remove color-named css classes Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/generic/common.scss | 5 ----- .../stylesheets/sections/notifications.scss | 22 +++++++++++++++++++ app/assets/stylesheets/sections/profile.scss | 17 -------------- app/assets/stylesheets/sections/projects.scss | 12 ++++++++++ app/helpers/notifications_helper.rb | 8 +++---- app/helpers/visibility_level_helper.rb | 6 ++--- app/views/projects/blob/_blob.html.haml | 2 +- 7 files changed, 42 insertions(+), 30 deletions(-) create mode 100644 app/assets/stylesheets/sections/notifications.scss diff --git a/app/assets/stylesheets/generic/common.scss b/app/assets/stylesheets/generic/common.scss index 0cb2090f53..3b034b757b 100644 --- a/app/assets/stylesheets/generic/common.scss +++ b/app/assets/stylesheets/generic/common.scss @@ -3,12 +3,7 @@ .clgray { color: #BBB } .cred { color: #D12F19 } .cgreen { color: #4a2 } -.cblue { color: #29A } -.cblack { color: #111 } .cdark { color: #444 } -.camber { color: #ffc000 } -.cwhite { color: #fff!important } -.bgred { background: #F2DEDE!important } /** COMMON CLASSES **/ .prepend-top-10 { margin-top:10px } diff --git a/app/assets/stylesheets/sections/notifications.scss b/app/assets/stylesheets/sections/notifications.scss new file mode 100644 index 0000000000..f11c5dff4a --- /dev/null +++ b/app/assets/stylesheets/sections/notifications.scss @@ -0,0 +1,22 @@ +.global-notifications-form .level-title { + font-size: 15px; + color: #333; + font-weight: bold; +} + +.notification-icon-holder { + width: 20px; + float: left; +} + +.ns-part { + color: $bg_primary; +} + +.ns-watch { + color: $bg_success; +} + +.ns-mute { + color: $bg_danger; +} diff --git a/app/assets/stylesheets/sections/profile.scss b/app/assets/stylesheets/sections/profile.scss index 67aaa36938..ed73e1630f 100644 --- a/app/assets/stylesheets/sections/profile.scss +++ b/app/assets/stylesheets/sections/profile.scss @@ -1,9 +1,3 @@ -.update-notifications { - .radio-inline { - margin-right: 9%; - } -} - .account-page { fieldset { margin-bottom: 15px; @@ -114,14 +108,3 @@ height: 50px; } } - -.global-notifications-form .level-title { - font-size: 15px; - color: #333; - font-weight: bold; -} - -.notification-icon-holder { - width: 20px; - float: left; -} diff --git a/app/assets/stylesheets/sections/projects.scss b/app/assets/stylesheets/sections/projects.scss index 949d646afc..35279bff6a 100644 --- a/app/assets/stylesheets/sections/projects.scss +++ b/app/assets/stylesheets/sections/projects.scss @@ -232,3 +232,15 @@ ul.nav.nav-projects-tabs { .deploy-project-label { margin: 1px; } + +.vs-public { + color: $bg_primary; +} + +.vs-internal { + color: $bg_warning; +} + +.vs-private { + color: $bg_success; +} diff --git a/app/helpers/notifications_helper.rb b/app/helpers/notifications_helper.rb index b2399bb6db..6c43f97446 100644 --- a/app/helpers/notifications_helper.rb +++ b/app/helpers/notifications_helper.rb @@ -1,13 +1,13 @@ module NotificationsHelper def notification_icon(notification) if notification.disabled? - content_tag :i, nil, class: 'icon-volume-off cred' + content_tag :i, nil, class: 'icon-volume-off ns-mute' elsif notification.participating? - content_tag :i, nil, class: 'icon-volume-down cblue' + content_tag :i, nil, class: 'icon-volume-down ns-part' elsif notification.watch? - content_tag :i, nil, class: 'icon-volume-up cgreen' + content_tag :i, nil, class: 'icon-volume-up ns-watch' else - content_tag :i, nil, class: 'icon-circle-blank cblue' + content_tag :i, nil, class: 'icon-circle-blank ns-default' end end end diff --git a/app/helpers/visibility_level_helper.rb b/app/helpers/visibility_level_helper.rb index 81e10f3685..8b83b8ff64 100644 --- a/app/helpers/visibility_level_helper.rb +++ b/app/helpers/visibility_level_helper.rb @@ -2,11 +2,11 @@ module VisibilityLevelHelper def visibility_level_color(level) case level when Gitlab::VisibilityLevel::PRIVATE - 'cgreen' + 'vs-private' when Gitlab::VisibilityLevel::INTERNAL - 'camber' + 'vs-internal' when Gitlab::VisibilityLevel::PUBLIC - 'cblue' + 'vs-public' end end diff --git a/app/views/projects/blob/_blob.html.haml b/app/views/projects/blob/_blob.html.haml index 863e4e3de5..b0cac828f3 100644 --- a/app/views/projects/blob/_blob.html.haml +++ b/app/views/projects/blob/_blob.html.haml @@ -8,7 +8,7 @@ - if path - if path.end_with?(@path) = link_to project_blob_path(@project, path) do - %span.cblue + %strong = truncate(title, length: 40) - else = link_to truncate(title, length: 40), project_tree_path(@project, path) From fe302d4cb6146b27f4d93b7b9924bcd8130b0aab Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 3 Jun 2014 15:47:57 +0300 Subject: [PATCH 192/360] New base colors Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/main/variables.scss | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/assets/stylesheets/main/variables.scss b/app/assets/stylesheets/main/variables.scss index 8bcdad3579..68f7f6b858 100644 --- a/app/assets/stylesheets/main/variables.scss +++ b/app/assets/stylesheets/main/variables.scss @@ -14,8 +14,8 @@ $link_hover_color: #2FA0BB; /* * Success colors (green) */ -$border_success: #469408; -$bg_success: #469408; +$border_success: #019875; +$bg_success: #019875; /* * Danger colors (red) @@ -32,8 +32,8 @@ $bg_primary: #446e9b; /* * Warning colors (yellow) */ -$bg_warning: #d9831f; -$border_warning: #d9831f; +$bg_warning: #EB9532; +$border_warning: #EB9532; /** * Commit Diff Colors From 754b0838e0c2857b0ca73d2ced675ed5b3042242 Mon Sep 17 00:00:00 2001 From: GitLab Date: Tue, 3 Jun 2014 15:17:08 +0200 Subject: [PATCH 193/360] Set x-frame-option to sameorigin to allow the Sidekiq iframe to display. --- CHANGELOG | 1 + app/controllers/application_controller.rb | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 97d1299bae..53db2dc2dc 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -13,6 +13,7 @@ v 7.0.0 - Group masters can create projects in group - Deprecate ruby 1.9.3 support - Only masters can rewrite/remove git tags + - Header X-Frame-Options allows SAMEORIGIN to display the Sidekiq interface v 6.9.2 - Revert the commit that broke the LDAP user filter diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 2730e9942e..efb7ad2de1 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -164,7 +164,7 @@ class ApplicationController < ActionController::Base end def default_headers - headers['X-Frame-Options'] = 'DENY' + headers['X-Frame-Options'] = 'SAMEORIGIN' # Allow for the Sidekiq iframe in /admin/background_jobs headers['X-XSS-Protection'] = '1; mode=block' headers['X-UA-Compatible'] = 'IE=edge' headers['X-Content-Type-Options'] = 'nosniff' From 5b87a4dc517eccb0e100ce751bf631bc0ee01100 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 3 Jun 2014 16:22:46 +0300 Subject: [PATCH 194/360] Use same colors for disabled buttons Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/generic/buttons.scss | 8 -------- 1 file changed, 8 deletions(-) diff --git a/app/assets/stylesheets/generic/buttons.scss b/app/assets/stylesheets/generic/buttons.scss index a9849aa487..36fc771a9d 100644 --- a/app/assets/stylesheets/generic/buttons.scss +++ b/app/assets/stylesheets/generic/buttons.scss @@ -67,8 +67,6 @@ &.disabled, &[disabled] { color: #ffffff; - background-color: #3286b1; - border-color: #286e8e; } } @@ -83,8 +81,6 @@ &.disabled, &[disabled] { color: #ffffff; - background-color: #47a447; - border-color: #398439; } } @@ -99,8 +95,6 @@ &.disabled, &[disabled] { color: #ffffff; - background-color: #d2322d; - border-color: #ac2925; } } @@ -115,8 +109,6 @@ &.disabled, &[disabled] { color: #ffffff; - background-color: #e38c02; - border-color: #e38c02; } } From ad432583a91ada2e75a2546cef51982a566ecc0f Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 3 Jun 2014 16:40:50 +0300 Subject: [PATCH 195/360] Improve UI/UX for create/edit group in admin area Signed-off-by: Dmitriy Zaporozhets --- app/views/admin/groups/_form.html.haml | 57 ++++++++++++++++++++++++++ app/views/admin/groups/edit.html.haml | 32 +-------------- app/views/admin/groups/new.html.haml | 32 +-------------- app/views/admin/groups/show.html.haml | 4 +- 4 files changed, 64 insertions(+), 61 deletions(-) create mode 100644 app/views/admin/groups/_form.html.haml diff --git a/app/views/admin/groups/_form.html.haml b/app/views/admin/groups/_form.html.haml new file mode 100644 index 0000000000..31990ee593 --- /dev/null +++ b/app/views/admin/groups/_form.html.haml @@ -0,0 +1,57 @@ += form_for [:admin, @group], html: { class: "form-horizontal" } do |f| + - if @group.errors.any? + .alert.alert-danger + %span= @group.errors.full_messages.first + .form-group.group_name_holder + = f.label :name, class: 'control-label' do + Group name + .col-sm-10 + = f.text_field :name, placeholder: "Example Group", class: "form-control" + + .form-group.group-description-holder + = f.label :description, "Details", class: 'control-label' + .col-sm-10 + = f.text_area :description, maxlength: 250, class: "form-control js-gfm-input", rows: 4 + + .form-group.group-description-holder + = f.label :avatar, "Group avatar", class: 'control-label' + .col-sm-10 + %a.choose-btn.btn.btn-small.js-choose-group-avatar-button + %i.icon-paper-clip + %span Choose File ... +   + %span.file_name.js-avatar-filename File name... + = f.file_field :avatar, class: "js-group-avatar-input hidden" + .light The maximum file size allowed is 100KB. + + - if @group.new_record? + .form-group + .col-sm-2 + .col-sm-10 + .bs-callout.bs-callout-info + %ul + %li A group is a collection of several projects + %li Groups are private by default + %li Members of a group may only view projects they have permission to access + %li Group project URLs are prefixed with the group namespace + %li Existing projects may be moved into a group + .form-actions + = f.submit 'Create group', class: "btn btn-create" + = link_to 'Cancel', admin_groups_path, class: "btn btn-cancel" + + - else + .form-group.group_name_holder + = f.label :path, class: 'control-label' do + %span Group path + .col-sm-10 + = f.text_field :path, placeholder: "example-group", class: "form-control danger" + .bs-callout.bs-callout-danger + %ul + %li Changing group path can have unintended side effects. + %li Renaming group path will rename directory for all related projects + %li It will change web url for access group and group projects. + %li It will change the git path to repositories under this group. + .form-actions + = f.submit 'Save changes', class: "btn btn-primary" + = link_to 'Cancel', admin_group_path(@group), class: "btn btn-cancel" + diff --git a/app/views/admin/groups/edit.html.haml b/app/views/admin/groups/edit.html.haml index eb5c91050a..824e51c1cf 100644 --- a/app/views/admin/groups/edit.html.haml +++ b/app/views/admin/groups/edit.html.haml @@ -1,31 +1,3 @@ -%h3.page-title Edit Group +%h3.page-title Edit group: #{@group.name} %hr -= form_for [:admin, @group], html: { class: "form-horizontal" } do |f| - - if @group.errors.any? - .alert.alert-danger - %span= @group.errors.full_messages.first - .form-group.group_name_holder - = f.label :name, class: 'control-label' do - Group name - .col-sm-10 - = f.text_field :name, placeholder: "Example Group", class: "form-control" - - .form-group.group-description-holder - = f.label :description, "Details", class: 'control-label' - .col-sm-10 - = f.text_area :description, maxlength: 250, class: "form-control js-gfm-input", rows: 4 - - .form-group.group_name_holder - = f.label :path, class: 'control-label' do - %span.cred Group path - .col-sm-10 - = f.text_field :path, placeholder: "example-group", class: "form-control danger" - %ul.cred - %li Changing group path can have unintended side effects. - %li Renaming group path will rename directory for all related projects - %li It will change web url for access group and group projects. - %li It will change the git path to repositories under this group. - - .form-actions - = f.submit 'Save changes', class: "btn btn-primary" - = link_to 'Cancel', admin_groups_path, class: "btn btn-cancel" += render 'form' diff --git a/app/views/admin/groups/new.html.haml b/app/views/admin/groups/new.html.haml index ae0604cf98..f46f45c551 100644 --- a/app/views/admin/groups/new.html.haml +++ b/app/views/admin/groups/new.html.haml @@ -1,31 +1,3 @@ -%h3.page-title New Group +%h3.page-title New group %hr -= form_for [:admin, @group], html: { class: 'group-form form-horizontal' } do |f| - - if @group.errors.any? - .alert.alert-danger - %span= @group.errors.full_messages.first - .form-group - = f.label :name, class: 'control-label' do - Group name - .col-sm-10 - = f.text_field :name, placeholder: "Ex. OpenSource", class: "form-control" - - .form-group.group-description-holder - = f.label :description, "Details", class: 'control-label' - .col-sm-10 - = f.text_area :description, maxlength: 250, class: "form-control js-gfm-input", rows: 4 - - .form-group - .col-sm-2 - .col-sm-10 - %ul - %li A group is a collection of several projects - %li Groups are private by default - %li Members of a group may only view projects they have permission to access - %li Group project URLs are prefixed with the group namespace - %li Existing projects may be moved into a group - - .form-actions - = f.submit 'Create group', class: "btn btn-create" - - += render 'form' diff --git a/app/views/admin/groups/show.html.haml b/app/views/admin/groups/show.html.haml index b8068886be..8634f46053 100644 --- a/app/views/admin/groups/show.html.haml +++ b/app/views/admin/groups/show.html.haml @@ -1,7 +1,7 @@ %h3.page-title Group: #{@group.name} - = link_to edit_admin_group_path(@group), class: "btn btn-small pull-right" do + = link_to edit_admin_group_path(@group), class: "btn pull-right" do %i.icon-edit Edit %hr @@ -11,6 +11,8 @@ .panel-heading Group info: %ul.well-list + %li + = image_tag group_icon(@group.path), class: "avatar s60" %li %span.light Name: %strong= @group.name From f758438ed5de9e8ccf2d91131626610787470b00 Mon Sep 17 00:00:00 2001 From: GitLab Date: Tue, 3 Jun 2014 15:44:46 +0200 Subject: [PATCH 196/360] Revert "Set x-frame-option to sameorigin to allow the Sidekiq iframe to display." This reverts commit 754b0838e0c2857b0ca73d2ced675ed5b3042242. Sidekiq rendered via mounted sinatra app. We don't need to change controller headers. It won't affect sidekiq at all. Please modify nginx config instead for all gitlab app. --- CHANGELOG | 1 - app/controllers/application_controller.rb | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 53db2dc2dc..97d1299bae 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -13,7 +13,6 @@ v 7.0.0 - Group masters can create projects in group - Deprecate ruby 1.9.3 support - Only masters can rewrite/remove git tags - - Header X-Frame-Options allows SAMEORIGIN to display the Sidekiq interface v 6.9.2 - Revert the commit that broke the LDAP user filter diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index efb7ad2de1..2730e9942e 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -164,7 +164,7 @@ class ApplicationController < ActionController::Base end def default_headers - headers['X-Frame-Options'] = 'SAMEORIGIN' # Allow for the Sidekiq iframe in /admin/background_jobs + headers['X-Frame-Options'] = 'DENY' headers['X-XSS-Protection'] = '1; mode=block' headers['X-UA-Compatible'] = 'IE=edge' headers['X-Content-Type-Options'] = 'nosniff' From f870507659e1ed169b9e9396dbd350c205c150e4 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 3 Jun 2014 17:36:53 +0300 Subject: [PATCH 197/360] Improve green theme Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/themes/ui_modern.scss | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/app/assets/stylesheets/themes/ui_modern.scss b/app/assets/stylesheets/themes/ui_modern.scss index 67616a4a10..308a03477d 100644 --- a/app/assets/stylesheets/themes/ui_modern.scss +++ b/app/assets/stylesheets/themes/ui_modern.scss @@ -16,28 +16,28 @@ @extend .header-dark; &.navbar-gitlab { .navbar-inner { - background: #00AC7E; - border-bottom: 1px solid #00AC7E; + background: #019875; + border-bottom: 1px solid #019875; .app_logo, .navbar-toggle { &:hover { - background-color: #009C6E; + background-color: #018865; } } .separator { - background: #009C6F; - border-left: 1px solid #10BC8E; + background: #018865; + border-left: 1px solid #11A885; } .nav > li > a { color: #ADC; } .search-input { - border-color: #7fd5be; + border-color: #8ba; } } } } .nav-pills > li.active > a, .nav-pills > li.active > a:hover, .nav-pills > li.active > a:focus { - background: #00AC7E; + background: #019875; } } From f39db7e5ed2712244a3ddfd3b36e5a74a53a8cc8 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 3 Jun 2014 18:02:03 +0300 Subject: [PATCH 198/360] Case-insensetive search for issue/mr title Signed-off-by: Dmitriy Zaporozhets --- app/models/concerns/issuable.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb index de167f8803..713eab5ad7 100644 --- a/app/models/concerns/issuable.rb +++ b/app/models/concerns/issuable.rb @@ -42,7 +42,7 @@ module Issuable module ClassMethods def search(query) - where("title like :query", query: "%#{query}%") + where("LOWER(title) like :query", query: "%#{query.downcase}%") end def sort(method) From fdcc5ddec1e599289e09aeef0c5fbc276abcc05c Mon Sep 17 00:00:00 2001 From: GitLab Date: Tue, 3 Jun 2014 17:06:27 +0200 Subject: [PATCH 199/360] Ensure sidekiq is displayed by setting X-Frame-Options. --- CHANGELOG | 1 + lib/support/nginx/gitlab | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 97d1299bae..306ff4d340 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -13,6 +13,7 @@ v 7.0.0 - Group masters can create projects in group - Deprecate ruby 1.9.3 support - Only masters can rewrite/remove git tags + - Add X-Frame-Options SAMEORIGIN to Nginx config so Sidekiq admin is visible v 6.9.2 - Revert the commit that broke the LDAP user filter diff --git a/lib/support/nginx/gitlab b/lib/support/nginx/gitlab index 98c9163739..36306eeb3a 100644 --- a/lib/support/nginx/gitlab +++ b/lib/support/nginx/gitlab @@ -54,6 +54,7 @@ server { proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Frame-Options SAMEORIGIN; proxy_pass http://gitlab; } From 7984e5b1efd430ce1ea1486c647f4beaa1c13e46 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 3 Jun 2014 18:09:51 +0300 Subject: [PATCH 200/360] Show events from all projects on user page Signed-off-by: Dmitriy Zaporozhets --- app/controllers/users_controller.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index d42c2db9e5..c17c6f9694 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -11,7 +11,8 @@ class UsersController < ApplicationController end @groups = @user.groups.accessible_to(current_user) - @events = @user.recent_events.where(project_id: @projects.pluck(:id)).limit(20) + accessible_projects = @user.authorized_projects.accessible_to(current_user) + @events = @user.recent_events.where(project_id: accessible_projects.pluck(:id)).limit(20) @title = @user.name end From 62e523f4f4db67e3792980c4b56473f86c7c5e91 Mon Sep 17 00:00:00 2001 From: Corey Hinshaw Date: Tue, 3 Jun 2014 11:22:29 -0400 Subject: [PATCH 201/360] Project commit count respects default branch. Closes #299 --- app/models/repository.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/repository.rb b/app/models/repository.rb index b7239236ae..f6e44a5248 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -106,7 +106,7 @@ class Repository def commit_count Rails.cache.fetch(cache_key(:commit_count)) do begin - raw_repository.raw.commit_count + raw_repository.raw.commit_count(self.root_ref) rescue 0 end From be85d1d2b203120402b95c88036b36d3b7db6dd4 Mon Sep 17 00:00:00 2001 From: Daniel Aquino Date: Tue, 3 Jun 2014 11:46:47 -0400 Subject: [PATCH 202/360] project: ci_service should only catch ci services ci_service should return true if a ci service is enabled. Currently it's checking for any service being enabled instead of only services in the ci category. --- app/models/project.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/project.rb b/app/models/project.rb index 1e74ae735b..758ef14703 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -330,7 +330,7 @@ class Project < ActiveRecord::Base end def ci_service - @ci_service ||= services.select(&:activated?).first + @ci_service ||= ci_services.select(&:activated?).first end # For compatibility with old code From 7a385b811c7c304863c75e0023f63e7a15871ce6 Mon Sep 17 00:00:00 2001 From: Sytse Sijbrandij Date: Tue, 3 Jun 2014 19:10:03 +0200 Subject: [PATCH 203/360] Add chrome app of Go Sueyoshi. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7bff30b35e..d19efe4c8b 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ * [GitLab CI](https://www.gitlab.com/gitlab-ci/) is a continuous integration (CI) server that is easy to integrate with GitLab. -* Unofficial third-party [iPhone app](http://gitlabcontrol.com/), [Android app](https://play.google.com/store/apps/details?id=com.bd.gitlab&hl=en) and [command line client](https://github.com/drewblessing/gitlab-cli) and [Ruby API wrapper](https://github.com/NARKOZ/gitlab) for GitLab. +* Unofficial third-party [iPhone app](http://gitlabcontrol.com/), [Android app](https://play.google.com/store/apps/details?id=com.bd.gitlab&hl=en) and [command line client](https://github.com/drewblessing/gitlab-cli), [Ruby API wrapper](https://github.com/NARKOZ/gitlab) and [Chrome app](https://chrome.google.com/webstore/detail/chrome-gitlab-notifier/eageapgbnjicdjjihgclpclilenjbobi) for GitLab. ### Requirements From df92f825fca070401ef9fdab11af15041543a25a Mon Sep 17 00:00:00 2001 From: Sytse Sijbrandij Date: Tue, 3 Jun 2014 19:12:01 +0200 Subject: [PATCH 204/360] Small spelling correction in the readme. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d19efe4c8b..9cdb6bf3a6 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ * [GitLab CI](https://www.gitlab.com/gitlab-ci/) is a continuous integration (CI) server that is easy to integrate with GitLab. -* Unofficial third-party [iPhone app](http://gitlabcontrol.com/), [Android app](https://play.google.com/store/apps/details?id=com.bd.gitlab&hl=en) and [command line client](https://github.com/drewblessing/gitlab-cli), [Ruby API wrapper](https://github.com/NARKOZ/gitlab) and [Chrome app](https://chrome.google.com/webstore/detail/chrome-gitlab-notifier/eageapgbnjicdjjihgclpclilenjbobi) for GitLab. +* Unofficial third-party [iPhone app](http://gitlabcontrol.com/), [Android app](https://play.google.com/store/apps/details?id=com.bd.gitlab&hl=en), [command line client](https://github.com/drewblessing/gitlab-cli), [Ruby API wrapper](https://github.com/NARKOZ/gitlab) and [Chrome app](https://chrome.google.com/webstore/detail/chrome-gitlab-notifier/eageapgbnjicdjjihgclpclilenjbobi) for GitLab. ### Requirements From de1a7aa7eb523cf2fdad12f8eeda2ba4c5b51820 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 3 Jun 2014 22:46:54 +0300 Subject: [PATCH 205/360] Add some entries to changelog Signed-off-by: Dmitriy Zaporozhets --- CHANGELOG | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 306ff4d340..60d3efeba2 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -14,6 +14,8 @@ v 7.0.0 - Deprecate ruby 1.9.3 support - Only masters can rewrite/remove git tags - Add X-Frame-Options SAMEORIGIN to Nginx config so Sidekiq admin is visible + - UI improvements + - Case-insensetive search for issues v 6.9.2 - Revert the commit that broke the LDAP user filter From fd348de76d651d49acc8eb742cc647dc777ef5fc Mon Sep 17 00:00:00 2001 From: Ciro Santilli Date: Fri, 25 Apr 2014 00:48:22 +0200 Subject: [PATCH 206/360] Update docs to markdown style guide. --- CONTRIBUTING.md | 30 ++- MAINTENANCE.md | 22 +-- PROCESS.md | 35 ++-- README.md | 90 ++++----- doc/README.md | 40 ++-- doc/api/README.md | 108 +++++------ doc/api/branches.md | 23 +-- doc/api/commits.md | 15 +- doc/api/deploy_keys.md | 28 ++- doc/api/issues.md | 47 ++--- doc/api/merge_requests.md | 67 +++---- doc/api/milestones.md | 30 ++- doc/api/project_snippets.md | 37 ++-- doc/api/repository_files.md | 36 ++-- doc/api/system_hooks.md | 14 +- doc/api/users.md | 112 +++++------- doc/development/README.md | 8 +- doc/development/architecture.md | 115 +++++------- doc/development/shell_commands.md | 22 +-- doc/install/README.md | 10 +- doc/install/installation.md | 171 +++++++----------- doc/install/requirements.md | 35 ++-- doc/integration/README.md | 9 +- doc/integration/external-issue-tracker.md | 2 + doc/integration/github.md | 46 +++-- doc/integration/google.md | 59 +++--- doc/integration/ldap.md | 5 + doc/integration/omniauth.md | 53 +++--- doc/integration/slack.md | 42 +++-- doc/integration/twitter.md | 67 ++++--- doc/legal/README.md | 6 +- ...corporate_contributor_license_agreement.md | 18 +- ...ndividual_contributor_license_agreement.md | 18 +- doc/markdown/markdown.md | 95 ++++------ doc/permissions/permissions.md | 72 ++++---- doc/public_access/public_access.md | 30 ++- doc/raketasks/README.md | 12 +- doc/raketasks/backup_restore.md | 7 +- doc/raketasks/cleanup.md | 3 +- doc/raketasks/features.md | 38 ++++ doc/raketasks/maintenance.md | 20 +- doc/raketasks/user_management.md | 17 +- doc/raketasks/web_hooks.md | 18 +- doc/release/README.md | 8 +- doc/release/monthly.md | 72 ++++---- doc/release/patch.md | 7 +- doc/release/security.md | 16 +- doc/security/README.md | 6 +- doc/security/password_length_limits.md | 1 + doc/security/rack_attack.md | 20 +- doc/ssh/README.md | 6 +- doc/ssh/deploy_keys.md | 11 +- doc/ssh/ssh.md | 11 +- doc/system_hooks/system_hooks.md | 12 +- doc/update/2.6-to-3.0.md | 8 +- doc/update/2.9-to-3.0.md | 7 +- doc/update/3.0-to-3.1.md | 34 ++-- doc/update/3.1-to-4.0.md | 38 ++-- doc/update/4.0-to-4.1.md | 22 +-- doc/update/4.1-to-4.2.md | 11 +- doc/update/4.2-to-5.0.md | 30 ++- doc/update/5.0-to-5.1.md | 24 +-- doc/update/5.1-to-5.2.md | 31 ++-- doc/update/5.1-to-5.4.md | 33 ++-- doc/update/5.1-to-6.0.md | 58 +++--- doc/update/5.2-to-5.3.md | 28 +-- doc/update/5.3-to-5.4.md | 29 ++- doc/update/5.4-to-6.0.md | 53 +++--- doc/update/6.0-to-6.1.md | 41 +++-- doc/update/6.0-to-6.8.md | 40 ++-- doc/update/6.1-to-6.2.md | 51 +++--- doc/update/6.2-to-6.3.md | 33 ++-- doc/update/6.3-to-6.4.md | 18 +- doc/update/6.4-to-6.5.md | 23 +-- doc/update/6.5-to-6.6.md | 18 +- doc/update/6.6-to-6.7.md | 22 +-- doc/update/6.7-to-6.8.md | 32 ++-- doc/update/README.md | 10 +- doc/update/mysql_to_postgresql.md | 24 +-- doc/update/patch_versions.md | 4 +- doc/update/ruby.md | 19 +- doc/update/upgrader.md | 27 +-- doc/web_hooks/web_hooks.md | 13 +- doc/workflow/README.md | 5 +- .../authorization_for_merge_requests.md | 6 + doc/workflow/project_features.md | 18 +- doc/workflow/workflow.md | 40 ++-- features/steps/help.rb | 2 +- 88 files changed, 1346 insertions(+), 1408 deletions(-) create mode 100644 doc/raketasks/features.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 85f751919e..8c0f16c1ee 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -24,16 +24,11 @@ Issues and merge requests should be in English and contain appropriate language To get support for your particular problem please use the channels as detailed in the [getting help section of the readme](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/README.md#getting-help). Professional [support subscriptions](http://www.gitlab.com/subscription/) and [consulting services](http://www.gitlab.com/consultancy/) are available from [GitLab.com](http://www.gitlab.com/). -The [issue tracker](https://gitlab.com/gitlab-org/gitlab-ce/issues) is only for obvious errors in the latest [stable or development release of GitLab](MAINTENANCE.md). -If something is wrong but it is not a regression compared to older versions of GitLab please do not open an issue but a feature request. -When submitting an issue please conform to the issue submission guidelines listed below. -Not all issues will be addressed and your issue is more likely to be addressed if you submit a merge request which partially or fully addresses the issue. +The [issue tracker](https://gitlab.com/gitlab-org/gitlab-ce/issues) is only for obvious errors in the latest [stable or development release of GitLab](MAINTENANCE.md). If something is wrong but it is not a regression compared to older versions of GitLab please do not open an issue but a feature request. When submitting an issue please conform to the issue submission guidelines listed below. Not all issues will be addressed and your issue is more likely to be addressed if you submit a merge request which partially or fully addresses the issue. Issues can be filed either at [gitlab.com](https://gitlab.com/gitlab-org/gitlab-ce/issues) or [github.com](https://github.com/gitlabhq/gitlabhq/issues). -Do not use the issue tracker for feature requests. -We have a specific [feature request forum](http://feedback.gitlab.com) for this purpose. -Please keep feature requests as small and simple as possible, complex ones might be edited to make them small and simple. +Do not use the issue tracker for feature requests. We have a specific [feature request forum](http://feedback.gitlab.com) for this purpose. Please keep feature requests as small and simple as possible, complex ones might be edited to make them small and simple. Please send a merge request with a tested solution or a merge request with a failing test instead of opening an issue if you can. If you're unsure where to post, post to the [mailing list](https://groups.google.com/forum/#!forum/gitlabhq) or [Stack Overflow](http://stackoverflow.com/questions/tagged/gitlab) first. There are a lot of helpful GitLab users there who may be able to help you quickly. If your particular issue turns out to be a bug, it will find its way from there. @@ -42,16 +37,16 @@ Please send a merge request with a tested solution or a merge request with a fai **[Search the issues](https://gitlab.com/gitlab-org/gitlab-ce/issues)** for similar entries before submitting your own, there's a good chance somebody else had the same issue. Show your support with `:+1:` and/or join the discussion. Please submit issues in the following format (as the first post): 1. **Summary:** Summarize your issue in one sentence (what goes wrong, what did you expect to happen) -2. **Steps to reproduce:** How can we reproduce the issue, preferably on the [GitLab development virtual machine with vagrant](https://gitlab.com/gitlab-org/cookbook-gitlab/blob/master/doc/development.md) (start your issue with: `vagrant destroy && vagrant up && vagrant ssh`) -3. **Expected behavior:** Describe your issue in detail -4. **Observed behavior** -5. **Relevant logs and/or screenshots:** Please use code blocks (\`\`\`) to format console output, logs, and code as it's very hard to read otherwise. -6. **Output of checks** +1. **Steps to reproduce:** How can we reproduce the issue, preferably on the [GitLab development virtual machine with vagrant](https://gitlab.com/gitlab-org/cookbook-gitlab/blob/master/doc/development.md) (start your issue with: `vagrant destroy && vagrant up && vagrant ssh`) +1. **Expected behavior:** Describe your issue in detail +1. **Observed behavior** +1. **Relevant logs and/or screenshots:** Please use code blocks (\`\`\`) to format console output, logs, and code as it's very hard to read otherwise. +1. **Output of checks** * Results of GitLab [Application Check](doc/install/installation.md#check-application-status) (`sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production`); we will only investigate if the tests are passing * Version of GitLab you are running; we will only investigate issues in the latest stable and development releases as per the [maintenance policy](MAINTENANCE.md) * Add the last commit sha1 of the GitLab version you used to replicate the issue (obtainable from the help page) * Describe your setup (use relevant parts from `sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production`) -7. **Possible fixes**: If you can, link to the line of code that might be responsible for the problem +1. **Possible fixes**: If you can, link to the line of code that might be responsible for the problem ## Merge requests @@ -87,10 +82,10 @@ For examples of feedback on merge requests please look at already [closed merge **Please format your merge request description as follows:** 1. What does this MR do? -2. Are there points in the code the reviewer needs to double check? -3. Why was this MR needed? -4. What are the relevant issue numbers / [Feature requests](http://feedback.gitlab.com/)? -5. Screenshots (If appropiate) +1. Are there points in the code the reviewer needs to double check? +1. Why was this MR needed? +1. What are the relevant issue numbers / [Feature requests](http://feedback.gitlab.com/)? +1. Screenshots (If appropiate) ## Contribution acceptance criteria @@ -106,6 +101,7 @@ For examples of feedback on merge requests please look at already [closed merge 1. It conforms to the following style guides ## Style guides + 1. [Ruby](https://github.com/bbatsov/ruby-style-guide) 1. [Rails](https://github.com/bbatsov/rails-style-guide) 1. [Formatting](https://github.com/thoughtbot/guides/tree/master/style#formatting) diff --git a/MAINTENANCE.md b/MAINTENANCE.md index 95d9f0a5e7..19200fef38 100644 --- a/MAINTENANCE.md +++ b/MAINTENANCE.md @@ -1,24 +1,14 @@ # GitLab Maintenance Policy -GitLab is a fast moving and evolving project. We currently don't have the -resources to support many releases concurrently. We support exactly one stable -release at any given time. +GitLab is a fast moving and evolving project. We currently don't have the resources to support many releases concurrently. We support exactly one stable release at any given time. -GitLab follows the [Semantic Versioning](http://semver.org/) for its releases: -`(Major).(Minor).(Patch)`. +GitLab follows the [Semantic Versioning](http://semver.org/) for its releases: `(Major).(Minor).(Patch)`. -* **Major version**: Whenever there is something significant or any backwards - incompatible changes are introduced to the public API. -* **Minor version**: When new, backwards compatible functionality is introduced - to the public API or a minor feature is introduced, or when a set of smaller - features is rolled out. -* **Patch number**: When backwards compatible bug fixes are introduced that fix - incorrect behavior. +- **Major version**: Whenever there is something significant or any backwards incompatible changes are introduced to the public API. +- **Minor version**: When new, backwards compatible functionality is introduced to the public API or a minor feature is introduced, or when a set of smaller features is rolled out. +- **Patch number**: When backwards compatible bug fixes are introduced that fix incorrect behavior. -The current stable release will receive security patches and bug fixes -(eg. `5.0` -> `5.0.1`). Feature releases will mark the next supported stable -release where the minor version is increased numerically by increments of one -(eg. `5.0 -> 5.1`). +The current stable release will receive security patches and bug fixes (eg. `5.0` -> `5.0.1`). Feature releases will mark the next supported stable release where the minor version is increased numerically by increments of one (eg. `5.0 -> 5.1`). We encourage everyone to run the latest stable release to ensure that you can easily upgrade to the most secure and feature rich GitLab experience. In order to make sure you can easily run the most recent stable release, we are working hard to keep the update process simple and reliable. diff --git a/PROCESS.md b/PROCESS.md index 89ad12ecd5..a6ff62a9a6 100644 --- a/PROCESS.md +++ b/PROCESS.md @@ -24,9 +24,9 @@ Below we describe the contributing process to GitLab for two reasons. So that co ## Priorities of the issue team 1. Mentioning people (critical) -2. Workflow labels (normal) -3. Functional labels (minor) -4. Assigning issues (avoid if possible) +1. Workflow labels (normal) +1. Functional labels (minor) +1. Assigning issues (avoid if possible) ## Mentioning people @@ -36,11 +36,11 @@ The most important thing is making sure valid issues receive feedback from the d Workflow labels are purposely not very detailed since that would be hard to keep updated as you would need to reevaluate them after every comment. We optionally use functional labels on demand when want to group related issues to get an overview (for example all issues related to RVM, to tackle them in one go) and to add details to the issue. -- _Awaiting feedback_: Feedback pending from the reporter -- _Awaiting confirmation of fix_: The issue should already be solved in **master** (generally you can avoid this workflow item and just close the issue right away) -- _Attached MR_: There is a MR attached and the discussion should happen there - - We need to let issues stay in sync with the MR's. We can do this with a "Closing #XXXX" or "Fixes #XXXX" comment in the MR. We can't close the issue when there is a merge request because sometimes a MR is not good and we just close the MR, then the issue must stay. -- _Awaiting developer action/feedback_: Issue needs to be fixed or clarified by a developer +- *Awaiting feedback*: Feedback pending from the reporter +- *Awaiting confirmation of fix*: The issue should already be solved in **master** (generally you can avoid this workflow item and just close the issue right away) +- *Attached MR*: There is a MR attached and the discussion should happen there + - We need to let issues stay in sync with the MR's. We can do this with a "Closing #XXXX" or "Fixes #XXXX" comment in the MR. We can't close the issue when there is a merge request because sometimes a MR is not good and we just close the MR, then the issue must stay. +- *Awaiting developer action/feedback*: Issue needs to be fixed or clarified by a developer ## Functional labels @@ -51,12 +51,13 @@ These labels describe what development specialities are involved such as: Postgr If an issue is complex and needs the attention of a specific person, assignment is a good option but assigning issues might discourage other people from contributing to that issue. We need all the contributions we can get so this should never be discouraged. Also, an assigned person might not have time for a few weeks, so others should feel free to takeover. ## Label colors -- Light orange `#fef2c0`: workflow labels for issue team members (awaiting feedback, awaiting confirmation of fix) -- Bright orange `#eb6420`: workflow labels for core team members (attached MR, awaiting developer action/feedback) -- Light blue `#82C5FF`: functional labels -- Green labels `#009800`: issues that can generally be ignored. For example, issues given the following labels normally can be closed immediately: - - Feature request (see copy & paste response: [Feature requests](#feature-requests)) - - Support (see copy & paste response: [Support requests and configuration questions](#support-requests-and-configuration-questions) + +- Light orange `#fef2c0`: workflow labels for issue team members (awaiting feedback, awaiting confirmation of fix) +- Bright orange `#eb6420`: workflow labels for core team members (attached MR, awaiting developer action/feedback) +- Light blue `#82C5FF`: functional labels +- Green labels `#009800`: issues that can generally be ignored. For example, issues given the following labels normally can be closed immediately: + - Feature request (see copy & paste response: [Feature requests](#feature-requests)) + - Support (see copy & paste response: [Support requests and configuration questions](#support-requests-and-configuration-questions) ## Be kind @@ -102,8 +103,4 @@ This merge request has been closed because a request for more information has no ### Accepting merge requests -Is there a request on [the feature request forum](http://feedback.gitlab.com/forums/176466-general) that is similar to this? -If so, can you make a comment with a link to it? -Please be aware that new functionality that is not marked [accepting merge/pull requests](http://feedback.gitlab.com/forums/176466-general/status/796455) on the forum might not make it into GitLab. -You might be asked to make changes and even after implementing them your feature might still be declined. -If you want to reduce the chance of this happening please have a discussion in the forum first. +Is there a request on [the feature request forum](http://feedback.gitlab.com/forums/176466-general) that is similar to this? If so, can you make a comment with a link to it? Please be aware that new functionality that is not marked [accepting merge/pull requests](http://feedback.gitlab.com/forums/176466-general/status/796455) on the forum might not make it into GitLab. You might be asked to make changes and even after implementing them your feature might still be declined. If you want to reduce the chance of this happening please have a discussion in the forum first. diff --git a/README.md b/README.md index 9cdb6bf3a6..166e1187bf 100644 --- a/README.md +++ b/README.md @@ -1,53 +1,55 @@ -## GitLab: self hosted Git management software +# GitLab + +## Self hosted Git management software ![logo](https://gitlab.com/gitlab-org/gitlab-ce/raw/master/public/gitlab_logo.png) ![animated-screenshots](https://gist.github.com/fnkr/2f9badd56bfe0ed04ee7/raw/4f48806fbae97f556c2f78d8c2d299c04500cb0d/compiled.gif) -### Gitlab is open source software to collaborate on code +## Open source software to collaborate on code -* Manage git repositories with fine grained access controls that keep your code secure -* Perform code reviews and enhance collaboration with merge requests -* Each project can also have an issue tracker and a wiki -* Used by more than 100,000 organizations, GitLab is the most popular solution to manage git repositories on-premises -* Completely free and open source (MIT Expat license) -* Powered by Ruby on Rails +- Manage Git repositories with fine grained access controls that keep your code secure +- Perform code reviews and enhance collaboration with merge requests +- Each project can also have an issue tracker and a wiki +- Used by more than 100,000 organizations, GitLab is the most popular solution to manage Git repositories on-premises +- Completely free and open source (MIT Expat license) +- Powered by Ruby on Rails -### Canonical source +## Canonical source -* The source of GitLab Community Edition is [hosted on GitLab.com](https://gitlab.com/gitlab-org/gitlab-ce/) and there are mirrors to make [contributing](CONTRIBUTING.md) as easy as possible. +- The source of GitLab Community Edition is [hosted on GitLab.com](https://gitlab.com/gitlab-org/gitlab-ce/) and there are mirrors to make [contributing](CONTRIBUTING.md) as easy as possible. -### Code status +## Code status -* [![build status](https://ci.gitlab.org/projects/1/status.png?ref=master)](https://ci.gitlab.org/projects/1?ref=master) on ci.gitlab.org (master branch) +- [![build status](https://ci.gitlab.org/projects/1/status.png?ref=master)](https://ci.gitlab.org/projects/1?ref=master) on ci.gitlab.org (master branch) -* [![Code Climate](https://codeclimate.com/github/gitlabhq/gitlabhq.png)](https://codeclimate.com/github/gitlabhq/gitlabhq) +- [![Code Climate](https://codeclimate.com/github/gitlabhq/gitlabhq.png)](https://codeclimate.com/github/gitlabhq/gitlabhq) -* [![Coverage Status](https://coveralls.io/repos/gitlabhq/gitlabhq/badge.png?branch=master)](https://coveralls.io/r/gitlabhq/gitlabhq) +- [![Coverage Status](https://coveralls.io/repos/gitlabhq/gitlabhq/badge.png?branch=master)](https://coveralls.io/r/gitlabhq/gitlabhq) -* [![PullReview stats](https://www.pullreview.com/gitlab/gitlab-org/gitlab-ce/badges/master.svg?)](https://www.pullreview.com/gitlab.gitlab.com/gitlab-org/gitlab-ce/reviews/master) +- [![PullReview stats](https://www.pullreview.com/gitlab/gitlab-org/gitlab-ce/badges/master.svg?)](https://www.pullreview.com/gitlab.gitlab.com/gitlab-org/gitlab-ce/reviews/master) ### Resources -* [www.gitlab.com](https://www.gitlab.com/) includes information about [subscriptions](https://www.gitlab.com/subscription/), [consultancy](https://www.gitlab.com/consultancy/), the [community](https://www.gitlab.com/community/) and the [hosted GitLab.com](https://www.gitlab.com/gitlab-com/). +- [www.gitlab.com](https://www.gitlab.com/) includes information about [subscriptions](https://www.gitlab.com/subscription/), [consultancy](https://www.gitlab.com/consultancy/), the [community](https://www.gitlab.com/community/) and the [hosted GitLab.com](https://www.gitlab.com/gitlab-com/). -* [GitLab Enterprise Edition](https://www.gitlab.com/gitlab-ee/) offers additional features aimed at larger organizations. +- [GitLab Enterprise Edition](https://www.gitlab.com/gitlab-ee/) offers additional features aimed at larger organizations. -* [GitLab CI](https://www.gitlab.com/gitlab-ci/) is a continuous integration (CI) server that is easy to integrate with GitLab. +- [GitLab CI](https://www.gitlab.com/gitlab-ci/) is a continuous integration (CI) server that is easy to integrate with GitLab. -* Unofficial third-party [iPhone app](http://gitlabcontrol.com/), [Android app](https://play.google.com/store/apps/details?id=com.bd.gitlab&hl=en), [command line client](https://github.com/drewblessing/gitlab-cli), [Ruby API wrapper](https://github.com/NARKOZ/gitlab) and [Chrome app](https://chrome.google.com/webstore/detail/chrome-gitlab-notifier/eageapgbnjicdjjihgclpclilenjbobi) for GitLab. +- Unofficial third-party [iPhone app](http://gitlabcontrol.com/), [Android app](https://play.google.com/store/apps/details?id=com.bd.gitlab&hl=en), [command line client](https://github.com/drewblessing/gitlab-cli), [Ruby API wrapper](https://github.com/NARKOZ/gitlab) and [Chrome app](https://chrome.google.com/webstore/detail/chrome-gitlab-notifier/eageapgbnjicdjjihgclpclilenjbobi) for GitLab. -### Requirements +## Requirements -* Ubuntu/Debian/CentOS/RHEL** -* ruby 2.0+ -* git 1.7.10+ -* redis 2.0+ -* MySQL or PostgreSQL +- Ubuntu/Debian/CentOS/RHEL** +- ruby 2.0+ +- git 1.7.10+ +- redis 2.0+ +- MySQL or PostgreSQL -** More details are in the [requirements doc](doc/install/requirements.md) +** More details are in the [requirements doc](doc/install/requirements.md). -### Installation +## Installation Please see [the installation page on the GitLab website](https://www.gitlab.com/installation/). @@ -59,22 +61,21 @@ Since 2011 a minor or major version of GitLab is released on the 22nd of every m For updating the the Omnibus installation please see the [update documentation](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/update.md). For manual installations there is an [upgrader script](doc/update/upgrader.md) and there are [upgrade guides](doc/update). -### Run in production mode +## Run in production mode The Installation guide contains instructions on how to download an init script and run it automatically on boot. You can also start the init script manually: sudo service gitlab start -or by directly calling the script +or by directly calling the script: sudo /etc/init.d/gitlab start -Please login with root / 5iveL!fe +Please login with `root` / `5iveL!fe`. ### Install a development environment -We recommend setting up your development environment with [the cookbook](https://gitlab.com/gitlab-org/cookbook-gitlab/blob/master/README.md#installation). -If you do not use the cookbook you might need to copy the example development unicorn configuration file +We recommend setting up your development environment with [the cookbook](https://gitlab.com/gitlab-org/cookbook-gitlab/blob/master/README.md#installation). If you do not use the cookbook you might need to copy the example development unicorn configuration file cp config/unicorn.rb.example.development config/unicorn.rb @@ -84,36 +85,35 @@ Start it with [Foreman](https://github.com/ddollar/foreman) bundle exec foreman start -p 3000 -or start each component separately +or start each component separately: bundle exec rails s bin/background_jobs start -And surf to [localhost:3000](http://localhost:3000/) and login with root / 5iveL!fe +And surf to [localhost:3000](http://localhost:3000/) and login with `root` / `5iveL!fe`. -### Run the tests +## Run the tests -* Run all tests +- Run all tests: bundle exec rake test -* [RSpec](http://rspec.info/) unit and functional tests +- [RSpec](http://rspec.info/) unit and functional tests. - All RSpec tests: bundle exec rake spec + All RSpec tests: `bundle exec rake spec` - Single RSpec file: bundle exec rspec spec/controllers/commit_controller_spec.rb + Single RSpec file: `bundle exec rspec spec/controllers/commit_controller_spec.rb` -* [Spinach](https://github.com/codegram/spinach) integration tests +- [Spinach](https://github.com/codegram/spinach) integration tests. - All Spinach tests: bundle exec rake spinach + All Spinach tests: `bundle exec rake spinach` - Single Spinach test: bundle exec spinach features/project/issues/milestones.feature + Single Spinach test: `bundle exec spinach features/project/issues/milestones.feature` - -### Documentation +## Documentation All documentation can be found on [doc.gitlab.com/ce/](http://doc.gitlab.com/ce/). -### Getting help +## Getting help Please see [Getting help for GitLab](https://www.gitlab.com/getting-help/) on our website for the many options to get help. diff --git a/doc/README.md b/doc/README.md index b73d7bb38e..f05078ee38 100644 --- a/doc/README.md +++ b/doc/README.md @@ -1,24 +1,26 @@ -**User documentation** +# Documentation -+ [API](api/README.md) Explore how you can access GitLab via a simple and powerful API. -+ [Markdown](markdown/markdown.md) Learn what you can do with GitLab's advanced formatting system. -+ [Permissions](permissions/permissions.md) Learn what each role in a project (guest/reporter/developer/master/owner) can do. -+ [Public access](public_access/public_access.md) Learn how you can allow public and internal access to a project. -+ [SSH](ssh/README.md) Setup your ssh keys and deploy keys for secure access to your projects. -+ [Web hooks](web_hooks/web_hooks.md) Let GitLab notify you when new code has been pushed to your project. -+ [Workflow](workflow/README.md) Learn how to use Git and GitLab together. +## User documentation -**Administrator documentation** +- [API](api/README.md) Explore how you can access GitLab via a simple and powerful API. +- [Markdown](markdown/markdown.md) Learn what you can do with GitLab's advanced formatting system. +- [Permissions](permissions/permissions.md) Learn what each role in a project (guest/reporter/developer/master/owner) can do. +- [Public access](public_access/public_access.md) Learn how you can allow public and internal access to a project. +- [SSH](ssh/README.md) Setup your ssh keys and deploy keys for secure access to your projects. +- [Web hooks](web_hooks/web_hooks.md) Let GitLab notify you when new code has been pushed to your project. +- [Workflow](workflow/README.md) Learn how to use Git and GitLab together. -+ [Install](install/README.md) Requirements, directory structures and manual installation. -+ [Integration](integration/README.md) How to integrate with systems such as JIRA, Redmine, LDAP and Twitter. -+ [Raketasks](raketasks/README.md) Explore what GitLab has in store for you to make administration easier. -+ [System hooks](system_hooks/system_hooks.md) Let GitLab notify you when certain management tasks need to be carried out. -+ [Security](security/README.md) Learn what you can do to further secure your GitLab instance. -+ [Update](update/README.md) Update guides to upgrade your installation. +## Administrator documentation -**Contributor documentation** +- [Install](install/README.md) Requirements, directory structures and manual installation. +- [Integration](integration/README.md) How to integrate with systems such as JIRA, Redmine, LDAP and Twitter. +- [Raketasks](raketasks/README.md) Explore what GitLab has in store for you to make administration easier. +- [System hooks](system_hooks/system_hooks.md) Let GitLab notify you when certain management tasks need to be carried out. +- [Security](security/README.md) Learn what you can do to further secure your GitLab instance. +- [Update](update/README.md) Update guides to upgrade your installation. -+ [Development](development/README.md) Explains the architecture and the guidelines for shell commands. -+ [Legal](legal/README.md) Contributor license agreements. -+ [Release](release/README.md) How to make the monthly and security releases. +## Contributor documentation + +- [Development](development/README.md) Explains the architecture and the guidelines for shell commands. +- [Legal](legal/README.md) Contributor license agreements. +- [Release](release/README.md) How to make the monthly and security releases. diff --git a/doc/api/README.md b/doc/api/README.md index acd2f524be..e91d3af59d 100644 --- a/doc/api/README.md +++ b/doc/api/README.md @@ -2,31 +2,31 @@ ## Resources -+ [Users](users.md) -+ [Session](session.md) -+ [Projects](projects.md) -+ [Project Snippets](project_snippets.md) -+ [Repositories](repositories.md) -+ [Repository Files](repository_files.md) -+ [Commits](commits.md) -+ [Branches](branches.md) -+ [Merge Requests](merge_requests.md) -+ [Issues](issues.md) -+ [Milestones](milestones.md) -+ [Notes](notes.md) (comments) -+ [Deploy Keys](deploy_keys.md) -+ [System Hooks](system_hooks.md) -+ [Groups](groups.md) +- [Users](users.md) +- [Session](session.md) +- [Projects](projects.md) +- [Project Snippets](project_snippets.md) +- [Repositories](repositories.md) +- [Repository Files](repository_files.md) +- [Commits](commits.md) +- [Branches](branches.md) +- [Merge Requests](merge_requests.md) +- [Issues](issues.md) +- [Milestones](milestones.md) +- [Notes](notes.md) (comments) +- [Deploy Keys](deploy_keys.md) +- [System Hooks](system_hooks.md) +- [Groups](groups.md) ## Clients -+ [php-gitlab-api](https://github.com/m4tthumphrey/php-gitlab-api) - PHP -+ [Laravel API Wrapper for GitLab CE](https://github.com/adamgoose/gitlab) - PHP / [Laravel](http://laravel.com) -+ [Ruby Wrapper](https://github.com/NARKOZ/gitlab) - Ruby -+ [python-gitlab](https://github.com/Itxaka/python-gitlab) - Python -+ [java-gitlab-api](https://github.com/timols/java-gitlab-api) - Java -+ [node-gitlab](https://github.com/moul/node-gitlab) - Node.js -+ [NGitLab](https://github.com/Scooletz/NGitLab) - .NET +- [php-gitlab-api](https://github.com/m4tthumphrey/php-gitlab-api) - PHP +- [Laravel API Wrapper for GitLab CE](https://github.com/adamgoose/gitlab) - PHP / [Laravel](http://laravel.com) +- [Ruby Wrapper](https://github.com/NARKOZ/gitlab) - Ruby +- [python-gitlab](https://github.com/Itxaka/python-gitlab) - Python +- [java-gitlab-api](https://github.com/timols/java-gitlab-api) - Java +- [node-gitlab](https://github.com/moul/node-gitlab) - Node.js +- [NGitLab](https://github.com/Scooletz/NGitLab) - .NET ## Introduction @@ -54,41 +54,35 @@ Example for a valid API request using curl and authentication via header: curl --header "PRIVATE-TOKEN: QVy1PB7sTxfy4pqfZM1U" "http://example.com/api/v3/projects" ``` - The API uses JSON to serialize data. You don't need to specify `.json` at the end of API URL. - - ## Status codes -The API is designed to return different status codes according to context and action. In this way -if a request results in an error the caller is able to get insight into what went wrong, e.g. -status code `400 Bad Request` is returned if a required attribute is missing from the request. -The following list gives an overview of how the API functions generally behave. +The API is designed to return different status codes according to context and action. In this way if a request results in an error the caller is able to get insight into what went wrong, e.g. status code `400 Bad Request` is returned if a required attribute is missing from the request. The following list gives an overview of how the API functions generally behave. API request types: -* `GET` requests access one or more resources and return the result as JSON -* `POST` requests return `201 Created` if the resource is successfully created and return the newly created resource as JSON -* `GET`, `PUT` and `DELETE` return `200 Ok` if the resource is accessed, modified or deleted successfully, the (modified) result is returned as JSON -* `DELETE` requests are designed to be idempotent, meaning a request a resource still returns `200 Ok` even it was deleted before or is not available. The reasoning behind it is the user is not really interested if the resource existed before or not. - +- `GET` requests access one or more resources and return the result as JSON +- `POST` requests return `201 Created` if the resource is successfully created and return the newly created resource as JSON +- `GET`, `PUT` and `DELETE` return `200 Ok` if the resource is accessed, modified or deleted successfully, the (modified) result is returned as JSON +- `DELETE` requests are designed to be idempotent, meaning a request a resource still returns `200 Ok` even it was deleted before or is not available. The reasoning behind it is the user is not really interested if the resource existed before or not. The following list shows the possible return codes for API requests. Return values: -* `200 Ok` - The `GET`, `PUT` or `DELETE` request was successful, the resource(s) itself is returned as JSON -* `201 Created` - The `POST` request was successful and the resource is returned as JSON -* `400 Bad Request` - A required attribute of the API request is missing, e.g. the title of an issue is not given -* `401 Unauthorized` - The user is not authenticated, a valid user token is necessary, see above -* `403 Forbidden` - The request is not allowed, e.g. the user is not allowed to delete a project -* `404 Not Found` - A resource could not be accessed, e.g. an ID for a resource could not be found -* `405 Method Not Allowed` - The request is not supported -* `409 Conflict` - A conflicting resource already exists, e.g. creating a project with a name that already exists -* `500 Server Error` - While handling the request something went wrong on the server side +- `200 Ok` - The `GET`, `PUT` or `DELETE` request was successful, the resource(s) itself is returned as JSON +- `201 Created` - The `POST` request was successful and the resource is returned as JSON +- `400 Bad Request` - A required attribute of the API request is missing, e.g. the title of an issue is not given +- `401 Unauthorized` - The user is not authenticated, a valid user token is necessary, see above +- `403 Forbidden` - The request is not allowed, e.g. the user is not allowed to delete a project +- `404 Not Found` - A resource could not be accessed, e.g. an ID for a resource could not be found +- `405 Method Not Allowed` - The request is not supported +- `409 Conflict` - A conflicting resource already exists, e.g. creating a project with a name that already exists +- `500 Server Error` - While handling the request something went wrong on the server side ## Sudo + All API requests support performing an api call as if you were another user, if your private token is for an administration account. You need to pass `sudo` parameter by url or header with an id or username of the user you want to perform the operation as. If passed as header, the header name must be "SUDO" (capitals). If a non administrative `private_token` is provided then an error message will be returned with status code 403: @@ -112,16 +106,17 @@ Example of a valid API with sudo request: ``` GET http://example.com/api/v3/projects?private_token=QVy1PB7sTxfy4pqfZM1U&sudo=username ``` + ``` GET http://example.com/api/v3/projects?private_token=QVy1PB7sTxfy4pqfZM1U&sudo=23 ``` - Example for a valid API request with sudo using curl and authentication via header: ``` curl --header "PRIVATE-TOKEN: QVy1PB7sTxfy4pqfZM1U" --header "SUDO: username" "http://example.com/api/v3/projects" ``` + ``` curl --header "PRIVATE-TOKEN: QVy1PB7sTxfy4pqfZM1U" --header "SUDO: 23" "http://example.com/api/v3/projects" ``` @@ -130,24 +125,21 @@ curl --header "PRIVATE-TOKEN: QVy1PB7sTxfy4pqfZM1U" --header "SUDO: 23" "http:// When listing resources you can pass the following parameters: -+ `page` (default: `1`) - page number -+ `per_page` (default: `20`, max: `100`) - number of items to list per page +- `page` (default: `1`) - page number +- `per_page` (default: `20`, max: `100`) - number of items to list per page -[Link headers](http://www.w3.org/wiki/LinkHeader) are send back with each response. -These have `rel` prev/next/first/last and contain the relevant url. -Please use these instead of generating your own urls. +[Link headers](http://www.w3.org/wiki/LinkHeader) are send back with each response. These have `rel` prev/next/first/last and contain the relevant URL. Please use these instead of generating your own urls. ## id vs iid -When you work with API you may notice two similar fields in api entites: id and iid. -The main difference between them is scope. Example: +When you work with API you may notice two similar fields in api entites: id and iid. The main difference between them is scope. Example: -Issue - id: 46 - iid: 5 +Issue: -* id - is uniq across all Issues table. It used for any api calls. -* iid - is uniq only in scope of single project. When you browse issues or merge requests with Web UI - you see iid. + id: 46 + iid: 5 -So if you want to get issue with api you use `http://host/api/v3/.../issues/:id.json` -But when you want to create a link to web page - use `http:://host/project/issues/:iid.json` +- id - is uniq across all Issues table. It used for any api calls. +- iid - is uniq only in scope of single project. When you browse issues or merge requests with Web UI - you see iid. + +So if you want to get issue with api you use `http://host/api/v3/.../issues/:id.json`. But when you want to create a link to web page - use `http:://host/project/issues/:iid.json` diff --git a/doc/api/branches.md b/doc/api/branches.md index bb2d3fec09..f695b48fe2 100644 --- a/doc/api/branches.md +++ b/doc/api/branches.md @@ -10,7 +10,7 @@ GET /projects/:id/repository/branches Parameters: -+ `id` (required) - The ID of a project +- `id` (required) - The ID of a project ```json [ @@ -52,8 +52,8 @@ GET /projects/:id/repository/branches/:branch Parameters: -+ `id` (required) - The ID of a project -+ `branch` (required) - The name of the branch +- `id` (required) - The ID of a project +- `branch` (required) - The name of the branch ```json { @@ -82,7 +82,6 @@ Parameters: } ``` - ## Protect repository branch Protects a single project repository branch. This is an idempotent function, protecting an already @@ -94,8 +93,8 @@ PUT /projects/:id/repository/branches/:branch/protect Parameters: -+ `id` (required) - The ID of a project -+ `branch` (required) - The name of the branch +- `id` (required) - The ID of a project +- `branch` (required) - The name of the branch ```json { @@ -124,7 +123,6 @@ Parameters: } ``` - ## Unprotect repository branch Unprotects a single project repository branch. This is an idempotent function, unprotecting an already @@ -136,8 +134,8 @@ PUT /projects/:id/repository/branches/:branch/unprotect Parameters: -+ `id` (required) - The ID of a project -+ `branch` (required) - The name of the branch +- `id` (required) - The ID of a project +- `branch` (required) - The name of the branch ```json { @@ -168,16 +166,15 @@ Parameters: ## Create repository branch - ``` POST /projects/:id/repository/branches ``` Parameters: -+ `id` (required) - The ID of a project -+ `branch_name` (required) - The name of the branch -+ `ref` (required) - Create branch from commit sha or existing branch +- `id` (required) - The ID of a project +- `branch_name` (required) - The name of the branch +- `ref` (required) - Create branch from commit sha or existing branch ```json { diff --git a/doc/api/commits.md b/doc/api/commits.md index 241fe0e585..d55b34c0c1 100644 --- a/doc/api/commits.md +++ b/doc/api/commits.md @@ -10,8 +10,8 @@ GET /projects/:id/repository/commits Parameters: -+ `id` (required) - The ID of a project -+ `ref_name` (optional) - The name of a repository branch or tag or if not given the default branch +- `id` (required) - The ID of a project +- `ref_name` (optional) - The name of a repository branch or tag or if not given the default branch ```json [ @@ -44,8 +44,8 @@ GET /projects/:id/repository/commits/:sha Parameters: -+ `id` (required) - The ID of a project -+ `sha` (required) - The commit hash or name of a repository branch or tag +- `id` (required) - The ID of a project +- `sha` (required) - The commit hash or name of a repository branch or tag ```json { @@ -63,7 +63,6 @@ Parameters: } ``` - ## Get the diff of a commit Get the diff of a commit in a project. @@ -74,8 +73,8 @@ GET /projects/:id/repository/commits/:sha/diff Parameters: -+ `id` (required) - The ID of a project -+ `sha` (required) - The name of a repository branch or tag or if not given the default branch +- `id` (required) - The ID of a project +- `sha` (required) - The name of a repository branch or tag or if not given the default branch ```json [ @@ -91,5 +90,3 @@ Parameters: } ] ``` - - diff --git a/doc/api/deploy_keys.md b/doc/api/deploy_keys.md index 6aa7be93c0..e4492fc609 100644 --- a/doc/api/deploy_keys.md +++ b/doc/api/deploy_keys.md @@ -1,6 +1,6 @@ # Deploy Keys -### List deploy keys +## List deploy keys Get a list of a project's deploy keys. @@ -10,7 +10,7 @@ GET /projects/:id/keys Parameters: -+ `id` (required) - The ID of the project +- `id` (required) - The ID of the project ```json [ @@ -29,8 +29,7 @@ Parameters: ] ``` - -### Single deploy key +## Single deploy key Get a single key. @@ -40,8 +39,8 @@ GET /projects/:id/keys/:key_id Parameters: -+ `id` (required) - The ID of the project -+ `key_id` (required) - The ID of the deploy key +- `id` (required) - The ID of the project +- `key_id` (required) - The ID of the deploy key ```json { @@ -52,8 +51,7 @@ Parameters: } ``` - -### Add deploy key +## Add deploy key Creates a new deploy key for a project. If deploy key already exists in another project - it will be joined to project but only if original one was is accessible by same user @@ -64,12 +62,11 @@ POST /projects/:id/keys Parameters: -+ `id` (required) - The ID of the project -+ `title` (required) - New deploy key's title -+ `key` (required) - New deploy key +- `id` (required) - The ID of the project +- `title` (required) - New deploy key's title +- `key` (required) - New deploy key - -### Delete deploy key +## Delete deploy key Delete a deploy key from a project @@ -79,6 +76,5 @@ DELETE /projects/:id/keys/:key_id Parameters: -+ `id` (required) - The ID of the project -+ `key_id` (required) - The ID of the deploy key - +- `id` (required) - The ID of the project +- `key_id` (required) - The ID of the deploy key diff --git a/doc/api/issues.md b/doc/api/issues.md index c769d7bb69..f775d502a6 100644 --- a/doc/api/issues.md +++ b/doc/api/issues.md @@ -73,7 +73,6 @@ GET /issues ] ``` - ## List project issues Get a list of project issues. This function accepts pagination parameters `page` and `per_page` @@ -85,8 +84,7 @@ GET /projects/:id/issues Parameters: -+ `id` (required) - The ID of a project - +- `id` (required) - The ID of a project ## Single issue @@ -98,8 +96,8 @@ GET /projects/:id/issues/:issue_id Parameters: -+ `id` (required) - The ID of a project -+ `issue_id` (required) - The ID of a project issue +- `id` (required) - The ID of a project +- `issue_id` (required) - The ID of a project issue ```json { @@ -142,7 +140,6 @@ Parameters: } ``` - ## New issue Creates a new project issue. @@ -153,13 +150,12 @@ POST /projects/:id/issues Parameters: -+ `id` (required) - The ID of a project -+ `title` (required) - The title of an issue -+ `description` (optional) - The description of an issue -+ `assignee_id` (optional) - The ID of a user to assign issue -+ `milestone_id` (optional) - The ID of a milestone to assign issue -+ `labels` (optional) - Comma-separated label names for an issue - +- `id` (required) - The ID of a project +- `title` (required) - The title of an issue +- `description` (optional) - The description of an issue +- `assignee_id` (optional) - The ID of a user to assign issue +- `milestone_id` (optional) - The ID of a milestone to assign issue +- `labels` (optional) - Comma-separated label names for an issue ## Edit issue @@ -171,21 +167,18 @@ PUT /projects/:id/issues/:issue_id Parameters: -+ `id` (required) - The ID of a project -+ `issue_id` (required) - The ID of a project's issue -+ `title` (optional) - The title of an issue -+ `description` (optional) - The description of an issue -+ `assignee_id` (optional) - The ID of a user to assign issue -+ `milestone_id` (optional) - The ID of a milestone to assign issue -+ `labels` (optional) - Comma-separated label names for an issue -+ `state_event` (optional) - The state event of an issue ('close' to close issue and 'reopen' to reopen it) - +- `id` (required) - The ID of a project +- `issue_id` (required) - The ID of a project's issue +- `title` (optional) - The title of an issue +- `description` (optional) - The description of an issue +- `assignee_id` (optional) - The ID of a user to assign issue +- `milestone_id` (optional) - The ID of a milestone to assign issue +- `labels` (optional) - Comma-separated label names for an issue +- `state_event` (optional) - The state event of an issue ('close' to close issue and 'reopen' to reopen it) ## Delete existing issue (**Deprecated**) -The function is deprecated and returns a `405 Method Not Allowed` -error if called. An issue gets now closed and is done by calling `PUT /projects/:id/issues/:issue_id` with -parameter `closed` set to 1. +The function is deprecated and returns a `405 Method Not Allowed` error if called. An issue gets now closed and is done by calling `PUT /projects/:id/issues/:issue_id` with parameter `closed` set to 1. ``` DELETE /projects/:id/issues/:issue_id @@ -193,8 +186,8 @@ DELETE /projects/:id/issues/:issue_id Parameters: -+ `id` (required) - The project ID -+ `issue_id` (required) - The ID of the issue +- `id` (required) - The project ID +- `issue_id` (required) - The ID of the issue ## Comments on issues diff --git a/doc/api/merge_requests.md b/doc/api/merge_requests.md index 284c2befe6..27c0d644e1 100644 --- a/doc/api/merge_requests.md +++ b/doc/api/merge_requests.md @@ -2,11 +2,7 @@ ## List merge requests -Get all merge requests for this project. -The `state` parameter can be used to get only merge requests with a -given state (`opened`, `closed`, or `merged`) or all of them (`all`). -The pagination parameters `page` and `per_page` can be used to restrict the -list of merge requests. +Get all merge requests for this project. The `state` parameter can be used to get only merge requests with a given state (`opened`, `closed`, or `merged`) or all of them (`all`). The pagination parameters `page` and `per_page` can be used to restrict the list of merge requests. ``` GET /projects/:id/merge_requests @@ -16,8 +12,8 @@ GET /projects/:id/merge_requests?state=all Parameters: -+ `id` (required) - The ID of a project -+ `state` (optional) - Return `all` requests or just those that are `merged`, `opened` or `closed` +- `id` (required) - The ID of a project +- `state` (optional) - Return `all` requests or just those that are `merged`, `opened` or `closed` ```json [ @@ -51,7 +47,6 @@ Parameters: ] ``` - ## Get single MR Shows information about a single merge request. @@ -62,8 +57,8 @@ GET /projects/:id/merge_request/:merge_request_id Parameters: -+ `id` (required) - The ID of a project -+ `merge_request_id` (required) - The ID of MR +- `id` (required) - The ID of a project +- `merge_request_id` (required) - The ID of MR ```json { @@ -95,7 +90,6 @@ Parameters: } ``` - ## Create MR Creates a new merge request. @@ -106,12 +100,12 @@ POST /projects/:id/merge_requests Parameters: -+ `id` (required) - The ID of a project -+ `source_branch` (required) - The source branch -+ `target_branch` (required) - The target branch -+ `assignee_id` (optional) - Assignee user ID -+ `title` (required) - Title of MR -+ `target_project_id` (optional) - The target project (numeric id) +- `id` (required) - The ID of a project +- `source_branch` (required) - The source branch +- `target_branch` (required) - The target branch +- `assignee_id` (optional) - Assignee user ID +- `title` (required) - Title of MR +- `target_project_id` (optional) - The target project (numeric id) ```json { @@ -142,7 +136,6 @@ Parameters: } ``` - ## Update MR Updates an existing merge request. You can change branches, title, or even close the MR. @@ -153,13 +146,13 @@ PUT /projects/:id/merge_request/:merge_request_id Parameters: -+ `id` (required) - The ID of a project -+ `merge_request_id` (required) - ID of MR -+ `source_branch` - The source branch -+ `target_branch` - The target branch -+ `assignee_id` - Assignee user ID -+ `title` - Title of MR -+ `state_event` - New state (close|reopen|merge) +- `id` (required) - The ID of a project +- `merge_request_id` (required) - ID of MR +- `source_branch` - The source branch +- `target_branch` - The target branch +- `assignee_id` - Assignee user ID +- `title` - Title of MR +- `state_event` - New state (close|reopen|merge) ```json { @@ -190,13 +183,16 @@ Parameters: } ``` - ## Accept MR Merge changes submitted with MR usign this API. + If merge success you get 200 OK. + If it has some conflicts and can not be merged - you get 405 and error message 'Branch cannot be merged' + If merge request is already merged or closed - you get 405 and error message 'Method Not Allowed' + If you dont have permissions to accept this merge request - you get 401 ``` @@ -205,9 +201,9 @@ PUT /projects/:id/merge_request/:merge_request_id/merge Parameters: -+ `id` (required) - The ID of a project -+ `merge_request_id` (required) - ID of MR -+ `merge_commit_message` (optional) - Custom merge commit message +- `id` (required) - The ID of a project +- `merge_request_id` (required) - ID of MR +- `merge_commit_message` (optional) - Custom merge commit message ```json { @@ -238,7 +234,6 @@ Parameters: } ``` - ## Post comment to MR Adds a comment to a merge request. @@ -249,10 +244,9 @@ POST /projects/:id/merge_request/:merge_request_id/comments Parameters: -+ `id` (required) - The ID of a project -+ `merge_request_id` (required) - ID of merge request -+ `note` (required) - Text of comment - +- `id` (required) - The ID of a project +- `merge_request_id` (required) - ID of merge request +- `note` (required) - Text of comment ```json { @@ -268,7 +262,6 @@ Parameters: } ``` - ## Get the comments on a MR Gets all the comments associated with a merge request. @@ -279,8 +272,8 @@ GET /projects/:id/merge_request/:merge_request_id/comments Parameters: -+ `id` (required) - The ID of a project -+ `merge_request_id` (required) - ID of merge request +- `id` (required) - The ID of a project +- `merge_request_id` (required) - ID of merge request ```json [ diff --git a/doc/api/milestones.md b/doc/api/milestones.md index b0f355b9a0..2f52532750 100644 --- a/doc/api/milestones.md +++ b/doc/api/milestones.md @@ -26,8 +26,7 @@ GET /projects/:id/milestones Parameters: -+ `id` (required) - The ID of a project - +- `id` (required) - The ID of a project ## Get single milestone @@ -39,9 +38,8 @@ GET /projects/:id/milestones/:milestone_id Parameters: -+ `id` (required) - The ID of a project -+ `milestone_id` (required) - The ID of a project milestone - +- `id` (required) - The ID of a project +- `milestone_id` (required) - The ID of a project milestone ## Create new milestone @@ -53,11 +51,10 @@ POST /projects/:id/milestones Parameters: -+ `id` (required) - The ID of a project -+ `title` (required) - The title of an milestone -+ `description` (optional) - The description of the milestone -+ `due_date` (optional) - The due date of the milestone - +- `id` (required) - The ID of a project +- `title` (required) - The title of an milestone +- `description` (optional) - The description of the milestone +- `due_date` (optional) - The due date of the milestone ## Edit milestone @@ -69,10 +66,9 @@ PUT /projects/:id/milestones/:milestone_id Parameters: -+ `id` (required) - The ID of a project -+ `milestone_id` (required) - The ID of a project milestone -+ `title` (optional) - The title of a milestone -+ `description` (optional) - The description of a milestone -+ `due_date` (optional) - The due date of the milestone -+ `state_event` (optional) - The state event of the milestone (close|activate) - +- `id` (required) - The ID of a project +- `milestone_id` (required) - The ID of a project milestone +- `title` (optional) - The title of a milestone +- `description` (optional) - The description of a milestone +- `due_date` (optional) - The due date of the milestone +- `state_event` (optional) - The state event of the milestone (close|activate) diff --git a/doc/api/project_snippets.md b/doc/api/project_snippets.md index 7a49827233..47c81b6446 100644 --- a/doc/api/project_snippets.md +++ b/doc/api/project_snippets.md @@ -10,8 +10,7 @@ GET /projects/:id/snippets Parameters: -+ `id` (required) - The ID of a project - +- `id` (required) - The ID of a project ## Single snippet @@ -23,8 +22,8 @@ GET /projects/:id/snippets/:snippet_id Parameters: -+ `id` (required) - The ID of a project -+ `snippet_id` (required) - The ID of a project's snippet +- `id` (required) - The ID of a project +- `snippet_id` (required) - The ID of a project's snippet ```json { @@ -45,7 +44,6 @@ Parameters: } ``` - ## Create new snippet Creates a new project snippet. The user must have permission to create new snippets. @@ -56,11 +54,10 @@ POST /projects/:id/snippets Parameters: -+ `id` (required) - The ID of a project -+ `title` (required) - The title of a snippet -+ `file_name` (required) - The name of a snippet file -+ `code` (required) - The content of a snippet - +- `id` (required) - The ID of a project +- `title` (required) - The title of a snippet +- `file_name` (required) - The name of a snippet file +- `code` (required) - The content of a snippet ## Update snippet @@ -72,12 +69,11 @@ PUT /projects/:id/snippets/:snippet_id Parameters: -+ `id` (required) - The ID of a project -+ `snippet_id` (required) - The ID of a project's snippet -+ `title` (optional) - The title of a snippet -+ `file_name` (optional) - The name of a snippet file -+ `code` (optional) - The content of a snippet - +- `id` (required) - The ID of a project +- `snippet_id` (required) - The ID of a project's snippet +- `title` (optional) - The title of a snippet +- `file_name` (optional) - The name of a snippet file +- `code` (optional) - The content of a snippet ## Delete snippet @@ -90,9 +86,8 @@ DELETE /projects/:id/snippets/:snippet_id Parameters: -+ `id` (required) - The ID of a project -+ `snippet_id` (required) - The ID of a project's snippet - +- `id` (required) - The ID of a project +- `snippet_id` (required) - The ID of a project's snippet ## Snippet content @@ -104,5 +99,5 @@ GET /projects/:id/snippets/:snippet_id/raw Parameters: -+ `id` (required) - The ID of a project -+ `snippet_id` (required) - The ID of a project's snippet +- `id` (required) - The ID of a project +- `snippet_id` (required) - The ID of a project's snippet diff --git a/doc/api/repository_files.md b/doc/api/repository_files.md index 820ae71361..ae56b04b6c 100644 --- a/doc/api/repository_files.md +++ b/doc/api/repository_files.md @@ -4,12 +4,11 @@ ## Create, read, update and delete repository files using this API -- - - +--- ## Get file from repository -Allows you to receive information about file in repository like name, size, content. -Note that file content is Base64 encoded. +Allows you to receive information about file in repository like name, size, content. Note that file content is Base64 encoded. ``` GET /projects/:id/repository/files @@ -32,8 +31,8 @@ Example response: Parameters: -+ `file_path` (required) - Full path to new file. Ex. lib/class.rb -+ `ref` (required) - The name of branch, tag or commit +- `file_path` (required) - Full path to new file. Ex. lib/class.rb +- `ref` (required) - The name of branch, tag or commit ## Create new file in repository @@ -52,11 +51,11 @@ Example response: Parameters: -+ `file_path` (required) - Full path to new file. Ex. lib/class.rb -+ `branch_name` (required) - The name of branch -+ `encoding` (optional) - 'text' or 'base64'. Text is default. -+ `content` (required) - File content -+ `commit_message` (required) - Commit message +- `file_path` (required) - Full path to new file. Ex. lib/class.rb +- `branch_name` (required) - The name of branch +- `encoding` (optional) - 'text' or 'base64'. Text is default. +- `content` (required) - File content +- `commit_message` (required) - Commit message ## Update existing file in repository @@ -75,11 +74,11 @@ Example response: Parameters: -+ `file_path` (required) - Full path to file. Ex. lib/class.rb -+ `branch_name` (required) - The name of branch -+ `encoding` (optional) - 'text' or 'base64'. Text is default. -+ `content` (required) - New file content -+ `commit_message` (required) - Commit message +- `file_path` (required) - Full path to file. Ex. lib/class.rb +- `branch_name` (required) - The name of branch +- `encoding` (optional) - 'text' or 'base64'. Text is default. +- `content` (required) - New file content +- `commit_message` (required) - Commit message ## Delete existing file in repository @@ -98,7 +97,6 @@ Example response: Parameters: -+ `file_path` (required) - Full path to file. Ex. lib/class.rb -+ `branch_name` (required) - The name of branch -+ `commit_message` (required) - Commit message - +- `file_path` (required) - Full path to file. Ex. lib/class.rb +- `branch_name` (required) - The name of branch +- `commit_message` (required) - Commit message diff --git a/doc/api/system_hooks.md b/doc/api/system_hooks.md index 0d33aee213..6483a73c7e 100644 --- a/doc/api/system_hooks.md +++ b/doc/api/system_hooks.md @@ -2,7 +2,7 @@ All methods require admin authorization. -The url endpoint of the system hooks can be configured in [the admin area under hooks](/admin/hooks). +The URL endpoint of the system hooks can be configured in [the admin area under hooks](/admin/hooks). ## List system hooks @@ -14,7 +14,7 @@ GET /hooks Parameters: -+ **none** +- **none** ```json [ @@ -34,8 +34,7 @@ POST /hooks Parameters: -+ `url` (required) - The hook URL - +- `url` (required) - The hook URL ## Test system hook @@ -45,7 +44,7 @@ GET /hooks/:id Parameters: -+ `id` (required) - The ID of hook +- `id` (required) - The ID of hook ```json { @@ -60,8 +59,7 @@ Parameters: ## Delete system hook -Deletes a system hook. This is an idempotent API function and returns `200 Ok` even if the hook -is not available. If the hook is deleted it is also returned as JSON. +Deletes a system hook. This is an idempotent API function and returns `200 Ok` even if the hook is not available. If the hook is deleted it is also returned as JSON. ``` DELETE /hooks/:id @@ -69,4 +67,4 @@ DELETE /hooks/:id Parameters: -+ `id` (required) - The ID of hook +- `id` (required) - The ID of hook diff --git a/doc/api/users.md b/doc/api/users.md index c185cf6478..94af37629f 100644 --- a/doc/api/users.md +++ b/doc/api/users.md @@ -3,6 +3,7 @@ ## List users Get a list of users. + This function takes pagination parameters `page` and `per_page` to restrict the list of users. ``` @@ -53,8 +54,7 @@ GET /users ] ``` -You can search for a users by email or username with: -`/users?search=John` +You can search for a users by email or username with: `/users?search=John` Also see `def search query` in `app/models/user.rb`. @@ -68,7 +68,7 @@ GET /users/:id Parameters: -+ `id` (required) - The ID of a user +- `id` (required) - The ID of a user ```json { @@ -93,7 +93,6 @@ Parameters: } ``` - ## User creation Creates a new user. Note only administrators can create new users. @@ -104,21 +103,20 @@ POST /users Parameters: -+ `email` (required) - Email -+ `password` (required) - Password -+ `username` (required) - Username -+ `name` (required) - Name -+ `skype` (optional) - Skype ID -+ `linkedin` (optional) - Linkedin -+ `twitter` (optional) - Twitter account -+ `website_url` (optional) - Website url -+ `projects_limit` (optional) - Number of projects user can create -+ `extern_uid` (optional) - External UID -+ `provider` (optional) - External provider name -+ `bio` (optional) - User's bio -+ `admin` (optional) - User is admin - true or false (default) -+ `can_create_group` (optional) - User can create groups - true or false - +- `email` (required) - Email +- `password` (required) - Password +- `username` (required) - Username +- `name` (required) - Name +- `skype` (optional) - Skype ID +- `linkedin` (optional) - Linkedin +- `twitter` (optional) - Twitter account +- `website_url` (optional) - Website url +- `projects_limit` (optional) - Number of projects user can create +- `extern_uid` (optional) - External UID +- `provider` (optional) - External provider name +- `bio` (optional) - User's bio +- `admin` (optional) - User is admin - true or false (default) +- `can_create_group` (optional) - User can create groups - true or false ## User modification @@ -130,30 +128,26 @@ PUT /users/:id Parameters: -+ `email` - Email -+ `username` - Username -+ `name` - Name -+ `password` - Password -+ `skype` - Skype ID -+ `linkedin` - Linkedin -+ `twitter` - Twitter account -+ `website_url` - Website url -+ `projects_limit` - Limit projects each user can create -+ `extern_uid` - External UID -+ `provider` - External provider name -+ `bio` - User's bio -+ `admin` (optional) - User is admin - true or false (default) -+ `can_create_group` (optional) - User can create groups - true or false - -Note, at the moment this method does only return a 404 error, even in cases where a 409 (Conflict) would -be more appropriate, e.g. when renaming the email address to some existing one. +- `email` - Email +- `username` - Username +- `name` - Name +- `password` - Password +- `skype` - Skype ID +- `linkedin` - Linkedin +- `twitter` - Twitter account +- `website_url` - Website url +- `projects_limit` - Limit projects each user can create +- `extern_uid` - External UID +- `provider` - External provider name +- `bio` - User's bio +- `admin` (optional) - User is admin - true or false (default) +- `can_create_group` (optional) - User can create groups - true or false +Note, at the moment this method does only return a 404 error, even in cases where a 409 (Conflict) would be more appropriate, e.g. when renaming the email address to some existing one. ## User deletion -Deletes a user. Available only for administrators. This is an idempotent function, calling this function -for a non-existent user id still returns a status code `200 Ok`. The JSON response differs if the user -was actually deleted or not. In the former the user is returned and in the latter not. +Deletes a user. Available only for administrators. This is an idempotent function, calling this function for a non-existent user id still returns a status code `200 Ok`. The JSON response differs if the user was actually deleted or not. In the former the user is returned and in the latter not. ``` DELETE /users/:id @@ -161,8 +155,7 @@ DELETE /users/:id Parameters: -+ `id` (required) - The ID of the user - +- `id` (required) - The ID of the user ## Current user @@ -194,7 +187,6 @@ GET /user } ``` - ## List SSH keys Get a list of currently authenticated user's SSH keys. @@ -220,7 +212,7 @@ GET /user/keys Parameters: -+ **none** +- **none** ## List SSH keys for user @@ -232,8 +224,7 @@ GET /users/:uid/keys Parameters: -+ `uid` (required) - id of specified user - +- `uid` (required) - id of specified user ## Single SSH key @@ -245,7 +236,7 @@ GET /user/keys/:id Parameters: -+ `id` (required) - The ID of an SSH key +- `id` (required) - The ID of an SSH key ```json { @@ -255,7 +246,6 @@ Parameters: } ``` - ## Add SSH key Creates a new key owned by the currently authenticated user. @@ -266,9 +256,8 @@ POST /user/keys Parameters: -+ `title` (required) - new SSH Key's title -+ `key` (required) - new SSH key - +- `title` (required) - new SSH Key's title +- `key` (required) - new SSH key ## Add SSH key for user @@ -280,17 +269,15 @@ POST /users/:id/keys Parameters: -+ `id` (required) - id of specified user -+ `title` (required) - new SSH Key's title -+ `key` (required) - new SSH key +- `id` (required) - id of specified user +- `title` (required) - new SSH Key's title +- `key` (required) - new SSH key -Will return created key with status `201 Created` on success, or `404 Not -found` on fail. +Will return created key with status `201 Created` on success, or `404 Not found` on fail. -## Delete SSH key +## Delete SSH key for current user -Deletes key owned by currently authenticated user. This is an idempotent function and calling it on a key that is already -deleted or not available results in `200 Ok`. +Deletes key owned by currently authenticated user. This is an idempotent function and calling it on a key that is already deleted or not available results in `200 Ok`. ``` DELETE /user/keys/:id @@ -298,9 +285,9 @@ DELETE /user/keys/:id Parameters: -+ `id` (required) - SSH key ID +- `id` (required) - SSH key ID -## Delete SSH key +## Delete SSH key for given user Deletes key owned by a specified user. Available only for admin. @@ -310,8 +297,7 @@ DELETE /users/:uid/keys/:id Parameters: -+ `uid` (required) - id of specified user -+ `id` (required) - SSH key ID +- `uid` (required) - id of specified user +- `id` (required) - SSH key ID Will return `200 Ok` on success, or `404 Not found` if either user or key cannot be found. - diff --git a/doc/development/README.md b/doc/development/README.md index eb88b6c860..67ee828db6 100644 --- a/doc/development/README.md +++ b/doc/development/README.md @@ -1,5 +1,5 @@ -## Development +# Development -+ [Architecture](architecture.md) of GitLab -+ [Shell commands](shell_commands.md) in the GitLab codebase -+ [Rake tasks](rake_tasks.md) for development +- [Architecture](architecture.md) of GitLab +- [Shell commands](shell_commands.md) in the GitLab codebase +- [Rake tasks](rake_tasks.md) for development diff --git a/doc/development/architecture.md b/doc/development/architecture.md index f2f7a3d5f0..9d0d58b3db 100644 --- a/doc/development/architecture.md +++ b/doc/development/architecture.md @@ -1,78 +1,54 @@ # GitLab Architecture Overview ---- -# Software delivery +## Software delivery -There are two editions of GitLab: [Enterprise Edition](https://www.gitlab.com/gitlab-ee/) (EE) and [Community Edition](https://www.gitlab.com/gitlab-ce/) (CE). -GitLab CE is delivered via git from the [gitlabhq repository](https://gitlab.com/gitlab-org/gitlab-ce/tree/master). -New versions of GitLab are released in stable branches and the master branch is for bleeding edge development. +There are two editions of GitLab: [Enterprise Edition](https://www.gitlab.com/gitlab-ee/) (EE) and [Community Edition](https://www.gitlab.com/gitlab-ce/) (CE). GitLab CE is delivered via git from the [gitlabhq repository](https://gitlab.com/gitlab-org/gitlab-ce/tree/master). New versions of GitLab are released in stable branches and the master branch is for bleeding edge development. -EE releases are available not long after CE releases. -To obtain the GitLab EE there is a [repository at gitlab.com](https://gitlab.com/subscribers/gitlab-ee). -For more information about the release process see the section 'New versions and upgrading' in the readme. +EE releases are available not long after CE releases. To obtain the GitLab EE there is a [repository at gitlab.com](https://gitlab.com/subscribers/gitlab-ee). For more information about the release process see the section 'New versions and upgrading' in the readme. -Both EE and CE require an add-on component called gitlab-shell. -It is obtained from the [gitlab-shell repository](https://gitlab.com/gitlab-org/gitlab-shell/tree/master). -New versions are usually tags but staying on the master branch will give you the latest stable version. -New releases are generally around the same time as GitLab CE releases with exception for informal security updates deemed critical. +Both EE and CE require an add-on component called gitlab-shell. It is obtained from the [gitlab-shell repository](https://gitlab.com/gitlab-org/gitlab-shell/tree/master). New versions are usually tags but staying on the master branch will give you the latest stable version. New releases are generally around the same time as GitLab CE releases with exception for informal security updates deemed critical. -# System Layout +## System Layout When referring to ~git in the pictures it means the home directory of the git user which is typically /home/git. -GitLab is primarily installed within the `/home/git` user home directory as `git` user. -Within the home directory is where the gitlabhq server software resides as well as the repositories (though the repository location is configurable). -The bare repositories are located in `/home/git/repositories`. -GitLab is a ruby on rails application so the particulars of the inner workings can be learned by studying how a ruby on rails application works. +GitLab is primarily installed within the `/home/git` user home directory as `git` user. Within the home directory is where the gitlabhq server software resides as well as the repositories (though the repository location is configurable). + +The bare repositories are located in `/home/git/repositories`. GitLab is a ruby on rails application so the particulars of the inner workings can be learned by studying how a ruby on rails application works. + To serve repositories over SSH there's an add-on application called gitlab-shell which is installed in `/home/git/gitlab-shell`. -## Components +### Components ![GitLab Diagram Overview](gitlab_diagram_overview.png) -A typical install of GitLab will be on Ubuntu Linux or RHEL/CentOS. -It uses Nginx or Apache as a web front end to proxypass the Unicorn web server. -By default, communication between Unicorn and the front end is via a Unix domain socket but forwarding requests via TCP is also supported. -The web front end accesses `/home/git/gitlab/public` bypassing the Unicorn server to serve static pages, uploads (e.g. avatar images or attachments), and precompiled assets. -GitLab serves web pages and a [GitLab API](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/api) using the Unicorn web server. -It uses Sidekiq as a job queue which, in turn, uses redis as a non-persistent database backend for job information, meta data, and incomming jobs. -The GitLab web app uses MySQL or PostgreSQL for persistent database information (e.g. users, permissions, issues, other meta data). -GitLab stores the bare git repositories it serves in `/home/git/repositories` by default. -It also keeps default branch and hook information with the bare repository. -`/home/git/gitlab-satellites` keeps checked out repositories when performing actions such as a merge request, editing files in the web interface, etc. -The satellite repository is used by the web interface for editing repositories and the wiki which is also a git repository. -When serving repositories over HTTP/HTTPS GitLab utilizes the GitLab API to resolve authorization and access as well as serving git objects. +A typical install of GitLab will be on Ubuntu Linux or RHEL/CentOS. It uses Nginx or Apache as a web front end to proxypass the Unicorn web server. By default, communication between Unicorn and the front end is via a Unix domain socket but forwarding requests via TCP is also supported. The web front end accesses `/home/git/gitlab/public` bypassing the Unicorn server to serve static pages, uploads (e.g. avatar images or attachments), and precompiled assets. GitLab serves web pages and a [GitLab API](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/api) using the Unicorn web server. It uses Sidekiq as a job queue which, in turn, uses redis as a non-persistent database backend for job information, meta data, and incomming jobs. -The add-on component gitlab-shell serves repositories over SSH. -It manages the SSH keys within `/home/git/.ssh/authorized_keys` which should not be manually edited. -gitlab-shell accesses the bare repositories directly to serve git objects and communicates with redis to submit jobs to Sidekiq for GitLab to process. - gitlab-shell queries the GitLab API to determine authorization and access. +The GitLab web app uses MySQL or PostgreSQL for persistent database information (e.g. users, permissions, issues, other meta data). GitLab stores the bare git repositories it serves in `/home/git/repositories` by default. It also keeps default branch and hook information with the bare repository. `/home/git/gitlab-satellites` keeps checked out repositories when performing actions such as a merge request, editing files in the web interface, etc. -## Installation Folder Summary +The satellite repository is used by the web interface for editing repositories and the wiki which is also a git repository. When serving repositories over HTTP/HTTPS GitLab utilizes the GitLab API to resolve authorization and access as well as serving git objects. + +The add-on component gitlab-shell serves repositories over SSH. It manages the SSH keys within `/home/git/.ssh/authorized_keys` which should not be manually edited. gitlab-shell accesses the bare repositories directly to serve git objects and communicates with redis to submit jobs to Sidekiq for GitLab to process. gitlab-shell queries the GitLab API to determine authorization and access. + +### Installation Folder Summary To summarize here's the [directory structure of the `git` user home directory](../install/structure.md). - -## Processes +### Processes ps aux | grep '^git' -GitLab has several components to operate. -As a system user (i.e. any user that is not the `git` user) it requires a persistent database (MySQL/PostreSQL) and redis database. -It also uses Apache httpd or nginx to proxypass Unicorn. -As the `git` user it starts Sidekiq and Unicorn (a simple ruby HTTP server running on port `8080` by default). -Under the gitlab user there are normally 4 processes: `unicorn_rails master` (1 process), `unicorn_rails worker` (2 processes), `sidekiq` (1 process). +GitLab has several components to operate. As a system user (i.e. any user that is not the `git` user) it requires a persistent database (MySQL/PostreSQL) and redis database. It also uses Apache httpd or nginx to proxypass Unicorn. As the `git` user it starts Sidekiq and Unicorn (a simple ruby HTTP server running on port `8080` by default). Under the gitlab user there are normally 4 processes: `unicorn_rails master` (1 process), `unicorn_rails worker` (2 processes), `sidekiq` (1 process). -## Repository access +### Repository access -Repositories get accessed via HTTP or SSH. -HTTP cloning/push/pull utilizes the GitLab API and SSH cloning is handled by gitlab-shell (previously explained). +Repositories get accessed via HTTP or SSH. HTTP cloning/push/pull utilizes the GitLab API and SSH cloning is handled by gitlab-shell (previously explained). -# Troubleshooting +## Troubleshooting See the README for more information. -## Init scripts of the services +### Init scripts of the services The GitLab init script starts and stops Unicorn and Sidekiq. @@ -115,61 +91,59 @@ $ /etc/init.d/postgresql Usage: /etc/init.d/postgresql {start|stop|restart|reload|force-reload|status} [version ..] ``` -## Log locations of the services +### Log locations of the services Note: `/home/git/` is shorthand for `/home/git`. gitlabhq (includes Unicorn and Sidekiq logs) -* `/home/git/gitlab/log/` contains `application.log`, `production.log`, `sidekiq.log`, `unicorn.stdout.log`, `githost.log`, `satellites.log`, and `unicorn.stderr.log` normally. +- `/home/git/gitlab/log/` contains `application.log`, `production.log`, `sidekiq.log`, `unicorn.stdout.log`, `githost.log`, `satellites.log`, and `unicorn.stderr.log` normally. gitlab-shell -* `/home/git/gitlab-shell/gitlab-shell.log` +- `/home/git/gitlab-shell/gitlab-shell.log` ssh -* `/var/log/auth.log` auth log (on Ubuntu). -* `/var/log/secure` auth log (on RHEL). +- `/var/log/auth.log` auth log (on Ubuntu). +- `/var/log/secure` auth log (on RHEL). nginx -* `/var/log/nginx/` contains error and access logs. +- `/var/log/nginx/` contains error and access logs. Apache httpd -* [Explanation of apache logs](http://httpd.apache.org/docs/2.2/logs.html). -* `/var/log/apache2/` contains error and output logs (on Ubuntu). -* `/var/log/httpd/` contains error and output logs (on RHEL). +- [Explanation of apache logs](http://httpd.apache.org/docs/2.2/logs.html). +- `/var/log/apache2/` contains error and output logs (on Ubuntu). +- `/var/log/httpd/` contains error and output logs (on RHEL). redis -* `/var/log/redis/redis.log` there are also logrotated logs there. +- `/var/log/redis/redis.log` there are also logrotated logs there. PostgreSQL -* `/var/log/postgresql/*` +- `/var/log/postgresql/*` MySQL -* `/var/log/mysql/*` -* `/var/log/mysql.*` +- `/var/log/mysql/*` +- `/var/log/mysql.*` -## GitLab specific config files +### GitLab specific config files -GitLab has configuration files located in `/home/git/gitlab/config/*`. -Commonly referenced config files include: +GitLab has configuration files located in `/home/git/gitlab/config/*`. Commonly referenced config files include: -* `gitlab.yml` - GitLab configuration. -* `unicorn.rb` - Unicorn web server settings. -* `database.yml` - Database connection settings. +- `gitlab.yml` - GitLab configuration. +- `unicorn.rb` - Unicorn web server settings. +- `database.yml` - Database connection settings. gitlab-shell has a configuration file at `/home/git/gitlab-shell/config.yml`. -## Maintenance Tasks +### Maintenance Tasks -[GitLab](https://gitlab.com/gitlab-org/gitlab-ce/tree/master) provides rake tasks with which you see version information and run a quick check on your configuration to ensure it is configured properly within the application. -See [maintenance rake tasks](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/raketasks/maintenance.md). +[GitLab](https://gitlab.com/gitlab-org/gitlab-ce/tree/master) provides rake tasks with which you see version information and run a quick check on your configuration to ensure it is configured properly within the application. See [maintenance rake tasks](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/raketasks/maintenance.md). In a nutshell, do the following: ``` @@ -179,5 +153,4 @@ bundle exec rake gitlab:env:info RAILS_ENV=production bundle exec rake gitlab:check RAILS_ENV=production ``` -Note: It is recommended to log into the `git` user using `sudo -i -u git` or `sudo su - git`. -While the sudo commands provided by gitlabhq work in Ubuntu they do not always work in RHEL. \ No newline at end of file +Note: It is recommended to log into the `git` user using `sudo -i -u git` or `sudo su - git`. While the sudo commands provided by gitlabhq work in Ubuntu they do not always work in RHEL. diff --git a/doc/development/shell_commands.md b/doc/development/shell_commands.md index af0d5ca442..1f3908f4e2 100644 --- a/doc/development/shell_commands.md +++ b/doc/development/shell_commands.md @@ -8,9 +8,7 @@ ## Use File and FileUtils instead of shell commands -Sometimes we invoke basic Unix commands via the shell when there is also a Ruby API for doing it. -Use the Ruby API if it exists. -http://www.ruby-doc.org/stdlib-2.0.0/libdoc/fileutils/rdoc/FileUtils.html#module-FileUtils-label-Module+Functions +Sometimes we invoke basic Unix commands via the shell when there is also a Ruby API for doing it. Use the Ruby API if it exists. ```ruby # Wrong @@ -30,12 +28,7 @@ This coding style could have prevented CVE-2013-4490. ## Bypass the shell by splitting commands into separate tokens -When we pass shell commands as a single string to Ruby, Ruby will let `/bin/sh` evaluate the entire string. -Essentially, we are asking the shell to evaluate a one-line script. -This creates a risk for shell injection attacks. -It is better to split the shell command into tokens ourselves. -Sometimes we use the scripting capabilities of the shell to change the working directory or set environment variables. -All of this can also be achieved securely straight from Ruby +When we pass shell commands as a single string to Ruby, Ruby will let `/bin/sh` evaluate the entire string. Essentially, we are asking the shell to evaluate a one-line script. This creates a risk for shell injection attacks. It is better to split the shell command into tokens ourselves. Sometimes we use the scripting capabilities of the shell to change the working directory or set environment variables. All of this can also be achieved securely straight from Ruby ```ruby # Wrong @@ -55,8 +48,7 @@ This coding style could have prevented CVE-2013-4546. ## Separate options from arguments with -- -Make the difference between options and arguments clear to the argument parsers of system commands with `--`. -This is supported by many but not all Unix commands. +Make the difference between options and arguments clear to the argument parsers of system commands with `--`. This is supported by many but not all Unix commands. To understand what `--` does, consider the problem below. @@ -68,9 +60,7 @@ cat: illegal option -- l usage: cat [-benstuv] [file ...] ``` -In the example above, the argument parser of `cat` assumes that `-l` is an option. -The solution in the example above is to make it clear to `cat` that `-l` is really an argument, not an option. -Many Unix command line tools follow the convention of separating options from arguments with `--`. +In the example above, the argument parser of `cat` assumes that `-l` is an option. The solution in the example above is to make it clear to `cat` that `-l` is really an argument, not an option. Many Unix command line tools follow the convention of separating options from arguments with `--`. ``` # Example (continued) @@ -91,9 +81,7 @@ This coding style could have prevented CVE-2013-4582. ## Do not use the backticks -Capturing the output of shell commands with backticks reads nicely, but you are forced to pass the command as one string to the shell. -We explained above that this is unsafe. -In the main GitLab codebase, the solution is to use `Gitlab::Popen.popen` instead. +Capturing the output of shell commands with backticks reads nicely, but you are forced to pass the command as one string to the shell. We explained above that this is unsafe. In the main GitLab codebase, the solution is to use `Gitlab::Popen.popen` instead. ```ruby # Wrong diff --git a/doc/install/README.md b/doc/install/README.md index ec80e3cd62..239f5f301e 100644 --- a/doc/install/README.md +++ b/doc/install/README.md @@ -1,4 +1,6 @@ -+ [Installation](installation.md) -+ [Requirements](requirements.md) -+ [Structure](structure.md) -+ [Database MySQL](database_mysql.md) +# Installation + +- [Installation](installation.md) +- [Requirements](requirements.md) +- [Structure](structure.md) +- [Database MySQL](database_mysql.md) diff --git a/doc/install/installation.md b/doc/install/installation.md index 0dc28d8da8..866032fb7c 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -1,14 +1,14 @@ # Installation -# Select Version to Install -Make sure you view [this installation guide](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/install/installation.md) from the branch (version) of GitLab you would like to install. In most cases -this should be the highest numbered stable branch (example shown below). +## Select Version to Install + +Make sure you view [this installation guide](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/install/installation.md) from the branch (version) of GitLab you would like to install. In most cases this should be the highest numbered stable branch (example shown below). ![capture](http://i.imgur.com/d2AlIVj.png) If the highest number stable branch is unclear please check the [GitLab Blog](https://www.gitlab.com/blog/) for installation guide links by version. -# Important notes +## Important notes This guide is long because it covers many cases and includes all commands you need, this is [one of the few installation scripts that actually works out of the box](https://twitter.com/robinvdvleuten/status/424163226532986880). @@ -20,21 +20,18 @@ The following steps have been known to work. Please **use caution when you devia If you find a bug/error in this guide please **submit a merge request** following the [contributing guide](../../CONTRIBUTING.md). -- - - - -# Overview +## Overview The GitLab installation consists of setting up the following components: 1. Packages / Dependencies -2. Ruby -3. System Users -4. Database -5. GitLab -6. Nginx +1. Ruby +1. System Users +1. Database +1. GitLab +1. Nginx - -# 1. Packages / Dependencies +## 1. Packages / Dependencies `sudo` is not installed on Debian by default. Make sure your system is up-to-date and install it. @@ -44,10 +41,7 @@ up-to-date and install it. apt-get upgrade -y apt-get install sudo -y -**Note:** -During this installation some files will need to be edited manually. -If you are familiar with vim set it as default editor with the commands below. -If you are not familiar with vim please skip this and keep using the default editor. +**Note:** During this installation some files will need to be edited manually. If you are familiar with vim set it as default editor with the commands below. If you are not familiar with vim please skip this and keep using the default editor. # Install vim and set as default editor sudo apt-get install -y vim @@ -84,15 +78,13 @@ Is the system packaged Git too old? Remove it and compile from source. # When editing config/gitlab.yml (Step 6), change the git bin_path to /usr/local/bin/git -**Note:** In order to receive mail notifications, make sure to install a -mail server. By default, Debian is shipped with exim4 whereas Ubuntu -does not ship with one. The recommended mail server is postfix and you can install it with: +**Note:** In order to receive mail notifications, make sure to install a mail server. By default, Debian is shipped with exim4 whereas Ubuntu does not ship with one. The recommended mail server is postfix and you can install it with: sudo apt-get install -y postfix Then select 'Internet Site' and press enter to confirm the hostname. -# 2. Ruby +## 2. Ruby The use of ruby version managers such as [RVM](http://rvm.io/), [rbenv](https://github.com/sstephenson/rbenv) or [chruby](https://github.com/postmodern/chruby) with GitLab in production frequently leads to hard to diagnose problems. For example, GitLab Shell is called from OpenSSH and having a version manager can prevent pushing and pulling over SSH. Version managers are not supported and we stronly advise everyone to follow the instructions below to use a system ruby. @@ -113,17 +105,15 @@ Install the Bundler Gem: sudo gem install bundler --no-ri --no-rdoc - -# 3. System Users +## 3. System Users Create a `git` user for Gitlab: sudo adduser --disabled-login --gecos 'GitLab' git -# 4. Database +## 4. Database -We recommend using a PostgreSQL database. For MySQL check [MySQL setup guide](database_mysql.md). -NOTE: because we need to make use of extensions you need at least pgsql 9.1. +We recommend using a PostgreSQL database. For MySQL check [MySQL setup guide](database_mysql.md). *Note*: because we need to make use of extensions you need at least pgsql 9.1. # Install the database packages sudo apt-get install -y postgresql-9.1 postgresql-client libpq-dev @@ -143,13 +133,12 @@ NOTE: because we need to make use of extensions you need at least pgsql 9.1. # Try connecting to the new database with the new user sudo -u git -H psql -d gitlabhq_production - -# 5. GitLab +## 5. GitLab # We'll install GitLab into home directory of the user "git" cd /home/git -## Clone the Source +### Clone the Source # Clone GitLab repository sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ce.git -b 6-9-stable gitlab @@ -157,10 +146,9 @@ NOTE: because we need to make use of extensions you need at least pgsql 9.1. # Go to gitlab dir cd /home/git/gitlab -**Note:** -You can change `6-9-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server! +**Note:** You can change `6-9-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server! -## Configure it +### Configure it cd /home/git/gitlab @@ -206,10 +194,9 @@ You can change `6-9-stable` to `master` if you want the *bleeding edge* version, sudo -u git -H git config --global user.email "example@example.com" sudo -u git -H git config --global core.autocrlf input -**Important Note:** -Make sure to edit both `gitlab.yml` and `unicorn.rb` to match your setup. +**Important Note:** Make sure to edit both `gitlab.yml` and `unicorn.rb` to match your setup. -## Configure GitLab DB settings +### Configure GitLab DB settings # PostgreSQL only: sudo -u git cp config/database.yml.postgresql config/database.yml @@ -229,14 +216,9 @@ Make sure to edit both `gitlab.yml` and `unicorn.rb` to match your setup. # Make config/database.yml readable to git only sudo -u git -H chmod o-rwx config/database.yml -## Install Gems +### Install Gems -**Note:** As of bundler 1.5.2, you can invoke `bundle install -jN` -(where `N` the number of your processor cores) and enjoy the parallel gems installation with measurable -difference in completion time (~60% faster). Check the number of your cores with `nproc`. -For more information check this [post](http://robots.thoughtbot.com/parallel-gem-installing-using-bundler). -First make sure you have bundler >= 1.5.2 (run `bundle -v`) as it addresses some [issues](https://devcenter.heroku.com/changelog-items/411) -that were [fixed](https://github.com/bundler/bundler/pull/2817) in 1.5.2. +**Note:** As of bundler 1.5.2, you can invoke `bundle install -jN` (where `N` the number of your processor cores) and enjoy the parallel gems installation with measurable difference in completion time (~60% faster). Check the number of your cores with `nproc`. For more information check this [post](http://robots.thoughtbot.com/parallel-gem-installing-using-bundler). First make sure you have bundler >= 1.5.2 (run `bundle -v`) as it addresses some [issues](https://devcenter.heroku.com/changelog-items/411) that were [fixed](https://github.com/bundler/bundler/pull/2817) in 1.5.2. cd /home/git/gitlab @@ -246,7 +228,7 @@ that were [fixed](https://github.com/bundler/bundler/pull/2817) in 1.5.2. # Or if you use MySQL (note, the option says "without ... postgres") sudo -u git -H bundle install --deployment --without development test postgres aws -## Install GitLab shell +### Install GitLab shell GitLab Shell is an ssh access and repository management software developed specially for GitLab. @@ -259,8 +241,7 @@ GitLab Shell is an ssh access and repository management software developed speci # By default, the gitlab-shell config is generated from your main gitlab config. You can review (and modify) it as follows: sudo -u git -H editor /home/git/gitlab-shell/config.yml - -## Initialize Database and Activate Advanced Features +### Initialize Database and Activate Advanced Features sudo -u git -H bundle exec rake gitlab:setup RAILS_ENV=production @@ -268,7 +249,7 @@ GitLab Shell is an ssh access and repository management software developed speci # When done you see 'Administrator account created:' -## Install Init Script +### Install Init Script Download the init script (will be /etc/init.d/gitlab): @@ -284,37 +265,34 @@ Make GitLab start on boot: sudo update-rc.d gitlab defaults 21 -## Set up logrotate +### Set up logrotate sudo cp lib/support/logrotate/gitlab /etc/logrotate.d/gitlab -## Check Application Status +### Check Application Status Check if GitLab and its environment are configured correctly: sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production -## Compile assets +### Compile assets sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production -## Start Your GitLab Instance +### Start Your GitLab Instance sudo service gitlab start # or sudo /etc/init.d/gitlab restart +## 6. Nginx -# 6. Nginx +**Note:** Nginx is the officially supported web server for GitLab. If you cannot or do not want to use Nginx as your web server, have a look at the [GitLab recipes](https://gitlab.com/gitlab-org/gitlab-recipes/). -**Note:** -Nginx is the officially supported web server for GitLab. If you cannot or do not want to use Nginx as your web server, have a look at the -[GitLab recipes](https://gitlab.com/gitlab-org/gitlab-recipes/). - -## Installation +### Installation sudo apt-get install -y nginx -## Site Configuration +### Site Configuration Download an example site config: @@ -327,14 +305,13 @@ Make sure to edit the config file to match your setup: # domain name of your host serving GitLab. sudo editor /etc/nginx/sites-available/gitlab -## Restart +### Restart sudo service nginx restart +## Done! -# Done! - -## Double-check Application Status +### Double-check Application Status To make sure you didn't miss anything run a more thorough check with: @@ -342,51 +319,38 @@ To make sure you didn't miss anything run a more thorough check with: If all items are green, then congratulations on successfully installing GitLab! -## Initial Login +### Initial Login -Visit YOUR_SERVER in your web browser for your first GitLab login. -The setup has created an admin account for you. You can use it to log in: +Visit YOUR_SERVER in your web browser for your first GitLab login. The setup has created an admin account for you. You can use it to log in: root 5iveL!fe -**Important Note:** -Please go over to your profile page and immediately change the password, so -nobody can access your GitLab by using this login information later on. +**Important Note:** Please go over to your profile page and immediately change the password, so nobody can access your GitLab by using this login information later on. **Enjoy!** +## Advanced Setup Tips -- - - +### Additional markup styles - -# Advanced Setup Tips - -## Additional markup styles - -Apart from the always supported markdown style there are other rich text files that GitLab can display. -But you might have to install a dependency to do so. -Please see the [github-markup gem readme](https://github.com/gitlabhq/markup#markups) for more information. -For example, reStructuredText markup language support requires python-docutils: +Apart from the always supported markdown style there are other rich text files that GitLab can display. But you might have to install a dependency to do so. Please see the [github-markup gem readme](https://github.com/gitlabhq/markup#markups) for more information. For example, reStructuredText markup language support requires python-docutils: sudo apt-get install -y python-docutils -## Custom Redis Connection +### Custom Redis Connection -If you'd like Resque to connect to a Redis server on a non-standard port or on -a different host, you can configure its connection string via the -`config/resque.yml` file. +If you'd like Resque to connect to a Redis server on a non-standard port or on a different host, you can configure its connection string via the `config/resque.yml` file. # example production: redis://redis.example.tld:6379 -If you want to connect the Redis server via socket, then use the "unix:" URL scheme -and the path to the Redis socket file in the `config/resque.yml` file. +If you want to connect the Redis server via socket, then use the "unix:" URL scheme and the path to the Redis socket file in the `config/resque.yml` file. # example production: unix:/path/to/redis/socket -## Custom SSH Connection +### Custom SSH Connection If you are running SSH on a non-standard port, you must change the gitlab user's SSH config. @@ -398,39 +362,44 @@ If you are running SSH on a non-standard port, you must change the gitlab user's You also need to change the corresponding options (e.g. ssh_user, ssh_host, admin_uri) in the `config\gitlab.yml` file. -## LDAP authentication +### LDAP authentication You can configure LDAP authentication in config/gitlab.yml. Please restart GitLab after editing this file. -## Using Custom Omniauth Providers +### Using Custom Omniauth Providers GitLab uses [Omniauth](http://www.omniauth.org/) for authentication and already ships with a few providers preinstalled (e.g. LDAP, GitHub, Twitter). But sometimes that is not enough and you need to integrate with other authentication solutions. For these cases you can use the Omniauth provider. -### Steps +#### Steps These steps are fairly general and you will need to figure out the exact details from the Omniauth provider's documentation. -* Stop GitLab - `sudo service gitlab stop` +- Stop GitLab: -* Add provider specific configuration options to your `config/gitlab.yml` (you can use the [auth providers section of the example config](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/config/gitlab.yml.example) as a reference) + sudo service gitlab stop -* Add the gem to your [Gemfile](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/Gemfile) - `gem "omniauth-your-auth-provider"` -* If you're using MySQL, install the new Omniauth provider gem by running the following command: - `sudo -u git -H bundle install --without development test postgres --path vendor/bundle --no-deployment` +- Add the gem to your [Gemfile](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/Gemfile): -* If you're using PostgreSQL, install the new Omniauth provider gem by running the following command: - `sudo -u git -H bundle install --without development test mysql --path vendor/bundle --no-deployment` + gem "omniauth-your-auth-provider" -> These are the same commands you used in the [Install Gems section](#install-gems) with `--path vendor/bundle --no-deployment` instead of `--deployment`. +- If you're using MySQL, install the new Omniauth provider gem by running the following command: -* Start GitLab - `sudo service gitlab start` + sudo -u git -H bundle install --without development test postgres --path vendor/bundle --no-deployment +- If you're using PostgreSQL, install the new Omniauth provider gem by running the following command: -### Examples + sudo -u git -H bundle install --without development test mysql --path vendor/bundle --no-deployment + + > These are the same commands you used in the [Install Gems section](#install-gems) with `--path vendor/bundle --no-deployment` instead of `--deployment`. + +- Start GitLab: + + `sudo service gitlab start` + +#### Examples If you have successfully set up a provider that is not shipped with GitLab itself, please let us know. + You can help others by reporting successful configurations and probably share a few insights or provide warnings for common errors or pitfalls by sharing your experience [in the public Wiki](https://github.com/gitlabhq/gitlab-public-wiki/wiki/Custom-omniauth-provider-configurations). + While we can't officially support every possible auth mechanism out there, we'd like to at least help those with special needs. diff --git a/doc/install/requirements.md b/doc/install/requirements.md index f8d2a423c0..cec35ca7be 100644 --- a/doc/install/requirements.md +++ b/doc/install/requirements.md @@ -4,7 +4,7 @@ GitLab is developed for the Linux operating system. For the installations options and instructions please see [the installation section of the readme](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/README.md#installation). -## Supported Linux distributions +### Supported Linux distributions - Ubuntu - Debian @@ -13,37 +13,42 @@ GitLab is developed for the Linux operating system. For the installations option - Scientific Linux - Oracle Linux -## Unsupported Linux distributions +### Unsupported Linux distributions - Arch Linux - Fedora - Gentoo -But on the above unsupported distributions is stll possible to install GitLab yourself with the [manual installation guide](https://github.com/gitlabhq/gitlabhq/blob/master/doc/install/installation.md). +But on the above unsupported distributions is still possible to install GitLab yourself with the [manual installation guide](https://github.com/gitlabhq/gitlabhq/blob/master/doc/install/installation.md). -## Unsupported Unix operating systems +### Unsupported Unix operating systems There is nothing that prevents GitLab from running on other Unix operating systems. + This means you may get it to work on systems running FreeBSD or OS X. + If you want to do this, please be aware it could be a lot of work. + Please consider using a virtual machine to run GitLab. -## Other operating systems such as Windows +### Other operating systems such as Windows GitLab does **not** run on Windows and we have no plans of supporting it in the near future. + Please consider using a virtual machine to run GitLab. - -# Ruby versions +## Ruby versions GitLab requires Ruby (MRI) 2.0+. + +>>>>>>> Update docs to markdown style guide. You will have to use the standard MRI implementation of Ruby. + We love [JRuby](http://jruby.org/) and [Rubinius](http://rubini.us/)) but GitLab needs several Gems that have native extensions. +## Hardware requirements -# Hardware requirements - -## CPU +### CPU - 1 core works supports up to 100 users but the application will not be responsive - **2 cores** is the **recommended** number of cores and supports up to 500 users @@ -53,7 +58,7 @@ We love [JRuby](http://jruby.org/) and [Rubinius](http://rubini.us/)) but GitLab - 32 cores supports up to 20,000 users - 64 cores supports up to 40,000 users -## Memory +### Memory - 512MB is the absolute minimum, you need 256MB of swap, you can configure only one slow unicorn worker, only ssh access will work, we do not recommend this - 1GB supports up to 100 users (with individual repositories under 250MB, otherwise git memory usage necessitates using swap space) @@ -64,11 +69,9 @@ We love [JRuby](http://jruby.org/) and [Rubinius](http://rubini.us/)) but GitLab - 32GB supports up to 20,000 users - 64GB supports up to 40,000 users -## Storage +### Storage -The necessary hard drive space largely depends on the size of the repos you want -to store in GitLab. But as a *rule of thumb* you should have at least twice as much -free space as your all repos combined take up. You need twice the storage because [GitLab satellites](structure.md) contain an extra copy of each repo. +The necessary hard drive space largely depends on the size of the repos you want to store in GitLab. But as a *rule of thumb* you should have at least twice as much free space as your all repos combined take up. You need twice the storage because [GitLab satellites](structure.md) contain an extra copy of each repo. If you want to be flexible about growing your hard drive space in the future consider mounting it using LVM so you can add more hard drives when you need them. @@ -80,7 +83,7 @@ If you have enough RAM memory and a recent CPU the speed of GitLab is mainly lim If you want to run the database separately, the **recommended** database size is **1 MB per user** -# Supported webbrowsers +## Supported webbrowsers - Chrome (Latest stable version) - Firefox (Latest released version) diff --git a/doc/integration/README.md b/doc/integration/README.md index 4773dd8fff..00c73afd87 100644 --- a/doc/integration/README.md +++ b/doc/integration/README.md @@ -1,11 +1,12 @@ # GitLab Integration GitLab integrates with multiple third-party services to allow external issue trackers and external authentication. + See the documentation below for details on how to configure these services. -+ [External issue tracker](external-issue-tracker.md) Redmine, JIRA, etc. -+ [LDAP](ldap.md) Set up sign in via LDAP -+ [OmniAuth](omniauth.md) Sign in via Twitter, GitHub, and Google via OAuth. -+ [Slack](slack.md) Integrate with the Slack chat service +- [External issue tracker](external-issue-tracker.md) Redmine, JIRA, etc. +- [LDAP](ldap.md) Set up sign in via LDAP +- [OmniAuth](omniauth.md) Sign in via Twitter, GitHub, and Google via OAuth. +- [Slack](slack.md) Integrate with the Slack chat service Jenkins support is [available in GitLab EE](http://doc.gitlab.com/ee/integration/jenkins.html). diff --git a/doc/integration/external-issue-tracker.md b/doc/integration/external-issue-tracker.md index 1b531aeeda..6245836bef 100644 --- a/doc/integration/external-issue-tracker.md +++ b/doc/integration/external-issue-tracker.md @@ -1,3 +1,5 @@ +# External issue tracker + GitLab has a great issue tracker but you can also use an external issue tracker such as JIRA or Redmine. This is something that you can turn on per GitLab project. If for example you configure JIRA it provides the following functionality: - the 'Issues' link on the GitLab project pages takes you to the appropriate JIRA issue index; diff --git a/doc/integration/github.md b/doc/integration/github.md index 672536b4da..b53a7c1285 100644 --- a/doc/integration/github.md +++ b/doc/integration/github.md @@ -2,18 +2,24 @@ To enable the GitHub OmniAuth provider you must register your application with GitHub. GitHub will generate a client ID and secret key for you to use. -1. Sign in to GitHub. -2. Navigate to your individual user settings or an organization's settings, depending on how you want the application registered. It does not matter if the application is registered as an individual or an organization - that is entirely up to you. -3. Select "Applications" in the left menu. -4. Select "Register new application". -5. Provide the required details. - * Application name: This can be anything. Consider something like "\'s GitLab" or "\'s GitLab" or something else descriptive. - * Homepage URL: The URL to your GitLab installation. 'https://gitlab.company.com' - * Application description: Fill this in if you wish. - * Authorization callback URL: 'https://gitlab.company.com/users/auth/github/callback' -6. Select "Register application". -7. You should now see a Client ID and Client Secret near the top right of the page (see screenshot). Keep this page open as you continue configuration. ![GitHub app](github_app.png) -8. On your GitLab server, open the configuration file. +1. Sign in to GitHub. + +1. Navigate to your individual user settings or an organization's settings, depending on how you want the application registered. It does not matter if the application is registered as an individual or an organization - that is entirely up to you. + +1. Select "Applications" in the left menu. + +1. Select "Register new application". + +1. Provide the required details. + - Application name: This can be anything. Consider something like "\'s GitLab" or "\'s GitLab" or something else descriptive. + - Homepage URL: The URL to your GitLab installation. 'https://gitlab.company.com' + - Application description: Fill this in if you wish. + - Authorization callback URL: 'https://gitlab.company.com/users/auth/github/callback' +1. Select "Register application". + +1. You should now see a Client ID and Client Secret near the top right of the page (see screenshot). Keep this page open as you continue configuration. ![GitHub app](github_app.png) + +1. On your GitLab server, open the configuration file. ```sh cd /home/git/gitlab @@ -21,8 +27,9 @@ To enable the GitHub OmniAuth provider you must register your application with G sudo -u git -H editor config/gitlab.yml ``` -9. Find the section dealing with OmniAuth. See [Initial OmniAuth Configuration](README.md#initial-omniauth-configuration) for more details. -10. Under `providers:` uncomment (or add) lines that look like the following: +1. Find the section dealing with OmniAuth. See [Initial OmniAuth Configuration](README.md#initial-omniauth-configuration) for more details. + +1. Under `providers:` uncomment (or add) lines that look like the following: ``` - { name: 'github', app_id: 'YOUR APP ID', @@ -30,9 +37,12 @@ To enable the GitHub OmniAuth provider you must register your application with G args: { scope: 'user:email' } } ``` -11. Change 'YOUR APP ID' to the client ID from the GitHub application page from step 7. -12. Change 'YOUR APP SECRET' to the client secret from the GitHub application page from step 7. -13. Save the configuration file. -14. Restart GitLab for the changes to take effect. +1. Change 'YOUR APP ID' to the client ID from the GitHub application page from step 7. + +1. Change 'YOUR APP SECRET' to the client secret from the GitHub application page from step 7. + +1. Save the configuration file. + +1. Restart GitLab for the changes to take effect. On the sign in page there should now be a GitHub icon below the regular sign in form. Click the icon to begin the authentication process. GitHub will ask the user to sign in and authorize the GitLab application. If everything goes well the user will be returned to GitLab and will be signed in. diff --git a/doc/integration/google.md b/doc/integration/google.md index 50f63502e7..3cf546bd77 100644 --- a/doc/integration/google.md +++ b/doc/integration/google.md @@ -2,28 +2,38 @@ To enable the Google OAuth2 OmniAuth provider you must register your application with Google. Google will generate a client ID and secret key for you to use. -1. Sign in to the [Google Developers Console](https://console.developers.google.com/) with the Google account you want to use to register GitLab. -2. Select "Create Project". -3. Provide the project information - * Project name: 'GitLab' works just fine here. - * Project ID: Must be unique to all Google Developer registered applications. Google provides a randomly generated Project ID by default. You can use the randomly generated ID or choose a new one. -4. Refresh the page. You should now see your new project in the list. Click on the project. -5. Select "APIs & auth" in the left menu. -6. Select "Credentials" in the submenu. -7. Select "Create New Client ID". -8. Fill in the required information - * Application type: "Web Application" - * Authorized JavaScript origins: This isn't really used by GitLab but go ahead and put 'https://gitlab.example.com' here. - * Authorized redirect URI: 'https://gitlab.example.com/users/auth/google_oauth2/callback' -9. Under the heading "Client ID for web application" you should see a Client ID and Client secret (see screenshot). Keep this page open as you continue configuration. ![Google app](google_app.png) -10. On your GitLab server, open the configuration file. +1. Sign in to the [Google Developers Console](https://console.developers.google.com/) with the Google account you want to use to register GitLab. + +1. Select "Create Project". + +1. Provide the project information + - Project name: 'GitLab' works just fine here. + - Project ID: Must be unique to all Google Developer registered applications. Google provides a randomly generated Project ID by default. You can use the randomly generated ID or choose a new one. +1. Refresh the page. You should now see your new project in the list. Click on the project. + +1. Select "APIs & auth" in the left menu. + +1. Select "Credentials" in the submenu. + +1. Select "Create New Client ID". + +1. Fill in the required information + - Application type: "Web Application" + - Authorized JavaScript origins: This isn't really used by GitLab but go ahead and put 'https://gitlab.example.com' here. + - Authorized redirect URI: 'https://gitlab.example.com/users/auth/google_oauth2/callback' +1. Under the heading "Client ID for web application" you should see a Client ID and Client secret (see screenshot). Keep this page open as you continue configuration. ![Google app](google_app.png) + +1. On your GitLab server, open the configuration file. + ```sh cd /home/git/gitlab sudo -u git -H editor config/gitlab.yml ``` -11. Find the section dealing with OmniAuth. See [Initial OmniAuth Configuration](README.md#initial-omniauth-configuration) for more details. -12. Under `providers:` uncomment (or add) lines that look like the following: + +1. Find the section dealing with OmniAuth. See [Initial OmniAuth Configuration](README.md#initial-omniauth-configuration) for more details. + +1. Under `providers:` uncomment (or add) lines that look like the following: ``` - { name: 'google_oauth2', app_id: 'YOUR APP ID', @@ -31,10 +41,13 @@ To enable the Google OAuth2 OmniAuth provider you must register your application args: { access_type: 'offline', approval_prompt: '' } } ``` -13. Change 'YOUR APP ID' to the client ID from the GitHub application page from step 7. -14. Change 'YOUR APP SECRET' to the client secret from the GitHub application page from step 7. -15. Save the configuration file. -16. Restart GitLab for the changes to take effect. +1. Change 'YOUR APP ID' to the client ID from the GitHub application page from step 7. + +1. Change 'YOUR APP SECRET' to the client secret from the GitHub application page from step 7. + +1. Save the configuration file. + +1. Restart GitLab for the changes to take effect. On the sign in page there should now be a Google icon below the regular sign in form. Click the icon to begin the authentication process. Google will ask the user to sign in and authorize the GitLab application. If everything goes well the user will be returned to GitLab and will be signed in. @@ -45,5 +58,5 @@ This further configuration is not required for Google authentication to function At this point, when users first try to authenticate to your GitLab installation with Google they will see a generic application name on the prompt screen. The prompt informs the user that "Project Default Service Account" would like to access their account. "Project Default Service Account" isn't very recognizable and may confuse or cause users to be concerned. This is easily changeable. 1. Select 'Consent screen' in the left menu. (See steps 1, 4 and 5 above for instructions on how to get here if you closed your window). -2. Scroll down until you find "Product Name". Change the product name to something more descriptive. -3. Add any additional information as you wish - homepage, logo, privacy policy, etc. None of this is required, but it may help your users. +1. Scroll down until you find "Product Name". Change the product name to something more descriptive. +1. Add any additional information as you wish - homepage, logo, privacy policy, etc. None of this is required, but it may help your users. diff --git a/doc/integration/ldap.md b/doc/integration/ldap.md index b52c4a4b5e..62bb957d95 100644 --- a/doc/integration/ldap.md +++ b/doc/integration/ldap.md @@ -1,14 +1,19 @@ # GitLab LDAP integration GitLab can be configured to allow your users to sign with their LDAP credentials to integrate with e.g. Active Directory. + The first time a user signs in with LDAP credentials, GitLab will create a new GitLab user associated with the LDAP Distinguished Name (DN) of the LDAP user. + GitLab user attributes such as nickname and email will be copied from the LDAP user entry. ## Enabling LDAP sign-in for existing GitLab users When a user signs in to GitLab with LDAP for the first time, and their LDAP email address is the primary email address of an existing GitLab user, then the LDAP DN will be associated with the existing user. + If the LDAP email attribute is not found in GitLab's database, a new user is created. In other words, if an existing GitLab user wants to enable LDAP sign-in for themselves, they should check that their GitLab email address matches their LDAP email address, and then sign into GitLab via their LDAP credentials. + GitLab recognizes the following LDAP attributes as email addresses: `mail`, `email` and `userPrincipalName`. + If multiple LDAP email attributes are present, e.g. `mail: foo@bar.com` and `email: foo@example.com`, then the first attribute found wins -- in this case `foo@bar.com`. diff --git a/doc/integration/omniauth.md b/doc/integration/omniauth.md index 84a5a8e8c2..1b0bf9c5f6 100644 --- a/doc/integration/omniauth.md +++ b/doc/integration/omniauth.md @@ -1,18 +1,18 @@ # OmniAuth GitLab leverages OmniAuth to allow users to sign in using Twitter, GitHub, and other popular services. Configuring -OmniAuth does not prevent standard GitLab authentication or LDAP (if configured) from continuing to work. Users can -choose to sign in using any of the configured mechanisms. -+ [Initial OmniAuth Configuration](#initial-omniauth-configuration) -+ [Supported Providers](#supported-providers) -+ [Enable OmniAuth for an Existing User](#enable-omniauth-for-an-existing-user) +OmniAuth does not prevent standard GitLab authentication or LDAP (if configured) from continuing to work. Users can choose to sign in using any of the configured mechanisms. -### Initial OmniAuth Configuration +- [Initial OmniAuth Configuration](#initial-omniauth-configuration) +- [Supported Providers](#supported-providers) +- [Enable OmniAuth for an Existing User](#enable-omniauth-for-an-existing-user) + +## Initial OmniAuth Configuration Before configuring individual OmniAuth providers there are a few global settings that need to be verified. -1. Open the configuration file
+1. Open the configuration file. ```sh cd /home/git/gitlab @@ -20,7 +20,7 @@ Before configuring individual OmniAuth providers there are a few global settings sudo -u git -H editor config/gitlab.yml ``` -2. Find the section dealing with OmniAuth. The section will look similar to the following.
+1. Find the section dealing with OmniAuth. The section will look similar to the following. ``` ## OmniAuth settings @@ -52,32 +52,33 @@ Before configuring individual OmniAuth providers there are a few global settings # args: { scope: 'user:email' } } ``` -3. Change `enabled` to `true`. -4. Consider the next two configuration options: `allow_single_sign_on` and `block_auto_created_users`. - * `allow_single_sign_on` defaults to `false`. If `false` users must be created manually or they will not be able to +1. Change `enabled` to `true`. + +1. Consider the next two configuration options: `allow_single_sign_on` and `block_auto_created_users`. + + - `allow_single_sign_on` defaults to `false`. If `false` users must be created manually or they will not be able to sign in via OmniAuth. - * `block_auto_created_users` defaults to `true`. If `true` auto created users will be blocked by default and will + - `block_auto_created_users` defaults to `true`. If `true` auto created users will be blocked by default and will have to be unblocked by an administrator before they are able to sign in. - * **Note:** If you set `allow_single_sign_on` to `true` and `block_auto_created_users` to `false` please be aware + - **Note:** If you set `allow_single_sign_on` to `true` and `block_auto_created_users` to `false` please be aware that any user on the Internet will be able to successfully sign in to your GitLab without administrative approval. -5. Choose one or more of the Supported Providers below to continue configuration. -### Supported Providers +1. Choose one or more of the Supported Providers below to continue configuration. -+ [GitHub](github.md) -+ [Google](google.md) -+ [Twitter](twitter.md) +## Supported Providers -### Enable OmniAuth for an Existing User +- [GitHub](github.md) +- [Google](google.md) +- [Twitter](twitter.md) -Existing users can enable OmniAuth for specific providers after the account is created. For example, if the user -originally signed in with LDAP an OmniAuth provider such as Twitter can be enabled. Follow the steps below to enable an -OmniAuth provider for an existing user. +## Enable OmniAuth for an Existing User + +Existing users can enable OmniAuth for specific providers after the account is created. For example, if the user originally signed in with LDAP an OmniAuth provider such as Twitter can be enabled. Follow the steps below to enable an OmniAuth provider for an existing user. 1. Sign in normally - whether standard sign in, LDAP, or another OmniAuth provider. -2. Go to profile settings (the silhouette icon in the top right corner). -3. Select the "Account" tab. -4. Under "Social Accounts" select the desired OmniAuth provider, such as Twitter. -5. The user will be redirected to the provider. Once the user authorized GitLab they will be redirected back to GitLab. +1. Go to profile settings (the silhouette icon in the top right corner). +1. Select the "Account" tab. +1. Under "Social Accounts" select the desired OmniAuth provider, such as Twitter. +1. The user will be redirected to the provider. Once the user authorized GitLab they will be redirected back to GitLab. The chosen OmniAuth provider is now active and can be used to sign in to GitLab from then on. diff --git a/doc/integration/slack.md b/doc/integration/slack.md index 057871a4b8..95cb0c6fae 100644 --- a/doc/integration/slack.md +++ b/doc/integration/slack.md @@ -1,34 +1,36 @@ -# Slack integration +# Slack integration -### On Slack +## On Slack To enable Slack integration you must create an Incoming WebHooks integration on Slack; - -1. Sign in to [Slack](https://slack.com) (https://YOURSUBDOMAIN.slack.com/services) -2. Click on the Integrations menu at the top of the page. -3. Add a new Integration. -4. Pick Incoming WebHooks -5. Choose the channel name you want to send notifications to, in the Settings section -6. Add Integrations. - * Optional step; You can change bot's name and avatar by clicking "change the name of your bot", and "change the icon" after that you have to click "Save settings". +1. Sign in to [Slack](https://slack.com) (https://YOURSUBDOMAIN.slack.com/services) +1. Click on the Integrations menu at the top of the page. +1. Add a new Integration. +1. Pick Incoming WebHooks +1. Choose the channel name you want to send notifications to, in the Settings section +1. Add Integrations. + - Optional step; You can change bot's name and avatar by clicking "change the name of your bot", and "change the icon" after that you have to click "Save settings". Now, Slack is ready to get external hooks. Before you leave this page don't forget to get the Token that you'll need on GitLab. You can find it by clicking Expand button, located in the "Instructions for creating Incoming WebHooks" section. It's a random alpha-numeric text 24 characters long. -### On GitLab +## On GitLab After Slack is ready we need to setup GitLab. Here are the steps to achieve this. +1. Sign in to GitLab -1. Sign in to GitLab -2. Pick the repository you want. -3. Navigate to Settings -> Services -> Slack -4. Fill in your Slack details - * Mark as active it - * Type your subdomain's prefix (If your subdomain is https://somedomain.slack.com you only have to type the somedomain) - * Type in the token you got from Slack - * Type in the channel name you want to use (eg. #announcements) +1. Pick the repository you want. + +1. Navigate to Settings -> Services -> Slack + +1. Fill in your Slack details + + - Mark as active it + - Type your subdomain's prefix (If your subdomain is https://somedomain.slack.com you only have to type the somedomain) + - Type in the token you got from Slack + - Type in the channel name you want to use (eg. #announcements) Have fun :) -_P.S. You can set "branch,pushed,Compare changes" as highlight words on your Slack profile settings, so that you can be aware of new commits when somebody pushes them._ +*P.S. You can set "branch,pushed,Compare changes" as highlight words on your Slack profile settings, so that you can be aware of new commits when somebody pushes them.* diff --git a/doc/integration/twitter.md b/doc/integration/twitter.md index 0440e2f21f..d1b52927d3 100644 --- a/doc/integration/twitter.md +++ b/doc/integration/twitter.md @@ -1,27 +1,37 @@ # Twitter OAuth2 OmniAuth Provider -To enable the Twitter OmniAuth provider you must register your application with Twitter. Twitter will generate a client -ID and secret key for you to use. +To enable the Twitter OmniAuth provider you must register your application with Twitter. Twitter will generate a client ID and secret key for you to use. -1. Sign in to [Twitter Developers](https://dev.twitter.com/) area. -2. Hover over the avatar in the top right corner and select "My applications." -3. Select "Create new app" -4. Fill in the application details. - * Name: This can be anything. Consider something like "\'s GitLab" or "\'s GitLab" or +1. Sign in to [Twitter Developers](https://dev.twitter.com/) area. + +1. Hover over the avatar in the top right corner and select "My applications." + +1. Select "Create new app" + +1. Fill in the application details. + - Name: This can be anything. Consider something like "\'s GitLab" or "\'s GitLab" or something else descriptive. - * Description: Create a description. - * Website: The URL to your GitLab installation. 'https://gitlab.example.com' - * Callback URL: 'https://gitlab.example.com/users/auth/github/callback' - * Agree to the "Rules of the Road." + - Description: Create a description. + - Website: The URL to your GitLab installation. 'https://gitlab.example.com' + - Callback URL: 'https://gitlab.example.com/users/auth/github/callback' + - Agree to the "Rules of the Road." + ![Twitter App Details](twitter_app_details.png) -6. Select "Create your Twitter application." -7. Select the "Settings" tab. -8. Underneath the Callback URL check the box next to "Allow this application to be used to Sign in the Twitter." -9. Select "Update settings" at the bottom to save changes. -10. Select the "API Keys" tab. -11. You should now see an API key and API secret (see screenshot). Keep this page open as you continue configuration. -![Twitter app](twitter_app_api_keys.png) -12. On your GitLab server, open the configuration file. +1. Select "Create your Twitter application." + +1. Select the "Settings" tab. + +1. Underneath the Callback URL check the box next to "Allow this application to be used to Sign in the Twitter." + +1. Select "Update settings" at the bottom to save changes. + +1. Select the "API Keys" tab. + +1. You should now see an API key and API secret (see screenshot). Keep this page open as you continue configuration. + + ![Twitter app](twitter_app_api_keys.png) + +1. On your GitLab server, open the configuration file. ```sh cd /home/git/gitlab @@ -29,19 +39,22 @@ ID and secret key for you to use. sudo -u git -H editor config/gitlab.yml ``` -13. Find the section dealing with OmniAuth. See [Initial OmniAuth Configuration](README.md#initial-omniauth-configuration) +1. Find the section dealing with OmniAuth. See [Initial OmniAuth Configuration](README.md#initial-omniauth-configuration) for more details. -14. Under `providers:` uncomment (or add) lines that look like the following: + +1. Under `providers:` uncomment (or add) lines that look like the following: ``` - { name: 'twitter', app_id: 'YOUR APP ID', app_secret: 'YOUR APP SECRET' } ``` -15. Change 'YOUR APP ID' to the API key from Twitter page in step 11. -16. Change 'YOUR APP SECRET' to the API secret from the Twitter page in step 11. -17. Save the configuration file. -18. Restart GitLab for the changes to take effect. +1. Change 'YOUR APP ID' to the API key from Twitter page in step 11. -On the sign in page there should now be a Twitter icon below the regular sign in form. Click the icon to begin the -authentication process. Twitter will ask the user to sign in and authorize the GitLab application. If everything goes well the user will be returned to GitLab and will be signed in. +1. Change 'YOUR APP SECRET' to the API secret from the Twitter page in step 11. + +1. Save the configuration file. + +1. Restart GitLab for the changes to take effect. + +On the sign in page there should now be a Twitter icon below the regular sign in form. Click the icon to begin the authentication process. Twitter will ask the user to sign in and authorize the GitLab application. If everything goes well the user will be returned to GitLab and will be signed in. diff --git a/doc/legal/README.md b/doc/legal/README.md index ebfdad1354..56d72ae385 100644 --- a/doc/legal/README.md +++ b/doc/legal/README.md @@ -1,2 +1,4 @@ -+ [Corporate contributor license agreement](corporate_contributor_license_agreement.md) -+ [Individual contributor license agreement](individual_contributor_license_agreement.md) +# Legal + +- [Corporate contributor license agreement](corporate_contributor_license_agreement.md) +- [Individual contributor license agreement](individual_contributor_license_agreement.md) diff --git a/doc/legal/corporate_contributor_license_agreement.md b/doc/legal/corporate_contributor_license_agreement.md index eb808d8a76..13bf15fcf4 100644 --- a/doc/legal/corporate_contributor_license_agreement.md +++ b/doc/legal/corporate_contributor_license_agreement.md @@ -2,26 +2,24 @@ You accept and agree to the following terms and conditions for Your present and future Contributions submitted to GitLab B.V.. Except for the license granted herein to GitLab B.V. and recipients of software distributed by GitLab B.V., You reserve all right, title, and interest in and to Your Contributions. -1. Definitions. +1. Definitions. "You" (or "Your") shall mean the copyright owner or legal entity authorized by the copyright owner that is making this Agreement with GitLab B.V.. For legal entities, the entity making a Contribution and all other entities that control, are controlled by, or are under common control with that entity are considered to be a single Contributor. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "Contribution" shall mean the code, documentation or other original works of authorship expressly identified in Schedule B, as well as any original work of authorship, including any modifications or additions to an existing work, that is intentionally submitted by You to GitLab B.V. for inclusion in, or documentation of, any of the products owned or managed by GitLab B.V. (the "Work"). For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to GitLab B.V. or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, GitLab B.V. for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by You as "Not a Contribution." -2. Grant of Copyright License. Subject to the terms and conditions of this Agreement, You hereby grant to GitLab B.V. and to recipients of software distributed by GitLab B.V. a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute Your Contributions and such derivative works. +2. Grant of Copyright License. Subject to the terms and conditions of this Agreement, You hereby grant to GitLab B.V. and to recipients of software distributed by GitLab B.V. a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute Your Contributions and such derivative works. -3. Grant of Patent License. Subject to the terms and conditions of this Agreement, You hereby grant to GitLab B.V. and to recipients of software distributed by GitLab B.V. a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by You that are necessarily infringed by Your Contribution(s) alone or by combination of Your Contribution(s) with the Work to which such Contribution(s) was submitted. If any entity institutes patent litigation against You or any other entity (including a cross-claim or counterclaim in a lawsuit) alleging that your Contribution, or the Work to which you have contributed, constitutes direct or contributory patent infringement, then any patent licenses granted to that entity under this Agreement for that Contribution or Work shall terminate as of the date such litigation is filed. +3. Grant of Patent License. Subject to the terms and conditions of this Agreement, You hereby grant to GitLab B.V. and to recipients of software distributed by GitLab B.V. a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by You that are necessarily infringed by Your Contribution(s) alone or by combination of Your Contribution(s) with the Work to which such Contribution(s) was submitted. If any entity institutes patent litigation against You or any other entity (including a cross-claim or counterclaim in a lawsuit) alleging that your Contribution, or the Work to which you have contributed, constitutes direct or contributory patent infringement, then any patent licenses granted to that entity under this Agreement for that Contribution or Work shall terminate as of the date such litigation is filed. -4. You represent that You are legally entitled to grant the above license. You represent further that each employee of the Corporation designated on Schedule A below (or in a subsequent written modification to that Schedule) is authorized to submit Contributions on behalf of the Corporation. +4. You represent that You are legally entitled to grant the above license. You represent further that each employee of the Corporation designated on Schedule A below (or in a subsequent written modification to that Schedule) is authorized to submit Contributions on behalf of the Corporation. -5. You represent that each of Your Contributions is Your original creation (see section 7 for submissions on behalf of others). +5. You represent that each of Your Contributions is Your original creation (see section 7 for submissions on behalf of others). -6. You are not expected to provide support for Your Contributions, except to the extent You desire to provide support. You may provide support for free, for a fee, or not at all. Unless required by applicable law or agreed to in writing, You provide Your Contributions on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. +6. You are not expected to provide support for Your Contributions, except to the extent You desire to provide support. You may provide support for free, for a fee, or not at all. Unless required by applicable law or agreed to in writing, You provide Your Contributions on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. -7. Should You wish to submit work that is not Your original creation, You may submit it to GitLab B.V. separately from any Contribution, identifying the complete details of its source and of any license or other restriction (including, but not limited to, related patents, trademarks, and license agreements) of which you are personally aware, and conspicuously marking the work as "Submitted on behalf of a third-party: [named here]". +7. Should You wish to submit work that is not Your original creation, You may submit it to GitLab B.V. separately from any Contribution, identifying the complete details of its source and of any license or other restriction (including, but not limited to, related patents, trademarks, and license agreements) of which you are personally aware, and conspicuously marking the work as "Submitted on behalf of a third-party: [named here]". -8. It is your responsibility to notify GitLab B.V. when any change is required to the list of designated employees authorized to submit Contributions on behalf of the Corporation, or to the Corporation's Point of Contact with GitLab B.V.. - ---------------------------------------- +8. It is your responsibility to notify GitLab B.V. when any change is required to the list of designated employees authorized to submit Contributions on behalf of the Corporation, or to the Corporation's Point of Contact with GitLab B.V.. This text is licensed under the [Creative Commons Attribution 3.0 License](http://creativecommons.org/licenses/by/3.0/) and the original source is the Google Open Source Programs Office. diff --git a/doc/legal/individual_contributor_license_agreement.md b/doc/legal/individual_contributor_license_agreement.md index 95cbed7e75..72b01433dd 100644 --- a/doc/legal/individual_contributor_license_agreement.md +++ b/doc/legal/individual_contributor_license_agreement.md @@ -2,26 +2,24 @@ You accept and agree to the following terms and conditions for Your present and future Contributions submitted to GitLab B.V.. Except for the license granted herein to GitLab B.V. and recipients of software distributed by GitLab B.V., You reserve all right, title, and interest in and to Your Contributions. -1. Definitions. +1. Definitions. "You" (or "Your") shall mean the copyright owner or legal entity authorized by the copyright owner that is making this Agreement with GitLab B.V.. For legal entities, the entity making a Contribution and all other entities that control, are controlled by, or are under common control with that entity are considered to be a single Contributor. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "Contribution" shall mean any original work of authorship, including any modifications or additions to an existing work, that is intentionally submitted by You to GitLab B.V. for inclusion in, or documentation of, any of the products owned or managed by GitLab B.V. (the "Work"). For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to GitLab B.V. or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, GitLab B.V. for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by You as "Not a Contribution." -2. Grant of Copyright License. Subject to the terms and conditions of this Agreement, You hereby grant to GitLab B.V. and to recipients of software distributed by GitLab B.V. a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute Your Contributions and such derivative works. +2. Grant of Copyright License. Subject to the terms and conditions of this Agreement, You hereby grant to GitLab B.V. and to recipients of software distributed by GitLab B.V. a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute Your Contributions and such derivative works. -3. Grant of Patent License. Subject to the terms and conditions of this Agreement, You hereby grant to GitLab B.V. and to recipients of software distributed by GitLab B.V. a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by You that are necessarily infringed by Your Contribution(s) alone or by combination of Your Contribution(s) with the Work to which such Contribution(s) was submitted. If any entity institutes patent litigation against You or any other entity (including a cross-claim or counterclaim in a lawsuit) alleging that your Contribution, or the Work to which you have contributed, constitutes direct or contributory patent infringement, then any patent licenses granted to that entity under this Agreement for that Contribution or Work shall terminate as of the date such litigation is filed. +3. Grant of Patent License. Subject to the terms and conditions of this Agreement, You hereby grant to GitLab B.V. and to recipients of software distributed by GitLab B.V. a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by You that are necessarily infringed by Your Contribution(s) alone or by combination of Your Contribution(s) with the Work to which such Contribution(s) was submitted. If any entity institutes patent litigation against You or any other entity (including a cross-claim or counterclaim in a lawsuit) alleging that your Contribution, or the Work to which you have contributed, constitutes direct or contributory patent infringement, then any patent licenses granted to that entity under this Agreement for that Contribution or Work shall terminate as of the date such litigation is filed. -4. You represent that you are legally entitled to grant the above license. If your employer(s) has rights to intellectual property that you create that includes your Contributions, you represent that you have received permission to make Contributions on behalf of that employer, that your employer has waived such rights for your Contributions to GitLab B.V., or that your employer has executed a separate Corporate CLA with GitLab B.V.. +4. You represent that you are legally entitled to grant the above license. If your employer(s) has rights to intellectual property that you create that includes your Contributions, you represent that you have received permission to make Contributions on behalf of that employer, that your employer has waived such rights for your Contributions to GitLab B.V., or that your employer has executed a separate Corporate CLA with GitLab B.V.. -5. You represent that each of Your Contributions is Your original creation (see section 7 for submissions on behalf of others). You represent that Your Contribution submissions include complete details of any third-party license or other restriction (including, but not limited to, related patents and trademarks) of which you are personally aware and which are associated with any part of Your Contributions. +5. You represent that each of Your Contributions is Your original creation (see section 7 for submissions on behalf of others). You represent that Your Contribution submissions include complete details of any third-party license or other restriction (including, but not limited to, related patents and trademarks) of which you are personally aware and which are associated with any part of Your Contributions. -6. You are not expected to provide support for Your Contributions, except to the extent You desire to provide support. You may provide support for free, for a fee, or not at all. Unless required by applicable law or agreed to in writing, You provide Your Contributions on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON- INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. +6. You are not expected to provide support for Your Contributions, except to the extent You desire to provide support. You may provide support for free, for a fee, or not at all. Unless required by applicable law or agreed to in writing, You provide Your Contributions on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON- INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. -7. Should You wish to submit work that is not Your original creation, You may submit it to GitLab B.V. separately from any Contribution, identifying the complete details of its source and of any license or other restriction (including, but not limited to, related patents, trademarks, and license agreements) of which you are personally aware, and conspicuously marking the work as "Submitted on behalf of a third-party: [[]named here]". +7. Should You wish to submit work that is not Your original creation, You may submit it to GitLab B.V. separately from any Contribution, identifying the complete details of its source and of any license or other restriction (including, but not limited to, related patents, trademarks, and license agreements) of which you are personally aware, and conspicuously marking the work as "Submitted on behalf of a third-party: [[]named here]". -8. You agree to notify GitLab B.V. of any facts or circumstances of which you become aware that would make these representations inaccurate in any respect. - ---------------------------------------- +8. You agree to notify GitLab B.V. of any facts or circumstances of which you become aware that would make these representations inaccurate in any respect. This text is licensed under the [Creative Commons Attribution 3.0 License](http://creativecommons.org/licenses/by/3.0/) and the original source is the Google Open Source Programs Office. diff --git a/doc/markdown/markdown.md b/doc/markdown/markdown.md index 47cb04cdb0..0d0a08d50d 100644 --- a/doc/markdown/markdown.md +++ b/doc/markdown/markdown.md @@ -1,11 +1,6 @@ # Markdown ----------------------------------------------- - -Table of Contents -================= - ----------------------------------------------- +## Table of Contents **[GitLab Flavored Markdown](#gitlab-flavored-markdown-gfm)** @@ -21,7 +16,6 @@ Table of Contents [Special GitLab references](#special-gitlab-references) - **[Standard Markdown](#standard-markdown)** [Headers](#headers) @@ -46,29 +40,24 @@ Table of Contents **[References](#references)** ----------------------------------------------- +## GitLab Flavored Markdown (GFM) -GitLab Flavored Markdown (GFM) -============================== -For GitLab we developed something we call "GitLab Flavored Markdown" (GFM). -It extends the standard Markdown in a few significant ways to add some useful functionality. +For GitLab we developed something we call "GitLab Flavored Markdown" (GFM). It extends the standard Markdown in a few significant ways to add some useful functionality. You can use GFM in -* commit messages -* comments -* wall posts -* issues -* merge requests -* milestones -* wiki pages +- commit messages +- comments +- wall posts +- issues +- merge requests +- milestones +- wiki pages -You can also use other rich text files in GitLab. -You might have to install a depency to do so. -Please see the [github-markup gem readme](https://github.com/gitlabhq/markup#markups) for more information. +You can also use other rich text files in GitLab. You might have to install a depency to do so. Please see the [github-markup gem readme](https://github.com/gitlabhq/markup#markups) for more information. + +## Newlines -Newlines --------- GFM honors the markdown specification in how [paragraphs and line breaks are handled](http://daringfireball.net/projects/markdown/syntax#p). A paragraph is simply one or more consecutive lines of text, separated by one or more blank lines.: @@ -83,8 +72,8 @@ Violets are blue Sugar is sweet -Multiple underscores in words ------------------------------ +## Multiple underscores in words + It is not reasonable to italicize just _part_ of a word, especially when you're dealing with code and names that often appear with multiple underscores. Therefore, GFM ignores multiple underscores in words. perform_complicated_task @@ -93,10 +82,9 @@ It is not reasonable to italicize just _part_ of a word, especially when you're perform_complicated_task do_this_and_do_that_and_another_thing -URL autolinking ---------------- -GFM will autolink standard URLs you copy and paste into your text. -So if you want to link to a URL (instead of a textural link), you can simply put the URL in verbatim and it will be turned into a link to that URL. +## URL autolinking + +GFM will autolink standard URLs you copy and paste into your text. So if you want to link to a URL (instead of a textural link), you can simply put the URL in verbatim and it will be turned into a link to that URL. http://www.google.com @@ -164,8 +152,7 @@ s = "There is no highlighting for this." But let's throw in a tag. ``` -Emoji ------ +## Emoji Sometimes you want to be :cool: and add some :sparkles: to your :speech_balloon:. Well we have a :gift: for you: @@ -187,26 +174,25 @@ If you are :new: to this, don't be :fearful:. You can easily join the emoji :cir Consult the [Emoji Cheat Sheet](http://www.emoji-cheat-sheet.com/) for a list of all supported emoji codes. :thumbsup: -Special GitLab References ------ +## Special GitLab References GFM recognized special references. + You can easily reference e.g. a team member, an issue, or a commit within a project. + GFM will turn that reference into a link so you can navigate between them easily. GFM will recognize the following: -* @foo : for team members -* #123 : for issues -* !123 : for merge requests -* $123 : for snippets -* 1234567 : for commits -* \[file\](path/to/file) : for file references +- @foo : for team members +- #123 : for issues +- !123 : for merge requests +- $123 : for snippets +- 1234567 : for commits +- \[file\](path/to/file) : for file references ----------------------------------- # Standard Markdown ----------------------------------- ## Headers ```no-highlight @@ -249,12 +235,12 @@ On hover a link to those IDs becomes visible to make it easier to copy the link The IDs are generated from the content of the header according to the following rules: -1) remove the heading hashes `#` and process the rest of the line as it would be processed if it were not a header -2) from the result, remove all HTML tags, but keep their inner content -3) convert all characters to lowercase -4) convert all characters except `[a-z0-9_-]` into hyphens `-` -5) transform multiple adjacent hyphens into a single hyphen -6) remove trailing and heading hyphens +1. remove the heading hashes `#` and process the rest of the line as it would be processed if it were not a header +2. from the result, remove all HTML tags, but keep their inner content +3. convert all characters to lowercase +4. convert all characters except `[a-z0-9_-]` into hyphens `-` +5. transform multiple adjacent hyphens into a single hyphen +6. remove trailing and heading hyphens For example: @@ -377,8 +363,7 @@ Some text to show that the reference links can follow later. **Note** -Relative links do not allow referencing project files in a wiki page or wiki page in a project file. -The reason for this is that, in GitLab, wiki is always a separate git repository. For example: +Relative links do not allow referencing project files in a wiki page or wiki page in a project file. The reason for this is that, in GitLab, wiki is always a separate git repository. For example: `[I'm a reference-style link][style]` @@ -399,9 +384,11 @@ will point the link to `wikis/style` when the link is inside of a wiki markdown Here's our logo: Inline-style: + ![alt text](/assets/logo-white.png) Reference-style: + ![alt text][logo] [logo]: /assets/logo-white.png @@ -518,10 +505,8 @@ Code above produces next output: | cell 1 | cell 2 | | cell 3 | cell 4 | ------------- - ## References -* This document leveraged heavily from the [Markdown-Cheatsheet](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet). -* The [Markdown Syntax Guide](http://daringfireball.net/projects/markdown/syntax) at Daring Fireball is an excellent resource for a detailed explanation of standard markdown. -* [Dillinger.io](http://dillinger.io) is a handy tool for testing standard markdown. +- This document leveraged heavily from the [Markdown-Cheatsheet](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet). +- The [Markdown Syntax Guide](http://daringfireball.net/projects/markdown/syntax) at Daring Fireball is an excellent resource for a detailed explanation of standard markdown. +- [Dillinger.io](http://dillinger.io) is a handy tool for testing standard markdown. diff --git a/doc/permissions/permissions.md b/doc/permissions/permissions.md index 40d748c057..9ddf56d046 100644 --- a/doc/permissions/permissions.md +++ b/doc/permissions/permissions.md @@ -1,48 +1,48 @@ # Permissions Users have different abilities depending on the access level they have in a particular group or project. + If a user is both in a project group and in the project itself, the highest permission level is used. + If a user is a GitLab administrator they receive all permissions. ---- - -#### Project: +## Project -| Action| Guest | Reporter | Developer | Master | Owner| -|-------|-------|----------|-----------|--------|------| -|Create new issue|✓|✓|✓|✓|✓| -|Leave comments|✓|✓|✓|✓|✓| -|Write on project wall|✓|✓|✓|✓|✓| -|Pull project code| |✓|✓|✓|✓| -|Download project| |✓|✓|✓|✓| -|Create code snippets| |✓|✓|✓|✓| -|Create new merge request| ||✓|✓|✓| -|Create new branches| ||✓|✓|✓| -|Push to non-protected branches| ||✓|✓|✓| -|Remove non-protected branches| ||✓|✓|✓| -|Add tags| ||✓|✓|✓| -|Write a wiki| ||✓|✓|✓| -|Manage issue tracker| ||✓|✓|✓| -|Add new team members| |||✓|✓| -|Push to protected branches| |||✓|✓| -|Enable/Disable branch protection| |||✓|✓| -|Rewrite/remove git tags| |||✓|✓| -|Edit project| |||✓|✓| -|Add Deploy Keys to project| |||✓|✓| -|Configure Project Hooks| |||✓|✓| -|Switch visibility level| ||||✓| -|Transfer project to another namespace| ||||✓| -|Remove project| ||||✓| +| Action | Guest | Reporter | Developer | Master | Owner | +|---------------------------------------|---------|------------|-------------|----------|--------| +| Create new issue | ✓ | ✓ | ✓ | ✓ | ✓ | +| Leave comments | ✓ | ✓ | ✓ | ✓ | ✓ | +| Write on project wall | ✓ | ✓ | ✓ | ✓ | ✓ | +| Pull project code | | ✓ | ✓ | ✓ | ✓ | +| Download project | | ✓ | ✓ | ✓ | ✓ | +| Create code snippets | | ✓ | ✓ | ✓ | ✓ | +| Create new merge request | | | ✓ | ✓ | ✓ | +| Create new branches | | | ✓ | ✓ | ✓ | +| Push to non-protected branches | | | ✓ | ✓ | ✓ | +| Remove non-protected branches | | | ✓ | ✓ | ✓ | +| Add tags | | | ✓ | ✓ | ✓ | +| Write a wiki | | | ✓ | ✓ | ✓ | +| Manage issue tracker | | | ✓ | ✓ | ✓ | +| Add new team members | | | | ✓ | ✓ | +| Push to protected branches | | | | ✓ | ✓ | +| Enable/Disable branch protection | | | | ✓ | ✓ | +| Rewrite/remove git tags | | | | ✓ | ✓ | +| Edit project | | | | ✓ | ✓ | +| Add Deploy Keys to project | | | | ✓ | ✓ | +| Configure Project Hooks | | | | ✓ | ✓ | +| Switch visibility level | | | | | ✓ | +| Transfer project to another namespace | | | | | ✓ | +| Remove project | | | | | ✓ | -#### Group +## Group -|Action|Guest|Reporter|Developer|Master|Owner| -|------|-----|--------|---------|------|-----| -|Browse group|✓|✓|✓|✓|✓| -|Edit group|||||✓| -|Create project in group||||✓|✓| -|Manage group members|||||✓| -|Remove group|||||✓| +| Action | Guest | Reporter | Developer | Master | Owner | +|-------------------------|-------|----------|-----------|--------|-------| +| Browse group | ✓ | ✓ | ✓ | ✓ | ✓ | +| Edit group | | | | | ✓ | +| Create project in group | | | | ✓ | ✓ | +| Manage group members | | | | | ✓ | +| Remove group | | | | | ✓ | Any user can remove himself from a group, unless he is the last Owner of the group. diff --git a/doc/public_access/public_access.md b/doc/public_access/public_access.md index 1714a7eeae..68c10a9f3c 100644 --- a/doc/public_access/public_access.md +++ b/doc/public_access/public_access.md @@ -1,34 +1,44 @@ # Public access Gitlab allows you to open selected projects to be accessed **publicly** or **internally**. + Projects with either of these visibility levels will be listen in the [public access directory](/public). + Internal projects will only be available to authenticated users. -#### Public projects +## Public projects + Public projects can be cloned **without any** authentication. + It will also be listed on the [public access directory](/public). + **Any logged in user** will have [Guest](/help/permissions) permissions on the repository. -#### Internal projects +## Internal projects + Internal projects can be cloned by any logged in user. + It will also be listed on the [public access directory](/public) for logged in users. + Any logged in user will have [Guest](/help/permissions) permissions on the repository. -#### How to change project visibility +## How to change project visibility + 1. Go to your project dashboard -2. Click on the "Edit" tab -3. Change "Visibility Level" +1. Click on the "Edit" tab +1. Change "Visibility Level" + +## Visibility of users -#### Visibility of users The public page of users, located at `/u/username` is visible if either: -* You are logged in. -* You are logged out, and the target user is authorized to (is Guest, Reporter, etc.) at least one public project. +- You are logged in. +- You are logged out, and the target user is authorized to (is Guest, Reporter, etc.) at least one public project. Otherwise, you will be redirected to the sign in page. When visiting the public page of an user, you will only see listed projects which you can view yourself. -#### Restricting the use of public or internal projects -In [gitlab.yml](https://gitlab.com/gitlab-org/gitlab-ce/blob/dbd88d453b8e6c78a423fa7e692004b1db6ea069/config/gitlab.yml.example#L64) you can disable public projects or public and internal projects for the entire GitLab installation to prevent people making code public by accident. +## Restricting the use of public or internal projects +In [gitlab.yml](https://gitlab.com/gitlab-org/gitlab-ce/blob/dbd88d453b8e6c78a423fa7e692004b1db6ea069/config/gitlab.yml.example#L64) you can disable public projects or public and internal projects for the entire GitLab installation to prevent people making code public by accident. diff --git a/doc/raketasks/README.md b/doc/raketasks/README.md index b1c97c8223..9e2f697bca 100644 --- a/doc/raketasks/README.md +++ b/doc/raketasks/README.md @@ -1,6 +1,6 @@ -+ [Backup restore](backup_restore.md) -+ [Cleanup](cleanup.md) -+ [Maintenance](maintenance.md) and self-checks -+ [User management](user_management.md) -+ [Web hooks](web_hooks.md) -+ [Import](import.md) of git repositories in bulk +- [Backup restore](backup_restore.md) +- [Cleanup](cleanup.md) +- [Maintenance](maintenance.md) and self-checks +- [User management](user_management.md) +- [Web hooks](web_hooks.md) +- [Import](import.md) of git repositories in bulk diff --git a/doc/raketasks/backup_restore.md b/doc/raketasks/backup_restore.md index f0be2b6a44..5c1594d13d 100644 --- a/doc/raketasks/backup_restore.md +++ b/doc/raketasks/backup_restore.md @@ -1,8 +1,9 @@ # Backup restore -### Create a backup of the GitLab system +## Create a backup of the GitLab system Creates a backup archive of the database and all repositories. This archive will be saved in backup_path (see `config/gitlab.yml`). + The filename will be `[TIMESTAMP]_gitlab_backup.tar`. This timestamp can be used to restore an specific backup. ``` @@ -38,7 +39,7 @@ Deleting tmp directories...[DONE] Deleting old backups... [SKIPPING] ``` -### Restore a previously created backup +## Restore a previously created backup ``` bundle exec rake gitlab:backup:restore RAILS_ENV=production @@ -81,7 +82,7 @@ Restoring repositories: Deleting tmp directories...[DONE] ``` -### Configure cron to make daily backups +## Configure cron to make daily backups ``` cd /home/git/gitlab diff --git a/doc/raketasks/cleanup.md b/doc/raketasks/cleanup.md index b0b82754da..4b3b6d71a7 100644 --- a/doc/raketasks/cleanup.md +++ b/doc/raketasks/cleanup.md @@ -1,6 +1,6 @@ # Cleanup -### Remove garbage from filesystem. Important! Data loss! +## Remove garbage from filesystem. Important! Data loss! Remove namespaces(dirs) from `/home/git/repositories` if they don't exist in GitLab database. @@ -13,4 +13,3 @@ Remove repositories (global only for now) from `/home/git/repositories` if they ``` bundle exec rake gitlab:cleanup:repos RAILS_ENV=production ``` - diff --git a/doc/raketasks/features.md b/doc/raketasks/features.md new file mode 100644 index 0000000000..eaa9af5f96 --- /dev/null +++ b/doc/raketasks/features.md @@ -0,0 +1,38 @@ +# Features + +## Enable usernames and namespaces for user projects + +This command will enable the namespaces feature introduced in v4.0. It will move every project in its namespace folder. + +Note: + +- Because the **repository location will change**, you will need to **update all your git url's** to point to the new location. +- Username can be changed at [Profile / Account](/profile/account) + +**Example:** + +Old path: `git@example.org:myrepo.git` + +New path: `git@example.org:username/myrepo.git` or `git@example.org:groupname/myrepo.git` + +``` +bundle exec rake gitlab:enable_namespaces RAILS_ENV=production +``` + +## Rebuild project satellites + +This command will build missing satellites for projects. After this you will be able to **merge a merge request** via GitLab and use the **online editor**. + +``` +bundle exec rake gitlab:satellites:create RAILS_ENV=production +``` + +Example output: + +``` +Creating satellite for abcd.git +[git clone output] +Creating satellite for abcd2.git +[git clone output] +done +``` diff --git a/doc/raketasks/maintenance.md b/doc/raketasks/maintenance.md index e9ae3fb300..30276dd762 100644 --- a/doc/raketasks/maintenance.md +++ b/doc/raketasks/maintenance.md @@ -1,9 +1,8 @@ # Maintenance -### Gather information about GitLab and the system it runs on +## Gather information about GitLab and the system it runs on -This command gathers information about your GitLab installation and the System -it runs on. These may be useful when asking for help or reporting issues. +This command gathers information about your GitLab installation and the System it runs on. These may be useful when asking for help or reporting issues. ``` bundle exec rake gitlab:env:info RAILS_ENV=production @@ -39,15 +38,14 @@ Hooks: /home/git/gitlab-shell/hooks/ Git: /usr/bin/git ``` - -### Check GitLab configuration +## Check GitLab configuration Runs the following rake tasks: -* gitlab:env:check -* gitlab:gitlab_shell:check -* gitlab:sidekiq:check -* gitlab:app:check +- `gitlab:env:check` +- `gitlab:gitlab_shell:check` +- `gitlab:sidekiq:check` +- `gitlab:app:check` It will check that each component was setup according to the installation guide and suggest fixes for issues found. @@ -103,10 +101,10 @@ Redis version >= 2.0.0? ... yes Checking GitLab ... Finished ``` - -### (Re-)Create satellite repos +## (Re-)Create satellite repos This will create satellite repos for all your projects. + If necessary, remove the `tmp/repo_satellites` directory and rerun the command below. ``` diff --git a/doc/raketasks/user_management.md b/doc/raketasks/user_management.md index d5b173fde6..81378494c6 100644 --- a/doc/raketasks/user_management.md +++ b/doc/raketasks/user_management.md @@ -1,34 +1,33 @@ # User management -### Add user as a developer to all projects +## Add user as a developer to all projects ```bash bundle exec rake gitlab:import:user_to_projects[username@domain.tld] ``` - -### Add all users to all projects +## Add all users to all projects Notes: -* admin users are added as masters +- admin users are added as masters ```bash bundle exec rake gitlab:import:all_users_to_all_projects ``` -### Add user as a developer to all groups +## Add user as a developer to all groups -``` +```bash bundle exec rake gitlab:import:user_to_groups[username@domain.tld] ``` -### Add all users to all groups +## Add all users to all groups Notes: -* admin users are added as owners so they can add additional users to the group +- admin users are added as owners so they can add additional users to the group -``` +```bash bundle exec rake gitlab:import:all_users_to_all_groups ``` diff --git a/doc/raketasks/web_hooks.md b/doc/raketasks/web_hooks.md index 4ffbf5f869..704473af2d 100644 --- a/doc/raketasks/web_hooks.md +++ b/doc/raketasks/web_hooks.md @@ -1,33 +1,27 @@ # Web hooks -### Add a web hook for **ALL** projects: +## Add a web hook for **ALL** projects: RAILS_ENV=production bundle exec rake gitlab:web_hook:add URL="http://example.com/hook" - -### Add a web hook for projects in a given **NAMESPACE**: +## Add a web hook for projects in a given **NAMESPACE**: RAILS_ENV=production bundle exec rake gitlab:web_hook:add URL="http://example.com/hook" NAMESPACE=acme - -### Remove a web hook from **ALL** projects using: +## Remove a web hook from **ALL** projects using: RAILS_ENV=production bundle exec rake gitlab:web_hook:rm URL="http://example.com/hook" - -### Remove a web hook from projects in a given **NAMESPACE**: +## Remove a web hook from projects in a given **NAMESPACE**: RAILS_ENV=production bundle exec rake gitlab:web_hook:rm URL="http://example.com/hook" NAMESPACE=acme - -### List **ALL** web hooks: +## List **ALL** web hooks: RAILS_ENV=production bundle exec rake gitlab:web_hook:list - -### List the web hooks from projects in a given **NAMESPACE**: +## List the web hooks from projects in a given **NAMESPACE**: RAILS_ENV=production bundle exec rake gitlab:web_hook:list NAMESPACE=/ > Note: `/` is the global namespace. - diff --git a/doc/release/README.md b/doc/release/README.md index d53720acbd..1342b90f3b 100644 --- a/doc/release/README.md +++ b/doc/release/README.md @@ -1,6 +1,6 @@ GitLab has the following updates: -+ [Monthly release](monthly.md), every month on the 22nd. -+ [Patch release](patch.md), if there are serious regressions. -+ [Security](security.md), for security problems. -+ [Master](master.md), update process for the master branch. +- [Monthly release](monthly.md), every month on the 22nd. +- [Patch release](patch.md), if there are serious regressions. +- [Security](security.md), for security problems. +- [Master](master.md), update process for the master branch. diff --git a/doc/release/monthly.md b/doc/release/monthly.md index 71cd56a099..4519ae12e2 100644 --- a/doc/release/monthly.md +++ b/doc/release/monthly.md @@ -25,16 +25,18 @@ Consider naming the issue "Release x.x.x.rc1" to make it easier for later search ### **2. Update the installation guide** 1. Check if it references the correct branch `x-x-stable` (doesn't exist yet, but that is okay) -2. Check the [GitLab Shell version](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/tasks/gitlab/check.rake#L782) -3. Check the [Git version](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/tasks/gitlab/check.rake#L794) -4. There might be other changes. Ask around. +1. Check the [GitLab Shell version](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/tasks/gitlab/check.rake#L782) +1. Check the [Git version](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/tasks/gitlab/check.rake#L794) +1. There might be other changes. Ask around. ### **3. Create an update guide** It's best to copy paste the previous guide and make changes where necessary. The typical steps are listed below with any points you should specifically look at. #### 0. Any major changes? -List any major changes here, so the user is aware of them before starting to upgrade. For instance: + +List any major changes here, so the user is aware of them before starting to upgrade. For instance: + - Database updates - Web server changes - File structure changes @@ -59,42 +61,43 @@ List any major changes here, so the user is aware of them before starting to upg Check if any of these changed since last release: -* https://gitlab.com/gitlab-org/gitlab-ce/commits/master/lib/support/nginx/gitlab -* https://gitlab.com/gitlab-org/gitlab-shell/commits/master/config.yml.example -* https://gitlab.com/gitlab-org/gitlab-ce/commits/master/config/gitlab.yml.example -* https://gitlab.com/gitlab-org/gitlab-ce/commits/master/config/unicorn.rb.example -* https://gitlab.com/gitlab-org/gitlab-ce/commits/master/config/database.yml.mysql -* https://gitlab.com/gitlab-org/gitlab-ce/commits/master/config/database.yml.postgresql +- +- +- +- +- +- #### 8. Need to update init script? -Check if the init.d/gitlab script changed since last release: https://gitlab.com/gitlab-org/gitlab-ce/commits/master/lib/support/init.d/gitlab +Check if the `init.d/gitlab` script changed since last release: #### 9. Start application #### 10. Check application status -### **4. Code quality indicatiors** +### **4. Code quality indicators** + Make sure the code quality indicators are green / good. -* [![build status](http://ci.gitlab.org/projects/1/status.png?ref=master)](http://ci.gitlab.org/projects/1?ref=master) on ci.gitlab.org (master branch) +- [![build status](http://ci.gitlab.org/projects/1/status.png?ref=master)](http://ci.gitlab.org/projects/1?ref=master) on ci.gitlab.org (master branch) -* [![build status](https://secure.travis-ci.org/gitlabhq/gitlabhq.png)](https://travis-ci.org/gitlabhq/gitlabhq) on travis-ci.org (master branch) +- [![build status](https://secure.travis-ci.org/gitlabhq/gitlabhq.png)](https://travis-ci.org/gitlabhq/gitlabhq) on travis-ci.org (master branch) -* [![Code Climate](https://codeclimate.com/github/gitlabhq/gitlabhq.png)](https://codeclimate.com/github/gitlabhq/gitlabhq) +- [![Code Climate](https://codeclimate.com/github/gitlabhq/gitlabhq.png)](https://codeclimate.com/github/gitlabhq/gitlabhq) -* [![Dependency Status](https://gemnasium.com/gitlabhq/gitlabhq.png)](https://gemnasium.com/gitlabhq/gitlabhq) this button can be yellow (small updates are available) but must not be red (a security fix or an important update is available) +- [![Dependency Status](https://gemnasium.com/gitlabhq/gitlabhq.png)](https://gemnasium.com/gitlabhq/gitlabhq) this button can be yellow (small updates are available) but must not be red (a security fix or an important update is available) -* [![Coverage Status](https://coveralls.io/repos/gitlabhq/gitlabhq/badge.png?branch=master)](https://coveralls.io/r/gitlabhq/gitlabhq) +- [![Coverage Status](https://coveralls.io/repos/gitlabhq/gitlabhq/badge.png?branch=master)](https://coveralls.io/r/gitlabhq/gitlabhq) ### **5. Set VERSION** -Change version in VERSION to x.x.0.rc1 - +Change version in VERSION to `x.x.0.rc1`. ### **6. Tag** -Create an annotated tag that points to the version change commit. +Create an annotated tag that points to the version change commit: + ``` git tag -a vx.x.0.rc1 -m 'Version x.x.0.rc1' ``` @@ -105,6 +108,7 @@ Tweet about the RC release: > GitLab x.x.x.rc1 is out. This is a release candidate intended for testing only. Please let us know if you find regressions. +n ### **8. Update GitLab.com** Merge the RC1 code into GitLab.com. Once the build is green, deploy in the morning. @@ -115,28 +119,27 @@ It is important to do this as soon as possible, so we can catch any errors befor ### **1. Prepare the blog post** -* Check the changelog of CE and EE for important changes. Based on [release blog template](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/doc/release_blog_template.md) fill in the important information. -* Create a WIP MR for the blog post and cc the team so everyone can give feedback. -* Ask Dmitriy to add screenshots to the WIP MR. -* Decide with team who will be the MVP user. -* Add a note if there are security fixes: This release fixes an important security issue and we advise everyone to upgrade as soon as possible. +- Check the changelog of CE and EE for important changes. Based on [release blog template](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/doc/release_blog_template.md) fill in the important information. +- Create a WIP MR for the blog post and cc the team so everyone can give feedback. +- Ask Dmitriy to add screenshots to the WIP MR. +- Decide with team who will be the MVP user. +- Add a note if there are security fixes: This release fixes an important security issue and we advise everyone to upgrade as soon as possible. ### **2. Q&A** -Create issue on dev.gitlab.org gitlab repository, named "GitLab X.X release" in order to keep track of the progress. +Create issue on dev.gitlab.org `gitlab` repository, named "GitLab X.X release" in order to keep track of the progress. Use the omnibus packages of Enterprise Edition using [this guide](https://dev.gitlab.org/gitlab/gitlab-ee/blob/master/doc/release/manual_testing.md). **NOTE** Upgrader can only be tested when tags are pushed to all repositories. Do not forget to confirm it is working before releasing. Note that in the issue. - ### **3. Fix anything coming out of the QA** Create an issue with description of a problem, if it is quick fix fix yourself otherwise contact the team for advice. # **22nd - Release CE and EE** -For GitLab EE, append -ee to the branches and tags. +For GitLab EE, append `-ee` to the branches and tags. `x-x-stable-ee` @@ -152,25 +155,24 @@ git push x-x-stable ``` ### **2. Build the Omnibus packages** + [Follow this guide](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/release.md) ### **3. Set VERSION to x.x.x and push** -Change the VERSION file in `master` branch of the CE repository and commit. -Cherry-pick into the `x-x-stable` branch of CE. +Change the VERSION file in `master` branch of the CE repository and commit. Cherry-pick into the `x-x-stable` branch of CE. -Change the VERSION file in `master branch of the EE repository and commit. -Cherry-pick into the `x-x-stable-ee` branch of EE. +Change the VERSION file in `master` branch of the EE repository and commit. Cherry-pick into the `x-x-stable-ee` branch of EE. ### **4. Create annotated tag vx.x.x** -In `x-x-stable` branch check for the sha1 of the commit with VERSION file changed. Tag that commit, +In `x-x-stable` branch check for the SHA-1 of the commit with VERSION file changed. Tag that commit, ``` git tag -a vx.x.0 -m 'Version x.x.0' xxxxx ``` -where `xxxxx` is sha1. +where `xxxxx` is SHA-1. ### **5. Push the tag** @@ -200,7 +202,7 @@ Proposed tweet for EE "GitLab X.X.X EE is released! It brings *** , also see the [disclosure section on the GitLab.com website](http://www.gitlab.com/disclosure/). Please do NOT create publicly viewable issues for suspected security vulnerabilities. ## Release Procedure -1. Verify that the issue can be repoduced +1. Verify that the issue can be reproduced 1. Acknowledge the issue to the researcher that disclosed it 1. Do the steps from [patch release document](doc/release/patch.md), starting with "Create an issue on private GitLab development server" 1. Create feature branches for the blog post on GitLab.com and link them from the code branch 1. Merge and publish the blog posts -1. Send tweets about the release from @gitlabhq +1. Send tweets about the release from `@gitlabhq` 1. Send out an email to the subscribers mailing list on MailChimp 1. Send out an email to [the community google mailing list](https://groups.google.com/forum/#!forum/gitlabhq) 1. Send out an email to [the GitLab newsletter list](http://gitlab.us5.list-manage.com/subscribe?u=498dccd07cf3e9482bee33ba4&id=98a9a4992c) 1. Post a signed copy of our complete announcement to [oss-security](http://www.openwall.com/lists/oss-security/) and request a CVE number 1. Add the security researcher to the [Security Researcher Acknowledgments list](http://www.gitlab.com/vulnerability-acknowledgements/) 1. Thank the security researcher in an email for their cooperation -1. Update the blogpost and the CHANGELOG when we receive the CVE number +1. Update the blog post and the CHANGELOG when we receive the CVE number The timing of the code merge into master should be coordinated in advance. + After the merge we strive to publish the announcements within 60 minutes. ## Blog post template XXX Security Advisory for GitLab -A recently discovered critical vulnerability in GitLab allows [unauthenticated API access|remote code execution|unauthorized access to repositories|XXX|PICKSOMETHING]. All users should update GitLab and gitlab-shell immediately. -We [have|haven't|XXX|PICKSOMETHING|] heard of this vulnerability being actively exploited. +A recently discovered critical vulnerability in GitLab allows [unauthenticated API access|remote code execution|unauthorized access to repositories|XXX|PICKSOMETHING]. All users should update GitLab and gitlab-shell immediately. We [have|haven't|XXX|PICKSOMETHING|] heard of this vulnerability being actively exploited. ### Version affected GitLab Community Edition XXX and lower + GitLab Enterprise Edition XXX and lower ### Fixed versions GitLab Community Edition XXX and up + GitLab Enterprise Edition XXX and up ### Impact diff --git a/doc/security/README.md b/doc/security/README.md index f8dd1291b9..b89e8cbe02 100644 --- a/doc/security/README.md +++ b/doc/security/README.md @@ -1,2 +1,4 @@ -+ [Password length limits](password_length_limits.md) -+ [Rack attack](rack_attack.md) +# Security + +- [Password length limits](password_length_limits.md) +- [Rack attack](rack_attack.md) diff --git a/doc/security/password_length_limits.md b/doc/security/password_length_limits.md index c8d66e9636..d21b26a43e 100644 --- a/doc/security/password_length_limits.md +++ b/doc/security/password_length_limits.md @@ -1,6 +1,7 @@ # Custom password length limits If you want to enforce longer user passwords you can create an extra Devise initializer with the steps below. + If you do not use the `devise_password_length.rb` initializer the password length is set to a minimum of 8 characters in `config/initializers/devise.rb`. ```bash diff --git a/doc/security/rack_attack.md b/doc/security/rack_attack.md index 9e863bbd19..92066997be 100644 --- a/doc/security/rack_attack.md +++ b/doc/security/rack_attack.md @@ -1,18 +1,22 @@ # Rack attack To prevent abusive clients doing damage GitLab uses rack-attack gem. + If you installed or upgraded GitLab by following the official guides this should be enabled by default. + If you are missing `config/initializers/rack_attack.rb` the following steps need to be taken in order to enable protection for your GitLab instance: -1. In config/application.rb find and uncomment the following line: - config.middleware.use Rack::Attack -2. Rename config/initializers/rack_attack.rb.example to config/initializers/rack_attack.rb -3. Review the paths_to_be_protected and add any other path you need protecting -4. Restart GitLab instance +1. In config/application.rb find and uncomment the following line: -By default, user sign-in, user sign-up(if enabled) and user password reset is limited to 6 requests per minute. -After trying for 6 times, client will have to wait for the next minute to be able to try again. -These settings can be found in `config/initializers/rack_attack.rb` + config.middleware.use Rack::Attack + +1. Rename `config/initializers/rack_attack.rb.example` to `config/initializers/rack_attack.rb`. + +1. Review the `paths_to_be_protected` and add any other path you need protecting. + +1. Restart GitLab instance. + +By default, user sign-in, user sign-up(if enabled) and user password reset is limited to 6 requests per minute. After trying for 6 times, client will have to wait for the next minute to be able to try again. These settings can be found in `config/initializers/rack_attack.rb` If you want more restrictive/relaxed throttle rule change the `limit` or `period` values. For example, more relaxed throttle rule will be if you set limit: 3 and period: 1.second(this will allow 3 requests per second). You can also add other paths to the protected list by adding to `paths_to_be_protected` variable. If you change any of these settings do not forget to restart your GitLab instance. diff --git a/doc/ssh/README.md b/doc/ssh/README.md index 76d9e8bb07..c87fffd7d2 100644 --- a/doc/ssh/README.md +++ b/doc/ssh/README.md @@ -1,2 +1,4 @@ -+ [Deploy keys](deploy_keys.md) -+ [SSH](ssh.md) +# SSH + +- [Deploy keys](deploy_keys.md) +- [SSH](ssh.md) diff --git a/doc/ssh/deploy_keys.md b/doc/ssh/deploy_keys.md index e113160c9b..dcca8bdc61 100644 --- a/doc/ssh/deploy_keys.md +++ b/doc/ssh/deploy_keys.md @@ -2,13 +2,8 @@ Deploy keys allow read-only access one or multiple projects with a single SSH key. -This is really useful for cloning repositories to your Continuous Integration (CI) server. -By using a deploy keys you don't have to setup a dummy user account. +This is really useful for cloning repositories to your Continuous Integration (CI) server. By using a deploy keys you don't have to setup a dummy user account. -If you are a project master or owner you can add a deploy key in the project settings under the section Deploy Keys. -Press the 'New Deploy Key' button and upload a public ssh key. -After this the machine that uses the corresponding private key has read-only access to the project. +If you are a project master or owner you can add a deploy key in the project settings under the section Deploy Keys. Press the 'New Deploy Key' button and upload a public ssh key. After this the machine that uses the corresponding private key has read-only access to the project. -You can't add the same deploy key twice with the 'New Deploy Key' option. -If you want to add the same key to another project please enable it in the list that says 'Deploy keys from projects available to you'. -All the deploy keys of all the projects you have access to are available. This project access can happen through being a direct member of the project or through a group. See `def accessible_deploy_keys` in `app/models/user.rb` for more information. +You can't add the same deploy key twice with the 'New Deploy Key' option. If you want to add the same key to another project please enable it in the list that says 'Deploy keys from projects available to you'. All the deploy keys of all the projects you have access to are available. This project access can happen through being a direct member of the project or through a group. See `def accessible_deploy_keys` in `app/models/user.rb` for more information. diff --git a/doc/ssh/ssh.md b/doc/ssh/ssh.md index f89b6a14ce..d466c1bde7 100644 --- a/doc/ssh/ssh.md +++ b/doc/ssh/ssh.md @@ -2,13 +2,9 @@ SSH key allows you to establish a secure connection between your computer and GitLab +Before generating an SSH key, check if your system already has one by running `cat ~/.ssh/id_rsa.pub` If your see a long string starting with `ssh-rsa` or `ssh-dsa`, you can skip the ssh-keygen step. -Before generating an SSH key, check if your system already has one by running `cat ~/.ssh/id_rsa.pub` -If your see a long string starting with `ssh-rsa` or `ssh-dsa`, you can skip the ssh-keygen step. - - -To generate a new SSH key just open your terminal and use code below. The ssh-keygen command prompts you for a location and filename to store the key pair and for a password. -When prompted for the location and filename you can press enter to use the default. +To generate a new SSH key just open your terminal and use code below. The ssh-keygen command prompts you for a location and filename to store the key pair and for a password. When prompted for the location and filename you can press enter to use the default. It is a best practice to use a password for an SSH key but it is not required and you can skip creating a password by pressing enter. Note that the password you choose here can't be altered or retrieved. @@ -22,5 +18,4 @@ Use the code below to show your public key. cat ~/.ssh/id_rsa.pub ``` -Copy-paste the key to the 'My SSH Keys' section under the 'SSH' tab in your user profile. -Please copy the complete key starting with `ssh-` and ending with your username and host. +Copy-paste the key to the 'My SSH Keys' section under the 'SSH' tab in your user profile. Please copy the complete key starting with `ssh-` and ending with your username and host. diff --git a/doc/system_hooks/system_hooks.md b/doc/system_hooks/system_hooks.md index 5a1a32c1ed..47f17c1a08 100644 --- a/doc/system_hooks/system_hooks.md +++ b/doc/system_hooks/system_hooks.md @@ -4,7 +4,7 @@ Your GitLab instance can perform HTTP POST requests on the following events: `cr System hooks can be used, e.g. for logging or changing information in a LDAP server. -#### Hooks request example: +## Hooks request example **Project created:** @@ -73,23 +73,23 @@ System hooks can be used, e.g. for logging or changing information in a LDAP ser **User created:** ```json -{ +{ "created_at": "2012-07-21T07:44:07Z", "email": "js@gitlabhq.com", "event_name": "user_create", - "name": "John Smith", - "user_id": 41 + "name": "John Smith", + "user_id": 41 } ``` **User removed:** ```json -{ +{ "created_at": "2012-07-21T07:44:07Z", "email": "js@gitlabhq.com", "event_name": "user_destroy", "name": "John Smith", - "user_id": 41 + "user_id": 41 } ``` diff --git a/doc/update/2.6-to-3.0.md b/doc/update/2.6-to-3.0.md index d7047d8eb1..6aabbe095d 100644 --- a/doc/update/2.6-to-3.0.md +++ b/doc/update/2.6-to-3.0.md @@ -1,10 +1,10 @@ # From 2.6 to 3.0 -### 1. Stop server & resque +## 1. Stop server & resque sudo service gitlab stop -### 2. Update code & db +## 2. Update code & db ```bash @@ -54,10 +54,8 @@ sudo -u git -H sed -i "s/\(GIT_CONFIG_KEYS\s*=>*\s*\).\{2\}/\\1'\.\*'/g" /home/g # Check app status sudo -u gitlab bundle exec rake gitlab:app:status RAILS_ENV=production - ``` - -### 3. Start all +## 3. Start all sudo service gitlab start diff --git a/doc/update/2.9-to-3.0.md b/doc/update/2.9-to-3.0.md index af929e027a..8af86b0dc9 100644 --- a/doc/update/2.9-to-3.0.md +++ b/doc/update/2.9-to-3.0.md @@ -1,10 +1,10 @@ # From 2.9 to 3.0 -### 1. Stop server & resque +## 1. Stop server & resque sudo service gitlab stop -### 2. Follow instructions +## 2. Follow instructions ```bash @@ -31,7 +31,6 @@ sudo -u git -H sed -i 's/\(GL_GITCONFIG_KEYS\s*=>*\s*\).\{2\}/\\1"\.\*"/g' /home sudo -u gitlab -H bundle exec rake gitlab:app:status RAILS_ENV=production ``` - -### 3. Start all +## 3. Start all sudo service gitlab start diff --git a/doc/update/3.0-to-3.1.md b/doc/update/3.0-to-3.1.md index 5f06f818d1..3206df3499 100644 --- a/doc/update/3.0-to-3.1.md +++ b/doc/update/3.0-to-3.1.md @@ -1,26 +1,22 @@ # From 3.0 to 3.1 -__IMPORTANT!__ +**IMPORTANT!** -In this release __we moved Resque jobs under own gitlab namespace__. +In this release **we moved Resque jobs under own gitlab namespace** -Despite a lot of advantages it requires from our users to __replace gitolite post-receive hook with new one__. +Despite a lot of advantages it requires from our users to **replace gitolite post-receive hook with new one**. -Most of projects has post-receive file as symlink to gitolite `/home/git/.gitolite/hooks/post-receive`. -But some of them may have a real file. In this case you should rewrite it with symlink to gitolite hook. +Most of projects has post-receive file as symlink to gitolite `/home/git/.gitolite/hooks/post-receive`. But some of them may have a real file. In this case you should rewrite it with symlink to gitolite hook. I wrote a bash script which will do it automatically for you. Just make sure all path inside is valid for you -- - - - -### 1. Stop server & resque +## 1. Stop server & resque sudo service gitlab stop -### 2. Update GitLab +## 2. Update GitLab ```bash - # Get latest code sudo -u gitlab -H git fetch sudo -u gitlab -H git checkout v3.1.0 @@ -35,12 +31,11 @@ sudo -u gitlab -H bundle install --without development test postgres sqlite # Migrate db sudo -u gitlab -H bundle exec rake db:migrate RAILS_ENV=production - ``` -### 3. Update post-receive hooks +## 3. Update post-receive hooks -#### Gitolite 3 +### Gitolite 3 Step 1: Rewrite post-receive hook @@ -60,7 +55,7 @@ sudo -u gitlab -H vim lib/support/rewrite-hooks.sh sudo -u git -H lib/support/rewrite-hooks.sh ``` -#### Gitolite v2 +### Gitolite v2 Step 1: rewrite post-receive hook for gitolite 2 @@ -71,7 +66,6 @@ sudo chown git:git /home/git/share/gitolite/hooks/common/post-receive Step 2: Replace symlinks in project to valid place - #!/bin/bash src="/home/git/repositories" for dir in `ls "$src/"` @@ -90,19 +84,13 @@ Step 2: Replace symlinks in project to valid place fi done - -### 4. Check app status +## 4. Check app status ```bash - # Check APP Status sudo -u gitlab -H bundle exec rake gitlab:app:status RAILS_ENV=production - - - ``` - -### 5. Start all +## 5. Start all sudo service gitlab start diff --git a/doc/update/3.1-to-4.0.md b/doc/update/3.1-to-4.0.md index c5ae3a40a7..165f4e6a30 100644 --- a/doc/update/3.1-to-4.0.md +++ b/doc/update/3.1-to-4.0.md @@ -2,25 +2,22 @@ ## Important changes -* Support for SQLite was dropped -* Support for gitolite 2 was dropped -* Projects are organized in namespaces -* The GitLab post-receive hook needs to be updated -* The configuration file needs to be updated -* Availability of `python2` executable +- Support for SQLite was dropped +- Support for Gitolite 2 was dropped +- Projects are organized in namespaces +- The GitLab post-receive hook needs to be updated +- The configuration file needs to be updated +- Availability of `python2` executable -Most of projects has post-receive file as symlink to gitolite `/home/git/.gitolite/hooks/post-receive`. -But some of them may have a real file. In this case you should rewrite it with symlink to gitolite hook. +Most of projects has post-receive file as symlink to Gitolite `/home/git/.gitolite/hooks/post-receive`. But some of them may have a real file. In this case you should rewrite it with symlink to Gitolite hook. I wrote a bash script which will do it automatically for you. Just make sure all path inside is valid for you -- - - - -### 1. Stop GitLab & Resque +## 1. Stop GitLab & Resque sudo service gitlab stop -### 2. Update GitLab +## 2. Update GitLab ```bash @@ -43,8 +40,7 @@ sudo -u gitlab -H bundle exec rake gitlab:enable_namespaces RAILS_ENV=production ``` -### 3. Update post-receive hooks (Requires gitolite v3 ) - +## 3. Update post-receive hooks (Requires Gitolite v3 ) Step 1: Rewrite post-receive hook @@ -63,9 +59,7 @@ sudo -u gitlab -H vim lib/support/rewrite-hooks.sh sudo -u git -H lib/support/rewrite-hooks.sh ``` - -### 4. Replace config with new one - +## 4. Replace config with new one # backup old one sudo -u gitlab -H cp config/gitlab.yml config/gitlab.yml.old @@ -76,9 +70,7 @@ sudo -u git -H lib/support/rewrite-hooks.sh # edit it sudo -u gitlab -H vim config/gitlab.yml - -### 5. Disable ssh known_host check for own domain - +## 5. Disable ssh known_host check for own domain echo "Host localhost StrictHostKeyChecking no @@ -88,12 +80,10 @@ sudo -u git -H lib/support/rewrite-hooks.sh StrictHostKeyChecking no UserKnownHostsFile=/dev/null" | sudo tee -a /etc/ssh/ssh_config - -### 6. Check GitLab's status +## 6. Check GitLab's status sudo -u gitlab -H bundle exec rake gitlab:check RAILS_ENV=production - -### 7. Start GitLab & Resque +## 7. Start GitLab & Resque sudo service gitlab start diff --git a/doc/update/4.0-to-4.1.md b/doc/update/4.0-to-4.1.md index 324af7597b..d5e5d62fb1 100644 --- a/doc/update/4.0-to-4.1.md +++ b/doc/update/4.0-to-4.1.md @@ -2,18 +2,16 @@ ## Important changes -* Resque replaced with Sidekiq -* New options for configuration file added -* Init.d script should be updated -* __requires ruby1.9.3-p327__ +- Resque replaced with Sidekiq +- New options for configuration file added +- Init.d script should be updated +- **requires ruby1.9.3-p327** -- - - - -### 1. Stop GitLab & Resque +## 1. Stop GitLab & Resque sudo service gitlab stop -### 2. Update GitLab +## 2. Update GitLab ```bash # Set the working directory @@ -31,7 +29,7 @@ sudo -u gitlab -H bundle exec rake db:migrate RAILS_ENV=production ``` -### 3. Replace init.d script with a new one +## 3. Replace init.d script with a new one ``` # backup old one @@ -43,15 +41,15 @@ sudo chmod +x /etc/init.d/gitlab ``` -### 4. Check GitLab's status +## 4. Check GitLab's status sudo -u gitlab -H bundle exec rake gitlab:check RAILS_ENV=production -### 5. Start GitLab & Sidekiq +## 5. Start GitLab & Sidekiq sudo service gitlab start -### 6. Remove old init.d script +## 6. Remove old init.d script sudo rm /etc/init.d/gitlab.old diff --git a/doc/update/4.1-to-4.2.md b/doc/update/4.1-to-4.2.md index 3aaf17b772..5ee8e8781e 100644 --- a/doc/update/4.1-to-4.2.md +++ b/doc/update/4.1-to-4.2.md @@ -1,10 +1,10 @@ # From 4.1 to 4.2 -### 1. Stop server & resque +## 1. Stop server & Resque sudo service gitlab stop -### 2. Update code & db +## 2. Update code & DB ```bash @@ -24,15 +24,12 @@ sudo -u gitlab -H bundle exec rake db:migrate RAILS_ENV=production ``` - -### 3. Check GitLab's status +## 3. Check GitLab's status ```bash sudo -u gitlab -H bundle exec rake gitlab:check RAILS_ENV=production ``` - - -### 4. Start all +## 4. Start all sudo service gitlab start diff --git a/doc/update/4.2-to-5.0.md b/doc/update/4.2-to-5.0.md index f8fb607e01..230c1e88b2 100644 --- a/doc/update/4.2-to-5.0.md +++ b/doc/update/4.2-to-5.0.md @@ -1,32 +1,32 @@ # From 4.2 to 5.0 ## Warning + GitLab 5.0 is affected by critical security vulnerability CVE-2013-4490. ## Important changes -* We don't use `gitlab` user any more. Everything will be moved to `git` user -* __requires ruby1.9.3__ +- We don't use `gitlab` user any more. Everything will be moved to `git` user +- **requires ruby1.9.3** - -__0. Stop gitlab__ +## 0. Stop gitlab sudo service gitlab stop -__1. add bash to git user__ +## 1. add bash to git user ``` sudo chsh -s /bin/bash git ``` -__2. git clone gitlab-shell__ +## 2. git clone gitlab-shell ``` cd /home/git/ sudo -u git -H git clone https://github.com/gitlabhq/gitlab-shell.git /home/git/gitlab-shell ``` -__3. setup gitlab-shell__ +## 3. setup gitlab-shell ```bash # chmod all repos and files under git @@ -55,7 +55,7 @@ ruby -v exit ``` -__4. Copy gitlab instance to git user__ +## 4. Copy gitlab instance to git user ```bash sudo cp -R /home/gitlab/gitlab /home/git/gitlab @@ -66,7 +66,7 @@ sudo rm -rf /home/gitlab/gitlab-satellites sudo rm /tmp/gitlab.socket ``` -__5. Update gitlab to recent version__ +## 5. Update gitlab to recent version ```bash cd /home/git/gitlab @@ -110,7 +110,7 @@ sudo chmod -R u+rwX /home/git/gitlab/tmp/pids ``` -__6. Update init.d script and nginx config__ +## 6. Update init.d script and nginx config ```bash # init.d @@ -127,14 +127,11 @@ sudo -u git -H cp /home/git/gitlab/config/unicorn.rb.example /home/git/gitlab/co sudo vim /etc/nginx/sites-enabled/gitlab sudo service nginx restart - ``` -__7. Start gitlab instance__ +## 7. Start GitLab instance ``` - - sudo service gitlab start # check if unicorn and sidekiq started @@ -145,7 +142,7 @@ ps aux | grep sidekiq ``` -__8. Check installation__ +## 8. Check installation ```bash @@ -164,5 +161,4 @@ sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production ``` - -__P.S. If everything works as expected you can remove gitlab user from system__ +**P.S. If everything works as expected you can remove gitlab user from system** diff --git a/doc/update/5.0-to-5.1.md b/doc/update/5.0-to-5.1.md index ba56507dd8..628d8bc7df 100644 --- a/doc/update/5.0-to-5.1.md +++ b/doc/update/5.0-to-5.1.md @@ -1,18 +1,19 @@ # From 5.0 to 5.1 ## Warning + GitLab 5.1 is affected by critical security vulnerability CVE-2013-4490. -## Release notes: +## Release notes -* `unicorn` replaced with `puma` -* merge request cached diff will be truncated +- `unicorn` replaced with `puma` +- merge request cached diff will be truncated -### 1. Stop server +## 1. Stop server sudo service gitlab stop -### 2. Get latest code +## 2. Get latest code ```bash cd /home/git/gitlab @@ -20,7 +21,7 @@ sudo -u git -H git fetch sudo -u git -H git checkout 5-1-stable ``` -### 3. Update gitlab-shell +## 3. Update gitlab-shell ```bash cd /home/git/gitlab-shell @@ -33,8 +34,7 @@ sudo -u git -H cp config.yml.example config.yml sudo -u git -H vi config.yml ``` - -### 4. Install libs, migrations etc +## 4. Install libs, migrations etc ```bash cd /home/git/gitlab @@ -47,7 +47,7 @@ sudo -u git -H bundle exec rake migrate_merge_requests RAILS_ENV=production sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production ``` -### 5. Update init.d script with a new one +## 5. Update init.d script with a new one ```bash # init.d @@ -56,9 +56,9 @@ sudo curl --output /etc/init.d/gitlab https://raw.github.com/gitlabhq/gitlab-rec sudo chmod +x /etc/init.d/gitlab ``` -### 6. Mysql grant privileges +## 6. MySQL grant privileges -Only if you are using mysql: +Only if you are using MySQL: ```bash mysql -u root -p @@ -66,6 +66,6 @@ mysql> GRANT LOCK TABLES ON `gitlabhq_production`.* TO 'gitlab'@'localhost'; mysql> \q ``` -### 7. Start application +## 7. Start application sudo service gitlab start diff --git a/doc/update/5.1-to-5.2.md b/doc/update/5.1-to-5.2.md index 466c815195..c37f20ce55 100644 --- a/doc/update/5.1-to-5.2.md +++ b/doc/update/5.1-to-5.2.md @@ -1,9 +1,10 @@ # From 5.1 to 5.2 ## Warning + GitLab 5.2 is affected by critical security vulnerabilities CVE-2013-4490 and CVE-2013-4489. -### 0. Backup +## 0. Backup It's useful to make a backup just in case things go south: (With MySQL, this may require granting "LOCK TABLES" privileges to the GitLab user on the database version) @@ -13,11 +14,11 @@ cd /home/git/gitlab sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production ``` -### 1. Stop server +## 1. Stop server sudo service gitlab stop -### 2. Get latest code +## 2. Get latest code ```bash cd /home/git/gitlab @@ -25,7 +26,7 @@ sudo -u git -H git fetch sudo -u git -H git checkout 5-2-stable ``` -### 3. Update gitlab-shell +## 3. Update gitlab-shell ```bash cd /home/git/gitlab-shell @@ -33,7 +34,7 @@ sudo -u git -H git fetch sudo -u git -H git checkout v1.4.0 ``` -### 4. Install libs, migrations, etc. +## 4. Install libs, migrations, etc. ```bash cd /home/git/gitlab @@ -49,12 +50,12 @@ sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production ``` -### 5. Update config files +## 5. Update config files -* Make `/home/git/gitlab/config/gitlab.yml` same as https://gitlab.com/gitlab-org/gitlab-ce/blob/5-2-stable/config/gitlab.yml.example but with your settings. -* Make `/home/git/gitlab/config/puma.rb` same as https://gitlab.com/gitlab-org/gitlab-ce/blob/5-2-stable/config/puma.rb.example but with your settings. +- Make `/home/git/gitlab/config/gitlab.yml` same as https://gitlab.com/gitlab-org/gitlab-ce/blob/5-2-stable/config/gitlab.yml.example but with your settings. +- Make `/home/git/gitlab/config/puma.rb` same as https://gitlab.com/gitlab-org/gitlab-ce/blob/5-2-stable/config/puma.rb.example but with your settings. -### 6. Update Init script +## 6. Update Init script ```bash cd /home/git/gitlab @@ -63,7 +64,7 @@ sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab sudo chmod +x /etc/init.d/gitlab ``` -### 7. Create uploads directory +## 7. Create uploads directory ```bash cd /home/git/gitlab @@ -71,12 +72,12 @@ sudo -u git -H mkdir public/uploads sudo chmod -R u+rwX public/uploads ``` -### 8. Start application +## 8. Start application sudo service gitlab start sudo service nginx restart -### 9. Check application status +## 9. Check application status Check if GitLab and its environment are configured correctly: @@ -91,10 +92,10 @@ If all items are green, then congratulations upgrade complete! ## Things went south? Revert to previous version (5.1) ### 1. Revert the code to the previous version -Follow the [`upgrade guide from 5.0 to 5.1`](5.0-to-5.1.md), except for the database migration -(The backup is already migrated to the previous version) -### 2. Restore from the backup: +Follow the [`upgrade guide from 5.0 to 5.1`](5.0-to-5.1.md), except for the database migration (the backup is already migrated to the previous version). + +### 2. Restore from the backup ```bash cd /home/git/gitlab diff --git a/doc/update/5.1-to-5.4.md b/doc/update/5.1-to-5.4.md index 56f4854daf..53dbfd00ad 100644 --- a/doc/update/5.1-to-5.4.md +++ b/doc/update/5.1-to-5.4.md @@ -1,21 +1,21 @@ # From 5.1 to 5.4 + Also works starting from 5.2. -### 0. Backup +## 0. Backup -It's useful to make a backup just in case things go south: -(With MySQL, this may require granting "LOCK TABLES" privileges to the GitLab user on the database version) +It's useful to make a backup just in case things go south (with MySQL, this may require granting "LOCK TABLES" privileges to the GitLab user on the database version): ```bash cd /home/git/gitlab sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production ``` -### 1. Stop server +## 1. Stop server sudo service gitlab stop -### 2. Get latest code +## 2. Get latest code ```bash cd /home/git/gitlab @@ -23,7 +23,7 @@ sudo -u git -H git fetch sudo -u git -H git checkout 5-4-stable # Latest version of 5-4-stable addresses CVE-2013-4489 ``` -### 3. Update gitlab-shell +## 3. Update gitlab-shell ```bash cd /home/git/gitlab-shell @@ -31,7 +31,7 @@ sudo -u git -H git fetch sudo -u git -H git checkout v1.7.9 # Addresses multiple critical security vulnerabilities ``` -### 4. Install libs, migrations, etc. +## 4. Install libs, migrations, etc. ```bash cd /home/git/gitlab @@ -47,12 +47,12 @@ sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production ``` -### 5. Update config files +## 5. Update config files -* Make `/home/git/gitlab/config/gitlab.yml` same as https://gitlab.com/gitlab-org/gitlab-ce/blob/5-4-stable/config/gitlab.yml.example but with your settings. -* Make `/home/git/gitlab/config/puma.rb` same as https://gitlab.com/gitlab-org/gitlab-ce/blob/5-4-stable/config/puma.rb.example but with your settings. +- Make `/home/git/gitlab/config/gitlab.yml` same as https://gitlab.com/gitlab-org/gitlab-ce/blob/5-4-stable/config/gitlab.yml.example but with your settings. +- Make `/home/git/gitlab/config/puma.rb` same as https://gitlab.com/gitlab-org/gitlab-ce/blob/5-4-stable/config/puma.rb.example but with your settings. -### 6. Update Init script +## 6. Update Init script ```bash sudo rm /etc/init.d/gitlab @@ -60,7 +60,7 @@ sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab sudo chmod +x /etc/init.d/gitlab ``` -### 7. Create uploads directory +## 7. Create uploads directory ```bash cd /home/git/gitlab @@ -68,13 +68,12 @@ sudo -u git -H mkdir public/uploads sudo chmod -R u+rwX public/uploads ``` - -### 8. Start application +## 8. Start application sudo service gitlab start sudo service nginx restart -### 9. Check application status +## 9. Check application status Check if GitLab and its environment are configured correctly: @@ -89,8 +88,8 @@ If all items are green, then congratulations upgrade complete! ## Things went south? Revert to previous version (5.3) ### 1. Revert the code to the previous version -Follow the [`upgrade guide from 5.2 to 5.3`](5.2-to-5.3.md), except for the database migration -(The backup is already migrated to the previous version) + +Follow the [`upgrade guide from 5.2 to 5.3`](5.2-to-5.3.md), except for the database migration (the backup is already migrated to the previous version). ### 2. Restore from the backup: diff --git a/doc/update/5.1-to-6.0.md b/doc/update/5.1-to-6.0.md index 5b74b1f893..11afc75f0f 100644 --- a/doc/update/5.1-to-6.0.md +++ b/doc/update/5.1-to-6.0.md @@ -1,26 +1,34 @@ # From 5.1 to 6.0 ## Warning + GitLab 6.0 is affected by critical security vulnerabilities CVE-2013-4490 and CVE-2013-4489. -### Deprecations +## Deprecations -#### Global projects +### Global projects The root (global) namespace for projects is deprecated. -So you need to move all your global projects under groups or users manually before update or they will be automatically moved to the project owner namespace during the update. When a project is moved all its members will receive an email with instructions how to update their git remote url. Please make sure you disable sending email when you do a test of the upgrade. -#### Teams +So you need to move all your global projects under groups or users manually before update or they will be automatically moved to the project owner namespace during the update. When a project is moved all its members will receive an email with instructions how to update their git remote URL. Please make sure you disable sending email when you do a test of the upgrade. + +### Teams We introduce group membership in 6.0 as a replacement for teams. + The old combination of groups and teams was confusing for a lot of people. + And when the members of a team where changed this wasn't reflected in the project permissions. + In GitLab 6.0 you will be able to add members to a group with a permission level for each member. + These group members will have access to the projects in that group. + Any changes to group members will immediately be reflected in the project permissions. + You can even have multiple owners for a group, greatly simplifying administration. -### 0. Backup +## 0. Backup It's useful to make a backup just in case things go south: (With MySQL, this may require granting "LOCK TABLES" privileges to the GitLab user on the database version) @@ -30,11 +38,11 @@ cd /home/git/gitlab sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production ``` -### 1. Stop server +## 1. Stop server sudo service gitlab stop -### 2. Get latest code +## 2. Get latest code ```bash cd /home/git/gitlab @@ -42,7 +50,7 @@ sudo -u git -H git fetch sudo -u git -H git checkout 6-0-stable ``` -### 3. Update gitlab-shell +## 3. Update gitlab-shell ```bash cd /home/git/gitlab-shell @@ -50,14 +58,14 @@ sudo -u git -H git fetch sudo -u git -H git checkout v1.7.9 ``` -### 4. Install additional packages +## 4. Install additional packages ```bash # For reStructuredText markup language support install required package: sudo apt-get install python-docutils ``` -### 5. Install libs, migrations, etc. +## 5. Install libs, migrations, etc. ```bash cd /home/git/gitlab @@ -83,14 +91,14 @@ sudo -u git -H bundle exec rake assets:clean RAILS_ENV=production sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production ``` -### 6. Update config files +## 6. Update config files Note: We switched from Puma in GitLab 5.x to unicorn in GitLab 6.0. -* Make `/home/git/gitlab/config/gitlab.yml` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/masterconfig/gitlab.yml.example but with your settings. -* Make `/home/git/gitlab/config/unicorn.rb` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/masterconfig/unicorn.rb.example but with your settings. +- Make `/home/git/gitlab/config/gitlab.yml` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/masterconfig/gitlab.yml.example but with your settings. +- Make `/home/git/gitlab/config/unicorn.rb` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/masterconfig/unicorn.rb.example but with your settings. -### 7. Update Init script +## 7. Update Init script ```bash cd /home/git/gitlab @@ -99,7 +107,7 @@ sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab sudo chmod +x /etc/init.d/gitlab ``` -### 8. Create uploads directory +## 8. Create uploads directory ```bash cd /home/git/gitlab @@ -107,12 +115,12 @@ sudo -u git -H mkdir -p public/uploads sudo chmod -R u+rwX public/uploads ``` -### 9. Start application +## 9. Start application sudo service gitlab start sudo service nginx restart -### 10. Check application status +## 10. Check application status Check if GitLab and its environment are configured correctly: @@ -127,8 +135,8 @@ If all items are green, then congratulations upgrade complete! ## Things went south? Revert to previous version (5.1) ### 1. Revert the code to the previous version -Follow the [`upgrade guide from 5.0 to 5.1`](5.0-to-5.1.md), except for the database migration -(The backup is already migrated to the previous version) + +Follow the [`upgrade guide from 5.0 to 5.1`](5.0-to-5.1.md), except for the database migration (the backup is already migrated to the previous version). ### 2. Restore from the backup: @@ -137,20 +145,24 @@ cd /home/git/gitlab sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production ``` -### Troubleshooting +## Troubleshooting + The migrations in this update are very sensitive to incomplete or inconsistent data. If you have a long-running GitLab installation and some of the previous upgrades did not work out 100% correct this may bite you now. The following commands can be run in the rails console to look for 'bad' data. -All project owners should have an owner +All project owners should have an owner: + ``` Project.all.select { |project| project.owner.blank? } ``` -Every user should have a namespace +Every user should have a namespace: + ``` User.all.select { |u| u.namespace.blank? } ``` -Projects in the global namespace should not conflict with projects in the owner namespace +Projects in the global namespace should not conflict with projects in the owner namespace: + ``` Project.where(namespace_id: nil).select { |p| Project.where(path: p.path, namespace_id: p.owner.try(:namespace).try(:id)).present? } ``` diff --git a/doc/update/5.2-to-5.3.md b/doc/update/5.2-to-5.3.md index e3c3016db6..e39e18d421 100644 --- a/doc/update/5.2-to-5.3.md +++ b/doc/update/5.2-to-5.3.md @@ -1,23 +1,23 @@ # From 5.2 to 5.3 ## Warning + GitLab 5.3 is affected by critical security vulnerabilities CVE-2013-4490 and CVE-2013-4489. -### 0. Backup +## 0. Backup -It's useful to make a backup just in case things go south: -(With MySQL, this may require granting "LOCK TABLES" privileges to the GitLab user on the database version) +It's useful to make a backup just in case things go south (with MySQL, this may require granting "LOCK TABLES" privileges to the GitLab user on the database version): ```bash cd /home/git/gitlab sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production ``` -### 1. Stop server +## 1. Stop server sudo service gitlab stop -### 2. Get latest code +## 2. Get latest code ```bash cd /home/git/gitlab @@ -25,7 +25,7 @@ sudo -u git -H git fetch sudo -u git -H git checkout 5-3-stable ``` -### 3. Install libs, migrations, etc. +## 3. Install libs, migrations, etc. ```bash cd /home/git/gitlab @@ -41,12 +41,12 @@ sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production ``` -### 4. Update config files +## 4. Update config files -* Make `/home/git/gitlab/config/gitlab.yml` same as https://gitlab.com/gitlab-org/gitlab-ce/blob/5-3-stable/config/gitlab.yml.example but with your settings. -* Make `/home/git/gitlab/config/puma.rb` same as https://gitlab.com/gitlab-org/gitlab-ce/blob/5-3-stable/config/puma.rb.example but with your settings. +- Make `/home/git/gitlab/config/gitlab.yml` same as https://gitlab.com/gitlab-org/gitlab-ce/blob/5-3-stable/config/gitlab.yml.example but with your settings. +- Make `/home/git/gitlab/config/puma.rb` same as https://gitlab.com/gitlab-org/gitlab-ce/blob/5-3-stable/config/puma.rb.example but with your settings. -### 5. Update Init script +## 5. Update Init script ```bash sudo rm /etc/init.d/gitlab @@ -54,12 +54,12 @@ sudo curl --output /etc/init.d/gitlab https://raw.github.com/gitlabhq/gitlabhq/5 sudo chmod +x /etc/init.d/gitlab ``` -### 6. Start application +## 6. Start application sudo service gitlab start sudo service nginx restart -### 7. Check application status +## 7. Check application status Check if GitLab and its environment are configured correctly: @@ -74,8 +74,8 @@ If all items are green, then congratulations upgrade complete! ## Things went south? Revert to previous version (5.2) ### 1. Revert the code to the previous version -Follow the [`upgrade guide from 5.1 to 5.2`](5.1-to-5.2.md), except for the database migration -(The backup is already migrated to the previous version) + +Follow the [`upgrade guide from 5.1 to 5.2`](5.1-to-5.2.md), except for the database migration (the backup is already migrated to the previous version). ### 2. Restore from the backup: diff --git a/doc/update/5.3-to-5.4.md b/doc/update/5.3-to-5.4.md index 213ce77ec3..e1749f133b 100644 --- a/doc/update/5.3-to-5.4.md +++ b/doc/update/5.3-to-5.4.md @@ -1,20 +1,19 @@ # From 5.3 to 5.4 -### 0. Backup +## 0. Backup -It's useful to make a backup just in case things go south: -(With MySQL, this may require granting "LOCK TABLES" privileges to the GitLab user on the database version) +It's useful to make a backup just in case things go south (with MySQL, this may require granting "LOCK TABLES" privileges to the GitLab user on the database version): ```bash cd /home/git/gitlab sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production ``` -### 1. Stop server +## 1. Stop server sudo service gitlab stop -### 2. Get latest code +## 2. Get latest code ```bash cd /home/git/gitlab @@ -22,7 +21,7 @@ sudo -u git -H git fetch sudo -u git -H git checkout 5-4-stable # Latest version of 5-4-stable addresses CVE-2013-4489 ``` -### 3. Update gitlab-shell +## 3. Update gitlab-shell ```bash cd /home/git/gitlab-shell @@ -30,7 +29,7 @@ sudo -u git -H git fetch sudo -u git -H git checkout v1.7.9 # Addresses multiple critical security vulnerabilities ``` -### 4. Install libs, migrations, etc. +## 4. Install libs, migrations, etc. ```bash cd /home/git/gitlab @@ -46,12 +45,12 @@ sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production ``` -### 5. Update config files +## 5. Update config files -* Make `/home/git/gitlab/config/gitlab.yml` same as https://gitlab.com/gitlab-org/gitlab-ce/blob/5-4-stable/config/gitlab.yml.example but with your settings. -* Make `/home/git/gitlab/config/puma.rb` same as https://gitlab.com/gitlab-org/gitlab-ce/blob/5-4-stable/config/puma.rb.example but with your settings. +- Make `/home/git/gitlab/config/gitlab.yml` same as https://gitlab.com/gitlab-org/gitlab-ce/blob/5-4-stable/config/gitlab.yml.example but with your settings. +- Make `/home/git/gitlab/config/puma.rb` same as https://gitlab.com/gitlab-org/gitlab-ce/blob/5-4-stable/config/puma.rb.example but with your settings. -### 6. Update Init script +## 6. Update Init script ```bash sudo rm /etc/init.d/gitlab @@ -59,12 +58,12 @@ sudo curl --output /etc/init.d/gitlab https://raw.github.com/gitlabhq/gitlabhq/5 sudo chmod +x /etc/init.d/gitlab ``` -### 7. Start application +## 7. Start application sudo service gitlab start sudo service nginx restart -### 8. Check application status +## 8. Check application status Check if GitLab and its environment are configured correctly: @@ -79,8 +78,8 @@ If all items are green, then congratulations upgrade complete! ## Things went south? Revert to previous version (5.3) ### 1. Revert the code to the previous version -Follow the [`upgrade guide from 5.2 to 5.3`](5.2-to-5.3.md), except for the database migration -(The backup is already migrated to the previous version) + +Follow the [`upgrade guide from 5.2 to 5.3`](5.2-to-5.3.md), except for the database migration (the backup is already migrated to the previous version). ### 2. Restore from the backup: diff --git a/doc/update/5.4-to-6.0.md b/doc/update/5.4-to-6.0.md index c289fcb57f..7bf7bce6aa 100644 --- a/doc/update/5.4-to-6.0.md +++ b/doc/update/5.4-to-6.0.md @@ -1,40 +1,47 @@ # From 5.4 to 6.0 ## Warning + GitLab 6.0 is affected by critical security vulnerabilities CVE-2013-4490 and CVE-2013-4489. -### Deprecations +## Deprecations -#### Global projects +### Global projects The root (global) namespace for projects is deprecated. + So you need to move all your global projects under groups or users manually before update or they will be automatically moved to the project owner namespace during the update. When a project is moved all its members will receive an email with instructions how to update their git remote url. Please make sure you disable sending email when you do a test of the upgrade. -#### Teams +### Teams We introduce group membership in 6.0 as a replacement for teams. + The old combination of groups and teams was confusing for a lot of people. + And when the members of a team where changed this wasn't reflected in the project permissions. + In GitLab 6.0 you will be able to add members to a group with a permission level for each member. + These group members will have access to the projects in that group. + Any changes to group members will immediately be reflected in the project permissions. + You can even have multiple owners for a group, greatly simplifying administration. -### 0. Backup +## 0. Backup -It's useful to make a backup just in case things go south: -(With MySQL, this may require granting "LOCK TABLES" privileges to the GitLab user on the database version) +It's useful to make a backup just in case things go south (with MySQL, this may require granting "LOCK TABLES" privileges to the GitLab user on the database version): ```bash cd /home/git/gitlab sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production ``` -### 1. Stop server +## 1. Stop server sudo service gitlab stop -### 2. Get latest code +## 2. Get latest code ```bash cd /home/git/gitlab @@ -42,7 +49,7 @@ sudo -u git -H git fetch sudo -u git -H git checkout 6-0-stable ``` -### 3. Update gitlab-shell +## 3. Update gitlab-shell ```bash cd /home/git/gitlab-shell @@ -50,14 +57,14 @@ sudo -u git -H git fetch sudo -u git -H git checkout v1.7.9 ``` -### 4. Install additional packages +## 4. Install additional packages ```bash # For reStructuredText markup language support install required package: sudo apt-get install python-docutils ``` -### 5. Install libs, migrations, etc. +## 5. Install libs, migrations, etc. ```bash cd /home/git/gitlab @@ -83,14 +90,14 @@ sudo -u git -H bundle exec rake assets:clean RAILS_ENV=production sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production ``` -### 6. Update config files +## 6. Update config files Note: We switched from Puma in GitLab 5.4 to unicorn in GitLab 6.0. -* Make `/home/git/gitlab/config/gitlab.yml` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/master/config/gitlab.yml.example but with your settings. -* Make `/home/git/gitlab/config/unicorn.rb` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/master/config/unicorn.rb.example but with your settings. +- Make `/home/git/gitlab/config/gitlab.yml` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/master/config/gitlab.yml.example but with your settings. +- Make `/home/git/gitlab/config/unicorn.rb` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/master/config/unicorn.rb.example but with your settings. -### 7. Update Init script +## 7. Update Init script ```bash sudo rm /etc/init.d/gitlab @@ -98,12 +105,12 @@ sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab sudo chmod +x /etc/init.d/gitlab ``` -### 8. Start application +## 8. Start application sudo service gitlab start sudo service nginx restart -### 9. Check application status +## 9. Check application status Check if GitLab and its environment are configured correctly: @@ -115,20 +122,24 @@ To make sure you didn't miss anything run a more thorough check with: If all items are green, then congratulations upgrade complete! -### Troubleshooting +## Troubleshooting + The migrations in this update are very sensitive to incomplete or inconsistent data. If you have a long-running GitLab installation and some of the previous upgrades did not work out 100% correct this may bite you now. The following commands can be run in the rails console to look for 'bad' data. -All project owners should have an owner +All project owners should have an owner: + ``` Project.all.select { |project| project.owner.blank? } ``` -Every user should have a namespace +Every user should have a namespace: + ``` User.all.select { |u| u.namespace.blank? } ``` -Projects in the global namespace should not conflict with projects in the owner namespace +Projects in the global namespace should not conflict with projects in the owner namespace: + ``` Project.where(namespace_id: nil).select { |p| Project.where(path: p.path, namespace_id: p.owner.try(:namespace).try(:id)).present? } ``` diff --git a/doc/update/6.0-to-6.1.md b/doc/update/6.0-to-6.1.md index b4cc920358..36c7f04f63 100644 --- a/doc/update/6.0-to-6.1.md +++ b/doc/update/6.0-to-6.1.md @@ -1,32 +1,33 @@ # From 6.0 to 6.1 ## Warning + GitLab 6.1 is affected by critical security vulnerabilities CVE-2013-4490 and CVE-2013-4489. -# In 6.1 we remove a lot of deprecated code. -# You should update to 6.0 before installing 6.1 so all the necessary conversions are run. +**In 6.1 we remove a lot of deprecated code.** -### Deprecations +**You should update to 6.0 before installing 6.1 so all the necessary conversions are run.** -#### Global issue numbers +## Deprecations -In 6.1 issue numbers are project specific. This means all issues are renumbered and get a new number in their url. If you use an old issue number url and the issue number does not exist yet you are redirected to the new one. This conversion does not trigger if the old number already exists for this project, this is unlikely but will happen with old issues and large projects. +### Global issue numbers -### 0. Backup +In 6.1 issue numbers are project specific. This means all issues are renumbered and get a new number in their URL. If you use an old issue number URL and the issue number does not exist yet you are redirected to the new one. This conversion does not trigger if the old number already exists for this project, this is unlikely but will happen with old issues and large projects. -It's useful to make a backup just in case things go south: -(With MySQL, this may require granting "LOCK TABLES" privileges to the GitLab user on the database version) +## 0. Backup + +It's useful to make a backup just in case things go south (with MySQL, this may require granting "LOCK TABLES" privileges to the GitLab user on the database version): ```bash cd /home/git/gitlab sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production ``` -### 1. Stop server +## 1. Stop server sudo service gitlab stop -### 2. Get latest code +## 2. Get latest code ```bash cd /home/git/gitlab @@ -35,7 +36,7 @@ sudo -u git -H git checkout 6-1-stable # For GitLab Enterprise Edition: sudo -u git -H git checkout 6-1-stable-ee ``` -### 3. Update gitlab-shell +## 3. Update gitlab-shell ```bash cd /home/git/gitlab-shell @@ -43,7 +44,7 @@ sudo -u git -H git fetch sudo -u git -H git checkout v1.7.9 ``` -### 4. Install libs, migrations, etc. +## 4. Install libs, migrations, etc. ```bash cd /home/git/gitlab @@ -62,12 +63,12 @@ sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production ``` -### 5. Update config files +## 5. Update config files -* Make `/home/git/gitlab/config/gitlab.yml` same as https://gitlab.com/gitlab-org/gitlab-ce/blob/6-1-stable/config/gitlab.yml.example but with your settings. -* Make `/home/git/gitlab/config/unicorn.rb` same as https://gitlab.com/gitlab-org/gitlab-ce/blob/6-1-stable/config/unicorn.rb.example but with your settings. +- Make `/home/git/gitlab/config/gitlab.yml` same as https://gitlab.com/gitlab-org/gitlab-ce/blob/6-1-stable/config/gitlab.yml.example but with your settings. +- Make `/home/git/gitlab/config/unicorn.rb` same as https://gitlab.com/gitlab-org/gitlab-ce/blob/6-1-stable/config/unicorn.rb.example but with your settings. -### 6. Update Init script +## 6. Update Init script ```bash sudo rm /etc/init.d/gitlab @@ -75,12 +76,12 @@ sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab sudo chmod +x /etc/init.d/gitlab ``` -### 7. Start application +## 7. Start application sudo service gitlab start sudo service nginx restart -### 8. Check application status +## 8. Check application status Check if GitLab and its environment are configured correctly: @@ -96,8 +97,8 @@ If all items are green, then congratulations upgrade complete! ## Things went south? Revert to previous version (6.0) ### 1. Revert the code to the previous version -Follow the [`upgrade guide from 5.4 to 6.0`](5.4-to-6.0.md), except for the database migration -(The backup is already migrated to the previous version) + +Follow the [`upgrade guide from 5.4 to 6.0`](5.4-to-6.0.md), except for the database migration (the backup is already migrated to the previous version). ### 2. Restore from the backup: diff --git a/doc/update/6.0-to-6.8.md b/doc/update/6.0-to-6.8.md index 5c71e99aa5..0205d0d2e2 100644 --- a/doc/update/6.0-to-6.8.md +++ b/doc/update/6.0-to-6.8.md @@ -1,15 +1,16 @@ # From 6.0 to 6.8 -# In 6.1 we remove a lot of deprecated code. -# You should update to 6.0 before installing 6.1 or higher so all the necessary conversions are run. +**In 6.1 we remove a lot of deprecated code.** -### Deprecations +**You should update to 6.0 before installing 6.1 or higher so all the necessary conversions are run.** -#### Global issue numbers +## Deprecations -As of 6.1 issue numbers are project specific. This means all issues are renumbered and get a new number in their url. If you use an old issue number url and the issue number does not exist yet you are redirected to the new one. This conversion does not trigger if the old number already exists for this project, this is unlikely but will happen with old issues and large projects. +## Global issue numbers -### 0. Backup +As of 6.1 issue numbers are project specific. This means all issues are renumbered and get a new number in their URL. If you use an old issue number URL and the issue number does not exist yet you are redirected to the new one. This conversion does not trigger if the old number already exists for this project, this is unlikely but will happen with old issues and large projects. + +## 0. Backup It's useful to make a backup just in case things go south: (With MySQL, this may require granting "LOCK TABLES" privileges to the GitLab user on the database version) @@ -19,18 +20,18 @@ cd /home/git/gitlab sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production ``` -### 1. Stop server +## 1. Stop server sudo service gitlab stop -### 2. Get latest code +## 2. Get latest code ```bash cd /home/git/gitlab sudo -u git -H git fetch --all ``` -For Gitlab Community Edition: +For GitLab Community Edition: ```bash sudo -u git -H git checkout 6-8-stable @@ -45,14 +46,14 @@ sudo -u git -H git checkout 6-8-stable-ee ``` -### 3. Install additional packages +## 3. Install additional packages ```bash # Add support for lograte for better log file handling sudo apt-get install logrotate ``` -### 4. Update gitlab-shell +## 4. Update gitlab-shell ```bash cd /home/git/gitlab-shell @@ -60,7 +61,7 @@ sudo -u git -H git fetch sudo -u git -H git checkout v1.9.3 # Addresses multiple critical security vulnerabilities ``` -### 5. Install libs, migrations, etc. +## 5. Install libs, migrations, etc. ```bash cd /home/git/gitlab @@ -85,7 +86,7 @@ sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS sudo chmod u+rwx,g+rx,o-rwx /home/git/gitlab-satellites ``` -### 6. Update config files +## 6. Update config files TIP: to see what changed in gitlab.yml.example in this release use next command: @@ -108,18 +109,18 @@ sudo -u git -H cp config/initializers/rack_attack.rb.example config/initializers sudo cp lib/support/logrotate/gitlab /etc/logrotate.d/gitlab ``` -### 7. Update Init script +## 7. Update Init script ```bash sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab ``` -### 8. Start application +## 8. Start application sudo service gitlab start sudo service nginx restart -### 9. Check application status +## 9. Check application status Check if GitLab and its environment are configured correctly: @@ -135,8 +136,8 @@ If all items are green, then congratulations upgrade complete! ## Things went south? Revert to previous version (6.0) ### 1. Revert the code to the previous version -Follow the [`upgrade guide from 5.4 to 6.0`](5.4-to-6.0.md), except for the database migration -(The backup is already migrated to the previous version) + +Follow the [`upgrade guide from 5.4 to 6.0`](5.4-to-6.0.md), except for the database migration (the backup is already migrated to the previous version). ### 2. Restore from the backup: @@ -146,4 +147,5 @@ sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production ``` ## Login issues after upgrade? -If running in https mode, be sure to read [Can't Verify csrf token authenticity](https://github.com/gitlabhq/gitlab-public-wiki/wiki/Trouble-Shooting-Guide#cant-verify-csrf-token-authenticitycant-get-past-login-pageredirected-to-login-page) + +If running in HTTPS mode, be sure to read [Can't Verify CSRF token authenticity](https://github.com/gitlabhq/gitlab-public-wiki/wiki/Trouble-Shooting-Guide#cant-verify-csrf-token-authenticitycant-get-past-login-pageredirected-to-login-page) diff --git a/doc/update/6.1-to-6.2.md b/doc/update/6.1-to-6.2.md index c618e599dc..9ab53aae24 100644 --- a/doc/update/6.1-to-6.2.md +++ b/doc/update/6.1-to-6.2.md @@ -1,22 +1,21 @@ # From 6.1 to 6.2 -# You should update to 6.1 before installing 6.2 so all the necessary conversions are run. +**You should update to 6.1 before installing 6.2 so all the necessary conversions are run.** -### 0. Backup +## 0. Backup -It's useful to make a backup just in case things go south: -(With MySQL, this may require granting "LOCK TABLES" privileges to the GitLab user on the database version) +It's useful to make a backup just in case things go south: (With MySQL, this may require granting "LOCK TABLES" privileges to the GitLab user on the database version). ```bash cd /home/git/gitlab sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production ``` -### 1. Stop server +## 1. Stop server sudo service gitlab stop -### 2. Get latest code +## 2. Get latest code ```bash cd /home/git/gitlab @@ -25,7 +24,7 @@ sudo -u git -H git checkout 6-2-stable # Latest version of 6-2-stable addresses # For GitLab Enterprise Edition: sudo -u git -H git checkout 6-2-stable-ee ``` -### 3. Update gitlab-shell +## 3. Update gitlab-shell ```bash cd /home/git/gitlab-shell @@ -33,14 +32,14 @@ sudo -u git -H git fetch sudo -u git -H git checkout v1.7.9 # Addresses multiple critical security vulnerabilities ``` -### 4. Install additional packages +## 4. Install additional packages ```bash # Add support for lograte for better log file handling sudo apt-get install logrotate ``` -### 5. Install libs, migrations, etc. +## 5. Install libs, migrations, etc. ```bash cd /home/git/gitlab @@ -58,29 +57,33 @@ sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production ``` -### 6. Update config files +## 6. Update config files -TIP: to see what changed in gitlab.yml.example in this release use next command: +TIP: to see what changed in `gitlab.yml.example` in this release use next command: ``` git diff 6-1-stable:config/gitlab.yml.example 6-2-stable:config/gitlab.yml.example ``` -* Make `/home/git/gitlab/config/gitlab.yml` same as https://gitlab.com/gitlab-org/gitlab-ce/blob/6-2-stable/config/gitlab.yml.example but with your settings. -* Make `/home/git/gitlab/config/unicorn.rb` same as https://gitlab.com/gitlab-org/gitlab-ce/blob/6-2-stable/config/unicorn.rb.example but with your settings. -* Copy rack attack middleware config +- Make `/home/git/gitlab/config/gitlab.yml` same as https://gitlab.com/gitlab-org/gitlab-ce/blob/6-2-stable/config/gitlab.yml.example but with your settings. -```bash -sudo -u git -H cp config/initializers/rack_attack.rb.example config/initializers/rack_attack.rb -``` -* Uncomment `config.middleware.use Rack::Attack` in `/home/git/gitlab/config/application.rb` -* Set up logrotate +- Make `/home/git/gitlab/config/unicorn.rb` same as https://gitlab.com/gitlab-org/gitlab-ce/blob/6-2-stable/config/unicorn.rb.example but with your settings. + +- Copy rack attack middleware config: + + ```bash + sudo -u git -H cp config/initializers/rack_attack.rb.example config/initializers/rack_attack.rb + ``` + +- Uncomment `config.middleware.use Rack::Attack` in `/home/git/gitlab/config/application.rb` + +- Set up logrotate. ```bash sudo cp lib/support/logrotate/gitlab /etc/logrotate.d/gitlab ``` -### 7. Update Init script +## 7. Update Init script ```bash sudo rm /etc/init.d/gitlab @@ -88,12 +91,12 @@ sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab sudo chmod +x /etc/init.d/gitlab ``` -### 8. Start application +## 8. Start application sudo service gitlab start sudo service nginx restart -### 9. Check application status +## 9. Check application status Check if GitLab and its environment are configured correctly: @@ -108,8 +111,8 @@ If all items are green, then congratulations upgrade complete! ## Things went south? Revert to previous version (6.1) ### 1. Revert the code to the previous version -Follow the [`upgrade guide from 6.0 to 6.1`](6.0-to-6.1.md), except for the database migration -(The backup is already migrated to the previous version) + +Follow the [`upgrade guide from 6.0 to 6.1`](6.0-to-6.1.md), except for the database migration (the backup is already migrated to the previous version). ### 2. Restore from the backup: diff --git a/doc/update/6.2-to-6.3.md b/doc/update/6.2-to-6.3.md index 7f91604736..dfe2e551b3 100644 --- a/doc/update/6.2-to-6.3.md +++ b/doc/update/6.2-to-6.3.md @@ -1,22 +1,21 @@ # From 6.2 to 6.3 -## Requires version: 6.1 or 6.2 +**Requires version: 6.1 or 6.2.** -### 0. Backup +## 0. Backup -It's useful to make a backup just in case things go south: -(With MySQL, this may require granting "LOCK TABLES" privileges to the GitLab user on the database version) +It's useful to make a backup just in case things go south: (With MySQL, this may require granting "LOCK TABLES" privileges to the GitLab user on the database version) ```bash cd /home/git/gitlab sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production ``` -### 1. Stop server +## 1. Stop server sudo service gitlab stop -### 2. Get latest code +## 2. Get latest code ```bash cd /home/git/gitlab @@ -25,7 +24,7 @@ sudo -u git -H git checkout 6-3-stable # For GitLab Enterprise Edition: sudo -u git -H git checkout 6-3-stable-ee ``` -### 3. Update gitlab-shell (and its config) +## 3. Update gitlab-shell (and its config) ```bash cd /home/git/gitlab-shell @@ -33,9 +32,9 @@ sudo -u git -H git fetch sudo -u git -H git checkout v1.7.9 # Addresses multiple critical security vulnerabilities ``` -The Gitlab-shell config changed recently, so check for config file changes and make `/home/git/gitlab-shell/config.yml` the same as https://github.com/gitlabhq/gitlab-shell/blob/master/config.yml.example +The Gitlab-shell config changed recently, so check for config file changes and make `/home/git/gitlab-shell/config.yml` the same as -### 4. Install libs, migrations, etc. +## 4. Install libs, migrations, etc. ```bash cd /home/git/gitlab @@ -54,7 +53,7 @@ sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production ``` -### 5. Update config files +## 5. Update config files TIP: to see what changed in gitlab.yml.example in this release use next command: @@ -62,8 +61,8 @@ TIP: to see what changed in gitlab.yml.example in this release use next command: git diff 6-2-stable:config/gitlab.yml.example 6-3-stable:config/gitlab.yml.example ``` -* Make `/home/git/gitlab/config/gitlab.yml` same as https://gitlab.com/gitlab-org/gitlab-ce/blob/6-3-stable/config/gitlab.yml.example but with your settings. -* Make `/home/git/gitlab/config/unicorn.rb` same as https://gitlab.com/gitlab-org/gitlab-ce/blob/6-3-stable/config/unicorn.rb.example but with your settings. +- Make `/home/git/gitlab/config/gitlab.yml` same as https://gitlab.com/gitlab-org/gitlab-ce/blob/6-3-stable/config/gitlab.yml.example but with your settings. +- Make `/home/git/gitlab/config/unicorn.rb` same as https://gitlab.com/gitlab-org/gitlab-ce/blob/6-3-stable/config/unicorn.rb.example but with your settings. ```bash # Copy rack attack middleware config @@ -71,19 +70,19 @@ cd /home/git/gitlab sudo -u git -H cp config/initializers/rack_attack.rb.example config/initializers/rack_attack.rb ``` -### 6. Update Init script +## 6. Update Init script ```bash sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab sudo chmod +x /etc/init.d/gitlab ``` -### 7. Start application +## 7. Start application sudo service gitlab start sudo service nginx restart -### 8. Check application status +## 8. Check application status Check if GitLab and its environment are configured correctly: @@ -98,8 +97,8 @@ If all items are green, then congratulations upgrade complete! ## Things went south? Revert to previous version (6.2) ### 1. Revert the code to the previous version -Follow the [`upgrade guide from 6.1 to 6.2`](6.1-to-6.2.md), except for the database migration -(The backup is already migrated to the previous version) + +Follow the [`upgrade guide from 6.1 to 6.2`](6.1-to-6.2.md), except for the database migration (the backup is already migrated to the previous version). ### 2. Restore from the backup: diff --git a/doc/update/6.3-to-6.4.md b/doc/update/6.3-to-6.4.md index cfe75a6f14..18dce9b5f9 100644 --- a/doc/update/6.3-to-6.4.md +++ b/doc/update/6.3-to-6.4.md @@ -1,19 +1,19 @@ # From 6.3 to 6.4 -### 0. Backup +## 0. Backup ```bash cd /home/git/gitlab sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production ``` -### 1. Stop server +## 1. Stop server ```bash sudo service gitlab stop ```` -### 2. Get latest code +## 2. Get latest code ```bash cd /home/git/gitlab @@ -22,7 +22,7 @@ sudo -u git -H git checkout 6-4-stable # For GitLab Enterprise Edition: sudo -u git -H git checkout 6-4-stable-ee ``` -### 3. Update gitlab-shell (and its config) +## 3. Update gitlab-shell (and its config) ```bash cd /home/git/gitlab-shell @@ -30,7 +30,7 @@ sudo -u git -H git fetch sudo -u git -H git checkout v1.8.0 ``` -### 4. Install libs, migrations, etc. +## 4. Install libs, migrations, etc. ```bash cd /home/git/gitlab @@ -52,14 +52,14 @@ sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab ``` -### 5. Start application +## 5. Start application ```bash sudo service gitlab start sudo service nginx restart ``` -### 6. Check application status +## 6. Check application status Check if GitLab and its environment are configured correctly: @@ -78,8 +78,8 @@ If all items are green, then congratulations upgrade complete! ## Things went south? Revert to previous version (6.3) ### 1. Revert the code to the previous version -Follow the [`upgrade guide from 6.2 to 6.3`](6.2-to-6.3.md), except for the database migration -(The backup is already migrated to the previous version) + +Follow the [`upgrade guide from 6.2 to 6.3`](6.2-to-6.3.md), except for the database migration (the backup is already migrated to the previous version). ### 2. Restore from the backup: diff --git a/doc/update/6.4-to-6.5.md b/doc/update/6.4-to-6.5.md index c88be3582c..1a95a98b6f 100644 --- a/doc/update/6.4-to-6.5.md +++ b/doc/update/6.4-to-6.5.md @@ -1,24 +1,24 @@ # From 6.4 to 6.5 -### 0. Backup +## 0. Backup ```bash cd /home/git/gitlab sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production ``` -### 1. Stop server +## 1. Stop server sudo service gitlab stop -### 2. Get latest code +## 2. Get latest code ```bash cd /home/git/gitlab sudo -u git -H git fetch --all ``` -For Gitlab Community Edition: +For GitLab Community Edition: ```bash sudo -u git -H git checkout 6-5-stable @@ -32,7 +32,7 @@ For GitLab Enterprise Edition: sudo -u git -H git checkout 6-5-stable-ee ``` -### 3. Update gitlab-shell (and its config) +## 3. Update gitlab-shell (and its config) ```bash cd /home/git/gitlab-shell @@ -40,7 +40,7 @@ sudo -u git -H git fetch sudo -u git -H git checkout v1.8.0 ``` -### 4. Install libs, migrations, etc. +## 4. Install libs, migrations, etc. ```bash cd /home/git/gitlab @@ -62,12 +62,12 @@ sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab ``` -### 5. Start application +## 5. Start application sudo service gitlab start sudo service nginx restart -### 6. Check application status +## 6. Check application status Check if GitLab and its environment are configured correctly: @@ -82,13 +82,14 @@ If all items are green, then congratulations upgrade is complete! ## Things went south? Revert to previous version (6.4) ### 1. Revert the code to the previous version -Follow the [`upgrade guide from 6.3 to 6.4`](6.3-to-6.4.md), except for the database migration -(The backup is already migrated to the previous version) -### 2. Restore from the backup: +Follow the [`upgrade guide from 6.3 to 6.4`](6.3-to-6.4.md), except for the database migration (the backup is already migrated to the previous version). + +### 2. Restore from the backup ```bash cd /home/git/gitlab sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production ``` + If you have more than one backup *.tar file(s) please add `BACKUP=timestamp_of_backup` to the command above. diff --git a/doc/update/6.5-to-6.6.md b/doc/update/6.5-to-6.6.md index 589c18c27c..ee6a5a9bdf 100644 --- a/doc/update/6.5-to-6.6.md +++ b/doc/update/6.5-to-6.6.md @@ -1,24 +1,24 @@ # From 6.5 to 6.6 -### 0. Backup +## 0. Backup ```bash cd /home/git/gitlab sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production ``` -### 1. Stop server +## 1. Stop server sudo service gitlab stop -### 2. Get latest code +## 2. Get latest code ```bash cd /home/git/gitlab sudo -u git -H git fetch --all ``` -For Gitlab Community Edition: +For GitLab Community Edition: ```bash sudo -u git -H git checkout 6-6-stable @@ -32,7 +32,7 @@ For GitLab Enterprise Edition: sudo -u git -H git checkout 6-6-stable-ee ``` -### 3. Update gitlab-shell (and its config) +## 3. Update gitlab-shell (and its config) ```bash cd /home/git/gitlab-shell @@ -40,7 +40,7 @@ sudo -u git -H git fetch sudo -u git -H git checkout v1.8.0 ``` -### 4. Install libs, migrations, etc. +## 4. Install libs, migrations, etc. ```bash cd /home/git/gitlab @@ -62,12 +62,12 @@ sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab ``` -### 5. Start application +## 5. Start application sudo service gitlab start sudo service nginx restart -### 6. Check application status +## 6. Check application status Check if GitLab and its environment are configured correctly: @@ -82,6 +82,7 @@ If all items are green, then congratulations upgrade is complete! ## Things went south? Revert to previous version (6.5) ### 1. Revert the code to the previous version + Follow the [`upgrade guide from 6.4 to 6.5`](6.4-to-6.5.md), except for the database migration (The backup is already migrated to the previous version) @@ -91,4 +92,5 @@ Follow the [`upgrade guide from 6.4 to 6.5`](6.4-to-6.5.md), except for the data cd /home/git/gitlab sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production ``` + If you have more than one backup *.tar file(s) please add `BACKUP=timestamp_of_backup` to the command above. diff --git a/doc/update/6.6-to-6.7.md b/doc/update/6.6-to-6.7.md index 3093923007..1e3b7da12d 100644 --- a/doc/update/6.6-to-6.7.md +++ b/doc/update/6.6-to-6.7.md @@ -1,17 +1,17 @@ # From 6.6 to 6.7 -### 0. Backup +## 0. Backup ```bash cd /home/git/gitlab sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production ``` -### 1. Stop server +## 1. Stop server sudo service gitlab stop -### 2. Get latest code +## 2. Get latest code ```bash cd /home/git/gitlab @@ -32,7 +32,7 @@ For GitLab Enterprise Edition: sudo -u git -H git checkout 6-7-stable-ee ``` -### 3. Update gitlab-shell (and its config) +## 3. Update gitlab-shell (and its config) ```bash cd /home/git/gitlab-shell @@ -40,7 +40,7 @@ sudo -u git -H git fetch sudo -u git -H git checkout v1.9.1 ``` -### 4. Install libs, migrations, etc. +## 4. Install libs, migrations, etc. ```bash cd /home/git/gitlab @@ -72,13 +72,12 @@ sudo -u git -H gzip /home/git/gitlab-shell/gitlab-shell.log.1 sudo chmod u+rwx,g=rx,o-rwx /home/git/gitlab-satellites ``` - -### 5. Start application +## 5. Start application sudo service gitlab start sudo service nginx restart -### 6. Check application status +## 6. Check application status Check if GitLab and its environment are configured correctly: @@ -93,13 +92,14 @@ If all items are green, then congratulations upgrade is complete! ## Things went south? Revert to previous version (6.6) ### 1. Revert the code to the previous version -Follow the [`upgrade guide from 6.5 to 6.6`](6.5-to-6.6.md), except for the database migration -(The backup is already migrated to the previous version) -### 2. Restore from the backup: +Follow the [`upgrade guide from 6.5 to 6.6`](6.5-to-6.6.md), except for the database migration (the backup is already migrated to the previous version). + +### 2. Restore from the backup ```bash cd /home/git/gitlab sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production ``` + If you have more than one backup *.tar file(s) please add `BACKUP=timestamp_of_backup` to the command above. diff --git a/doc/update/6.7-to-6.8.md b/doc/update/6.7-to-6.8.md index 1afcb9f9c6..3c98896a9b 100644 --- a/doc/update/6.7-to-6.8.md +++ b/doc/update/6.7-to-6.8.md @@ -1,26 +1,26 @@ # From 6.7 to 6.8 -### 0. Backup +## 0. Backup ```bash cd /home/git/gitlab sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production ``` -### 1. Stop server +## 1. Stop server ```bash sudo service gitlab stop ``` -### 2. Get latest code +## 2. Get latest code ```bash cd /home/git/gitlab sudo -u git -H git fetch --all ``` -For Gitlab Community Edition: +For GitLab Community Edition: ```bash sudo -u git -H git checkout 6-8-stable @@ -34,7 +34,7 @@ For GitLab Enterprise Edition: sudo -u git -H git checkout 6-8-stable-ee ``` -### 3. Update gitlab-shell (and its config) +## 3. Update gitlab-shell (and its config) ```bash cd /home/git/gitlab-shell @@ -42,7 +42,7 @@ sudo -u git -H git fetch sudo -u git -H git checkout v1.9.3 ``` -### 4. Install libs, migrations, etc. +## 4. Install libs, migrations, etc. ```bash cd /home/git/gitlab @@ -68,9 +68,9 @@ sudo chmod +x /etc/init.d/gitlab sudo chmod u+rwx,g=rx,o-rwx /home/git/gitlab-satellites ``` -### 5. Update config files +## 5. Update config files -#### New configuration options for gitlab.yml +### New configuration options for gitlab.yml There are new configuration options available for gitlab.yml. View them with the command below and apply them to your current gitlab.yml if desired. @@ -78,24 +78,24 @@ There are new configuration options available for gitlab.yml. View them with the git diff 6-7-stable:config/gitlab.yml.example 6-8-stable:config/gitlab.yml.example ``` -#### MySQL? Remove reaping frequency +### MySQL? Remove reaping frequency If you are using MySQL as a database, remove `reaping_frequency` from you database.yml to prevent crashes. [Relevant commit](https://gitlab.com/gitlab-org/gitlab-ce/commit/5163a8fcb9cfd63435560fda00173b76df2ccc93). -#### HTTPS? Disable gzip +### HTTPS? Disable gzip If you are using HTTPS, disable gzip as in [this commit](https://gitlab.com/gitlab-org/gitlab-ce/commit/563fec734912d81cd7caea6fa8ec2b397fb72a9b) to prevent BREACH attacks. -#### Turn on asset compression +### Turn on asset compression To improve performance, enable gzip asset compression as seen [in this commit](https://gitlab.com/gitlab-org/gitlab-ce/commit/8af94ed75505f0253823b9b2d44320fecea5b5fb). -### 6. Start application +## 6. Start application sudo service gitlab start sudo service nginx restart -### 7. Check application status +## 7. Check application status Check if GitLab and its environment are configured correctly: @@ -110,10 +110,10 @@ If all items are green, then congratulations upgrade is complete! ## Things went south? Revert to previous version (6.7) ### 1. Revert the code to the previous version -Follow the [`upgrade guide from 6.6 to 6.7`](6.6-to-6.7.md), except for the database migration -(The backup is already migrated to the previous version) -### 2. Restore from the backup: +Follow the [`upgrade guide from 6.6 to 6.7`](6.6-to-6.7.md), except for the database migration (the backup is already migrated to the previous version). + +### 2. Restore from the backup ```bash cd /home/git/gitlab diff --git a/doc/update/README.md b/doc/update/README.md index 9ce48a019e..8c0cf5f7b2 100644 --- a/doc/update/README.md +++ b/doc/update/README.md @@ -1,5 +1,5 @@ -+ [The individual upgrade guides](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update) -+ [Upgrader](upgrader.md) -+ [Ruby](ruby.md) -+ [Patch versions](patch_versions.md) -+ [MySQL to PostgreSQL](mysql_to_postgresql.md) +- [The individual upgrade guides](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update) +- [Upgrader](upgrader.md) +- [Ruby](ruby.md) +- [Patch versions](patch_versions.md) +- [MySQL to PostgreSQL](mysql_to_postgresql.md) diff --git a/doc/update/mysql_to_postgresql.md b/doc/update/mysql_to_postgresql.md index 5083bef1e2..05c9567967 100644 --- a/doc/update/mysql_to_postgresql.md +++ b/doc/update/mysql_to_postgresql.md @@ -1,11 +1,6 @@ # Migrating GitLab from MySQL to Postgres -If you are replacing MySQL with Postgres while keeping GitLab on the same -server all you need to do is to export from MySQL, import into Postgres and -rebuild the indexes as described below. If you are also moving GitLab to -another server, or if you are switching to omnibus-gitlab, you may want to use -a GitLab backup file. The second part of this documents explains the procedure -to do this. +If you are replacing MySQL with Postgres while keeping GitLab on the same server all you need to do is to export from MySQL, import into Postgres and rebuild the indexes as described below. If you are also moving GitLab to another server, or if you are switching to omnibus-gitlab, you may want to use a GitLab backup file. The second part of this documents explains the procedure to do this. ## Export from MySQL and import into Postgres @@ -27,18 +22,13 @@ psql -f databasename.psql -d gitlabhq_production sudo service gitlab start ``` - ## Rebuild indexes -The lanyrd database converter script does not preserve all indexes, so we have -to recreate them ourselves after migrating from MySQL. It is not necessary to -shut down GitLab for this process. - +The lanyrd database converter script does not preserve all indexes, so we have to recreate them ourselves after migrating from MySQL. It is not necessary to shut down GitLab for this process. ### For non-omnibus installations -On non-omnibus installations (distributed using Git) we retrieve the index -declarations from version control using `git stash`. +On non-omnibus installations (distributed using Git) we retrieve the index declarations from version control using `git stash`. ``` # Clone the database converter on your Postgres-backed GitLab server @@ -59,8 +49,7 @@ sudo -u git -H bundle exec rails runner -e production 'eval $stdin.read' < /tmp/ ### For omnibus-gitlab installations -On omnibus-gitlab we need to get the index declarations from a file called -`schema.rb.bundled`. For versions older than 6.9, we need to download the file. +On omnibus-gitlab we need to get the index declarations from a file called `schema.rb.bundled`. For versions older than 6.9, we need to download the file. ``` # Clone the database converter on your Postgres-backed GitLab server @@ -80,10 +69,7 @@ test -e /opt/gitlab/embedded/service/gitlab-rails/db/schema.rb.bundled || sudo / ## Converting a GitLab backup file from MySQL to Postgres -GitLab backup files (_gitlab_backup.tar) contain a SQL dump. Using -the lanyrd database converter we can replace a MySQL database dump inside the -tar file with a Postgres database dump. This can be useful if you are moving to -another server. +GitLab backup files (_gitlab_backup.tar) contain a SQL dump. Using the lanyrd database converter we can replace a MySQL database dump inside the tar file with a Postgres database dump. This can be useful if you are moving to another server. ``` # Stop GitLab diff --git a/doc/update/patch_versions.md b/doc/update/patch_versions.md index 2b947adaa1..c4a77d1280 100644 --- a/doc/update/patch_versions.md +++ b/doc/update/patch_versions.md @@ -1,4 +1,6 @@ -# Universal update guide for patch versions. For example from 6.2.0 to 6.2.1, also see the [semantic versioning specification](http://semver.org/). +# Universal update guide for patch versions + +For example from 6.2.0 to 6.2.1, also see the [semantic versioning specification](http://semver.org/). ### 0. Backup diff --git a/doc/update/ruby.md b/doc/update/ruby.md index e98167f6b6..d1d9d3e77f 100644 --- a/doc/update/ruby.md +++ b/doc/update/ruby.md @@ -2,28 +2,31 @@ This guide explains how to update Ruby in case you installed it from source according to the [instructions](../install/installation.md#2-ruby). -### 1. Look for Ruby versions +## 1. Look for Ruby versions + This guide will only update `/usr/local/bin/ruby`. You can see which Ruby binaries are installed on your system by running: ```bash ls -l $(which -a ruby) ``` -### 2. Stop GitLab +## 2. Stop GitLab ```bash sudo service gitlab stop ``` -### 3. Install or update dependencies +## 3. Install or update dependencies + Here we are assuming you are using Debian/Ubuntu. ```bash sudo apt-get install build-essential zlib1g-dev libyaml-dev libssl-dev libgdbm-dev libreadline-dev libncurses5-dev libffi-dev curl ``` -### 4. Download, compile and install Ruby -Find the latest stable version of Ruby 1.9 or 2.0 at https://www.ruby-lang.org/en/downloads/ . We recommend at least 2.0.0-p353, which is patched against [CVE-2013-4164](https://www.ruby-lang.org/en/news/2013/11/22/heap-overflow-in-floating-point-parsing-cve-2013-4164/). +## 4. Download, compile and install Ruby + +Find the latest stable version of Ruby 1.9 or 2.0 at . We recommend at least 2.0.0-p353, which is patched against [CVE-2013-4164](https://www.ruby-lang.org/en/news/2013/11/22/heap-overflow-in-floating-point-parsing-cve-2013-4164/). ```bash cd /tmp @@ -36,6 +39,7 @@ sudo gem install bundler ``` ### 5. Reinstall GitLab gem bundle + Just to be sure we will reinstall the gems used by GitLab. Note that the `bundle install` command [depends on your choice of database](../install/installation.md#install-gems). ```bash @@ -44,11 +48,12 @@ sudo -u git -H rm -rf vendor/bundle # remove existing Gem bundle sudo -u git -H bundle install --deployment --without development test mysql aws # Assuming PostgreSQL ``` -### 6. Start GitLab +## 6. Start GitLab + We are now ready to restart GitLab. ```bash sudo service gitlab start ``` -### Done +## Done diff --git a/doc/update/upgrader.md b/doc/update/upgrader.md index 19faca4ec4..00dc87e2f9 100644 --- a/doc/update/upgrader.md +++ b/doc/update/upgrader.md @@ -1,22 +1,25 @@ -# GitLab Upgrader +# GitLab Upgrader GitLab Upgrader - a ruby script that allows you easily upgrade GitLab to latest minor version. + For example it can update your application from 6.4 to latest GitLab 6 version (like 6.6.1). -You still need to create a a backup and manually restart GitLab after runnning the script but all other operations are done by this upgrade script. + +You still need to create a backup and manually restart GitLab after running the script but all other operations are done by this upgrade script. + If you have local changes to your GitLab repository the script will stash them and you need to use `git stash pop` after running the script. -__GitLab Upgrader is available only for GitLab version 6.4.2 or higher__ +**GitLab Upgrader is available only for GitLab version 6.4.2 or higher.** -### 0. Backup +## 0. Backup cd /home/git/gitlab sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production -### 1. Stop server +## 1. Stop server sudo service gitlab stop -### 2. Run gitlab upgrade tool +## 2. Run GitLab upgrade tool # Starting with GitLab version 7.0 upgrader script has been moved to bin directory cd /home/git/gitlab @@ -25,12 +28,12 @@ __GitLab Upgrader is available only for GitLab version 6.4.2 or higher__ # to perform a non-interactive install (no user input required) you can add -y # if [ -f bin/upgrade.rb ]; then sudo -u git -H ruby bin/upgrade.rb -y; else sudo -u git -H ruby script/upgrade.rb -y; fi -### 3. Start application +## 3. Start application sudo service gitlab start sudo service nginx restart -### 4. Check application status +## 4. Check application status Check if GitLab and its dependencies are configured correctly: @@ -38,9 +41,10 @@ Check if GitLab and its dependencies are configured correctly: If all items are green, then congratulations upgrade is complete! -### 5. Upgrade GitLab Shell (if needed) +## 5. Upgrade GitLab Shell (if needed) + +If the `gitlab:check` task reports an outdated version of `gitlab-shell` you should upgrade it. -If the `gitlab:check` task reports an outdated version of gitlab-shell you should upgrade it. Upgrade it by running the commands below after replacing 1.9.4 with the correct version number: ``` @@ -49,9 +53,10 @@ sudo -u git -H git fetch sudo -u git -H git checkout v1.9.4 ``` -### One line upgrade command +## One line upgrade command You've read through the entire guide and probably already did all the steps one by one. + Here is a one line command with step 1 to 4 for the next time you upgrade: ```bash diff --git a/doc/web_hooks/web_hooks.md b/doc/web_hooks/web_hooks.md index 19a60db00a..ada21d23ac 100644 --- a/doc/web_hooks/web_hooks.md +++ b/doc/web_hooks/web_hooks.md @@ -2,16 +2,13 @@ Project web hooks allow you to trigger an URL if new code is pushed or a new issue is created. ---- +You can configure web hooks to listen for specific events like pushes, issues or merge requests. GitLab will send a POST request with data to the web hook URL. -You can configure web hooks to listen for specific events like pushes, issues or merge requests. -GitLab will send a POST request with data to the web hook URL. Web hooks can be used to update an external issue tracker, trigger CI builds, update a backup mirror, or even deploy to your production server. + If you send a web hook to an SSL endpoint [the certificate will not be verified](https://gitlab.com/gitlab-org/gitlab-ce/blob/ccd617e58ea71c42b6b073e692447d0fe3c00be6/app/models/web_hook.rb#L35) since many people use self-signed certificates. ---- - -#### Push events +## Push events Triggered when you push to the repository except when pushing tags. @@ -57,7 +54,7 @@ Triggered when you push to the repository except when pushing tags. } ``` -#### Issues events +## Issues events Triggered when a new issue is created or an existing issue was updated/closed/reopened. @@ -84,7 +81,7 @@ Triggered when a new issue is created or an existing issue was updated/closed/re } ``` -#### Merge request events +## Merge request events Triggered when a new merge request is created or an existing merge request was updated/merged/closed. diff --git a/doc/workflow/README.md b/doc/workflow/README.md index 39b3059e07..c715f6e594 100644 --- a/doc/workflow/README.md +++ b/doc/workflow/README.md @@ -1,2 +1,3 @@ -+ [Workflow](workflow.md) -+ [Project Features](project_features.md) +- [Workflow](workflow.md) +- [Project Features](project_features.md) +- [Authorization for merge requests](authorization_for_merge_requests.md) diff --git a/doc/workflow/authorization_for_merge_requests.md b/doc/workflow/authorization_for_merge_requests.md index cc7031b11e..d1d6d94ec1 100644 --- a/doc/workflow/authorization_for_merge_requests.md +++ b/doc/workflow/authorization_for_merge_requests.md @@ -5,9 +5,13 @@ There are two main ways to have a merge request flow with GitLab: working with p ## Protected branch flow With the protected branch flow everybody works within the same GitLab project. + The project maintainers get Master access and the regular developers get Developer access. + The maintainers mark the authoritative branches as 'Protected'. + The developers push feature branches to the project and create merge requests to have their feature branches reviewed and merged into one of the protected branches. + Only users with Master access can merge changes into a protected branch. ### Advantages @@ -22,7 +26,9 @@ Only users with Master access can merge changes into a protected branch. ## Forking workflow With the forking workflow the maintainers get Master access and the regular developers get Reporter access to the authoritative repository, which prohibits them from pushing any changes to it. + Developers create forks of the authoritative project and push their feature branches to their own forks. + To get their changes into master they need to create a merge request across forks. ### Advantages diff --git a/doc/workflow/project_features.md b/doc/workflow/project_features.md index ec2c273db0..6ed9c1127a 100644 --- a/doc/workflow/project_features.md +++ b/doc/workflow/project_features.md @@ -1,37 +1,41 @@ # Project features When in a Project -> Settings, you will find Features on the bottom of the page that you can toggle. -Below you will find a more elaborate explanation of each of these. +Below you will find a more elaborate explanation of each of these. ## Issues Issues is a really powerful, but lightweight issue tracking system. -You can make tickets, assign them to people, file them under milestones, order them with labels and have discussion in them. -They integrate deeply into GitLab and are easily referenced from anywhere by using # and the issuenumber. +You can make tickets, assign them to people, file them under milestones, order them with labels and have discussion in them. + +They integrate deeply into GitLab and are easily referenced from anywhere by using `#` and the issue number. ## Merge Requests Using a merge request, you can review and discuss code before it is merged in the branch of your code. -As with issues, it can be assigned; people, issues, etc. can be refereced; milestones attached. -We see it as an integral part of working together on code and couldn't work without it. +As with issues, it can be assigned; people, issues, etc. can be refereced; milestones attached. + +We see it as an integral part of working together on code and couldn't work without it. ## Wiki This is a separate system for documentation, built right into GitLab. -It is source controlled and is very convenient if you don't want to keep you documentation in your source code, but you do want to keep it in your GitLab project. +It is source controlled and is very convenient if you don't want to keep you documentation in your source code, but you do want to keep it in your GitLab project. ## Wall For simple, project specific conversations, the wall can be used. -It's very lightweight and simple and works well if you're not interested in using issues, but still want to occasionally communicate within a project. +It's very lightweight and simple and works well if you're not interested in using issues, but still want to occasionally communicate within a project. ## Snippets Snippets are little bits of code or text. + This is a nice place to put code or text that is used semi-regularly within the project, but does not belong in source control. + For example, a specific config file that is used by > the team that is only valid for the people that work on the code. diff --git a/doc/workflow/workflow.md b/doc/workflow/workflow.md index 8186cd53b2..ab29cfb670 100644 --- a/doc/workflow/workflow.md +++ b/doc/workflow/workflow.md @@ -1,29 +1,31 @@ # Workflow -1. Clone project +1. Clone project: - ```bash - git clone git@example.com:project-name.git - ``` + ```bash + git clone git@example.com:project-name.git + ``` -2. Create branch with your feature +1. Create branch with your feature: - ```bash - git checkout -b $feature_name - ``` + ```bash + git checkout -b $feature_name + ``` -3. Write code. Commit changes +1. Write code. Commit changes: - ```bash - git commit -am "My feature is ready" - ``` + ```bash + git commit -am "My feature is ready" + ``` -4. Push your branch to GitLab +1. Push your branch to GitLab: - ```bash - git push origin $feature_name - ``` + ```bash + git push origin $feature_name + ``` -5. Review your code on commits page -6. Create a merge request -7. Your team lead will review the code & merge it to the main branch +1. Review your code on commits page. + +1. Create a merge request. + +1. Your team lead will review the code & merge it to the main branch. diff --git a/features/steps/help.rb b/features/steps/help.rb index bfb3a38a29..67054e1430 100644 --- a/features/steps/help.rb +++ b/features/steps/help.rb @@ -16,6 +16,6 @@ class Spinach::Features::Help < Spinach::FeatureSteps end step 'Header "Rebuild project satellites" should have correct ids and links' do - header_should_have_correct_id_and_link(3, '(Re-)Create satellite repos', 're-create-satellite-repos', '.documentation') + header_should_have_correct_id_and_link(2, '(Re-)Create satellite repos', 're-create-satellite-repos', '.documentation') end end From 18b1f171bd0b9700e73c37c23150bea9fb251b3e Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Wed, 4 Jun 2014 08:37:19 +0200 Subject: [PATCH 207/360] Rename snippets scopes to plural names. --- app/controllers/snippets_controller.rb | 12 ++++++------ app/models/snippet.rb | 4 ++-- app/views/snippets/current_user_index.html.haml | 12 ++++++------ config/initializers/state_machine_patch.rb | 6 +++--- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/app/controllers/snippets_controller.rb b/app/controllers/snippets_controller.rb index 89edd9fd7e..4fe98f804d 100644 --- a/app/controllers/snippets_controller.rb +++ b/app/controllers/snippets_controller.rb @@ -14,7 +14,7 @@ class SnippetsController < ApplicationController layout 'navless' def index - @snippets = Snippet.is_public.fresh.non_expired.page(params[:page]).per(20) + @snippets = Snippet.are_public.fresh.non_expired.page(params[:page]).per(20) end def user_index @@ -26,15 +26,15 @@ class SnippetsController < ApplicationController if @user == current_user @snippets = case params[:scope] - when 'is_public' then - @snippets.is_public - when 'is_private' then - @snippets.is_private + when 'are_public' then + @snippets.are_public + when 'are_private' then + @snippets.are_private else @snippets end else - @snippets = @snippets.is_public + @snippets = @snippets.are_public end @snippets = @snippets.page(params[:page]).per(20) diff --git a/app/models/snippet.rb b/app/models/snippet.rb index 0727bb1639..9e4409daa1 100644 --- a/app/models/snippet.rb +++ b/app/models/snippet.rb @@ -34,8 +34,8 @@ class Snippet < ActiveRecord::Base validates :content, presence: true # Scopes - scope :is_public, -> { where(private: false) } - scope :is_private, -> { where(private: true) } + scope :are_public, -> { where(private: false) } + scope :are_private, -> { where(private: true) } scope :fresh, -> { order("created_at DESC") } scope :expired, -> { where(["expires_at IS NOT NULL AND expires_at < ?", Time.current]) } scope :non_expired, -> { where(["expires_at IS NULL OR expires_at > ?", Time.current]) } diff --git a/app/views/snippets/current_user_index.html.haml b/app/views/snippets/current_user_index.html.haml index 3e03042870..e3edd85698 100644 --- a/app/views/snippets/current_user_index.html.haml +++ b/app/views/snippets/current_user_index.html.haml @@ -18,16 +18,16 @@ All %span.pull-right = @user.snippets.count - = nav_tab :scope, 'is_private' do - = link_to user_snippets_path(@user, scope: 'is_private') do + = nav_tab :scope, 'are_private' do + = link_to user_snippets_path(@user, scope: 'are_private') do Private %span.pull-right - = @user.snippets.is_private.count - = nav_tab :scope, 'is_public' do - = link_to user_snippets_path(@user, scope: 'is_public') do + = @user.snippets.are_private.count + = nav_tab :scope, 'are_public' do + = link_to user_snippets_path(@user, scope: 'are_public') do Public %span.pull-right - = @user.snippets.is_public.count + = @user.snippets.are_public.count .col-md-9.my-snippets = render 'snippets' diff --git a/config/initializers/state_machine_patch.rb b/config/initializers/state_machine_patch.rb index a446b6275c..72d010fa5d 100644 --- a/config/initializers/state_machine_patch.rb +++ b/config/initializers/state_machine_patch.rb @@ -2,8 +2,8 @@ # where gem 'state_machine' was not working for Rails 4.1 module StateMachine module Integrations - module ActiveModel - public :around_validation - end + module ActiveModel + public :around_validation + end end end From 4147fc7eb62eb58fe33a9eea7b5450ae011b6e96 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Wed, 4 Jun 2014 09:27:23 +0200 Subject: [PATCH 208/360] Update patch release document. --- doc/release/patch.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/release/patch.md b/doc/release/patch.md index 4f7f967370..7762c9f0e1 100644 --- a/doc/release/patch.md +++ b/doc/release/patch.md @@ -17,14 +17,14 @@ Otherwise include it in the monthly release and note there was a regression fix 1. Fix the issue on a feature branch, do this on the private GitLab development server 1. Consider creating and testing workarounds 1. After the branch is merged into master, cherry pick the commit(s) into the current stable branch -1. In a separate commit in the stable branch update the VERSION 1. In a separate commit in the stable branch update the CHANGELOG 1. For EE, update the CHANGELOG-EE if it is EE specific fix. Otherwise, merge the stable CE branch and add to CHANGELOG-EE "Merge community edition changes for version X.X.X" -1. Create an annotated tag vX.X.X for CE and another patch release for EE +1. In a separate commit in the stable branch update the VERSION +1. Create an annotated tag vX.X.X for CE and another patch release for EE `git tag -a vx.x.x -m 'Version x.x.x'` 1. Make sure that the build has passed and all tests are passing 1. Push the code and the tags to all the CE and EE repositories 1. Apply the patch to GitLab Cloud and the private GitLab development server -1. Build new packages with the latest version +1. [Build new packages with the latest version](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/release.md) 1. Cherry-pick the changelog update back into master 1. Send tweets about the release from `@gitlabhq`, tweet should include the most important feature that the release is addressing as well as the link to the changelog -1. Note in the 'GitLab X.X regressions' issue that the patch was published +1. Note in the 'GitLab X.X regressions' issue that the patch was published(CE only) From 0d861c9935485c9d26ebb98b00cc9b8411889108 Mon Sep 17 00:00:00 2001 From: Kaizer Sogiawala Date: Wed, 4 Jun 2014 00:43:53 -0700 Subject: [PATCH 209/360] Fixing typo --- doc/public_access/public_access.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/public_access/public_access.md b/doc/public_access/public_access.md index 68c10a9f3c..493e59af22 100644 --- a/doc/public_access/public_access.md +++ b/doc/public_access/public_access.md @@ -2,7 +2,7 @@ Gitlab allows you to open selected projects to be accessed **publicly** or **internally**. -Projects with either of these visibility levels will be listen in the [public access directory](/public). +Projects with either of these visibility levels will be listed in the [public access directory](/public). Internal projects will only be available to authenticated users. From 5921c7481302913bffe88788c354f415cd19df82 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 4 Jun 2014 10:58:40 +0300 Subject: [PATCH 210/360] Mention 4.1 rails update in CHANGELOG Signed-off-by: Dmitriy Zaporozhets --- CHANGELOG | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG b/CHANGELOG index 60d3efeba2..02e2840ffe 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -16,6 +16,7 @@ v 7.0.0 - Add X-Frame-Options SAMEORIGIN to Nginx config so Sidekiq admin is visible - UI improvements - Case-insensetive search for issues + - Update to rails 4.1 v 6.9.2 - Revert the commit that broke the LDAP user filter From 74bcc8321e5c9eb2f84306d1688ead35f3c86579 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 4 Jun 2014 11:04:36 +0300 Subject: [PATCH 211/360] Allow set broadcast color with 3 digits like #444 Signed-off-by: Dmitriy Zaporozhets --- app/models/broadcast_message.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/models/broadcast_message.rb b/app/models/broadcast_message.rb index 85ab7ed6ae..ce8b7973cd 100644 --- a/app/models/broadcast_message.rb +++ b/app/models/broadcast_message.rb @@ -20,8 +20,8 @@ class BroadcastMessage < ActiveRecord::Base validates :starts_at, presence: true validates :ends_at, presence: true - validates :color, format: { with: /\A\#[0-9A-Fa-f]{6}+\Z/ }, allow_blank: true - validates :font, format: { with: /\A\#[0-9A-Fa-f]{6}+\Z/ }, allow_blank: true + validates :color, format: { with: /\A\#[0-9A-Fa-f]{3}{1,2}+\Z/ }, allow_blank: true + validates :font, format: { with: /\A\#[0-9A-Fa-f]{3}{1,2}+\Z/ }, allow_blank: true def self.current where("ends_at > :now AND starts_at < :now", now: Time.zone.now).last From 4e249dadb5bbcda8e36e6282a36ea2aa1b7900fd Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 4 Jun 2014 11:08:21 +0300 Subject: [PATCH 212/360] Fix 500 error when generate labels on labels page. Fixes #1311 Signed-off-by: Dmitriy Zaporozhets --- app/controllers/projects/labels_controller.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/controllers/projects/labels_controller.rb b/app/controllers/projects/labels_controller.rb index b037cf5650..30fcb64cbb 100644 --- a/app/controllers/projects/labels_controller.rb +++ b/app/controllers/projects/labels_controller.rb @@ -16,6 +16,8 @@ class Projects::LabelsController < Projects::ApplicationController redirect_to project_issues_path(@project) elsif params[:redirect] == 'merge_requests' redirect_to project_merge_requests_path(@project) + else + redirect_to project_labels_path(@project) end end From c283fba3b7e9fb89ae2ed77597adee2700982718 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 4 Jun 2014 11:52:17 +0300 Subject: [PATCH 213/360] Improve performance of application for large teams This commit fixes a lot of sql queries to db for for groups and projects with big amount of members. Signed-off-by: Dmitriy Zaporozhets --- CHANGELOG | 1 + app/models/ability.rb | 8 ++++---- app/models/project_team.rb | 16 +++++++++++++++ spec/models/project_team_spec.rb | 35 +++++++++++++++++++++++++------- 4 files changed, 49 insertions(+), 11 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 02e2840ffe..760218690b 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -17,6 +17,7 @@ v 7.0.0 - UI improvements - Case-insensetive search for issues - Update to rails 4.1 + - Improve performance of application for projects and groups with a lot of members v 6.9.2 - Revert the commit that broke the LDAP user filter diff --git a/app/models/ability.rb b/app/models/ability.rb index 70c26caded..df9b210dfc 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -71,16 +71,16 @@ class Ability team = project.team # Rules based on role in project - if team.masters.include?(user) + if team.master?(user) rules += project_master_rules - elsif team.developers.include?(user) + elsif team.developer?(user) rules += project_dev_rules - elsif team.reporters.include?(user) + elsif team.reporter?(user) rules += project_report_rules - elsif team.guests.include?(user) + elsif team.guest?(user) rules += project_guest_rules end diff --git a/app/models/project_team.rb b/app/models/project_team.rb index eca13e5606..639f78dcd3 100644 --- a/app/models/project_team.rb +++ b/app/models/project_team.rb @@ -117,6 +117,22 @@ class ProjectTeam false end + def guest?(user) + find_tm(user.id).access_field == Gitlab::Access::GUEST + end + + def reporter?(user) + find_tm(user.id).access_field == Gitlab::Access::REPORTER + end + + def developer?(user) + find_tm(user.id).access_field == Gitlab::Access::DEVELOPER + end + + def master?(user) + find_tm(user.id).access_field == Gitlab::Access::MASTER + end + private def fetch_members(level = nil) diff --git a/spec/models/project_team_spec.rb b/spec/models/project_team_spec.rb index 3e3543e85e..1a7e3cd94b 100644 --- a/spec/models/project_team_spec.rb +++ b/spec/models/project_team_spec.rb @@ -1,15 +1,36 @@ require "spec_helper" describe ProjectTeam do - let(:team) { create(:project).team } + let(:group) { create(:group) } + let(:project) { create(:empty_project, group: group) } - describe "Respond to" do - subject { team } + let(:master) { create(:user) } + let(:reporter) { create(:user) } + let(:guest) { create(:user) } + let(:nonmember) { create(:user) } - it { should respond_to(:developers) } - it { should respond_to(:masters) } - it { should respond_to(:reporters) } - it { should respond_to(:guests) } + before do + group.add_user(master, Gitlab::Access::MASTER) + group.add_user(reporter, Gitlab::Access::REPORTER) + group.add_user(guest, Gitlab::Access::GUEST) + + # Add group guest as master to this project + # to test project access priority over group members + project.team << [guest, :master] + end + + describe 'members collection' do + it { team.masters.should include(master) } + it { team.masters.should include(guest) } + it { team.masters.should_not include(reporter) } + it { team.masters.should_not include(nonmember) } + end + + describe 'access methods' do + it { team.master?(master).should be_true } + it { team.master?(guest).should be_true } + it { team.master?(reporter).should be_false } + it { team.master?(nonmember).should be_false } end end From b9c6ca14963af5ad07da5ed5db43b7cbe20624fc Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 4 Jun 2014 12:29:05 +0300 Subject: [PATCH 214/360] Make MR tabs look like tabs :) Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/sections/merge_requests.scss | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/assets/stylesheets/sections/merge_requests.scss b/app/assets/stylesheets/sections/merge_requests.scss index c1eaae82e5..5bff00f376 100644 --- a/app/assets/stylesheets/sections/merge_requests.scss +++ b/app/assets/stylesheets/sections/merge_requests.scss @@ -21,13 +21,15 @@ .merge-request .merge-request-tabs{ border-bottom: 2px solid $border_primary; - padding-bottom: 10px; margin-bottom: 20px; li { a { - padding: 20px 40px; + padding: 18px 40px; font-size: 14px; + margin-bottom: -2px; + border-bottom: 2px solid $border_primary; + @include border-radius(0px); } } } From a89c590ffef54c9ff4c790b5d91a8afe68b1ee42 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 4 Jun 2014 12:56:03 +0300 Subject: [PATCH 215/360] Prevent exceptions for methods like ProjectTeam#developer? if no membership exists Signed-off-by: Dmitriy Zaporozhets --- app/models/project_team.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/models/project_team.rb b/app/models/project_team.rb index 639f78dcd3..cc8bb60aac 100644 --- a/app/models/project_team.rb +++ b/app/models/project_team.rb @@ -118,19 +118,19 @@ class ProjectTeam end def guest?(user) - find_tm(user.id).access_field == Gitlab::Access::GUEST + find_tm(user.id).try(:access_field) == Gitlab::Access::GUEST end def reporter?(user) - find_tm(user.id).access_field == Gitlab::Access::REPORTER + find_tm(user.id).try(:access_field) == Gitlab::Access::REPORTER end def developer?(user) - find_tm(user.id).access_field == Gitlab::Access::DEVELOPER + find_tm(user.id).try(:access_field) == Gitlab::Access::DEVELOPER end def master?(user) - find_tm(user.id).access_field == Gitlab::Access::MASTER + find_tm(user.id).try(:access_field) == Gitlab::Access::MASTER end private From d95d56f0b9b2a321e18bb0f92b008f58e37b20a7 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 4 Jun 2014 18:07:15 +0300 Subject: [PATCH 216/360] Add current_user_id to gon vars Signed-off-by: Dmitriy Zaporozhets --- app/controllers/application_controller.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 2730e9942e..aa532de7aa 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -174,10 +174,14 @@ class ApplicationController < ActionController::Base def add_gon_variables gon.default_issues_tracker = Project.issues_tracker.default_value gon.api_version = API::API.version - gon.api_token = current_user.private_token if current_user gon.gravatar_url = request.ssl? || Gitlab.config.gitlab.https ? Gitlab.config.gravatar.ssl_url : Gitlab.config.gravatar.plain_url gon.relative_url_root = Gitlab.config.gitlab.relative_url_root gon.gravatar_enabled = Gitlab.config.gravatar.enabled + + if current_user + gon.current_user_id = current_user.id + gon.api_token = current_user.private_token + end end def check_password_expiration From ad60701e9e097a046f65048bd4e707da512daa07 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 4 Jun 2014 18:10:53 +0300 Subject: [PATCH 217/360] Add only open/reopen scopes to issues Signed-off-by: Dmitriy Zaporozhets --- app/models/concerns/issuable.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb index 713eab5ad7..9a227fcef5 100644 --- a/app/models/concerns/issuable.rb +++ b/app/models/concerns/issuable.rb @@ -24,6 +24,8 @@ module Issuable scope :unassigned, -> { where("assignee_id IS NULL") } scope :of_projects, ->(ids) { where(project_id: ids) } scope :opened, -> { with_state(:opened, :reopened) } + scope :only_opened, -> { with_state(:opened) } + scope :only_reopened, -> { with_state(:reopened) } scope :closed, -> { with_state(:closed) } delegate :name, From 47937802a2c29f6ec4a1bd15bb06e8e2866fdb7f Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 4 Jun 2014 18:51:01 +0300 Subject: [PATCH 218/360] Add js milestone class. Activate drag-drop for issues on milestone page Signed-off-by: Dmitriy Zaporozhets --- app/assets/javascripts/dispatcher.js.coffee | 2 ++ app/assets/javascripts/milestone.js.coffee | 40 +++++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 app/assets/javascripts/milestone.js.coffee diff --git a/app/assets/javascripts/dispatcher.js.coffee b/app/assets/javascripts/dispatcher.js.coffee index b61d9875e0..6518c380bd 100644 --- a/app/assets/javascripts/dispatcher.js.coffee +++ b/app/assets/javascripts/dispatcher.js.coffee @@ -21,6 +21,8 @@ class Dispatcher Issues.init() when 'projects:issues:show' new Issue() + when 'projects:milestones:show' + new Milestone() when 'projects:issues:new', 'projects:merge_requests:new' GitLab.GfmAutoComplete.setup() when 'dashboard:show' diff --git a/app/assets/javascripts/milestone.js.coffee b/app/assets/javascripts/milestone.js.coffee new file mode 100644 index 0000000000..bbbaa288b8 --- /dev/null +++ b/app/assets/javascripts/milestone.js.coffee @@ -0,0 +1,40 @@ +class Milestone + @updateIssue: (li, issue_url, data) -> + $.ajax + type: "PUT" + url: issue_url + data: data + success: (data) -> + if data.saved == true + $(li).effect 'highlight' + else + new Flash("Issue update failed", 'alert') + dataType: "json" + + constructor: -> + @bindSorting() + + bindSorting: -> + $("#issues-list-unassigned, #issues-list-ongoing, #issues-list-closed, #issues-list-reopened").sortable( + connectWith: ".issues-sortable-list", + dropOnEmpty: true, + receive: (event, ui) -> + new_state = $(this).data('state') + issue_id = ui.item.data('iid') + issue_url = ui.item.data('url') + + data = switch new_state + when 'ongoing' + "issue[assignee_id]=" + gon.current_user_id + when 'unassigned' + "issue[assignee_id]=" + when 'closed' + "issue[state_event]=close" + when 'reopened' + "issue[state_event]=reopen" + + Milestone.updateIssue(ui.item, issue_url, data) + + ).disableSelection() + +@Milestone = Milestone From f1ec62f465711c136d9ffc84b328f7c55e68fa9c Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 4 Jun 2014 18:52:35 +0300 Subject: [PATCH 219/360] Add reopened tab to milestone issues. Add ids and data to milestone issues to enable dragging Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/main/mixins.scss | 2 +- .../stylesheets/sections/milestone.scss | 3 +++ app/controllers/projects/issues_controller.rb | 5 ++++ .../projects/milestones/_issue.html.haml | 9 +++++++ .../projects/milestones/_issues.html.haml | 11 +++----- app/views/projects/milestones/show.html.haml | 25 +++++++++++-------- 6 files changed, 35 insertions(+), 20 deletions(-) create mode 100644 app/assets/stylesheets/sections/milestone.scss create mode 100644 app/views/projects/milestones/_issue.html.haml diff --git a/app/assets/stylesheets/main/mixins.scss b/app/assets/stylesheets/main/mixins.scss index 289490712b..cf6d5ba933 100644 --- a/app/assets/stylesheets/main/mixins.scss +++ b/app/assets/stylesheets/main/mixins.scss @@ -124,7 +124,7 @@ margin-bottom: 10px; } -@mixin str-truncated($max_width: "82%") { +@mixin str-truncated($max_width: 82%) { display: inline-block; overflow: hidden; text-overflow: ellipsis; diff --git a/app/assets/stylesheets/sections/milestone.scss b/app/assets/stylesheets/sections/milestone.scss new file mode 100644 index 0000000000..d20391e38f --- /dev/null +++ b/app/assets/stylesheets/sections/milestone.scss @@ -0,0 +1,3 @@ +.issues-sortable-list .str-truncated { + max-width: 70%; +} diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb index 6eec2094f8..6c6fc7e077 100644 --- a/app/controllers/projects/issues_controller.rb +++ b/app/controllers/projects/issues_controller.rb @@ -87,6 +87,11 @@ class Projects::IssuesController < Projects::ApplicationController render :edit end end + format.json do + render json: { + saved: @issue.valid?, + } + end end end diff --git a/app/views/projects/milestones/_issue.html.haml b/app/views/projects/milestones/_issue.html.haml new file mode 100644 index 0000000000..5fba8cd536 --- /dev/null +++ b/app/views/projects/milestones/_issue.html.haml @@ -0,0 +1,9 @@ +%li{ 'data-iid' => issue.iid, 'data-url' => project_issue_path(@project, issue) } + %span.str-truncated + = link_to [@project, issue] do + %span.cgray ##{issue.iid} + = link_to_gfm issue.title, [@project, issue] + - if issue.assignee + .pull-right + = image_tag avatar_icon(issue.assignee.email, 16), class: "avatar s16" + diff --git a/app/views/projects/milestones/_issues.html.haml b/app/views/projects/milestones/_issues.html.haml index 83eb327975..9dbcab19a2 100644 --- a/app/views/projects/milestones/_issues.html.haml +++ b/app/views/projects/milestones/_issues.html.haml @@ -1,11 +1,6 @@ .panel.panel-default .panel-heading= title - %ul.well-list + %ul{ class: "well-list issues-sortable-list", id: "issues-list-#{id}", "data-state" => id } - issues.each do |issue| - %li - = link_to [@project, issue] do - %span.label{class: issue.closed? ? 'label-danger' : 'label-info'} ##{issue.iid} - = link_to_gfm truncate(issue.title, length: 40), [@project, issue] - - if issue.assignee - .pull-right - = image_tag avatar_icon(issue.assignee.email, 16), class: "avatar s16" + = render 'issue', issue: issue + %li.light Drag and drop available diff --git a/app/views/projects/milestones/show.html.haml b/app/views/projects/milestones/show.html.haml index d355f25882..594b6a0c72 100644 --- a/app/views/projects/milestones/show.html.haml +++ b/app/views/projects/milestones/show.html.haml @@ -35,6 +35,12 @@ %h4.title = gfm escape_once(@milestone.title) + - if @milestone.description.present? + .description + .wiki + = preserve do + = markdown @milestone.description + .context %p Progress: @@ -45,11 +51,6 @@ .progress.progress-info .progress-bar{style: "width: #{@milestone.percent_complete}%;"} - - if @milestone.description.present? - .description - .wiki - = preserve do - = markdown @milestone.description %ul.nav.nav-tabs %li.active @@ -74,12 +75,14 @@ .tab-content .tab-pane.active#tab-issues .row - .col-md-4 - = render('issues', title: 'Unstarted Issues (open and unassigned)', issues: @issues.opened.unassigned) - .col-md-4 - = render('issues', title: 'Ongoing Issues (open and assigned)', issues: @issues.opened.assigned) - .col-md-4 - = render('issues', title: 'Completed Issues (closed)', issues: @issues.closed) + .col-md-3 + = render('issues', title: 'Unstarted Issues (open and unassigned)', issues: @issues.only_opened.unassigned, id: 'unassigned') + .col-md-3 + = render('issues', title: 'Ongoing Issues (open and assigned)', issues: @issues.only_opened.assigned, id: 'ongoing') + .col-md-3 + = render('issues', title: 'Completed Issues (closed)', issues: @issues.closed, id: 'closed') + .col-md-3 + = render('issues', title: 'Reopened Issues (reopened)', issues: @issues.only_reopened, id: 'reopened') .tab-pane#tab-merge-requests .row From 0cedd7039a882b67f1a94875f4e99de4c63b173b Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 4 Jun 2014 19:20:25 +0300 Subject: [PATCH 220/360] Prevent a lot of sql queries for ProjectTeam#fetch_members method Signed-off-by: Dmitriy Zaporozhets --- app/models/project_team.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/models/project_team.rb b/app/models/project_team.rb index cc8bb60aac..afaca37413 100644 --- a/app/models/project_team.rb +++ b/app/models/project_team.rb @@ -144,7 +144,10 @@ class ProjectTeam group_members = group_members.send(level) if group end - (project_members + group_members).map(&:user).uniq + user_ids = project_members.pluck(:user_id) + user_ids += group_members.pluck(:user_id) if group + + User.where(id: user_ids) end def group From 181aa2b9160347ad23de3ef1e6f5ce45234261e1 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 4 Jun 2014 19:23:31 +0300 Subject: [PATCH 221/360] More efficient query for mentionable users Signed-off-by: Dmitriy Zaporozhets --- app/models/concerns/mentionable.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/concerns/mentionable.rb b/app/models/concerns/mentionable.rb index 5858fe1bb6..a46a593c6e 100644 --- a/app/models/concerns/mentionable.rb +++ b/app/models/concerns/mentionable.rb @@ -50,7 +50,7 @@ module Mentionable matches.each do |match| identifier = match.delete "@" if has_project - id = project.team.members.find { |u| u.username == identifier }.try(:id) + id = project.team.members.find_by(username: identifier).try(:id) else id = User.where(username: identifier).pluck(:id).first end From eeef2c7350502bb1f77a723ff4677901d2a68926 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 4 Jun 2014 20:39:43 +0300 Subject: [PATCH 222/360] Fix tests Signed-off-by: Dmitriy Zaporozhets --- app/views/projects/milestones/_issue.html.haml | 2 +- features/steps/project/milestones.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/projects/milestones/_issue.html.haml b/app/views/projects/milestones/_issue.html.haml index 5fba8cd536..fe93164a70 100644 --- a/app/views/projects/milestones/_issue.html.haml +++ b/app/views/projects/milestones/_issue.html.haml @@ -1,4 +1,4 @@ -%li{ 'data-iid' => issue.iid, 'data-url' => project_issue_path(@project, issue) } +%li{ class: 'issue-row', 'data-iid' => issue.iid, 'data-url' => project_issue_path(@project, issue) } %span.str-truncated = link_to [@project, issue] do %span.cgray ##{issue.iid} diff --git a/features/steps/project/milestones.rb b/features/steps/project/milestones.rb index 9ce18fbaab..5562b523d1 100644 --- a/features/steps/project/milestones.rb +++ b/features/steps/project/milestones.rb @@ -54,6 +54,6 @@ class ProjectMilestones < Spinach::FeatureSteps end Then "I should see 3 issues" do - page.should have_selector('#tab-issues li', count: 4) + page.should have_selector('#tab-issues li.issue-row', count: 4) end end From e84057da1bc0d96e7f24424f423a9491d99d5585 Mon Sep 17 00:00:00 2001 From: Jeroen van Baarsen Date: Wed, 4 Jun 2014 22:55:27 +0200 Subject: [PATCH 223/360] Splitted the Spinach tests to prevent time-outs Signed-off-by: Jeroen van Baarsen --- .travis.yml | 6 ++++-- features/admin/active_tab.feature | 1 + features/admin/broadcast_messages.feature | 1 + features/admin/groups.feature | 1 + features/admin/logs.feature | 1 + features/admin/projects.feature | 1 + features/admin/users.feature | 1 + features/dashboard/active_tab.feature | 1 + features/dashboard/archived_projects.feature | 1 + features/dashboard/dashboard.feature | 1 + features/dashboard/event_filters.feature | 1 + features/dashboard/help.feature | 1 + features/dashboard/issues.feature | 1 + features/dashboard/merge_requests.feature | 1 + features/dashboard/projects.feature | 1 + features/dashboard/search.feature | 1 + features/profile/active_tab.feature | 1 + features/profile/emails.feature | 1 + features/profile/group.feature | 1 + features/profile/notifications.feature | 1 + features/profile/profile.feature | 1 + features/profile/ssh_keys.feature | 1 + features/public/projects.feature | 1 + features/public/public_groups.feature | 1 + features/snippets/discover.feature | 1 + features/snippets/snippets.feature | 1 + features/snippets/user.feature | 1 + lib/tasks/spinach.rake | 21 ++++++++++++++++++++ 28 files changed, 51 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9bab337f33..c90bba8dee 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,12 +3,14 @@ env: global: - TRAVIS=true matrix: - - TASK=spinach DB=mysql + - TASK=spinach_project DB=mysql + - TASK=spinach_other DB=mysql - TASK=spec:api DB=mysql - TASK=spec:feature DB=mysql - TASK=spec:other DB=mysql - TASK=jasmine:ci DB=mysql - - TASK=spinach DB=postgresql + - TASK=spinach_project DB=postgresql + - TASK=spinach_other DB=postgresql - TASK=spec:api DB=postgresql - TASK=spec:feature DB=postgresql - TASK=spec:other DB=postgresql diff --git a/features/admin/active_tab.feature b/features/admin/active_tab.feature index 15fcda45e4..b28e16f0d6 100644 --- a/features/admin/active_tab.feature +++ b/features/admin/active_tab.feature @@ -1,3 +1,4 @@ +@admin Feature: Admin active tab Background: Given I sign in as an admin diff --git a/features/admin/broadcast_messages.feature b/features/admin/broadcast_messages.feature index 5f16120b7c..b2c3112320 100644 --- a/features/admin/broadcast_messages.feature +++ b/features/admin/broadcast_messages.feature @@ -1,3 +1,4 @@ +@admin Feature: Admin Broadcast Messages Background: Given I sign in as an admin diff --git a/features/admin/groups.feature b/features/admin/groups.feature index 352c1b3803..1a465c1be5 100644 --- a/features/admin/groups.feature +++ b/features/admin/groups.feature @@ -1,3 +1,4 @@ +@admin Feature: Admin Groups Background: Given I sign in as an admin diff --git a/features/admin/logs.feature b/features/admin/logs.feature index d07f004808..ceb3bc3492 100644 --- a/features/admin/logs.feature +++ b/features/admin/logs.feature @@ -1,3 +1,4 @@ +@admin Feature: Admin Logs Background: Given I sign in as an admin diff --git a/features/admin/projects.feature b/features/admin/projects.feature index 4a4ee1c11e..fb07ccdb35 100644 --- a/features/admin/projects.feature +++ b/features/admin/projects.feature @@ -1,3 +1,4 @@ +@admin Feature: Admin Projects Background: Given I sign in as an admin diff --git a/features/admin/users.feature b/features/admin/users.feature index ce9f32f50d..ce31aafd29 100644 --- a/features/admin/users.feature +++ b/features/admin/users.feature @@ -1,3 +1,4 @@ +@admin Feature: Admin Users Background: Given I sign in as an admin diff --git a/features/dashboard/active_tab.feature b/features/dashboard/active_tab.feature index 3e1cf5aa0c..22dfa2f784 100644 --- a/features/dashboard/active_tab.feature +++ b/features/dashboard/active_tab.feature @@ -1,3 +1,4 @@ +@dashboard Feature: Dashboard active tab Background: Given I sign in as a user diff --git a/features/dashboard/archived_projects.feature b/features/dashboard/archived_projects.feature index 399c9b53d8..e23238d225 100644 --- a/features/dashboard/archived_projects.feature +++ b/features/dashboard/archived_projects.feature @@ -1,3 +1,4 @@ +@dashboard Feature: Dashboard with archived projects Background: Given I sign in as a user diff --git a/features/dashboard/dashboard.feature b/features/dashboard/dashboard.feature index e249f392de..bebaa78e46 100644 --- a/features/dashboard/dashboard.feature +++ b/features/dashboard/dashboard.feature @@ -1,3 +1,4 @@ +@dashboard Feature: Dashboard Background: Given I sign in as a user diff --git a/features/dashboard/event_filters.feature b/features/dashboard/event_filters.feature index e0c6b84b00..41de0ae831 100644 --- a/features/dashboard/event_filters.feature +++ b/features/dashboard/event_filters.feature @@ -1,3 +1,4 @@ +@dashboard Feature: Event filters Background: Given I sign in as a user diff --git a/features/dashboard/help.feature b/features/dashboard/help.feature index 02ec688f80..56a0a860ab 100644 --- a/features/dashboard/help.feature +++ b/features/dashboard/help.feature @@ -1,3 +1,4 @@ +@dashboard Feature: Help Background: Given I sign in as a user diff --git a/features/dashboard/issues.feature b/features/dashboard/issues.feature index d316b2d920..72627e43e0 100644 --- a/features/dashboard/issues.feature +++ b/features/dashboard/issues.feature @@ -1,3 +1,4 @@ +@dashboard Feature: Dashboard Issues Background: Given I sign in as a user diff --git a/features/dashboard/merge_requests.feature b/features/dashboard/merge_requests.feature index de56030073..dcef1290e7 100644 --- a/features/dashboard/merge_requests.feature +++ b/features/dashboard/merge_requests.feature @@ -1,3 +1,4 @@ +@dashboard Feature: Dashboard Merge Requests Background: Given I sign in as a user diff --git a/features/dashboard/projects.feature b/features/dashboard/projects.feature index 7d8c129fac..5214cfc28e 100644 --- a/features/dashboard/projects.feature +++ b/features/dashboard/projects.feature @@ -1,3 +1,4 @@ +@dashboard Feature: Dashboard projects Background: Given I sign in as a user diff --git a/features/dashboard/search.feature b/features/dashboard/search.feature index 91d870f46f..24c4502869 100644 --- a/features/dashboard/search.feature +++ b/features/dashboard/search.feature @@ -1,3 +1,4 @@ +@dashboard Feature: Dashboard Search Background: Given I sign in as a user diff --git a/features/profile/active_tab.feature b/features/profile/active_tab.feature index 475641a33e..a99409d9fd 100644 --- a/features/profile/active_tab.feature +++ b/features/profile/active_tab.feature @@ -1,3 +1,4 @@ +@profile Feature: Profile active tab Background: Given I sign in as a user diff --git a/features/profile/emails.feature b/features/profile/emails.feature index 148fc76608..19ed949f6a 100644 --- a/features/profile/emails.feature +++ b/features/profile/emails.feature @@ -1,3 +1,4 @@ +@profile Feature: Profile Emails Background: Given I sign in as a user diff --git a/features/profile/group.feature b/features/profile/group.feature index 70b682e291..e2fbfde77b 100644 --- a/features/profile/group.feature +++ b/features/profile/group.feature @@ -1,3 +1,4 @@ +@profile Feature: Profile Group Background: Given I sign in as "John Doe" diff --git a/features/profile/notifications.feature b/features/profile/notifications.feature index e7937953c1..55997d44de 100644 --- a/features/profile/notifications.feature +++ b/features/profile/notifications.feature @@ -1,3 +1,4 @@ +@profile Feature: Profile Notifications Background: Given I sign in as a user diff --git a/features/profile/profile.feature b/features/profile/profile.feature index 44bb190f62..d2125e013b 100644 --- a/features/profile/profile.feature +++ b/features/profile/profile.feature @@ -1,3 +1,4 @@ +@profile Feature: Profile Background: Given I sign in as a user diff --git a/features/profile/ssh_keys.feature b/features/profile/ssh_keys.feature index 018d124e41..581503fc5f 100644 --- a/features/profile/ssh_keys.feature +++ b/features/profile/ssh_keys.feature @@ -1,3 +1,4 @@ +@profile Feature: Profile SSH Keys Background: Given I sign in as a user diff --git a/features/public/projects.feature b/features/public/projects.feature index 57fe834b4b..c7bb3b4f8c 100644 --- a/features/public/projects.feature +++ b/features/public/projects.feature @@ -1,3 +1,4 @@ +@public Feature: Public Projects Feature Background: Given public project "Community" diff --git a/features/public/public_groups.feature b/features/public/public_groups.feature index 7f1ec718e3..8bbda8cb6d 100644 --- a/features/public/public_groups.feature +++ b/features/public/public_groups.feature @@ -1,3 +1,4 @@ +@public Feature: Public Projects Feature Background: Given group "TestGroup" has private project "Enterprise" diff --git a/features/snippets/discover.feature b/features/snippets/discover.feature index d6fd2cd780..f0b8d3a408 100644 --- a/features/snippets/discover.feature +++ b/features/snippets/discover.feature @@ -1,3 +1,4 @@ +@snippets Feature: Discover Snippets Background: Given I sign in as a user diff --git a/features/snippets/snippets.feature b/features/snippets/snippets.feature index 1119defa17..3ee8720ddd 100644 --- a/features/snippets/snippets.feature +++ b/features/snippets/snippets.feature @@ -1,3 +1,4 @@ +@snippets Feature: Snippets Feature Background: Given I sign in as a user diff --git a/features/snippets/user.feature b/features/snippets/user.feature index 4c8a91501c..d032a33686 100644 --- a/features/snippets/user.feature +++ b/features/snippets/user.feature @@ -1,3 +1,4 @@ +@snippets Feature: User Snippets Background: Given I sign in as a user diff --git a/lib/tasks/spinach.rake b/lib/tasks/spinach.rake index dcc7d0fe01..507b315759 100644 --- a/lib/tasks/spinach.rake +++ b/lib/tasks/spinach.rake @@ -6,7 +6,28 @@ task :spinach do %W(rake gitlab:setup), %W(spinach), ] + run_commands(cmds) +end +desc "GITLAB | Run project spinach features" +task :spinach_project do + cmds = [ + %W(rake gitlab:setup), + %W(spinach --tags ~@admin,~@dashboard,~@profile,~@public,~@snippets), + ] + run_commands(cmds) +end + +desc "GITLAB | Run other spinach features" +task :spinach_other do + cmds = [ + %W(rake gitlab:setup), + %W(spinach --tags @admin,@dashboard,@profile,@public,@snippets), + ] + run_commands(cmds) +end + +def run_commands(cmds) cmds.each do |cmd| system({'RAILS_ENV' => 'test', 'force' => 'yes'}, *cmd) or raise("#{cmd} failed!") end From 793955cdfc8f2c2e6f19161426b80e63f8bffe02 Mon Sep 17 00:00:00 2001 From: Jeroen van Baarsen Date: Thu, 29 May 2014 17:28:49 +0200 Subject: [PATCH 224/360] We need to change config in step 5 --- 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 866032fb7c..d1acff3e49 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -76,7 +76,7 @@ Is the system packaged Git too old? Remove it and compile from source. # Install into /usr/local/bin sudo make prefix=/usr/local install - # When editing config/gitlab.yml (Step 6), change the git bin_path to /usr/local/bin/git + # When editing config/gitlab.yml (Step 5), change the git bin_path to /usr/local/bin/git **Note:** In order to receive mail notifications, make sure to install a mail server. By default, Debian is shipped with exim4 whereas Ubuntu does not ship with one. The recommended mail server is postfix and you can install it with: From 829c7282a3f3372f6cb1465c65d7b03309b889dd Mon Sep 17 00:00:00 2001 From: Ben Bodenmiller Date: Wed, 4 Jun 2014 18:14:31 -0700 Subject: [PATCH 225/360] improve no projects screen * correct odd capitalization pattern in tagline * remove "click on button" statement as telling a user to click something is not a good web development practice * add missing period for consistency --- app/views/dashboard/_zero_authorized_projects.html.haml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/app/views/dashboard/_zero_authorized_projects.html.haml b/app/views/dashboard/_zero_authorized_projects.html.haml index e0993293ea..ee086d88e3 100644 --- a/app/views/dashboard/_zero_authorized_projects.html.haml +++ b/app/views/dashboard/_zero_authorized_projects.html.haml @@ -1,5 +1,5 @@ %h3.page-title Welcome to GitLab! -%p.light Self Hosted Git Management application. +%p.light Self hosted Git management application. %hr %div .dashboard-intro-icon @@ -11,9 +11,8 @@ - if current_user.can_create_project? You can create up to %strong= pluralize(current_user.projects_limit, "project") + "." - Click on the button below to add a new one - else - If you are added to a project, it will be displayed here + If you are added to a project, it will be displayed here. - if current_user.can_create_project? .link_holder @@ -29,7 +28,7 @@ %p.slead You can create a group for several dependent projects. %br - Groups are the best way to manage projects and members + Groups are the best way to manage projects and members. .link_holder = link_to new_group_path, class: "btn btn-new" do New group » From 9654b098c6478e7c17bc8c848f9284daa26ead76 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 5 Jun 2014 09:29:24 +0300 Subject: [PATCH 226/360] Milestone drag-n-drop with 3 columns Signed-off-by: Dmitriy Zaporozhets --- app/assets/javascripts/milestone.js.coffee | 7 ++++--- app/views/projects/milestones/show.html.haml | 12 +++++------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/app/assets/javascripts/milestone.js.coffee b/app/assets/javascripts/milestone.js.coffee index bbbaa288b8..d2857948cd 100644 --- a/app/assets/javascripts/milestone.js.coffee +++ b/app/assets/javascripts/milestone.js.coffee @@ -15,7 +15,7 @@ class Milestone @bindSorting() bindSorting: -> - $("#issues-list-unassigned, #issues-list-ongoing, #issues-list-closed, #issues-list-reopened").sortable( + $("#issues-list-unassigned, #issues-list-ongoing, #issues-list-closed").sortable( connectWith: ".issues-sortable-list", dropOnEmpty: true, receive: (event, ui) -> @@ -30,8 +30,9 @@ class Milestone "issue[assignee_id]=" when 'closed' "issue[state_event]=close" - when 'reopened' - "issue[state_event]=reopen" + + if $(ui.sender).data('state') == "closed" + data += "&issue[state_event]=reopen" Milestone.updateIssue(ui.item, issue_url, data) diff --git a/app/views/projects/milestones/show.html.haml b/app/views/projects/milestones/show.html.haml index 594b6a0c72..67b45fc30b 100644 --- a/app/views/projects/milestones/show.html.haml +++ b/app/views/projects/milestones/show.html.haml @@ -75,14 +75,12 @@ .tab-content .tab-pane.active#tab-issues .row - .col-md-3 - = render('issues', title: 'Unstarted Issues (open and unassigned)', issues: @issues.only_opened.unassigned, id: 'unassigned') - .col-md-3 - = render('issues', title: 'Ongoing Issues (open and assigned)', issues: @issues.only_opened.assigned, id: 'ongoing') - .col-md-3 + .col-md-4 + = render('issues', title: 'Unstarted Issues (open and unassigned)', issues: @issues.opened.unassigned, id: 'unassigned') + .col-md-4 + = render('issues', title: 'Ongoing Issues (open and assigned)', issues: @issues.opened.assigned, id: 'ongoing') + .col-md-4 = render('issues', title: 'Completed Issues (closed)', issues: @issues.closed, id: 'closed') - .col-md-3 - = render('issues', title: 'Reopened Issues (reopened)', issues: @issues.only_reopened, id: 'reopened') .tab-pane#tab-merge-requests .row From 248a3e5688b7576995d21f1fb47c3deb2ae4de08 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 5 Jun 2014 09:39:03 +0300 Subject: [PATCH 227/360] Fix help page UI Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/sections/help.scss | 8 +++++--- app/views/help/index.html.haml | 12 ++++++------ 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/app/assets/stylesheets/sections/help.scss b/app/assets/stylesheets/sections/help.scss index 178a735941..94cef187d1 100644 --- a/app/assets/stylesheets/sections/help.scss +++ b/app/assets/stylesheets/sections/help.scss @@ -1,10 +1,12 @@ .documentation { - padding-bottom: 10px; - p { - padding: 10px 14px; + h1 { margin: 0; } + h2 { + font-size: 20px; + } + li { line-height: 24px; color: #888; diff --git a/app/views/help/index.html.haml b/app/views/help/index.html.haml index 1b714429f1..258a468f7b 100644 --- a/app/views/help/index.html.haml +++ b/app/views/help/index.html.haml @@ -36,9 +36,9 @@ .col-md-8 .panel.panel-default.documentation .panel-heading Documentation - - = preserve do - - readme_text = File.read(Rails.root.join("doc", "README.md")) - - text = readme_text.dup - - readme_text.scan(/\]\(([^(]+)\)/) { |match| text.gsub!(match.first, "help/#{match.first}") } - = markdown text + .panel-body + = preserve do + - readme_text = File.read(Rails.root.join("doc", "README.md")) + - text = readme_text.dup + - readme_text.scan(/\]\(([^(]+)\)/) { |match| text.gsub!(match.first, "help/#{match.first}") } + = markdown text From 4ed39a77ef79178b231f3fb309b41df1fd8cc2df Mon Sep 17 00:00:00 2001 From: Sytse Sijbrandij Date: Thu, 5 Jun 2014 08:45:12 +0200 Subject: [PATCH 228/360] Support Ruby 2.1 and better explain the memory requirements. --- CHANGELOG | 1 + doc/install/requirements.md | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 760218690b..f825c7f68f 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -18,6 +18,7 @@ v 7.0.0 - Case-insensetive search for issues - Update to rails 4.1 - Improve performance of application for projects and groups with a lot of members + - Formally support Ruby 2.1 v 6.9.2 - Revert the commit that broke the LDAP user filter diff --git a/doc/install/requirements.md b/doc/install/requirements.md index cec35ca7be..575df915a2 100644 --- a/doc/install/requirements.md +++ b/doc/install/requirements.md @@ -39,7 +39,7 @@ Please consider using a virtual machine to run GitLab. ## Ruby versions -GitLab requires Ruby (MRI) 2.0+. +GitLab requires Ruby (MRI) 2.0 or 2.1 >>>>>>> Update docs to markdown style guide. You will have to use the standard MRI implementation of Ruby. @@ -60,8 +60,8 @@ We love [JRuby](http://jruby.org/) and [Rubinius](http://rubini.us/)) but GitLab ### Memory -- 512MB is the absolute minimum, you need 256MB of swap, you can configure only one slow unicorn worker, only ssh access will work, we do not recommend this -- 1GB supports up to 100 users (with individual repositories under 250MB, otherwise git memory usage necessitates using swap space) +- 512MB is the absolute minimum but we do not recommend this amount of memory, you'll need to configure a minimum swap of 256MB, you're memory will only allow you to run one slow unicorn worker, things will case only git ssh access to work because the git http access requires two running workers (one to receive the user request and one for the authorization check), +- 1GB supports up to 100 users (with individual repositories under 250MB, otherwise git memory usage necessitates configuring swap space) - **2GB** is the **recommended** memory size and supports up to 500 users - 4GB supports up to 2,000 users - 8GB supports up to 5,000 users From 336d50d008e8efcaef89ce5656620cbe068aa064 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 5 Jun 2014 13:01:49 +0300 Subject: [PATCH 229/360] Merge request drag-n-drop on milestone page Allows moving milestone between 3 columns: unassigned, assigned, declined Signed-off-by: Dmitriy Zaporozhets --- app/assets/javascripts/milestone.js.coffee | 43 +++++++++++++++++-- .../milestones/_merge_request.html.haml | 10 ++--- .../milestones/_merge_requests.html.haml | 6 +++ app/views/projects/milestones/show.html.haml | 18 +++----- 4 files changed, 57 insertions(+), 20 deletions(-) create mode 100644 app/views/projects/milestones/_merge_requests.html.haml diff --git a/app/assets/javascripts/milestone.js.coffee b/app/assets/javascripts/milestone.js.coffee index d2857948cd..4a2c5068ba 100644 --- a/app/assets/javascripts/milestone.js.coffee +++ b/app/assets/javascripts/milestone.js.coffee @@ -11,10 +11,23 @@ class Milestone new Flash("Issue update failed", 'alert') dataType: "json" - constructor: -> - @bindSorting() + @updateMergeRequest: (li, merge_request_url, data) -> + $.ajax + type: "PUT" + url: merge_request_url + data: data + success: (data) -> + if data.saved == true + $(li).effect 'highlight' + else + new Flash("Issue update failed", 'alert') + dataType: "json" - bindSorting: -> + constructor: -> + @bindIssuesSorting() + @bindMergeRequestSorting() + + bindIssuesSorting: -> $("#issues-list-unassigned, #issues-list-ongoing, #issues-list-closed").sortable( connectWith: ".issues-sortable-list", dropOnEmpty: true, @@ -38,4 +51,28 @@ class Milestone ).disableSelection() + bindMergeRequestSorting: -> + $("#merge_requests-list-unassigned, #merge_requests-list-ongoing, #merge_requests-list-closed").sortable( + connectWith: ".merge_requests-sortable-list", + dropOnEmpty: true, + receive: (event, ui) -> + new_state = $(this).data('state') + merge_request_id = ui.item.data('iid') + merge_request_url = ui.item.data('url') + + data = switch new_state + when 'ongoing' + "merge_request[assignee_id]=" + gon.current_user_id + when 'unassigned' + "merge_request[assignee_id]=" + when 'closed' + "merge_request[state_event]=close" + + if $(ui.sender).data('state') == "closed" + data += "&merge_request[state_event]=reopen" + + Milestone.updateMergeRequest(ui.item, merge_request_url, data) + + ).disableSelection() + @Milestone = Milestone diff --git a/app/views/projects/milestones/_merge_request.html.haml b/app/views/projects/milestones/_merge_request.html.haml index faa35a25f2..4787da51e6 100644 --- a/app/views/projects/milestones/_merge_request.html.haml +++ b/app/views/projects/milestones/_merge_request.html.haml @@ -1,5 +1,5 @@ -%li - = link_to [@project, merge_request] do - %span.label.label-info ##{merge_request.iid} - – - = link_to_gfm truncate(merge_request.title, length: 60), [@project, merge_request] +%li{ class: 'mr-row', 'data-iid' => merge_request.iid, 'data-url' => project_merge_request_path(@project, merge_request) } + %span.str-truncated + = link_to [@project, merge_request] do + %span.cgray ##{merge_request.iid} + = link_to_gfm truncate(merge_request.title, length: 60), [@project, merge_request] diff --git a/app/views/projects/milestones/_merge_requests.html.haml b/app/views/projects/milestones/_merge_requests.html.haml new file mode 100644 index 0000000000..18c4660183 --- /dev/null +++ b/app/views/projects/milestones/_merge_requests.html.haml @@ -0,0 +1,6 @@ +.panel.panel-default + .panel-heading= title + %ul{ class: "well-list merge_requests-sortable-list", id: "merge_requests-list-#{id}", "data-state" => id } + - merge_requests.each do |merge_request| + = render 'merge_request', merge_request: merge_request + %li.light Drag and drop available diff --git a/app/views/projects/milestones/show.html.haml b/app/views/projects/milestones/show.html.haml index 67b45fc30b..206bf47449 100644 --- a/app/views/projects/milestones/show.html.haml +++ b/app/views/projects/milestones/show.html.haml @@ -84,18 +84,12 @@ .tab-pane#tab-merge-requests .row - .col-md-6 - .panel.panel-default - .panel-heading Open - %ul.well-list - - @merge_requests.opened.each do |merge_request| - = render 'merge_request', merge_request: merge_request - .col-md-6 - .panel.panel-default - .panel-heading Closed - %ul.well-list - - @merge_requests.closed.each do |merge_request| - = render 'merge_request', merge_request: merge_request + .col-md-4 + = render('merge_requests', title: 'Work in progress (open and unassigned)', merge_requests: @merge_requests.opened.unassigned, id: 'unassigned') + .col-md-4 + = render('merge_requests', title: 'Assigned (open and assigned)', merge_requests: @merge_requests.opened.assigned, id: 'ongoing') + .col-md-4 + = render('merge_requests', title: 'Declined (closed)', merge_requests: @merge_requests.closed, id: 'closed') .tab-pane#tab-participants %ul.bordered-list From 27f32ac6486c3bbd0ca3a5a19aa3aa1a4e4ded93 Mon Sep 17 00:00:00 2001 From: Ciro Santilli Date: Thu, 5 Jun 2014 14:47:51 +0200 Subject: [PATCH 230/360] Remove conflict artifact. --- doc/install/requirements.md | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/install/requirements.md b/doc/install/requirements.md index 575df915a2..d7c4c4da2e 100644 --- a/doc/install/requirements.md +++ b/doc/install/requirements.md @@ -41,7 +41,6 @@ Please consider using a virtual machine to run GitLab. GitLab requires Ruby (MRI) 2.0 or 2.1 ->>>>>>> Update docs to markdown style guide. You will have to use the standard MRI implementation of Ruby. We love [JRuby](http://jruby.org/) and [Rubinius](http://rubini.us/)) but GitLab needs several Gems that have native extensions. From ffd50e8cf562b69a897e389a968b9366ee1e6aae Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 5 Jun 2014 16:28:13 +0300 Subject: [PATCH 231/360] Add merged mrs list to milestone page Signed-off-by: Dmitriy Zaporozhets --- app/models/merge_request.rb | 1 + app/views/projects/milestones/show.html.haml | 16 +++++++++++----- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index b7c4a2a923..a501870115 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -113,6 +113,7 @@ class MergeRequest < ActiveRecord::Base # Closed scope for merge request should return # both merged and closed mr's scope :closed, -> { with_states(:closed, :merged) } + scope :declined, -> { with_states(:closed) } def validate_branches if target_project == source_project && target_branch == source_branch diff --git a/app/views/projects/milestones/show.html.haml b/app/views/projects/milestones/show.html.haml index 206bf47449..5cf7f33211 100644 --- a/app/views/projects/milestones/show.html.haml +++ b/app/views/projects/milestones/show.html.haml @@ -84,12 +84,18 @@ .tab-pane#tab-merge-requests .row - .col-md-4 + .col-md-3 = render('merge_requests', title: 'Work in progress (open and unassigned)', merge_requests: @merge_requests.opened.unassigned, id: 'unassigned') - .col-md-4 - = render('merge_requests', title: 'Assigned (open and assigned)', merge_requests: @merge_requests.opened.assigned, id: 'ongoing') - .col-md-4 - = render('merge_requests', title: 'Declined (closed)', merge_requests: @merge_requests.closed, id: 'closed') + .col-md-3 + = render('merge_requests', title: 'Waiting for merge (open and assigned)', merge_requests: @merge_requests.opened.assigned, id: 'ongoing') + .col-md-3 + = render('merge_requests', title: 'Declined (closed)', merge_requests: @merge_requests.declined, id: 'closed') + .col-md-3 + .panel.panel-primary + .panel-heading Merged + %ul.well-list + - @merge_requests.merged.each do |merge_request| + = render 'merge_request', merge_request: merge_request .tab-pane#tab-participants %ul.bordered-list From 7be6b8ca73b1bd7fd46f01ca43fe9d57a2ba0809 Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Thu, 5 Jun 2014 16:03:50 +0300 Subject: [PATCH 232/360] Move gitlab-ssl nginx config from gitlab-recipes --- CHANGELOG | 1 + doc/install/installation.md | 4 +- lib/support/nginx/gitlab-ssl | 164 +++++++++++++++++++++++++++++++++++ 3 files changed, 168 insertions(+), 1 deletion(-) create mode 100644 lib/support/nginx/gitlab-ssl diff --git a/CHANGELOG b/CHANGELOG index f825c7f68f..efb11a70cf 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -19,6 +19,7 @@ v 7.0.0 - Update to rails 4.1 - Improve performance of application for projects and groups with a lot of members - Formally support Ruby 2.1 + - Include Nginx gitlab-ssl config v 6.9.2 - Revert the commit that broke the LDAP user filter diff --git a/doc/install/installation.md b/doc/install/installation.md index 866032fb7c..7840cef890 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -294,7 +294,7 @@ Check if GitLab and its environment are configured correctly: ### Site Configuration -Download an example site config: +Copy the example site config: sudo cp lib/support/nginx/gitlab /etc/nginx/sites-available/gitlab sudo ln -s /etc/nginx/sites-available/gitlab /etc/nginx/sites-enabled/gitlab @@ -305,6 +305,8 @@ Make sure to edit the config file to match your setup: # domain name of your host serving GitLab. sudo editor /etc/nginx/sites-available/gitlab +**Note:** If you want to use https, replace the `gitlab` nginx config with `gitlab-ssl`. + ### Restart sudo service nginx restart diff --git a/lib/support/nginx/gitlab-ssl b/lib/support/nginx/gitlab-ssl new file mode 100644 index 0000000000..22e923b377 --- /dev/null +++ b/lib/support/nginx/gitlab-ssl @@ -0,0 +1,164 @@ +## GitLab +## Contributors: randx, yin8086, sashkab, orkoden, axilleas +## +## Modified from nginx http version +## Modified from http://blog.phusion.nl/2012/04/21/tutorial-setting-up-gitlab-on-debian-6/ +## +## Lines starting with two hashes (##) are comments containing information +## for configuration. One hash (#) comments are actual configuration parameters +## which you can comment/uncomment to your liking. +## +################################### +## SSL configuration ## +################################### +## +## Optimal configuration is taken from: +## https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html +## Make sure to read it and understand what each option does. +## +## [Optional] Generate a self-signed ssl certificate: +## mkdir /etc/nginx/ssl/ +## cd /etc/nginx/ssl/ +## sudo openssl req -newkey rsa:2048 -x509 -nodes -days 3560 -out gitlab.crt -keyout gitlab.key +## sudo chmod o-r gitlab.key +## +## Edit `gitlab-shell/config.yml`: +## 1) Set "gitlab_url" param in `gitlab-shell/config.yml` to `https://git.example.com` +## 2) Set "ca_file" to `/etc/nginx/ssl/gitlab.crt` +## 3) Set "self_signed_cert" to `true` +## Edit `gitlab/config/gitlab.yml`: +## 1) Define port for http "port: 443" +## 2) Enable https "https: true" +## 3) Update ssl for gravatar "ssl_url: https://secure.gravatar.com/avatar/%{hash}?s=%{size}&d=mm" +## +################################## +## CHUNKED TRANSFER ## +################################## +## +## It is a known issue that Git-over-HTTP requires chunked transfer encoding [0] +## which is not supported by Nginx < 1.3.9 [1]. As a result, pushing a large object +## with Git (i.e. a single large file) can lead to a 411 error. In theory you can get +## around this by tweaking this configuration file and either: +## - installing an old version of Nginx with the chunkin module [2] compiled in, or +## - using a newer version of Nginx. +## +## At the time of writing we do not know if either of these theoretical solutions works. As a workaround +## users can use Git over SSH to push large files. +## +## [0] https://git.kernel.org/cgit/git/git.git/tree/Documentation/technical/http-protocol.txt#n99 +## [1] https://github.com/agentzh/chunkin-nginx-module#status +## [2] https://github.com/agentzh/chunkin-nginx-module + + +upstream gitlab { + + ## Uncomment if you have set up unicorn to listen on a unix socket (recommended). + server unix:/home/git/gitlab/tmp/sockets/gitlab.socket; + + ## Uncomment if unicorn is configured to listen on a tcp port. + ## Check the port number in /home/git/gitlab/config/unicorn.rb + # server 127.0.0.1:8080; +} + +## This is a normal HTTP host which redirects all traffic to the HTTPS host. +server { + listen *:80; + ## Replace git.example.com with your FQDN. + server_name git.example.com; + server_tokens off; + ## root doesn't have to be a valid path since we are redirecting + root /nowhere; + rewrite ^ https://$server_name$request_uri permanent; +} + +server { + listen 443 ssl; + ## Replace git.example.com with your FQDN. + server_name git.example.com; + server_tokens off; + root /home/git/gitlab/public; + + ## Increase this if you want to upload large attachments + ## Or if you want to accept large git objects over http + client_max_body_size 20m; + + ## Strong SSL Security + ## https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html + ssl on; + ssl_certificate /etc/nginx/ssl/gitlab.crt; + ssl_certificate_key /etc/nginx/ssl/gitlab.key; + + ssl_ciphers 'ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4'; + + ssl_protocols TLSv1 TLSv1.1 TLSv1.2; + ssl_session_cache builtin:1000 shared:SSL:10m; + + ## Enable OCSP stapling to reduce the overhead and latency of running SSL. + ## Replace with your ssl_trusted_certificate. For more info see: + ## - https://medium.com/devops-programming/4445f4862461 + ## - https://www.ruby-forum.com/topic/4419319 + ssl_stapling on; + ssl_stapling_verify on; + ssl_trusted_certificate /etc/nginx/ssl/stapling.trusted.crt; + resolver 208.67.222.222 208.67.222.220 valid=300s; + resolver_timeout 10s; + + ssl_prefer_server_ciphers on; + ## [Optional] Generate a stronger DHE parameter (recommended): + ## cd /etc/ssl/certs + ## openssl dhparam -out dhparam.pem 2048 + ## + # ssl_dhparam /etc/ssl/certs/dhparam.pem; + + add_header Strict-Transport-Security max-age=63072000; + add_header X-Frame-Options DENY; + add_header X-Content-Type-Options nosniff; + + ## Individual nginx logs for this GitLab vhost + access_log /var/log/nginx/gitlab_access.log; + error_log /var/log/nginx/gitlab_error.log; + + location / { + ## Serve static files from defined root folder. + ## @gitlab is a named location for the upstream fallback, see below. + try_files $uri $uri/index.html $uri.html @gitlab; + } + + ## If a file, which is not found in the root folder is requested, + ## then the proxy pass the request to the upsteam (gitlab unicorn). + location @gitlab { + + ## If you use https make sure you disable gzip compression + ## to be safe against BREACH attack. + gzip off; + + ## https://github.com/gitlabhq/gitlabhq/issues/694 + ## Some requests take more than 30 seconds. + proxy_read_timeout 300; + proxy_connect_timeout 300; + proxy_redirect off; + + proxy_set_header Host $http_host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-Ssl on; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Frame-Options SAMEORIGIN; + + proxy_pass http://gitlab; + } + + ## Enable gzip compression as per rails guide: + ## http://guides.rubyonrails.org/asset_pipeline.html#gzip-compression + ## WARNING: If you are using relative urls do remove the block below + ## See config/application.rb under "Relative url support" for the list of + ## other files that need to be changed for relative url support + location ~ ^/(assets)/ { + root /home/git/gitlab/public; + gzip_static on; # to serve pre-gzipped version + expires max; + add_header Cache-Control public; + } + + error_page 502 /502.html; +} From 4ca6ebf017e93686ee885ee1a28dc5c6934c9d39 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 5 Jun 2014 20:36:59 +0300 Subject: [PATCH 233/360] Add GroupFinder for collection all groups user has access to Signed-off-by: Dmitriy Zaporozhets --- app/finders/groups_finder.rb | 38 ++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 app/finders/groups_finder.rb diff --git a/app/finders/groups_finder.rb b/app/finders/groups_finder.rb new file mode 100644 index 0000000000..d3597ef090 --- /dev/null +++ b/app/finders/groups_finder.rb @@ -0,0 +1,38 @@ +class GroupsFinder + def execute(current_user, options = {}) + all_groups(current_user) + end + + private + + def all_groups(current_user) + if current_user + if current_user.authorized_groups.any? + # User has access to groups + # + # Return only: + # groups with public projects + # groups with internal projects + # groups with joined projects + # + group_ids = Project.public_and_internal_only.pluck(:namespace_id) + + current_user.authorized_groups.pluck(:id) + Group.where(id: group_ids) + else + # User has no group membership + # + # Return only: + # groups with public projects + # groups with internal projects + # + Group.where(id: Project.public_and_internal_only.pluck(:namespace_id)) + end + else + # Not authenticated + # + # Return only: + # groups with public projects + Group.where(id: Project.public_only.pluck(:namespace_id)) + end + end +end From 0fdce4a52b1a9ba9e0efd98f00e558e4f07daeb5 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 5 Jun 2014 20:37:35 +0300 Subject: [PATCH 234/360] Refactor some search scopes to prevent wierd behaviour and PG::Error issues Signed-off-by: Dmitriy Zaporozhets --- app/controllers/users_controller.rb | 17 ++++++++++--- app/finders/base_finder.rb | 2 +- app/finders/projects_finder.rb | 36 ++++++++++++++++++++++++--- app/helpers/search_helper.rb | 2 +- app/helpers/submodule_helper.rb | 0 app/models/ability.rb | 2 +- app/models/group.rb | 10 +++----- app/models/namespace.rb | 8 ------ app/models/project.rb | 6 ----- app/services/search/global_service.rb | 2 +- 10 files changed, 53 insertions(+), 32 deletions(-) mode change 100755 => 100644 app/helpers/submodule_helper.rb diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index c17c6f9694..0b442f5383 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -4,15 +4,24 @@ class UsersController < ApplicationController def show @user = User.find_by_username!(params[:username]) - @projects = Project.personal(@user).accessible_to(current_user) unless current_user || @user.public_profile? return authenticate_user! end - @groups = @user.groups.accessible_to(current_user) - accessible_projects = @user.authorized_projects.accessible_to(current_user) - @events = @user.recent_events.where(project_id: accessible_projects.pluck(:id)).limit(20) + # Projects user can view + authorized_projects_ids = ProjectsFinder.new.execute(current_user).pluck(:id) + + @projects = @user.personal_projects. + where(id: authorized_projects_ids) + + # Collect only groups common for both users + @groups = @user.groups & GroupsFinder.new.execute(current_user) + + # Get user activity feed for projects common for both users + @events = @user.recent_events. + where(project_id: authorized_projects_ids).limit(20) + @title = @user.name end diff --git a/app/finders/base_finder.rb b/app/finders/base_finder.rb index 7fc5840561..7150bb2e31 100644 --- a/app/finders/base_finder.rb +++ b/app/finders/base_finder.rb @@ -49,7 +49,7 @@ class BaseFinder elsif current_user && params[:authorized_only].presence klass.of_projects(current_user.authorized_projects).references(:project) else - klass.of_projects(Project.accessible_to(current_user)).references(:project) + klass.of_projects(ProjectsFinder.new.execute(current_user)).references(:project) end end diff --git a/app/finders/projects_finder.rb b/app/finders/projects_finder.rb index bfaba75878..26898bad49 100644 --- a/app/finders/projects_finder.rb +++ b/app/finders/projects_finder.rb @@ -1,5 +1,5 @@ class ProjectsFinder - def execute(current_user, options) + def execute(current_user, options = {}) group = options[:group] if group @@ -56,8 +56,36 @@ class ProjectsFinder end end - def all_projects - # TODO: implement - raise 'Not implemented yet' + def all_projects(current_user) + if current_user + if current_user.authorized_projects.any? + # User has access to private projects + # + # Return only: + # public projects + # internal projects + # joined projects + # + Project.where( + "projects.id IN (?) OR projects.visibility_level IN (?)", + current_user.authorized_projects.pluck(:id), + Project.public_and_internal_levels + ) + else + # User has no access to private projects + # + # Return only: + # public projects + # internal projects + # + Project.public_and_internal_only + end + else + # Not authenticated + # + # Return only: + # public projects + Project.public_only + end end end diff --git a/app/helpers/search_helper.rb b/app/helpers/search_helper.rb index 01c3120569..a4471507da 100644 --- a/app/helpers/search_helper.rb +++ b/app/helpers/search_helper.rb @@ -81,7 +81,7 @@ module SearchHelper # Autocomplete results for the current user's projects def projects_autocomplete(term, limit = 5) - Project.accessible_to(current_user).search_by_title(term).non_archived.limit(limit).map do |p| + ProjectsFinder.new.execute(current_user).search_by_title(term).non_archived.limit(limit).map do |p| { label: "project: #{search_result_sanitize(p.name_with_namespace)}", url: project_path(p) diff --git a/app/helpers/submodule_helper.rb b/app/helpers/submodule_helper.rb old mode 100755 new mode 100644 diff --git a/app/models/ability.rb b/app/models/ability.rb index df9b210dfc..c60aa2d622 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -51,7 +51,7 @@ class Ability nil end - if group && group.has_projects_accessible_to?(nil) + if group && group.public_profile? [:read_group] else [] diff --git a/app/models/group.rb b/app/models/group.rb index 2e68779d36..e51e19ab60 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -27,12 +27,6 @@ class Group < Namespace mount_uploader :avatar, AttachmentUploader - def self.accessible_to(user) - accessible_ids = Project.accessible_to(user).pluck(:namespace_id) - accessible_ids += user.groups.pluck(:id) if user - where(id: accessible_ids) - end - def human_name name end @@ -77,4 +71,8 @@ class Group < Namespace self.errors.add :avatar, "only images allowed" end end + + def public_profile? + projects.public_only.any? + end end diff --git a/app/models/namespace.rb b/app/models/namespace.rb index 7973eef7e1..446e5f04c6 100644 --- a/app/models/namespace.rb +++ b/app/models/namespace.rb @@ -47,14 +47,6 @@ class Namespace < ActiveRecord::Base def self.global_id 'GLN' end - - def projects_accessible_to(user) - projects.accessible_to(user) - end - - def has_projects_accessible_to?(user) - projects_accessible_to(user).present? - end def to_param path diff --git a/app/models/project.rb b/app/models/project.rb index 758ef14703..f92cc40642 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -164,12 +164,6 @@ class Project < ActiveRecord::Base where(visibility_level: visibility_levels) end - def accessible_to(user) - accessible_ids = publicish(user).pluck(:id) - accessible_ids += user.authorized_projects.pluck(:id) if user - where(id: accessible_ids) - end - def with_push includes(:events).where('events.action = ?', Event::PUSHED) end diff --git a/app/services/search/global_service.rb b/app/services/search/global_service.rb index 8a1fce17ce..2121451118 100644 --- a/app/services/search/global_service.rb +++ b/app/services/search/global_service.rb @@ -12,7 +12,7 @@ module Search return result unless query.present? group = Group.find_by(id: params[:group_id]) if params[:group_id].present? - projects = Project.accessible_to(current_user) + projects = ProjectsFinder.new.execute(current_user) projects = projects.where(namespace_id: group.id) if group project_ids = projects.pluck(:id) From 2545b0f85851d1e4ebc1137a2c8786a238e02ee4 Mon Sep 17 00:00:00 2001 From: Jeroen van Baarsen Date: Thu, 5 Jun 2014 20:21:28 +0200 Subject: [PATCH 235/360] Revert "Fix for failing specs" This reverts commit 2314438925af827b694fbaaf59c31c49dd2c0c31. Signed-off-by: Jeroen van Baarsen Conflicts: Gemfile.lock --- Gemfile | 4 ++-- Gemfile.lock | 24 ++++++++++++------------ features/support/env.rb | 2 +- spec/support/db_cleaner.rb | 33 +++++++++++++++++---------------- 4 files changed, 32 insertions(+), 31 deletions(-) diff --git a/Gemfile b/Gemfile index 5b45b8bdcc..71855b5866 100644 --- a/Gemfile +++ b/Gemfile @@ -199,7 +199,7 @@ group :development, :test do # gem 'rails-dev-tweaks' gem 'spinach-rails' gem "rspec-rails" - gem "capybara", '~> 2.2.1' + gem "capybara" gem "pry" gem "awesome_print" gem "database_cleaner" @@ -222,7 +222,7 @@ group :development, :test do gem 'rb-inotify', require: linux_only('rb-inotify') # PhantomJS driver for Capybara - gem 'poltergeist', '~> 1.5.1' + gem 'poltergeist', '~> 1.4.1' gem 'jasmine', '2.0.2' diff --git a/Gemfile.lock b/Gemfile.lock index 5124863692..78561677e7 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -62,7 +62,7 @@ GEM celluloid (0.15.2) timers (~> 1.1.0) charlock_holmes (0.6.9.4) - cliver (0.3.2) + cliver (0.2.2) code_analyzer (0.4.3) sexp_processor coderay (1.1.0) @@ -283,9 +283,9 @@ GEM treetop (~> 1.4.8) method_source (0.8.2) mime-types (1.25.1) - mini_portile (0.6.0) - minitest (5.3.4) - multi_json (1.10.1) + mini_portile (0.5.3) + minitest (4.7.5) + multi_json (1.10.0) multi_xml (0.5.5) multipart-post (1.2.0) mysql2 (0.3.16) @@ -293,8 +293,8 @@ GEM net-scp (1.1.2) net-ssh (>= 2.6.5) net-ssh (2.8.0) - nokogiri (1.6.2.1) - mini_portile (= 0.6.0) + nokogiri (1.6.1) + mini_portile (~> 0.5.0) nprogress-rails (0.1.2.3) oauth (0.4.7) oauth2 (0.8.1) @@ -326,9 +326,9 @@ GEM orm_adapter (0.5.0) pg (0.15.1) phantomjs (1.9.2.0) - poltergeist (1.5.1) - capybara (~> 2.1) - cliver (~> 0.3.1) + poltergeist (1.4.1) + capybara (~> 2.1.0) + cliver (~> 0.2.1) multi_json (~> 1.0) websocket-driver (>= 0.2.0) polyglot (0.3.4) @@ -562,7 +562,7 @@ GEM webmock (1.16.0) addressable (>= 2.2.7) crack (>= 0.3.2) - websocket-driver (0.3.3) + websocket-driver (0.3.1) xpath (2.0.0) nokogiri (~> 1.3) @@ -578,7 +578,7 @@ DEPENDENCIES better_errors binding_of_caller bootstrap-sass (~> 3.0) - capybara (~> 2.2.1) + capybara carrierwave coffee-rails colored @@ -635,7 +635,7 @@ DEPENDENCIES omniauth-twitter org-ruby pg - poltergeist (~> 1.5.1) + poltergeist (~> 1.4.1) protected_attributes pry quiet_assets (~> 1.0.1) diff --git a/features/support/env.rb b/features/support/env.rb index 3ab2ce0a3e..a5b297775d 100644 --- a/features/support/env.rb +++ b/features/support/env.rb @@ -28,7 +28,7 @@ WebMock.allow_net_connect! require 'capybara/poltergeist' Capybara.javascript_driver = :poltergeist Capybara.register_driver :poltergeist do |app| - Capybara::Poltergeist::Driver.new(app, js_errors: false, timeout: 90) + Capybara::Poltergeist::Driver.new(app, :js_errors => false, :timeout => 60) end Spinach.hooks.on_tag("javascript") do ::Capybara.current_driver = ::Capybara.javascript_driver diff --git a/spec/support/db_cleaner.rb b/spec/support/db_cleaner.rb index f2b310245b..8c9c74f14b 100644 --- a/spec/support/db_cleaner.rb +++ b/spec/support/db_cleaner.rb @@ -1,21 +1,22 @@ +require 'database_cleaner' + RSpec.configure do |config| - config.around(:each) do - DatabaseCleaner.clean_with(:truncation) + config.before do + if example.metadata[:js] + DatabaseCleaner.strategy = :truncation + Capybara::Selenium::Driver::DEFAULT_OPTIONS[:resynchronize] = true + else + DatabaseCleaner.strategy = :transaction + end + + unless example.metadata[:no_db] + DatabaseCleaner.start + end end - config.around(:each) do - DatabaseCleaner.strategy = :transaction - end - - config.around(:each, js: true) do - DatabaseCleaner.strategy = :truncation - end - - config.before(:each) do - DatabaseCleaner.start - end - - config.after(:each) do - DatabaseCleaner.clean + config.after do + unless example.metadata[:no_db] + DatabaseCleaner.clean + end end end From 9bca8ae8f2feefe42acbdb61004ff5c3ec2a8a65 Mon Sep 17 00:00:00 2001 From: Jeroen van Baarsen Date: Thu, 5 Jun 2014 21:20:33 +0200 Subject: [PATCH 236/360] Gemfile fix Signed-off-by: Jeroen van Baarsen --- Gemfile.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 78561677e7..94cf38174e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -219,12 +219,12 @@ GEM lumberjack (~> 1.0) pry (>= 0.9.12) thor (>= 0.18.1) - guard-rspec (4.2.0) - guard (>= 2.1.1) - rspec (>= 2.14, < 4.0) guard-spinach (0.0.2) guard (>= 1.1) spinach + guard-spinachrspec (4.2.0) + guard (>= 2.1.1) + rspec (>= 2.14, < 4.0) haml (4.0.5) tilt haml-rails (0.5.3) @@ -283,9 +283,9 @@ GEM treetop (~> 1.4.8) method_source (0.8.2) mime-types (1.25.1) - mini_portile (0.5.3) - minitest (4.7.5) - multi_json (1.10.0) + mini_portile (0.6.0) + minitest (5.3.4) + multi_json (1.10.1) multi_xml (0.5.5) multipart-post (1.2.0) mysql2 (0.3.16) From dccfb374d396b1b7cbd86bde848165796618ef52 Mon Sep 17 00:00:00 2001 From: Nihad Abbasov Date: Fri, 6 Jun 2014 06:58:20 +0500 Subject: [PATCH 237/360] fix permissions for files API --- lib/api/files.rb | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/api/files.rb b/lib/api/files.rb index e0c46f92b8..e63e635a4d 100644 --- a/lib/api/files.rb +++ b/lib/api/files.rb @@ -2,7 +2,6 @@ module API # Projects API class Files < Grape::API before { authenticate! } - before { authorize! :push_code, user_project } resource :projects do # Get file from repository @@ -28,6 +27,8 @@ module API # } # get ":id/repository/files" do + authorize! :download_code, user_project + required_attributes! [:file_path, :ref] attrs = attributes_for_keys [:file_path, :ref] ref = attrs.delete(:ref) @@ -68,6 +69,8 @@ module API # POST /projects/:id/repository/files # post ":id/repository/files" do + authorize! :push_code, user_project + required_attributes! [:file_path, :branch_name, :content, :commit_message] attrs = attributes_for_keys [:file_path, :branch_name, :content, :commit_message, :encoding] branch_name = attrs.delete(:branch_name) @@ -98,6 +101,8 @@ module API # PUT /projects/:id/repository/files # put ":id/repository/files" do + authorize! :push_code, user_project + required_attributes! [:file_path, :branch_name, :content, :commit_message] attrs = attributes_for_keys [:file_path, :branch_name, :content, :commit_message, :encoding] branch_name = attrs.delete(:branch_name) @@ -128,6 +133,8 @@ module API # DELETE /projects/:id/repository/files # delete ":id/repository/files" do + authorize! :push_code, user_project + required_attributes! [:file_path, :branch_name, :commit_message] attrs = attributes_for_keys [:file_path, :branch_name, :commit_message] branch_name = attrs.delete(:branch_name) From 440036df69d147fcd4df10a85731199e6aa1d84b Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 6 Jun 2014 09:01:09 +0300 Subject: [PATCH 238/360] Revert "Gemfile fix" This reverts commit 9bca8ae8f2feefe42acbdb61004ff5c3ec2a8a65. --- Gemfile.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 94cf38174e..78561677e7 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -219,12 +219,12 @@ GEM lumberjack (~> 1.0) pry (>= 0.9.12) thor (>= 0.18.1) + guard-rspec (4.2.0) + guard (>= 2.1.1) + rspec (>= 2.14, < 4.0) guard-spinach (0.0.2) guard (>= 1.1) spinach - guard-spinachrspec (4.2.0) - guard (>= 2.1.1) - rspec (>= 2.14, < 4.0) haml (4.0.5) tilt haml-rails (0.5.3) @@ -283,9 +283,9 @@ GEM treetop (~> 1.4.8) method_source (0.8.2) mime-types (1.25.1) - mini_portile (0.6.0) - minitest (5.3.4) - multi_json (1.10.1) + mini_portile (0.5.3) + minitest (4.7.5) + multi_json (1.10.0) multi_xml (0.5.5) multipart-post (1.2.0) mysql2 (0.3.16) From 67ba36ebaca1a6346d443952ec06ac089a217de7 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 6 Jun 2014 09:01:17 +0300 Subject: [PATCH 239/360] Revert "Revert "Fix for failing specs"" This reverts commit 2545b0f85851d1e4ebc1137a2c8786a238e02ee4. --- Gemfile | 4 ++-- Gemfile.lock | 24 ++++++++++++------------ features/support/env.rb | 2 +- spec/support/db_cleaner.rb | 33 ++++++++++++++++----------------- 4 files changed, 31 insertions(+), 32 deletions(-) diff --git a/Gemfile b/Gemfile index 71855b5866..5b45b8bdcc 100644 --- a/Gemfile +++ b/Gemfile @@ -199,7 +199,7 @@ group :development, :test do # gem 'rails-dev-tweaks' gem 'spinach-rails' gem "rspec-rails" - gem "capybara" + gem "capybara", '~> 2.2.1' gem "pry" gem "awesome_print" gem "database_cleaner" @@ -222,7 +222,7 @@ group :development, :test do gem 'rb-inotify', require: linux_only('rb-inotify') # PhantomJS driver for Capybara - gem 'poltergeist', '~> 1.4.1' + gem 'poltergeist', '~> 1.5.1' gem 'jasmine', '2.0.2' diff --git a/Gemfile.lock b/Gemfile.lock index 78561677e7..5124863692 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -62,7 +62,7 @@ GEM celluloid (0.15.2) timers (~> 1.1.0) charlock_holmes (0.6.9.4) - cliver (0.2.2) + cliver (0.3.2) code_analyzer (0.4.3) sexp_processor coderay (1.1.0) @@ -283,9 +283,9 @@ GEM treetop (~> 1.4.8) method_source (0.8.2) mime-types (1.25.1) - mini_portile (0.5.3) - minitest (4.7.5) - multi_json (1.10.0) + mini_portile (0.6.0) + minitest (5.3.4) + multi_json (1.10.1) multi_xml (0.5.5) multipart-post (1.2.0) mysql2 (0.3.16) @@ -293,8 +293,8 @@ GEM net-scp (1.1.2) net-ssh (>= 2.6.5) net-ssh (2.8.0) - nokogiri (1.6.1) - mini_portile (~> 0.5.0) + nokogiri (1.6.2.1) + mini_portile (= 0.6.0) nprogress-rails (0.1.2.3) oauth (0.4.7) oauth2 (0.8.1) @@ -326,9 +326,9 @@ GEM orm_adapter (0.5.0) pg (0.15.1) phantomjs (1.9.2.0) - poltergeist (1.4.1) - capybara (~> 2.1.0) - cliver (~> 0.2.1) + poltergeist (1.5.1) + capybara (~> 2.1) + cliver (~> 0.3.1) multi_json (~> 1.0) websocket-driver (>= 0.2.0) polyglot (0.3.4) @@ -562,7 +562,7 @@ GEM webmock (1.16.0) addressable (>= 2.2.7) crack (>= 0.3.2) - websocket-driver (0.3.1) + websocket-driver (0.3.3) xpath (2.0.0) nokogiri (~> 1.3) @@ -578,7 +578,7 @@ DEPENDENCIES better_errors binding_of_caller bootstrap-sass (~> 3.0) - capybara + capybara (~> 2.2.1) carrierwave coffee-rails colored @@ -635,7 +635,7 @@ DEPENDENCIES omniauth-twitter org-ruby pg - poltergeist (~> 1.4.1) + poltergeist (~> 1.5.1) protected_attributes pry quiet_assets (~> 1.0.1) diff --git a/features/support/env.rb b/features/support/env.rb index a5b297775d..3ab2ce0a3e 100644 --- a/features/support/env.rb +++ b/features/support/env.rb @@ -28,7 +28,7 @@ WebMock.allow_net_connect! require 'capybara/poltergeist' Capybara.javascript_driver = :poltergeist Capybara.register_driver :poltergeist do |app| - Capybara::Poltergeist::Driver.new(app, :js_errors => false, :timeout => 60) + Capybara::Poltergeist::Driver.new(app, js_errors: false, timeout: 90) end Spinach.hooks.on_tag("javascript") do ::Capybara.current_driver = ::Capybara.javascript_driver diff --git a/spec/support/db_cleaner.rb b/spec/support/db_cleaner.rb index 8c9c74f14b..f2b310245b 100644 --- a/spec/support/db_cleaner.rb +++ b/spec/support/db_cleaner.rb @@ -1,22 +1,21 @@ -require 'database_cleaner' - RSpec.configure do |config| - config.before do - if example.metadata[:js] - DatabaseCleaner.strategy = :truncation - Capybara::Selenium::Driver::DEFAULT_OPTIONS[:resynchronize] = true - else - DatabaseCleaner.strategy = :transaction - end - - unless example.metadata[:no_db] - DatabaseCleaner.start - end + config.around(:each) do + DatabaseCleaner.clean_with(:truncation) end - config.after do - unless example.metadata[:no_db] - DatabaseCleaner.clean - end + config.around(:each) do + DatabaseCleaner.strategy = :transaction + end + + config.around(:each, js: true) do + DatabaseCleaner.strategy = :truncation + end + + config.before(:each) do + DatabaseCleaner.start + end + + config.after(:each) do + DatabaseCleaner.clean end end From 0faf80aa9d2a32d872a21f125862d46157013082 Mon Sep 17 00:00:00 2001 From: Jeroen van Baarsen Date: Fri, 6 Jun 2014 08:25:02 +0200 Subject: [PATCH 240/360] Temp fix for rspec so the specs are run again Signed-off-by: Jeroen van Baarsen --- spec/support/db_cleaner.rb | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/spec/support/db_cleaner.rb b/spec/support/db_cleaner.rb index f2b310245b..fa466ef5ae 100644 --- a/spec/support/db_cleaner.rb +++ b/spec/support/db_cleaner.rb @@ -1,21 +1,18 @@ RSpec.configure do |config| - config.around(:each) do - DatabaseCleaner.clean_with(:truncation) - end - config.around(:each) do + config.around(:each) do |example| DatabaseCleaner.strategy = :transaction + DatabaseCleaner.clean_with(:truncation) + DatabaseCleaner.cleaning do + example.run + end end - config.around(:each, js: true) do + config.around(:each, js: true) do |example| DatabaseCleaner.strategy = :truncation - end - - config.before(:each) do - DatabaseCleaner.start - end - - config.after(:each) do - DatabaseCleaner.clean + DatabaseCleaner.clean_with(:truncation) + DatabaseCleaner.cleaning do + example.run + end end end From 1a87fb754ed047e5966789f80e8eeedf7bc22473 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Fri, 6 Jun 2014 09:36:19 +0200 Subject: [PATCH 241/360] Protect stable branches --- doc/release/monthly.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/release/monthly.md b/doc/release/monthly.md index 4519ae12e2..446dbc6e6a 100644 --- a/doc/release/monthly.md +++ b/doc/release/monthly.md @@ -186,6 +186,8 @@ For GitLab CE, push to dev, GitLab.com and GitHub. For GitLab EE, push to the subscribers repo. +Make sure the branch is marked 'protected' on each of the remotes you pushed to. + NOTE: You might not have the rights to push to master on dev. Ask Dmitriy. ### **7. Publish blog for new release** From bd65f486d907b00f588bdfe7c7c241782fb491fd Mon Sep 17 00:00:00 2001 From: Jeroen van Baarsen Date: Fri, 6 Jun 2014 18:58:38 +0200 Subject: [PATCH 242/360] Gem update for database_cleaner Signed-off-by: Jeroen van Baarsen --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 5124863692..0d13ed5884 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -89,7 +89,7 @@ GEM d3_rails (3.1.10) railties (>= 3.1.0) daemons (1.1.9) - database_cleaner (1.2.0) + database_cleaner (1.3.0) debug_inspector (0.0.2) default_value_for (3.0.0) activerecord (>= 3.2.0, < 5.0) From 838bbb55e55c1ea41b16ffd0e31f617747ad0ce4 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 6 Jun 2014 20:41:42 +0300 Subject: [PATCH 243/360] Use bootstrap default padding for nav-tabs Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/gl_bootstrap.scss | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/assets/stylesheets/gl_bootstrap.scss b/app/assets/stylesheets/gl_bootstrap.scss index 8ab305695f..6c244afa50 100644 --- a/app/assets/stylesheets/gl_bootstrap.scss +++ b/app/assets/stylesheets/gl_bootstrap.scss @@ -114,8 +114,7 @@ $list-group-active-bg: $bg_style_color; li { > a { - padding: 8px 20px; - margin-right: 7px; + margin-right: 5px; line-height: 20px; border-color: #EEE; color: #888; From 7cf1a4259ac123725f2eb0ab6fc682e739d45734 Mon Sep 17 00:00:00 2001 From: Jeroen van Baarsen Date: Fri, 6 Jun 2014 19:55:49 +0200 Subject: [PATCH 244/360] Disable fixtures Signed-off-by: Jeroen van Baarsen --- spec/spec_helper.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index e6b1f816df..65a641bcf1 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -27,6 +27,8 @@ Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f} WebMock.disable_net_connect!(allow_localhost: true) RSpec.configure do |config| + config.use_transactional_fixtures = false + config.use_instantiated_fixtures = false config.mock_with :rspec config.include LoginHelpers, type: :feature @@ -39,7 +41,6 @@ RSpec.configure do |config| # If you're not using ActiveRecord, or you'd prefer not to run each of your # examples within a transaction, remove the following line or assign false # instead of true. - config.use_transactional_fixtures = false config.before(:suite) do TestEnv.init(observers: false, init_repos: true, repos: false) From 34d9f34a61bc20f1dec9e6ad504e08835716bd66 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 6 Jun 2014 21:39:30 +0300 Subject: [PATCH 245/360] Improve select2 css to match bootstrap style Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/generic/selects.scss | 15 +++++++++++++++ app/assets/stylesheets/sections/tree.scss | 14 +++++++++++++- app/views/projects/issues/_form.html.haml | 2 +- app/views/projects/merge_requests/_form.html.haml | 2 +- app/views/projects/tree/_tree.html.haml | 1 - app/views/projects/tree/show.html.haml | 9 ++++++--- 6 files changed, 36 insertions(+), 7 deletions(-) diff --git a/app/assets/stylesheets/generic/selects.scss b/app/assets/stylesheets/generic/selects.scss index 03597c1fc7..681f38716f 100644 --- a/app/assets/stylesheets/generic/selects.scss +++ b/app/assets/stylesheets/generic/selects.scss @@ -3,6 +3,10 @@ .select2-choice { background: #FFF; border-color: #BBB; + padding: 6px 12px; + font-size: 13px; + line-height: 18px; + height: auto; .select2-arrow { background: #FFF; @@ -10,6 +14,17 @@ } } +.select2-container-multi .select2-choices { + @include border-radius(4px) +} + +.select2-container-multi .select2-choices .select2-search-field input { + padding: 6px 12px; + font-size: 13px; + line-height: 18px; + height: auto; +} + .select2-drop-active { border: 1px solid #BBB !important; margin-top: 4px; diff --git a/app/assets/stylesheets/sections/tree.scss b/app/assets/stylesheets/sections/tree.scss index b0ce78ddb3..c019b62672 100644 --- a/app/assets/stylesheets/sections/tree.scss +++ b/app/assets/stylesheets/sections/tree.scss @@ -4,6 +4,10 @@ width: 100%; } + .breadcrumb { + padding: 2px 0; + } + .tree_progress { display: none; margin: 20px; @@ -122,9 +126,17 @@ } } +.tree-download-holder .btn { + padding: 4px 12px; +} + .tree-ref-holder { float: left; - margin-top: 8px; + margin-right: 6px; + + .select2-container .select2-choice, .select2-container.select2-drop-above .select2-choice { + padding: 4px 12px; + } } .readme-holder { diff --git a/app/views/projects/issues/_form.html.haml b/app/views/projects/issues/_form.html.haml index 73cbb79665..d29a797310 100644 --- a/app/views/projects/issues/_form.html.haml +++ b/app/views/projects/issues/_form.html.haml @@ -35,7 +35,7 @@ .col-sm-10 = project_users_select_tag('issue[assignee_id]', placeholder: 'Select a user', class: 'custom-form-control', selected: @issue.assignee_id)   - = link_to 'Assign to me', '#', class: 'btn btn-small assign-to-me-link' + = link_to 'Assign to me', '#', class: 'btn assign-to-me-link' .form-group .issue-milestone = f.label :milestone_id, class: 'control-label' do diff --git a/app/views/projects/merge_requests/_form.html.haml b/app/views/projects/merge_requests/_form.html.haml index b0e7aa6084..9ef232b526 100644 --- a/app/views/projects/merge_requests/_form.html.haml +++ b/app/views/projects/merge_requests/_form.html.haml @@ -37,7 +37,7 @@ .col-sm-10 = project_users_select_tag('merge_request[assignee_id]', placeholder: 'Select a user', class: 'custom-form-control', selected: @merge_request.assignee_id)   - = link_to 'Assign to me', '#', class: 'btn btn-small assign-to-me-link' + = link_to 'Assign to me', '#', class: 'btn assign-to-me-link' .form-group .issue-milestone = f.label :milestone_id, class: 'control-label' do diff --git a/app/views/projects/tree/_tree.html.haml b/app/views/projects/tree/_tree.html.haml index 49c9edffc6..f049aa58e0 100644 --- a/app/views/projects/tree/_tree.html.haml +++ b/app/views/projects/tree/_tree.html.haml @@ -1,6 +1,5 @@ %ul.breadcrumb %li - %i.icon-angle-right = link_to project_tree_path(@project, @ref) do = @project.path - tree_breadcrumbs(tree, 6) do |title, path| diff --git a/app/views/projects/tree/show.html.haml b/app/views/projects/tree/show.html.haml index 735ffae9e2..1ef3020f35 100644 --- a/app/views/projects/tree/show.html.haml +++ b/app/views/projects/tree/show.html.haml @@ -1,6 +1,9 @@ -%div.tree-ref-holder +.tree-ref-holder = render 'shared/ref_switcher', destination: 'tree', path: @path + - if can? current_user, :download_code, @project - = render 'projects/repositories/download_archive', ref: @ref, btn_class: 'btn-group-small pull-right', split_button: true -%div#tree-holder.tree-holder + .tree-download-holder + = render 'projects/repositories/download_archive', ref: @ref, btn_class: 'btn-group-small pull-right hidden-xs', split_button: true + +#tree-holder.tree-holder.clearfix = render "tree", tree: @tree From d325a279fb65b2c91f12e45aa20d61949919b95a Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 6 Jun 2014 22:01:34 +0300 Subject: [PATCH 246/360] Small UI improvements Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/generic/selects.scss | 1 + app/assets/stylesheets/sections/header.scss | 1 + app/views/projects/_home_panel.html.haml | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/app/assets/stylesheets/generic/selects.scss b/app/assets/stylesheets/generic/selects.scss index 681f38716f..0afd85aedf 100644 --- a/app/assets/stylesheets/generic/selects.scss +++ b/app/assets/stylesheets/generic/selects.scss @@ -10,6 +10,7 @@ .select2-arrow { background: #FFF; + border-left: 1px solid #DDD; } } } diff --git a/app/assets/stylesheets/sections/header.scss b/app/assets/stylesheets/sections/header.scss index 1adbdfd979..b811b0bc66 100644 --- a/app/assets/stylesheets/sections/header.scss +++ b/app/assets/stylesheets/sections/header.scss @@ -137,6 +137,7 @@ header { .profile-pic { position: relative; top: -1px; + padding-right: 0px !important; img { width: 26px; height: 26px; diff --git a/app/views/projects/_home_panel.html.haml b/app/views/projects/_home_panel.html.haml index 82ec68c916..b24fd5a851 100644 --- a/app/views/projects/_home_panel.html.haml +++ b/app/views/projects/_home_panel.html.haml @@ -8,7 +8,7 @@ = @project.name_with_namespace .col-sm-6 - - unless empty_repo + - if current_user && !empty_repo .project-home-dropdown = render "dropdown" = render "shared/clone_panel" From 71d074a674c07d9eed3572e071ef2d53479be5de Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 6 Jun 2014 22:06:04 +0300 Subject: [PATCH 247/360] Use same color for icon, arrow and project title on dash sidebar Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/sections/dashboard.scss | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/assets/stylesheets/sections/dashboard.scss b/app/assets/stylesheets/sections/dashboard.scss index abc9e57f2a..6487e0acd9 100644 --- a/app/assets/stylesheets/sections/dashboard.scss +++ b/app/assets/stylesheets/sections/dashboard.scss @@ -76,7 +76,6 @@ float: right; margin: 0; font-size: 20px; - color: #666; } .last-activity { @@ -110,6 +109,5 @@ .dash-project-access-icon { float: left; margin-right: 3px; - color: #999; width: 16px; } From dd03841fea7aa2d71130c7167b61d3c959ddaf19 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 6 Jun 2014 22:09:52 +0300 Subject: [PATCH 248/360] Make visibility icon more noticable Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/sections/projects.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/stylesheets/sections/projects.scss b/app/assets/stylesheets/sections/projects.scss index 35279bff6a..9fbed704ba 100644 --- a/app/assets/stylesheets/sections/projects.scss +++ b/app/assets/stylesheets/sections/projects.scss @@ -57,7 +57,7 @@ font-size: 17px; background: #f1f1f1; border-radius: 4px; - color: #888; + color: #444; position: absolute; margin-left: -55px; text-shadow: 0 1px 1px #FFF; From 910a99f90b27b0b6de0140ce89f356b746d43113 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 6 Jun 2014 22:21:07 +0300 Subject: [PATCH 249/360] Improve tree view for mobile Signed-off-by: Dmitriy Zaporozhets --- app/views/projects/tree/_blob_item.html.haml | 2 +- app/views/projects/tree/_submodule_item.html.haml | 3 +-- app/views/projects/tree/_tree.html.haml | 7 +++---- app/views/projects/tree/_tree_item.html.haml | 2 +- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/app/views/projects/tree/_blob_item.html.haml b/app/views/projects/tree/_blob_item.html.haml index 6fee604b55..0971a42652 100644 --- a/app/views/projects/tree/_blob_item.html.haml +++ b/app/views/projects/tree/_blob_item.html.haml @@ -5,4 +5,4 @@ = link_to blob_item.name, project_blob_path(@project, tree_join(@id || @commit.id, blob_item.name)) %td.tree_time_ago.cgray = render 'spinner' - %td.tree_commit{ colspan: 2 } + %td.hidden-xs.tree_commit{ colspan: 2 } diff --git a/app/views/projects/tree/_submodule_item.html.haml b/app/views/projects/tree/_submodule_item.html.haml index 3e2655cc4f..474604df65 100644 --- a/app/views/projects/tree/_submodule_item.html.haml +++ b/app/views/projects/tree/_submodule_item.html.haml @@ -11,5 +11,4 @@ - else = link_to "#{submodule_item.id[0..10]}", commit %td - %td - %td + %td.hidden-xs diff --git a/app/views/projects/tree/_tree.html.haml b/app/views/projects/tree/_tree.html.haml index f049aa58e0..dbb74a1caf 100644 --- a/app/views/projects/tree/_tree.html.haml +++ b/app/views/projects/tree/_tree.html.haml @@ -20,7 +20,7 @@ %tr %th Name %th Last Update - %th.hidden-sm + %th.hidden-sm.hidden-xs Last Commit %span.last-commit   @@ -30,15 +30,14 @@ = link_to @commit.short_id, project_commit_path(@project, @commit) – = truncate(@commit.title, length: 50) - %th= link_to "history", project_commits_path(@project, @id), class: "pull-right" + = link_to "history", project_commits_path(@project, @id), class: "pull-right" - if @path.present? %tr.tree-item %td.tree-item-file-name = link_to "..", project_tree_path(@project, up_dir_path(tree)), class: 'prepend-left-10' %td - %td - %td + %td.hidden-xs = render_tree(tree) diff --git a/app/views/projects/tree/_tree_item.html.haml b/app/views/projects/tree/_tree_item.html.haml index 1b3900bcba..760e95e84f 100644 --- a/app/views/projects/tree/_tree_item.html.haml +++ b/app/views/projects/tree/_tree_item.html.haml @@ -5,4 +5,4 @@ = link_to tree_item.name, project_tree_path(@project, tree_join(@id || @commit.id, tree_item.name)) %td.tree_time_ago.cgray = render 'spinner' - %td.tree_commit{ colspan: 2 } + %td.hidden-xs.tree_commit{ colspan: 2 } From bc6a17a6828f2695a7ad0f64671ac1b6845c111d Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 6 Jun 2014 22:33:52 +0300 Subject: [PATCH 250/360] Smaller event width for mobile devices Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/sections/events.scss | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/assets/stylesheets/sections/events.scss b/app/assets/stylesheets/sections/events.scss index 05361976ef..957af62c0e 100644 --- a/app/assets/stylesheets/sections/events.scss +++ b/app/assets/stylesheets/sections/events.scss @@ -183,3 +183,9 @@ line-height: 24px; } } + +@media (max-width: $screen-xs-max) { + .event-item .event-title { + @include str-truncated(65%); + } +} From 2aef3b00cf2ee06dc4128a1a54483cccc1fd48f9 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 6 Jun 2014 23:15:54 +0300 Subject: [PATCH 251/360] Refactor link to new diff note rendering Signed-off-by: Dmitriy Zaporozhets --- app/helpers/notes_helper.rb | 19 +++++++++++++++++++ app/models/note.rb | 14 +++++++++----- .../projects/commits/_text_file.html.haml | 2 +- 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/app/helpers/notes_helper.rb b/app/helpers/notes_helper.rb index 7ae104b8fd..9ed38ba84b 100644 --- a/app/helpers/notes_helper.rb +++ b/app/helpers/notes_helper.rb @@ -42,4 +42,23 @@ module NotesHelper project_id: noteable.project.id, }.to_json end + + def link_to_new_diff_note(line_code) + discussion_id = Note.build_discussion_id( + @comments_target[:noteable_type], + @comments_target[:noteable_id] || @comments_target[:commit_id], + line_code + ) + + data = { + noteable_type: @comments_target[:noteable_type], + noteable_id: @comments_target[:noteable_id], + commit_id: @comments_target[:commit_id], + line_code: line_code, + discussion_id: discussion_id + } + + link_to "", "javascript:;", class: "add-diff-note js-add-diff-note-button", + data: data, title: "Add a comment to this line" + end end diff --git a/app/models/note.rb b/app/models/note.rb index cee10ec90d..278c957af0 100644 --- a/app/models/note.rb +++ b/app/models/note.rb @@ -122,11 +122,15 @@ class Note < ActiveRecord::Base discussions end - end - # Determine whether or not a cross-reference note already exists. - def self.cross_reference_exists?(noteable, mentioner) - where(noteable_id: noteable.id, system: true, note: "_mentioned in #{mentioner.gfm_reference}_").any? + def build_discussion_id(type, id, line_code) + [:discussion, type.try(:underscore), id, line_code].join("-").to_sym + end + + # Determine whether or not a cross-reference note already exists. + def cross_reference_exists?(noteable, mentioner) + where(noteable_id: noteable.id, system: true, note: "_mentioned in #{mentioner.gfm_reference}_").any? + end end def commit_author @@ -194,7 +198,7 @@ class Note < ActiveRecord::Base end def discussion_id - @discussion_id ||= [:discussion, noteable_type.try(:underscore), noteable_id || commit_id, line_code].join("-").to_sym + @discussion_id ||= Note.build_discussion_id(noteable_type, noteable_id || commit_id, line_code) end # Returns true if this is a downvote note, diff --git a/app/views/projects/commits/_text_file.html.haml b/app/views/projects/commits/_text_file.html.haml index ba83d2e5a0..74a68b1bf8 100644 --- a/app/views/projects/commits/_text_file.html.haml +++ b/app/views/projects/commits/_text_file.html.haml @@ -13,7 +13,7 @@ %td.old_line = link_to raw(type == "new" ? " " : line_old), "##{line_code}", id: line_code - if @comments_allowed - = render "projects/notes/diff_note_link", line_code: line_code + = link_to_new_diff_note(line_code) %td.new_line= link_to raw(type == "old" ? " " : line_new) , "##{line_code}", id: line_code %td.line_content{class: "noteable_line #{type} #{line_code}", "line_code" => line_code}= raw diff_line_content(line) From 2838a993da78bf365d7a84dc51f57a605fc99c96 Mon Sep 17 00:00:00 2001 From: Jeroen van Baarsen Date: Sat, 7 Jun 2014 10:09:56 +0200 Subject: [PATCH 252/360] DB cleaner reverted to a known working version Signed-off-by: Jeroen van Baarsen --- spec/support/db_cleaner.rb | 43 ++++++++++++++++++++++++++++---------- 1 file changed, 32 insertions(+), 11 deletions(-) diff --git a/spec/support/db_cleaner.rb b/spec/support/db_cleaner.rb index fa466ef5ae..d2d532d973 100644 --- a/spec/support/db_cleaner.rb +++ b/spec/support/db_cleaner.rb @@ -1,18 +1,39 @@ -RSpec.configure do |config| +# RSpec.configure do |config| - config.around(:each) do |example| - DatabaseCleaner.strategy = :transaction +# config.around(:each) do |example| +# DatabaseCleaner.strategy = :transaction +# DatabaseCleaner.clean_with(:truncation) +# DatabaseCleaner.cleaning do +# example.run +# end +# end + +# config.around(:each, js: true) do |example| +# DatabaseCleaner.strategy = :truncation +# DatabaseCleaner.clean_with(:truncation) +# DatabaseCleaner.cleaning do +# example.run +# end +# end +# end +RSpec.configure do |config| + config.before(:suite) do DatabaseCleaner.clean_with(:truncation) - DatabaseCleaner.cleaning do - example.run - end end - config.around(:each, js: true) do |example| + config.before(:each) do + DatabaseCleaner.strategy = :transaction + end + + config.before(:each, :js => true) do DatabaseCleaner.strategy = :truncation - DatabaseCleaner.clean_with(:truncation) - DatabaseCleaner.cleaning do - example.run - end + end + + config.before(:each) do + DatabaseCleaner.start + end + + config.after(:each) do + DatabaseCleaner.clean end end From 3dc0bce9474ac52046f5c3efb2532af6334a7aae Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sat, 7 Jun 2014 15:06:55 +0300 Subject: [PATCH 253/360] Add users to /:id route So now when you type site/:username it redirects you to users page. And if you type site/:groupname it redirects you to group page Signed-off-by: Dmitriy Zaporozhets --- app/controllers/namespaces_controller.rb | 18 ++++++++++++++++++ config/routes.rb | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 app/controllers/namespaces_controller.rb diff --git a/app/controllers/namespaces_controller.rb b/app/controllers/namespaces_controller.rb new file mode 100644 index 0000000000..c59a2401ce --- /dev/null +++ b/app/controllers/namespaces_controller.rb @@ -0,0 +1,18 @@ +class NamespacesController < ApplicationController + skip_before_filter :authenticate_user! + + def show + namespace = Namespace.find_by(path: params[:id]) + + unless namespace + return render_404 + end + + if namespace.type == "Group" + redirect_to group_path(namespace) + else + redirect_to user_path(namespace.owner) + end + end +end + diff --git a/config/routes.rb b/config/routes.rb index 7c2ab6bd1d..67ff66757e 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -315,7 +315,7 @@ Gitlab::Application.routes.draw do end end - get ':id' => "groups#show", constraints: {id: /(?:[^.]|\.(?!atom$))+/, format: /atom/} + get ':id' => "namespaces#show", constraints: {id: /(?:[^.]|\.(?!atom$))+/, format: /atom/} root to: "dashboard#show" end From 98d697a1a6adf2e69831dafb05fc36fdd4b797b6 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sat, 7 Jun 2014 15:18:01 +0300 Subject: [PATCH 254/360] Show small notice at profile page about publicity Signed-off-by: Dmitriy Zaporozhets --- app/views/profiles/show.html.haml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/views/profiles/show.html.haml b/app/views/profiles/show.html.haml index 69598e799e..9a4c13af97 100644 --- a/app/views/profiles/show.html.haml +++ b/app/views/profiles/show.html.haml @@ -86,5 +86,11 @@ %hr = link_to 'Remove avatar', profile_avatar_path, data: { confirm: "Avatar will be removed. Are you sure?"}, method: :delete, class: "btn btn-remove btn-small remove-avatar" + - if @user.public_profile? + .bs-callout.bs-callout-info + %h4 Public profile + %p Your profile is publicly visible because you joined public project(s) + + .form-actions = f.submit 'Save changes', class: "btn btn-save" From 0d13abb1c8d527f2a6e6b97e34899e9b35f264bc Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sat, 7 Jun 2014 15:46:58 +0300 Subject: [PATCH 255/360] Specify language detection for highlight.js Because I am tired of CHANGELOG highlighted as sql file :) Signed-off-by: Dmitriy Zaporozhets --- app/helpers/blob_helper.rb | 18 ++++++++++++++++++ app/views/shared/_file_hljs.html.haml | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 app/helpers/blob_helper.rb diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb new file mode 100644 index 0000000000..11fbf1baae --- /dev/null +++ b/app/helpers/blob_helper.rb @@ -0,0 +1,18 @@ +module BlobHelper + def highlightjs_class(blob_name) + if blob_name.include?('.') + ext = blob_name.split('.').last + return 'language-' + ext + else + if no_highlight_files.include?(blob_name.downcase) + 'no-highlight' + else + blob_name.downcase + end + end + end + + def no_highlight_files + %w(credits changelog copying copyright license authors) + end +end diff --git a/app/views/shared/_file_hljs.html.haml b/app/views/shared/_file_hljs.html.haml index 338236c075..ceee2c7527 100644 --- a/app/views/shared/_file_hljs.html.haml +++ b/app/views/shared/_file_hljs.html.haml @@ -8,5 +8,5 @@ = i .highlight %pre - %code + %code{ class: highlightjs_class(blob.name) } = blob.data From 4dcf2f1c2dca266743f66056a382afe0002a7d3e Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sat, 7 Jun 2014 15:55:31 +0300 Subject: [PATCH 256/360] New entries to CHANGELOG Signed-off-by: Dmitriy Zaporozhets --- CHANGELOG | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index efb11a70cf..ce394e1f1a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -20,6 +20,12 @@ v 7.0.0 - Improve performance of application for projects and groups with a lot of members - Formally support Ruby 2.1 - Include Nginx gitlab-ssl config + - Add manual language detection foir highlight.js + - Added example.com/:username routing + - Show notice if your profile is public + - UI improvements for mobile devices + - Improve diff rendering performance + - Drag-n-drop for issues and merge requests between states at milestone page v 6.9.2 - Revert the commit that broke the LDAP user filter From 95b786ff79e4fd2320f4776e87dc498088d00cf6 Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Sat, 7 Jun 2014 16:39:48 +0000 Subject: [PATCH 257/360] Fix typo --- CHANGELOG | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index ce394e1f1a..900c7a1103 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -20,7 +20,7 @@ v 7.0.0 - Improve performance of application for projects and groups with a lot of members - Formally support Ruby 2.1 - Include Nginx gitlab-ssl config - - Add manual language detection foir highlight.js + - Add manual language detection for highlight.js - Added example.com/:username routing - Show notice if your profile is public - UI improvements for mobile devices @@ -790,4 +790,4 @@ v 0.8.0 - stability - security fixes - increased test coverage - - email notification + - email notification \ No newline at end of file From 597836d6ccc52588d90780313ccc4eef730e16df Mon Sep 17 00:00:00 2001 From: Jeroen van Baarsen Date: Sun, 8 Jun 2014 23:27:57 +0200 Subject: [PATCH 258/360] Fixed some broken specs Signed-off-by: Jeroen van Baarsen --- spec/helpers/notifications_helper_spec.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/spec/helpers/notifications_helper_spec.rb b/spec/helpers/notifications_helper_spec.rb index dce28525ca..3ecabbaf04 100644 --- a/spec/helpers/notifications_helper_spec.rb +++ b/spec/helpers/notifications_helper_spec.rb @@ -8,7 +8,7 @@ describe NotificationsHelper do before { notification.stub(disabled?: true) } it "has a red icon" do - notification_icon(notification).should match('class="icon-volume-off cred"') + notification_icon(notification).should match('class="icon-volume-off ns-mute"') end end @@ -16,7 +16,7 @@ describe NotificationsHelper do before { notification.stub(participating?: true) } it "has a blue icon" do - notification_icon(notification).should match('class="icon-volume-down cblue"') + notification_icon(notification).should match('class="icon-volume-down ns-part"') end end @@ -24,12 +24,12 @@ describe NotificationsHelper do before { notification.stub(watch?: true) } it "has a green icon" do - notification_icon(notification).should match('class="icon-volume-up cgreen"') + notification_icon(notification).should match('class="icon-volume-up ns-watch"') end end it "has a blue icon" do - notification_icon(notification).should match('class="icon-circle-blank cblue"') + notification_icon(notification).should match('class="icon-circle-blank ns-default"') end end end From a705d194facc24be0e265f95ed6d03d533547d7a Mon Sep 17 00:00:00 2001 From: Jeroen van Baarsen Date: Sun, 8 Jun 2014 23:36:09 +0200 Subject: [PATCH 259/360] Fixed the project team specs Signed-off-by: Jeroen van Baarsen --- spec/models/project_team_spec.rb | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/spec/models/project_team_spec.rb b/spec/models/project_team_spec.rb index 1a7e3cd94b..1cc37719e7 100644 --- a/spec/models/project_team_spec.rb +++ b/spec/models/project_team_spec.rb @@ -20,17 +20,17 @@ describe ProjectTeam do end describe 'members collection' do - it { team.masters.should include(master) } - it { team.masters.should include(guest) } - it { team.masters.should_not include(reporter) } - it { team.masters.should_not include(nonmember) } + it { project.team.masters.should include(master) } + it { project.team.masters.should include(guest) } + it { project.team.masters.should_not include(reporter) } + it { project.team.masters.should_not include(nonmember) } end describe 'access methods' do - it { team.master?(master).should be_true } - it { team.master?(guest).should be_true } - it { team.master?(reporter).should be_false } - it { team.master?(nonmember).should be_false } + it { project.team.master?(master).should be_true } + it { project.team.master?(guest).should be_true } + it { project.team.master?(reporter).should be_false } + it { project.team.master?(nonmember).should be_false } end end From f07f524badf39c197dbcb18e74935fc5957803a3 Mon Sep 17 00:00:00 2001 From: Jeroen van Baarsen Date: Sun, 8 Jun 2014 23:40:37 +0200 Subject: [PATCH 260/360] Fix for the broken routing specs Signed-off-by: Jeroen van Baarsen --- spec/routing/routing_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/routing/routing_spec.rb b/spec/routing/routing_spec.rb index 7bfd5d0b99..1e92cf62dd 100644 --- a/spec/routing/routing_spec.rb +++ b/spec/routing/routing_spec.rb @@ -245,7 +245,7 @@ describe "Groups", "routing" do end it "also display group#show on the short path" do - get("/1").should route_to('groups#show', id: '1') + get('/1').should route_to('namespaces#show', id: '1') end end From 6384344f156ccec0de746be68b168a745bdf73ae Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Tue, 10 Jun 2014 10:00:12 +0200 Subject: [PATCH 261/360] Add gitlab shell version file. --- GITLAB_SHELL_VERSION | 1 + 1 file changed, 1 insertion(+) create mode 100644 GITLAB_SHELL_VERSION diff --git a/GITLAB_SHELL_VERSION b/GITLAB_SHELL_VERSION new file mode 100644 index 0000000000..158c747293 --- /dev/null +++ b/GITLAB_SHELL_VERSION @@ -0,0 +1 @@ +1.9.5 From 3affaa9b984eb07564bdec3521ae44d639e5e011 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Tue, 10 Jun 2014 10:40:28 +0200 Subject: [PATCH 262/360] Add python-docutils to dependency list. --- doc/install/installation.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/doc/install/installation.md b/doc/install/installation.md index 7840cef890..123487f786 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -49,7 +49,7 @@ up-to-date and install it. Install the required packages (needed to compile Ruby and native extensions to Ruby gems): - sudo apt-get install -y build-essential zlib1g-dev libyaml-dev libssl-dev libgdbm-dev libreadline-dev libncurses5-dev libffi-dev curl openssh-server redis-server checkinstall libxml2-dev libxslt-dev libcurl4-openssl-dev libicu-dev logrotate + sudo apt-get install -y build-essential zlib1g-dev libyaml-dev libssl-dev libgdbm-dev libreadline-dev libncurses5-dev libffi-dev curl openssh-server redis-server checkinstall libxml2-dev libxslt-dev libcurl4-openssl-dev libicu-dev logrotate python-docutils Make sure you have the right version of Git installed @@ -336,9 +336,7 @@ Visit YOUR_SERVER in your web browser for your first GitLab login. The setup has ### Additional markup styles -Apart from the always supported markdown style there are other rich text files that GitLab can display. But you might have to install a dependency to do so. Please see the [github-markup gem readme](https://github.com/gitlabhq/markup#markups) for more information. For example, reStructuredText markup language support requires python-docutils: - - sudo apt-get install -y python-docutils +Apart from the always supported markdown style there are other rich text files that GitLab can display. But you might have to install a dependency to do so. Please see the [github-markup gem readme](https://github.com/gitlabhq/markup#markups) for more information. ### Custom Redis Connection From dca6c490ccb8eb1e9bc73e214acf2ac6654f11ea Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Tue, 10 Jun 2014 10:23:23 +0200 Subject: [PATCH 263/360] Update check task and add to monthly release doc lines about gitlab_shell_version file. --- doc/release/monthly.md | 4 ++++ lib/tasks/gitlab/check.rake | 18 +++++++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/doc/release/monthly.md b/doc/release/monthly.md index 446dbc6e6a..99f2d4cafe 100644 --- a/doc/release/monthly.md +++ b/doc/release/monthly.md @@ -160,6 +160,10 @@ git push x-x-stable ### **3. Set VERSION to x.x.x and push** +Change the GITLAB_SHELL_VERSION file in `master` of the CE repository if the version changed. + +Change the GITLAB_SHELL_VERSION file in `master` of the EE repository if the version changed. + Change the VERSION file in `master` branch of the CE repository and commit. Cherry-pick into the `x-x-stable` branch of CE. Change the VERSION file in `master` branch of the EE repository and commit. Cherry-pick into the `x-x-stable-ee` branch of EE. diff --git a/lib/tasks/gitlab/check.rake b/lib/tasks/gitlab/check.rake index 362693b060..00af8d1029 100644 --- a/lib/tasks/gitlab/check.rake +++ b/lib/tasks/gitlab/check.rake @@ -606,6 +606,22 @@ namespace :gitlab do Gitlab::Shell.new.version end + def required_gitlab_shell_version + File.read(File.join(Rails.root, "GITLAB_SHELL_VERSION")).strip + end + + def gitlab_shell_major_version + required_gitlab_shell_version.split(".")[0].to_i + end + + def gitlab_shell_minor_version + required_gitlab_shell_version.split(".")[1].to_i + end + + def gitlab_shell_patch_version + required_gitlab_shell_version.split(".")[2].to_i + end + def has_gitlab_shell3? gitlab_shell_version.try(:start_with?, "v3.") end @@ -779,7 +795,7 @@ namespace :gitlab do end def check_gitlab_shell - required_version = Gitlab::VersionInfo.new(1, 9, 5) + required_version = Gitlab::VersionInfo.new(gitlab_shell_major_version, gitlab_shell_minor_version, gitlab_shell_patch_version) current_version = Gitlab::VersionInfo.parse(gitlab_shell_version) print "GitLab Shell version >= #{required_version} ? ... " From 7edf65d1ee9e65e5d5d2bde573936715b46e250d Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 10 Jun 2014 12:25:43 +0300 Subject: [PATCH 264/360] Make a system comment when issue milestone changed Signed-off-by: Dmitriy Zaporozhets --- app/models/note.rb | 16 ++++++++++++++++ app/services/issues/base_service.rb | 4 ++++ app/services/issues/update_service.rb | 4 ++++ 3 files changed, 24 insertions(+) diff --git a/app/models/note.rb b/app/models/note.rb index 278c957af0..dc8b968c3d 100644 --- a/app/models/note.rb +++ b/app/models/note.rb @@ -90,6 +90,22 @@ class Note < ActiveRecord::Base create(note_options, without_protection: true) end + def create_milestone_change_note(noteable, project, author, milestone) + body = if milestone.nil? + '_Milestone removed_' + else + "_Milestone changed to #{milestone.title}_" + end + + create({ + noteable: noteable, + project: project, + author: author, + note: body, + system: true + }, without_protection: true) + end + def create_assignee_change_note(noteable, project, author, assignee) body = assignee.nil? ? '_Assignee removed_' : "_Reassigned to @#{assignee.username}_" diff --git a/app/services/issues/base_service.rb b/app/services/issues/base_service.rb index 2e1e1f7e0f..eac774210a 100644 --- a/app/services/issues/base_service.rb +++ b/app/services/issues/base_service.rb @@ -10,5 +10,9 @@ module Issues def execute_hooks(issue) issue.project.execute_hooks(issue.to_hook_data, :issue_hooks) end + + def create_milestone_note(issue) + Note.create_milestone_change_note(issue, issue.project, current_user, issue.milestone) + end end end diff --git a/app/services/issues/update_service.rb b/app/services/issues/update_service.rb index b562c401fd..f69370bedd 100644 --- a/app/services/issues/update_service.rb +++ b/app/services/issues/update_service.rb @@ -13,6 +13,10 @@ module Issues if params.present? && issue.update_attributes(params) issue.reset_events_cache + if issue.previous_changes.include?('milestone_id') + create_milestone_note(issue) + end + if issue.previous_changes.include?('assignee_id') notification_service.reassigned_issue(issue, current_user) create_assignee_note(issue) From 525fa6c11ba739968c1af5b3dbd69a23c3834811 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 10 Jun 2014 12:29:23 +0300 Subject: [PATCH 265/360] Fix tests Signed-off-by: Dmitriy Zaporozhets --- app/services/notification_service.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index 06140c5afe..3547552df8 100644 --- a/app/services/notification_service.rb +++ b/app/services/notification_service.rb @@ -254,7 +254,7 @@ class NotificationService # Remove users with disabled notifications from array # Also remove duplications and nil recipients def reject_muted_users(users, project = nil) - users = users.compact.uniq + users = users.to_a.compact.uniq users.reject do |user| next user.notification.disabled? unless project From 55440ac9bec0b2e113d75540b898e4b46d766ba1 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 10 Jun 2014 12:33:17 +0300 Subject: [PATCH 266/360] Make a comment to MR whne milestone was changed Signed-off-by: Dmitriy Zaporozhets --- app/services/merge_requests/base_service.rb | 4 ++++ app/services/merge_requests/update_service.rb | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/app/services/merge_requests/base_service.rb b/app/services/merge_requests/base_service.rb index c77f5d664e..2907f3587d 100644 --- a/app/services/merge_requests/base_service.rb +++ b/app/services/merge_requests/base_service.rb @@ -16,5 +16,9 @@ module MergeRequests merge_request.project.execute_hooks(merge_request.to_hook_data, :merge_request_hooks) end end + + def create_milestone_note(merge_request) + Note.create_milestone_change_note(merge_request, merge_request.project, current_user, merge_request.milestone) + end end end diff --git a/app/services/merge_requests/update_service.rb b/app/services/merge_requests/update_service.rb index bbedca6ffd..60d470a060 100644 --- a/app/services/merge_requests/update_service.rb +++ b/app/services/merge_requests/update_service.rb @@ -22,6 +22,10 @@ module MergeRequests if params.present? && merge_request.update_attributes(params) merge_request.reset_events_cache + if merge_request.previous_changes.include?('milestone_id') + create_milestone_note(merge_request) + end + if merge_request.previous_changes.include?('assignee_id') notification_service.reassigned_merge_request(merge_request, current_user) create_assignee_note(merge_request) From f2353352a24976829470b7eb60b295313dfa75bb Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 10 Jun 2014 12:39:48 +0300 Subject: [PATCH 267/360] Test for milestone changed comment Signed-off-by: Dmitriy Zaporozhets --- spec/features/issues_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/features/issues_spec.rb b/spec/features/issues_spec.rb index e62517ad71..d7f3f3a302 100644 --- a/spec/features/issues_spec.rb +++ b/spec/features/issues_spec.rb @@ -248,7 +248,7 @@ describe "Issues", feature: true do find('.edit-issue.inline-update').select(milestone.title, from: 'issue_milestone_id') click_button 'Update Issue' - page.should have_content "Milestone" + page.should have_content "Milestone changed to #{milestone.title}" page.has_select?('issue_assignee_id', :selected => milestone.title) end end From b980ab407e6194723546125c80a0911b5e557215 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Tue, 10 Jun 2014 11:58:11 +0200 Subject: [PATCH 268/360] Update installation doc to mention using https. --- doc/install/installation.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/doc/install/installation.md b/doc/install/installation.md index 7840cef890..eebc1a3e32 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -158,6 +158,8 @@ We recommend using a PostgreSQL database. For MySQL check [MySQL setup guide](da # Make sure to change "localhost" to the fully-qualified domain name of your # host serving GitLab where necessary # + # If you want to use https make sure that you set `https` to `true`. See #using-https for more details. + # # If you installed Git from source, change the git bin_path to /usr/local/bin/git sudo -u git -H editor config/gitlab.yml @@ -305,7 +307,7 @@ Make sure to edit the config file to match your setup: # domain name of your host serving GitLab. sudo editor /etc/nginx/sites-available/gitlab -**Note:** If you want to use https, replace the `gitlab` nginx config with `gitlab-ssl`. +**Note:** If you want to use https, replace the `gitlab` nginx config with `gitlab-ssl`. See #using-https for more details. ### Restart @@ -334,6 +336,15 @@ Visit YOUR_SERVER in your web browser for your first GitLab login. The setup has ## Advanced Setup Tips +### Using HTTPS + +This is a retrospective of what is needed to configure in order to use GitLab with HTTPS: + +1. In `gitlab.yml` enable https by setting `https` option to `true` +1. In gitlab-shell `config.yml` provide paths to the certificates under `ca_file` and `ca_path options. +In case you are using self signed certificate set `self_signed_cert` to `true`. `gitlab_url` must point to the https host. +1. Use `gitlab-ssl` nginx config + ### Additional markup styles Apart from the always supported markdown style there are other rich text files that GitLab can display. But you might have to install a dependency to do so. Please see the [github-markup gem readme](https://github.com/gitlabhq/markup#markups) for more information. For example, reStructuredText markup language support requires python-docutils: From fa9c39591c074d4766593f7ef93b91cbceb22c43 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Tue, 10 Jun 2014 12:57:50 +0200 Subject: [PATCH 269/360] Extract gitlab-shell configuration note to gitlab-shell section. --- doc/install/installation.md | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/doc/install/installation.md b/doc/install/installation.md index eebc1a3e32..5ce801dc39 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -240,7 +240,12 @@ GitLab Shell is an ssh access and repository management software developed speci # Run the installation task for gitlab-shell (replace `REDIS_URL` if needed): sudo -u git -H bundle exec rake gitlab:shell:install[v1.9.5] REDIS_URL=redis://localhost:6379 RAILS_ENV=production - # By default, the gitlab-shell config is generated from your main gitlab config. You can review (and modify) it as follows: + # By default, the gitlab-shell config is generated from your main gitlab config. + # + # Note: When using GitLab with HTTPS, provide paths to the certificates under `ca_file` and `ca_path options. + # In case you are using self signed certificate set `self_signed_cert` to `true`. `gitlab_url` must point to the https host. + # + # You can review (and modify) the gitlab-shell config as follows: sudo -u git -H editor /home/git/gitlab-shell/config.yml ### Initialize Database and Activate Advanced Features @@ -341,9 +346,9 @@ Visit YOUR_SERVER in your web browser for your first GitLab login. The setup has This is a retrospective of what is needed to configure in order to use GitLab with HTTPS: 1. In `gitlab.yml` enable https by setting `https` option to `true` -1. In gitlab-shell `config.yml` provide paths to the certificates under `ca_file` and `ca_path options. -In case you are using self signed certificate set `self_signed_cert` to `true`. `gitlab_url` must point to the https host. -1. Use `gitlab-ssl` nginx config +1. In gitlab-shell `config.yml` check if certificate options `ca_file`, `ca_path options` or `self_signed_cert` are set. +`gitlab_url` must point to the https host. +1. Use the `gitlab-ssl` nginx config. ### Additional markup styles From c8e6752414010fadeb4516a3d860719666ac7212 Mon Sep 17 00:00:00 2001 From: skv-headless Date: Thu, 8 May 2014 16:55:43 +0400 Subject: [PATCH 270/360] fix link to notes in merge request diff http://localhost:3000/gitlabhq/gitlab-ci/merge_requests/1/diffs#note_316 scroll in such links doesn't work. It happens because on page there are 2 elements with id="note_316" in changes and discussion. Browser takes first for scroll. This solution works because changes loads without diffs so tag with id="note_316" just one. Diffs loads with discussions, but in this case diff tag would be first. It is dirty but working solution. --- app/views/projects/merge_requests/_show.html.haml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/projects/merge_requests/_show.html.haml b/app/views/projects/merge_requests/_show.html.haml index 1072728af2..486454793b 100644 --- a/app/views/projects/merge_requests/_show.html.haml +++ b/app/views/projects/merge_requests/_show.html.haml @@ -26,11 +26,11 @@ - if @merge_request.closed? = link_to 'Reopen', project_merge_request_path(@project, @merge_request, merge_request: {state_event: :reopen }), method: :put, class: "btn btn-grouped btn-reopen reopen-mr-link", title: "Close merge request" - .notes.tab-content.voting_notes#notes{ class: (controller.action_name == 'show') ? "" : "hide" } - = render "projects/notes/notes_with_form" .diffs.tab-content - if current_page?(action: 'diffs') = render "projects/merge_requests/show/diffs" + .notes.tab-content.voting_notes#notes{ class: (controller.action_name == 'show') ? "" : "hide" } + = render "projects/notes/notes_with_form" .status :javascript From 95af7123bbe229f0e0c713de7271d668de105bd0 Mon Sep 17 00:00:00 2001 From: Sytse Sijbrandij Date: Tue, 10 Jun 2014 14:43:11 +0200 Subject: [PATCH 271/360] Reformulate some of the https instructions. --- doc/install/installation.md | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/doc/install/installation.md b/doc/install/installation.md index 092a740e04..d178143a68 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -158,7 +158,7 @@ We recommend using a PostgreSQL database. For MySQL check [MySQL setup guide](da # Make sure to change "localhost" to the fully-qualified domain name of your # host serving GitLab where necessary # - # If you want to use https make sure that you set `https` to `true`. See #using-https for more details. + # If you want to use https make sure that you set `https` to `true`. See [Using HTTPS](#using-https) for all necessary details. # # If you installed Git from source, change the git bin_path to /usr/local/bin/git sudo -u git -H editor config/gitlab.yml @@ -242,8 +242,11 @@ GitLab Shell is an ssh access and repository management software developed speci # By default, the gitlab-shell config is generated from your main gitlab config. # - # Note: When using GitLab with HTTPS, provide paths to the certificates under `ca_file` and `ca_path options. - # In case you are using self signed certificate set `self_signed_cert` to `true`. `gitlab_url` must point to the https host. + # Note: When using GitLab with HTTPS please change the following: + # - Provide paths to the certificates under `ca_file` and `ca_path options. + # - The `gitlab_url` option must point to the https endpoint of GitLab. + # - In case you are using self signed certificate set `self_signed_cert` to `true`. + # See [Using HTTPS](#using-https) for all necessary details. # # You can review (and modify) the gitlab-shell config as follows: sudo -u git -H editor /home/git/gitlab-shell/config.yml @@ -312,7 +315,7 @@ Make sure to edit the config file to match your setup: # domain name of your host serving GitLab. sudo editor /etc/nginx/sites-available/gitlab -**Note:** If you want to use https, replace the `gitlab` nginx config with `gitlab-ssl`. See #using-https for more details. +**Note:** If you want to use https, replace the `gitlab` nginx config with `gitlab-ssl`. See [Using HTTPS](#using-https) for all necessary details. ### Restart @@ -343,12 +346,11 @@ Visit YOUR_SERVER in your web browser for your first GitLab login. The setup has ### Using HTTPS -This is a retrospective of what is needed to configure in order to use GitLab with HTTPS: +To recapitulate what is needed to use GitLab with HTTPS: -1. In `gitlab.yml` enable https by setting `https` option to `true` -1. In gitlab-shell `config.yml` check if certificate options `ca_file`, `ca_path options` or `self_signed_cert` are set. -`gitlab_url` must point to the https host. -1. Use the `gitlab-ssl` nginx config. +1. In `gitlab.yml` set the `https` option to `true` +1. In the `config.yml` of gitlab-shell set the relevant options (see the [install GitLab Shell section](#install-gitlab-shell) of this document). +1. Use the `gitlab-ssl` nginx example config instead of the `gitlab` config. ### Additional markup styles From 5d95fc67262adba75c0227f7e200d820848c9ca5 Mon Sep 17 00:00:00 2001 From: Sytse Sijbrandij Date: Tue, 10 Jun 2014 14:45:03 +0200 Subject: [PATCH 272/360] Link in code sections do not work. --- doc/install/installation.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/install/installation.md b/doc/install/installation.md index d178143a68..ed54b41e61 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -158,7 +158,7 @@ We recommend using a PostgreSQL database. For MySQL check [MySQL setup guide](da # Make sure to change "localhost" to the fully-qualified domain name of your # host serving GitLab where necessary # - # If you want to use https make sure that you set `https` to `true`. See [Using HTTPS](#using-https) for all necessary details. + # If you want to use https make sure that you set `https` to `true`. See #using-https for all necessary details. # # If you installed Git from source, change the git bin_path to /usr/local/bin/git sudo -u git -H editor config/gitlab.yml @@ -246,7 +246,7 @@ GitLab Shell is an ssh access and repository management software developed speci # - Provide paths to the certificates under `ca_file` and `ca_path options. # - The `gitlab_url` option must point to the https endpoint of GitLab. # - In case you are using self signed certificate set `self_signed_cert` to `true`. - # See [Using HTTPS](#using-https) for all necessary details. + # See #using-https for all necessary details. # # You can review (and modify) the gitlab-shell config as follows: sudo -u git -H editor /home/git/gitlab-shell/config.yml From 123dea35b53cf1f6ac55359516bc4ca33fa402fc Mon Sep 17 00:00:00 2001 From: Ciro Santilli Date: Tue, 15 Apr 2014 21:40:18 +0200 Subject: [PATCH 273/360] Clarify that bbastov is the style of Hound CI. --- CONTRIBUTING.md | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8c0f16c1ee..21fcfb1467 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -102,11 +102,13 @@ For examples of feedback on merge requests please look at already [closed merge ## Style guides -1. [Ruby](https://github.com/bbatsov/ruby-style-guide) -1. [Rails](https://github.com/bbatsov/rails-style-guide) -1. [Formatting](https://github.com/thoughtbot/guides/tree/master/style#formatting) -1. [Naming](https://github.com/thoughtbot/guides/tree/master/style#naming) -1. [Testing](https://github.com/thoughtbot/guides/tree/master/style#testing) -1. [CoffeeScript](https://github.com/thoughtbot/guides/tree/master/style#coffeescript) -1. [Shell commands](doc/development/shell_commands.md) -1. [Markdown](http://www.cirosantilli.com/markdown-styleguide) +1. [Ruby](https://github.com/bbatsov/ruby-style-guide). Important sections include [Source Code Layout](https://github.com/bbatsov/ruby-style-guide#source-code-layout) and [Naming](https://github.com/bbatsov/ruby-style-guide#naming). Use: + - multi-line method chaining style **Option A**: leading `.` + - string literal quoting style **Option A**: single quoted by default +1. [Rails](https://github.com/bbatsov/rails-style-guide) +1. [Testing](https://github.com/thoughtbot/guides/tree/master/style#testing) +1. [CoffeeScript](https://github.com/thoughtbot/guides/tree/master/style#coffeescript) +1. [Shell commands](doc/development/shell_commands.md) +1. [Markdown](http://www.cirosantilli.com/markdown-styleguide) + +The above styles are used by Hound CI. From 9b346202bc09d808064fa5b9647be4e43cfd488b Mon Sep 17 00:00:00 2001 From: Ciro Santilli Date: Tue, 10 Jun 2014 16:30:07 +0200 Subject: [PATCH 274/360] Option B, Rubocop. --- CONTRIBUTING.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 21fcfb1467..ee17f1d6cc 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -102,8 +102,10 @@ For examples of feedback on merge requests please look at already [closed merge ## Style guides -1. [Ruby](https://github.com/bbatsov/ruby-style-guide). Important sections include [Source Code Layout](https://github.com/bbatsov/ruby-style-guide#source-code-layout) and [Naming](https://github.com/bbatsov/ruby-style-guide#naming). Use: - - multi-line method chaining style **Option A**: leading `.` +1. [Ruby](https://github.com/bbatsov/ruby-style-guide). + Important sections include [Source Code Layout](https://github.com/bbatsov/ruby-style-guide#source-code-layout) + and [Naming](https://github.com/bbatsov/ruby-style-guide#naming). Use: + - multi-line method chaining style **Option B**: dot `.` on previous line - string literal quoting style **Option A**: single quoted by default 1. [Rails](https://github.com/bbatsov/rails-style-guide) 1. [Testing](https://github.com/thoughtbot/guides/tree/master/style#testing) @@ -111,4 +113,5 @@ For examples of feedback on merge requests please look at already [closed merge 1. [Shell commands](doc/development/shell_commands.md) 1. [Markdown](http://www.cirosantilli.com/markdown-styleguide) -The above styles are used by Hound CI. +This is also the style used by linting tools such as [Rubocop](https://github.com/bbatsov/rubocop) +and [Hound CI](https://houndci.com). From a7be3dfa30a452b307d1fdc0b4157ecbe908da8d Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 10 Jun 2014 17:51:49 +0300 Subject: [PATCH 275/360] Remove set of thread variables Signed-off-by: Dmitriy Zaporozhets --- app/controllers/application_controller.rb | 10 ---------- app/observers/base_observer.rb | 8 -------- lib/api/helpers.rb | 10 ---------- lib/gitlab/seeder.rb | 7 +------ 4 files changed, 1 insertion(+), 34 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index aa532de7aa..685d41a552 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -4,7 +4,6 @@ class ApplicationController < ActionController::Base before_filter :authenticate_user! before_filter :reject_blocked! before_filter :check_password_expiration - around_filter :set_current_user_for_thread before_filter :add_abilities before_filter :ldap_security_check before_filter :dev_tools if Rails.env == 'development' @@ -53,15 +52,6 @@ class ApplicationController < ActionController::Base end end - def set_current_user_for_thread - Thread.current[:current_user] = current_user - begin - yield - ensure - Thread.current[:current_user] = nil - end - end - def abilities @abilities ||= Six.new end diff --git a/app/observers/base_observer.rb b/app/observers/base_observer.rb index d685bd5d81..260d1f05db 100644 --- a/app/observers/base_observer.rb +++ b/app/observers/base_observer.rb @@ -10,12 +10,4 @@ class BaseObserver < ActiveRecord::Observer def log_info message Gitlab::AppLogger.info message end - - def current_user - Thread.current[:current_user] - end - - def current_commit - Thread.current[:current_commit] - end end diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb index 654c1f62c6..b6a5806d64 100644 --- a/lib/api/helpers.rb +++ b/lib/api/helpers.rb @@ -36,16 +36,6 @@ module API end end - def set_current_user_for_thread - Thread.current[:current_user] = current_user - - begin - yield - ensure - Thread.current[:current_user] = nil - end - end - def user_project @project ||= find_project(params[:id]) @project || not_found! diff --git a/lib/gitlab/seeder.rb b/lib/gitlab/seeder.rb index 39de1223b1..31aa3528c4 100644 --- a/lib/gitlab/seeder.rb +++ b/lib/gitlab/seeder.rb @@ -9,12 +9,7 @@ module Gitlab end def self.by_user(user) - begin - Thread.current[:current_user] = user - yield - ensure - Thread.current[:current_user] = nil - end + yield end def self.mute_mailer From f8ea52c3a0fe29daf76fbd7a0e65399c09c95f5a Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 10 Jun 2014 17:56:35 +0300 Subject: [PATCH 276/360] Remove thread vars usage from API notes and mr's Signed-off-by: Dmitriy Zaporozhets --- app/observers/note_observer.rb | 4 ++-- lib/api/merge_requests.rb | 19 +++++++--------- lib/api/notes.rb | 40 +++++++++++++++------------------- 3 files changed, 28 insertions(+), 35 deletions(-) diff --git a/app/observers/note_observer.rb b/app/observers/note_observer.rb index 337bb1dc5a..9bb1f0f7b9 100644 --- a/app/observers/note_observer.rb +++ b/app/observers/note_observer.rb @@ -5,7 +5,7 @@ class NoteObserver < BaseObserver # Skip system notes, like status changes and cross-references. # Skip wall notes to prevent spamming of dashboard if note.noteable_type.present? && !note.system - event_service.leave_note(note, current_user) + event_service.leave_note(note, note.author) end unless note.system? @@ -18,6 +18,6 @@ class NoteObserver < BaseObserver end def after_update(note) - note.notice_added_references(note.project, current_user) + note.notice_added_references(note.project, note.author) end end diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb index 017cb1f562..fc1f1254a9 100644 --- a/lib/api/merge_requests.rb +++ b/lib/api/merge_requests.rb @@ -184,21 +184,18 @@ module API # POST /projects/:id/merge_request/:merge_request_id/comments # post ":id/merge_request/:merge_request_id/comments" do - set_current_user_for_thread do - required_attributes! [:note] + required_attributes! [:note] - merge_request = user_project.merge_requests.find(params[:merge_request_id]) - note = merge_request.notes.new(note: params[:note], project_id: user_project.id) - note.author = current_user + merge_request = user_project.merge_requests.find(params[:merge_request_id]) + note = merge_request.notes.new(note: params[:note], project_id: user_project.id) + note.author = current_user - if note.save - present note, with: Entities::MRNote - else - not_found! - end + if note.save + present note, with: Entities::MRNote + else + not_found! end end - end end end diff --git a/lib/api/notes.rb b/lib/api/notes.rb index f21907b1ff..cb2bc76447 100644 --- a/lib/api/notes.rb +++ b/lib/api/notes.rb @@ -41,19 +41,17 @@ module API # Example Request: # POST /projects/:id/notes post ":id/notes" do - set_current_user_for_thread do - required_attributes! [:body] + required_attributes! [:body] - @note = user_project.notes.new(note: params[:body]) - @note.author = current_user + @note = user_project.notes.new(note: params[:body]) + @note.author = current_user - if @note.save - present @note, with: Entities::Note - else - # :note is exposed as :body, but :note is set on error - bad_request!(:note) if @note.errors[:note].any? - not_found! - end + if @note.save + present @note, with: Entities::Note + else + # :note is exposed as :body, but :note is set on error + bad_request!(:note) if @note.errors[:note].any? + not_found! end end @@ -99,19 +97,17 @@ module API # POST /projects/:id/issues/:noteable_id/notes # POST /projects/:id/snippets/:noteable_id/notes post ":id/#{noteables_str}/:#{noteable_id_str}/notes" do - set_current_user_for_thread do - required_attributes! [:body] + required_attributes! [:body] - @noteable = user_project.send(:"#{noteables_str}").find(params[:"#{noteable_id_str}"]) - @note = @noteable.notes.new(note: params[:body]) - @note.author = current_user - @note.project = user_project + @noteable = user_project.send(:"#{noteables_str}").find(params[:"#{noteable_id_str}"]) + @note = @noteable.notes.new(note: params[:body]) + @note.author = current_user + @note.project = user_project - if @note.save - present @note, with: Entities::Note - else - not_found! - end + if @note.save + present @note, with: Entities::Note + else + not_found! end end end From c4b02642d2ca74f463e64dd591796aabe5c54af9 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 10 Jun 2014 18:07:52 +0300 Subject: [PATCH 277/360] Replace milestone observer with services Signed-off-by: Dmitriy Zaporozhets --- .../projects/milestones_controller.rb | 4 +-- app/observers/milestone_observer.rb | 13 ------- app/services/milestones/base_service.rb | 4 +++ app/services/milestones/close_service.rb | 11 ++++++ app/services/milestones/create_service.rb | 13 +++++++ app/services/milestones/reopen_service.rb | 11 ++++++ app/services/milestones/update_service.rb | 20 +++++++++++ config/application.rb | 3 +- lib/api/milestones.rb | 35 +++++++++---------- 9 files changed, 78 insertions(+), 36 deletions(-) delete mode 100644 app/observers/milestone_observer.rb create mode 100644 app/services/milestones/base_service.rb create mode 100644 app/services/milestones/close_service.rb create mode 100644 app/services/milestones/create_service.rb create mode 100644 app/services/milestones/reopen_service.rb create mode 100644 app/services/milestones/update_service.rb diff --git a/app/controllers/projects/milestones_controller.rb b/app/controllers/projects/milestones_controller.rb index 05237bbd2d..227cc1dfba 100644 --- a/app/controllers/projects/milestones_controller.rb +++ b/app/controllers/projects/milestones_controller.rb @@ -37,7 +37,7 @@ class Projects::MilestonesController < Projects::ApplicationController end def create - @milestone = @project.milestones.new(params[:milestone]) + @milestone = Milestones::CreateService.new(project, current_user, params[:milestone]).execute if @milestone.save redirect_to project_milestone_path(@project, @milestone) @@ -47,7 +47,7 @@ class Projects::MilestonesController < Projects::ApplicationController end def update - @milestone.update_attributes(params[:milestone]) + @milestone = Milestones::UpdateService.new(project, current_user, params[:milestone]).execute(milestone) respond_to do |format| format.js diff --git a/app/observers/milestone_observer.rb b/app/observers/milestone_observer.rb deleted file mode 100644 index a1a62a99a8..0000000000 --- a/app/observers/milestone_observer.rb +++ /dev/null @@ -1,13 +0,0 @@ -class MilestoneObserver < BaseObserver - def after_create(milestone) - event_service.open_milestone(milestone, current_user) - end - - def after_close(milestone, transition) - event_service.close_milestone(milestone, current_user) - end - - def after_reopen(milestone, transition) - event_service.reopen_milestone(milestone, current_user) - end -end diff --git a/app/services/milestones/base_service.rb b/app/services/milestones/base_service.rb new file mode 100644 index 0000000000..176ab9f1ab --- /dev/null +++ b/app/services/milestones/base_service.rb @@ -0,0 +1,4 @@ +module Milestones + class BaseService < ::BaseService + end +end diff --git a/app/services/milestones/close_service.rb b/app/services/milestones/close_service.rb new file mode 100644 index 0000000000..608fc49d76 --- /dev/null +++ b/app/services/milestones/close_service.rb @@ -0,0 +1,11 @@ +module Milestones + class CloseService < Milestones::BaseService + def execute(milestone) + if milestone.close + event_service.close_milestone(milestone, current_user) + end + + milestone + end + end +end diff --git a/app/services/milestones/create_service.rb b/app/services/milestones/create_service.rb new file mode 100644 index 0000000000..b8e08c9f1e --- /dev/null +++ b/app/services/milestones/create_service.rb @@ -0,0 +1,13 @@ +module Milestones + class CreateService < Milestones::BaseService + def execute + milestone = project.milestones.new(params) + + if milestone.save + event_service.open_milestone(milestone, current_user) + end + + milestone + end + end +end diff --git a/app/services/milestones/reopen_service.rb b/app/services/milestones/reopen_service.rb new file mode 100644 index 0000000000..ff1ba23bdb --- /dev/null +++ b/app/services/milestones/reopen_service.rb @@ -0,0 +1,11 @@ +module Milestones + class ReopenService < Milestones::BaseService + def execute(milestone) + if milestone.reopen + event_service.reopen_milestone(milestone, current_user) + end + + milestone + end + end +end diff --git a/app/services/milestones/update_service.rb b/app/services/milestones/update_service.rb new file mode 100644 index 0000000000..69254a7967 --- /dev/null +++ b/app/services/milestones/update_service.rb @@ -0,0 +1,20 @@ +module Milestones + class UpdateService < Milestones::BaseService + def execute(milestone) + state = params.delete('state_event') + + case state + when 'reopen' + Milestones::ReopenService.new(project, current_user, {}).execute(milestone) + when 'close' + Milestones::CloseService.new(project, current_user, {}).execute(milestone) + end + + if params.present? + milestone.update_attributes(params) + end + + milestone + end + end +end diff --git a/config/application.rb b/config/application.rb index f087d3507b..540426b667 100644 --- a/config/application.rb +++ b/config/application.rb @@ -19,8 +19,7 @@ module Gitlab # config.plugins = [ :exception_notification, :ssl_requirement, :all ] # Activate observers that should always be running. - config.active_record.observers = :milestone_observer, - :project_activity_cache_observer, + config.active_record.observers = :project_activity_cache_observer, :note_observer, :project_observer, :system_hook_observer, diff --git a/lib/api/milestones.rb b/lib/api/milestones.rb index f7e63b2309..a4fdb752d6 100644 --- a/lib/api/milestones.rb +++ b/lib/api/milestones.rb @@ -40,17 +40,15 @@ module API # Example Request: # POST /projects/:id/milestones post ":id/milestones" do - set_current_user_for_thread do - authorize! :admin_milestone, user_project - required_attributes! [:title] + authorize! :admin_milestone, user_project + required_attributes! [:title] + attrs = attributes_for_keys [:title, :description, :due_date] + milestone = ::Milestones::CreateService.new(user_project, current_user, attrs).execute - attrs = attributes_for_keys [:title, :description, :due_date] - @milestone = user_project.milestones.new attrs - if @milestone.save - present @milestone, with: Entities::Milestone - else - not_found! - end + if milestone.valid? + present milestone, with: Entities::Milestone + else + not_found! end end @@ -66,16 +64,15 @@ module API # Example Request: # PUT /projects/:id/milestones/:milestone_id put ":id/milestones/:milestone_id" do - set_current_user_for_thread do - authorize! :admin_milestone, user_project + authorize! :admin_milestone, user_project + attrs = attributes_for_keys [:title, :description, :due_date, :state_event] + milestone = user_project.milestones.find(params[:milestone_id]) + milestone = ::Milestones::UpdateService.new(user_project, current_user, attrs).execute(milestone) - @milestone = user_project.milestones.find(params[:milestone_id]) - attrs = attributes_for_keys [:title, :description, :due_date, :state_event] - if @milestone.update_attributes attrs - present @milestone, with: Entities::Milestone - else - not_found! - end + if milestone.valid? + present milestone, with: Entities::Milestone + else + not_found! end end end From 466b768bb34730ee6a24d950333c232009c34bbd Mon Sep 17 00:00:00 2001 From: Pierre de La Morinerie Date: Fri, 21 Feb 2014 19:39:09 +0100 Subject: [PATCH 278/360] Send notification emails to the "project", and put people in Cc This fixes email threading in Mail.app, that doesn't like when a thread doesn't have stable recipients. For instance, here is a possible sender-recipient combinations before: From: A To: Me New issue From: B To: Me Reply on new issue From: A To: Me Another reply Mail.app doesn't see B as a participant to the original email thread, and decides to break the thread: it will group all messages from A together, and separately all messages from B. This commit makes the thread look like this: From: A To: gitlab/project Cc: Me New issue From: B To: gitlab/project Cc: Me Reply on new issue From: A To: gitlab/project Cc: Me Another reply Mail.app sees a common recipient, and group the thread correctly. --- app/mailers/emails/groups.rb | 2 +- app/mailers/emails/issues.rb | 8 ++++---- app/mailers/emails/merge_requests.rb | 8 ++++---- app/mailers/emails/notes.rb | 8 ++++---- app/mailers/emails/projects.rb | 6 +++--- app/mailers/notify.rb | 14 ++++++++++++++ spec/mailers/notify_spec.rb | 8 ++++---- spec/services/issues/close_service_spec.rb | 2 +- spec/services/issues/update_service_spec.rb | 2 +- spec/services/merge_requests/close_service_spec.rb | 2 +- .../services/merge_requests/update_service_spec.rb | 2 +- 11 files changed, 38 insertions(+), 24 deletions(-) diff --git a/app/mailers/emails/groups.rb b/app/mailers/emails/groups.rb index 1654fc55bc..39527b00e9 100644 --- a/app/mailers/emails/groups.rb +++ b/app/mailers/emails/groups.rb @@ -4,7 +4,7 @@ module Emails @membership = UsersGroup.find(user_group_id) @group = @membership.group @target_url = group_url(@group) - mail(to: @membership.user.email, + mail(cc: @membership.user.email, subject: subject("Access to group was granted")) end end diff --git a/app/mailers/emails/issues.rb b/app/mailers/emails/issues.rb index a096df9dc0..50676ac10c 100644 --- a/app/mailers/emails/issues.rb +++ b/app/mailers/emails/issues.rb @@ -6,7 +6,7 @@ module Emails @target_url = project_issue_url(@project, @issue) set_message_id("issue_#{issue_id}") mail(from: sender(@issue.author_id), - to: recipient(recipient_id), + cc: recipient(recipient_id), subject: subject("#{@issue.title} (##{@issue.iid})")) end @@ -17,7 +17,7 @@ module Emails @target_url = project_issue_url(@project, @issue) set_reference("issue_#{issue_id}") mail(from: sender(updated_by_user_id), - to: recipient(recipient_id), + cc: recipient(recipient_id), subject: subject("#{@issue.title} (##{@issue.iid})")) end @@ -28,7 +28,7 @@ module Emails @target_url = project_issue_url(@project, @issue) set_reference("issue_#{issue_id}") mail(from: sender(updated_by_user_id), - to: recipient(recipient_id), + cc: recipient(recipient_id), subject: subject("#{@issue.title} (##{@issue.iid})")) end @@ -40,7 +40,7 @@ module Emails @target_url = project_issue_url(@project, @issue) set_reference("issue_#{issue_id}") mail(from: sender(updated_by_user_id), - to: recipient(recipient_id), + cc: recipient(recipient_id), subject: subject("#{@issue.title} (##{@issue.iid})")) end end diff --git a/app/mailers/emails/merge_requests.rb b/app/mailers/emails/merge_requests.rb index ea5671c450..6b46cc90e0 100644 --- a/app/mailers/emails/merge_requests.rb +++ b/app/mailers/emails/merge_requests.rb @@ -6,7 +6,7 @@ module Emails @target_url = project_merge_request_url(@project, @merge_request) set_message_id("merge_request_#{merge_request_id}") mail(from: sender(@merge_request.author_id), - to: recipient(recipient_id), + cc: recipient(recipient_id), subject: subject("#{@merge_request.title} (##{@merge_request.iid})")) end @@ -17,7 +17,7 @@ module Emails @target_url = project_merge_request_url(@project, @merge_request) set_reference("merge_request_#{merge_request_id}") mail(from: sender(updated_by_user_id), - to: recipient(recipient_id), + cc: recipient(recipient_id), subject: subject("#{@merge_request.title} (##{@merge_request.iid})")) end @@ -28,7 +28,7 @@ module Emails @target_url = project_merge_request_url(@project, @merge_request) set_reference("merge_request_#{merge_request_id}") mail(from: sender(updated_by_user_id), - to: recipient(recipient_id), + cc: recipient(recipient_id), subject: subject("#{@merge_request.title} (##{@merge_request.iid})")) end @@ -38,7 +38,7 @@ module Emails @target_url = project_merge_request_url(@project, @merge_request) set_reference("merge_request_#{merge_request_id}") mail(from: sender(updated_by_user_id), - to: recipient(recipient_id), + cc: recipient(recipient_id), subject: subject("#{@merge_request.title} (##{@merge_request.iid})")) end end diff --git a/app/mailers/emails/notes.rb b/app/mailers/emails/notes.rb index 8d1f17b0f8..d6ab63fe68 100644 --- a/app/mailers/emails/notes.rb +++ b/app/mailers/emails/notes.rb @@ -6,7 +6,7 @@ module Emails @project = @note.project @target_url = project_commit_url(@project, @commit, anchor: "note_#{@note.id}") mail(from: sender(@note.author_id), - to: recipient(recipient_id), + cc: recipient(recipient_id), subject: subject("#{@commit.title} (#{@commit.short_id})")) end @@ -17,7 +17,7 @@ module Emails @target_url = project_issue_url(@project, @issue, anchor: "note_#{@note.id}") set_reference("issue_#{@issue.id}") mail(from: sender(@note.author_id), - to: recipient(recipient_id), + cc: recipient(recipient_id), subject: subject("#{@issue.title} (##{@issue.iid})")) end @@ -28,7 +28,7 @@ module Emails @target_url = project_merge_request_url(@project, @merge_request, anchor: "note_#{@note.id}") set_reference("merge_request_#{@merge_request.id}") mail(from: sender(@note.author_id), - to: recipient(recipient_id), + cc: recipient(recipient_id), subject: subject("#{@merge_request.title} (##{@merge_request.iid})")) end @@ -37,7 +37,7 @@ module Emails @project = @note.project @target_url = project_wall_url(@note.project, anchor: "note_#{@note.id}") mail(from: sender(@note.author_id), - to: recipient(recipient_id), + cc: recipient(recipient_id), subject: subject("Note on wall")) end end diff --git a/app/mailers/emails/projects.rb b/app/mailers/emails/projects.rb index 9f99c11ea3..6017d9192e 100644 --- a/app/mailers/emails/projects.rb +++ b/app/mailers/emails/projects.rb @@ -4,7 +4,7 @@ module Emails @users_project = UsersProject.find user_project_id @project = @users_project.project @target_url = project_url(@project) - mail(to: @users_project.user.email, + mail(cc: @users_project.user.email, subject: subject("Access to project was granted")) end @@ -12,7 +12,7 @@ module Emails @user = User.find user_id @project = Project.find project_id @target_url = project_url(@project) - mail(to: @user.email, + mail(cc: @user.email, subject: subject("Project was moved")) end @@ -30,7 +30,7 @@ module Emails end mail(from: sender(author_id), - to: recipient, + cc: recipient, subject: subject("New push to repository")) end end diff --git a/app/mailers/notify.rb b/app/mailers/notify.rb index 84a0da0129..8eea8cf25e 100644 --- a/app/mailers/notify.rb +++ b/app/mailers/notify.rb @@ -1,4 +1,6 @@ class Notify < ActionMailer::Base + include ActionDispatch::Routing::PolymorphicRoutes + include Emails::Issues include Emails::MergeRequests include Emails::Notes @@ -16,6 +18,7 @@ class Notify < ActionMailer::Base default_url_options[:script_name] = Gitlab.config.gitlab.relative_url_root default from: Proc.new { default_sender_address.format } + default to: Proc.new { project_sender_address.format } default reply_to: "noreply@#{Gitlab.config.gitlab.host}" # Just send email with 2 seconds delay @@ -32,6 +35,17 @@ class Notify < ActionMailer::Base address end + # The default email address to send emails to. Includes the project name if possible. + def project_sender_address + if @project + address = default_sender_address + address.display_name = @project.name_with_namespace + address + else + default_sender_address + end + end + # Return an email address that displays the name of the sender. # Only the displayed name changes; the actual email address is always the same. def sender(sender_id) diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb index 547268d44f..6725e35089 100644 --- a/spec/mailers/notify_spec.rb +++ b/spec/mailers/notify_spec.rb @@ -10,7 +10,7 @@ describe Notify do shared_examples 'a multiple recipients email' do it 'is sent to the given recipient' do - should deliver_to recipient.email + should cc_to recipient.email end end @@ -141,7 +141,7 @@ describe Notify do end it 'is sent to the assignee' do - should deliver_to assignee.email + should cc_to assignee.email end end @@ -394,7 +394,7 @@ describe Notify do end it 'is sent to the given recipient' do - should deliver_to recipient.email + should cc_to recipient.email end it 'contains the message from the note' do @@ -538,7 +538,7 @@ describe Notify do end it 'is sent to recipient' do - should deliver_to 'devs@company.name' + should cc_to 'devs@company.name' end it 'has the correct subject' do diff --git a/spec/services/issues/close_service_spec.rb b/spec/services/issues/close_service_spec.rb index d4f2cc1339..7324650d53 100644 --- a/spec/services/issues/close_service_spec.rb +++ b/spec/services/issues/close_service_spec.rb @@ -22,7 +22,7 @@ describe Issues::CloseService do it 'should send email to user2 about assign of new issue' do email = ActionMailer::Base.deliveries.last - email.to.first.should == user2.email + email.cc.first.should == user2.email email.subject.should include(issue.title) end diff --git a/spec/services/issues/update_service_spec.rb b/spec/services/issues/update_service_spec.rb index 347560414e..47d1856503 100644 --- a/spec/services/issues/update_service_spec.rb +++ b/spec/services/issues/update_service_spec.rb @@ -31,7 +31,7 @@ describe Issues::UpdateService do it 'should send email to user2 about assign of new issue' do email = ActionMailer::Base.deliveries.last - email.to.first.should == user2.email + email.cc.first.should == user2.email email.subject.should include(issue.title) end diff --git a/spec/services/merge_requests/close_service_spec.rb b/spec/services/merge_requests/close_service_spec.rb index a504f916b0..2c5a7c4f26 100644 --- a/spec/services/merge_requests/close_service_spec.rb +++ b/spec/services/merge_requests/close_service_spec.rb @@ -22,7 +22,7 @@ describe MergeRequests::CloseService do it 'should send email to user2 about assign of new merge_request' do email = ActionMailer::Base.deliveries.last - email.to.first.should == user2.email + email.cc.first.should == user2.email email.subject.should include(merge_request.title) end diff --git a/spec/services/merge_requests/update_service_spec.rb b/spec/services/merge_requests/update_service_spec.rb index af5d3a3dc8..42ac05862b 100644 --- a/spec/services/merge_requests/update_service_spec.rb +++ b/spec/services/merge_requests/update_service_spec.rb @@ -31,7 +31,7 @@ describe MergeRequests::UpdateService do it 'should send email to user2 about assign of new merge_request' do email = ActionMailer::Base.deliveries.last - email.to.first.should == user2.email + email.cc.first.should == user2.email email.subject.should include(merge_request.title) end From de90b572d8f22708ea76ffbea9c513143fdeea2e Mon Sep 17 00:00:00 2001 From: Pierre de La Morinerie Date: Mon, 24 Feb 2014 12:12:29 +0100 Subject: [PATCH 279/360] Allow more mail clients to group emails by thread MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * send a ‘In-Reply-To’ header along the ‘References’ header * subject of answers to an existing thread begins with ‘Re: ’ This fixes threading with at least Mail.app and Airmail. --- app/mailers/emails/issues.rb | 32 ++++++++--------- app/mailers/emails/merge_requests.rb | 32 ++++++++--------- app/mailers/emails/notes.rb | 23 ++++++------ app/mailers/notify.rb | 52 +++++++++++++++++++++++----- spec/mailers/notify_spec.rb | 45 +++++++++++++++--------- 5 files changed, 116 insertions(+), 68 deletions(-) diff --git a/app/mailers/emails/issues.rb b/app/mailers/emails/issues.rb index 50676ac10c..516e3da84c 100644 --- a/app/mailers/emails/issues.rb +++ b/app/mailers/emails/issues.rb @@ -4,10 +4,10 @@ module Emails @issue = Issue.find(issue_id) @project = @issue.project @target_url = project_issue_url(@project, @issue) - set_message_id("issue_#{issue_id}") - mail(from: sender(@issue.author_id), - cc: recipient(recipient_id), - subject: subject("#{@issue.title} (##{@issue.iid})")) + mail_new_thread(@issue, + from: sender(@issue.author_id), + cc: recipient(recipient_id), + subject: subject("#{@issue.title} (##{@issue.iid})")) end def reassigned_issue_email(recipient_id, issue_id, previous_assignee_id, updated_by_user_id) @@ -15,10 +15,10 @@ module Emails @previous_assignee = User.find_by(id: previous_assignee_id) if previous_assignee_id @project = @issue.project @target_url = project_issue_url(@project, @issue) - set_reference("issue_#{issue_id}") - mail(from: sender(updated_by_user_id), - cc: recipient(recipient_id), - subject: subject("#{@issue.title} (##{@issue.iid})")) + mail_answer_thread(@issue, + from: sender(updated_by_user_id), + cc: recipient(recipient_id), + subject: subject("#{@issue.title} (##{@issue.iid})")) end def closed_issue_email(recipient_id, issue_id, updated_by_user_id) @@ -26,10 +26,10 @@ module Emails @project = @issue.project @updated_by = User.find updated_by_user_id @target_url = project_issue_url(@project, @issue) - set_reference("issue_#{issue_id}") - mail(from: sender(updated_by_user_id), - cc: recipient(recipient_id), - subject: subject("#{@issue.title} (##{@issue.iid})")) + mail_answer_thread(@issue, + from: sender(updated_by_user_id), + cc: recipient(recipient_id), + subject: subject("#{@issue.title} (##{@issue.iid})")) end def issue_status_changed_email(recipient_id, issue_id, status, updated_by_user_id) @@ -38,10 +38,10 @@ module Emails @project = @issue.project @updated_by = User.find updated_by_user_id @target_url = project_issue_url(@project, @issue) - set_reference("issue_#{issue_id}") - mail(from: sender(updated_by_user_id), - cc: recipient(recipient_id), - subject: subject("#{@issue.title} (##{@issue.iid})")) + mail_answer_thread(@issue, + from: sender(updated_by_user_id), + cc: recipient(recipient_id), + subject: subject("#{@issue.title} (##{@issue.iid})")) end end end diff --git a/app/mailers/emails/merge_requests.rb b/app/mailers/emails/merge_requests.rb index 6b46cc90e0..c4ca3a3b69 100644 --- a/app/mailers/emails/merge_requests.rb +++ b/app/mailers/emails/merge_requests.rb @@ -4,10 +4,10 @@ module Emails @merge_request = MergeRequest.find(merge_request_id) @project = @merge_request.project @target_url = project_merge_request_url(@project, @merge_request) - set_message_id("merge_request_#{merge_request_id}") - mail(from: sender(@merge_request.author_id), - cc: recipient(recipient_id), - subject: subject("#{@merge_request.title} (##{@merge_request.iid})")) + mail_new_thread(@merge_request, + from: sender(@merge_request.author_id), + cc: recipient(recipient_id), + subject: subject("#{@merge_request.title} (##{@merge_request.iid})")) end def reassigned_merge_request_email(recipient_id, merge_request_id, previous_assignee_id, updated_by_user_id) @@ -15,10 +15,10 @@ module Emails @previous_assignee = User.find_by(id: previous_assignee_id) if previous_assignee_id @project = @merge_request.project @target_url = project_merge_request_url(@project, @merge_request) - set_reference("merge_request_#{merge_request_id}") - mail(from: sender(updated_by_user_id), - cc: recipient(recipient_id), - subject: subject("#{@merge_request.title} (##{@merge_request.iid})")) + mail_answer_thread(@merge_request, + from: sender(updated_by_user_id), + cc: recipient(recipient_id), + subject: subject("#{@merge_request.title} (##{@merge_request.iid})")) end def closed_merge_request_email(recipient_id, merge_request_id, updated_by_user_id) @@ -26,20 +26,20 @@ module Emails @updated_by = User.find updated_by_user_id @project = @merge_request.project @target_url = project_merge_request_url(@project, @merge_request) - set_reference("merge_request_#{merge_request_id}") - mail(from: sender(updated_by_user_id), - cc: recipient(recipient_id), - subject: subject("#{@merge_request.title} (##{@merge_request.iid})")) + mail_answer_thread(@merge_request, + from: sender(updated_by_user_id), + cc: recipient(recipient_id), + subject: subject("#{@merge_request.title} (##{@merge_request.iid})")) end def merged_merge_request_email(recipient_id, merge_request_id, updated_by_user_id) @merge_request = MergeRequest.find(merge_request_id) @project = @merge_request.project @target_url = project_merge_request_url(@project, @merge_request) - set_reference("merge_request_#{merge_request_id}") - mail(from: sender(updated_by_user_id), - cc: recipient(recipient_id), - subject: subject("#{@merge_request.title} (##{@merge_request.iid})")) + mail_answer_thread(@merge_request, + from: sender(updated_by_user_id), + cc: recipient(recipient_id), + subject: subject("#{@merge_request.title} (##{@merge_request.iid})")) end end diff --git a/app/mailers/emails/notes.rb b/app/mailers/emails/notes.rb index d6ab63fe68..7848d34ab2 100644 --- a/app/mailers/emails/notes.rb +++ b/app/mailers/emails/notes.rb @@ -5,9 +5,10 @@ module Emails @commit = @note.noteable @project = @note.project @target_url = project_commit_url(@project, @commit, anchor: "note_#{@note.id}") - mail(from: sender(@note.author_id), - cc: recipient(recipient_id), - subject: subject("#{@commit.title} (#{@commit.short_id})")) + mail_answer_thread(@commit, + from: sender(@note.author_id), + cc: recipient(recipient_id), + subject: subject("#{@commit.title} (#{@commit.short_id})")) end def note_issue_email(recipient_id, note_id) @@ -15,10 +16,10 @@ module Emails @issue = @note.noteable @project = @note.project @target_url = project_issue_url(@project, @issue, anchor: "note_#{@note.id}") - set_reference("issue_#{@issue.id}") - mail(from: sender(@note.author_id), - cc: recipient(recipient_id), - subject: subject("#{@issue.title} (##{@issue.iid})")) + mail_answer_thread(@issue, + from: sender(@note.author_id), + cc: recipient(recipient_id), + subject: subject("#{@issue.title} (##{@issue.iid})")) end def note_merge_request_email(recipient_id, note_id) @@ -26,10 +27,10 @@ module Emails @merge_request = @note.noteable @project = @note.project @target_url = project_merge_request_url(@project, @merge_request, anchor: "note_#{@note.id}") - set_reference("merge_request_#{@merge_request.id}") - mail(from: sender(@note.author_id), - cc: recipient(recipient_id), - subject: subject("#{@merge_request.title} (##{@merge_request.iid})")) + mail_answer_thread(@merge_request, + from: sender(@note.author_id), + cc: recipient(recipient_id), + subject: subject("#{@merge_request.title} (##{@merge_request.iid})")) end def note_wall_email(recipient_id, note_id) diff --git a/app/mailers/notify.rb b/app/mailers/notify.rb index 8eea8cf25e..d65bead9cf 100644 --- a/app/mailers/notify.rb +++ b/app/mailers/notify.rb @@ -67,14 +67,6 @@ class Notify < ActionMailer::Base end end - # Set the Message-ID header field - # - # local_part - The local part of the message ID - # - def set_message_id(local_part) - headers["Message-ID"] = "<#{local_part}@#{Gitlab.config.gitlab.host}>" - end - # Set the References header field # # local_part - The local part of the referenced message ID @@ -107,4 +99,48 @@ class Notify < ActionMailer::Base subject << extra.join(' | ') if extra.present? subject end + + # Return a string suitable for inclusion in the 'Message-Id' mail header. + # + # The message-id is generated from the unique URL to a model object. + def message_id(model) + model_name = model.class.model_name.singular_route_key + "<#{model_name}_#{model.id}@#{Gitlab.config.gitlab.host}>" + end + + # Send an email that starts a new conversation thread, + # with headers suitable for grouping by thread in email clients. + # + # See: mail_answer_thread + def mail_new_thread(model, headers = {}, &block) + raise ArgumentError, '"To:" header will be overwritten; use "Cc:" or "Bcc:"' unless headers[:to].nil? + headers[:to] = project_sender_address.format + + headers['Message-ID'] = message_id(model) + + mail(headers, &block) + end + + # Send an email that responds to an existing conversation thread, + # with headers suitable for grouping by thread in email clients. + # + # For grouping emails by thread, email clients heuristics require the answers to: + # + # * have a subject that begin by 'Re: ' + # * have a 'In-Reply-To' or 'References' header that references the original 'Message-ID' + # * have stable 'From' and 'To' headers between messages of the same thread + # + def mail_answer_thread(model, headers = {}, &block) + raise ArgumentError, '"To:" header will be overwritten; use "Cc:" or "Bcc:"' unless headers[:to].nil? + headers[:to] = project_sender_address.format + + headers['In-Reply-To'] = message_id(model) + headers['References'] = message_id(model) + + if (headers[:subject]) + headers[:subject].prepend('Re: ') + end + + mail(headers, &block) + end end diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb index 6725e35089..32ba6c9b86 100644 --- a/spec/mailers/notify_spec.rb +++ b/spec/mailers/notify_spec.rb @@ -22,6 +22,23 @@ describe Notify do end end + shared_examples 'an email starting a new thread' do |message_id_prefix| + it 'has a discussion identifier' do + should have_header 'Message-ID', /<#{message_id_prefix}(.*)@#{Gitlab.config.gitlab.host}>/ + end + end + + shared_examples 'an answer to an existing thread' do |thread_id_prefix| + it 'has a subject that begins with Re: ' do + should have_subject /^Re: / + end + + it 'has headers that reference an existing thread' do + should have_header 'References', /<#{thread_id_prefix}(.*)@#{Gitlab.config.gitlab.host}>/ + should have_header 'In-Reply-To', /<#{thread_id_prefix}(.*)@#{Gitlab.config.gitlab.host}>/ + end + end + describe 'for new users, the email' do let(:example_site_path) { root_path } let(:new_user) { create(:user, email: 'newguy@example.com', created_by_id: 1) } @@ -153,6 +170,7 @@ describe Notify do subject { Notify.new_issue_email(issue.assignee_id, issue.id) } it_behaves_like 'an assignee email' + it_behaves_like 'an email starting a new thread', 'issue' it 'has the correct subject' do should have_subject /#{project.name} \| #{issue.title} \(##{issue.iid}\)/ @@ -161,10 +179,6 @@ describe Notify do it 'contains a link to the new issue' do should have_body_text /#{project_issue_path project, issue}/ end - - it 'has the correct message-id set' do - should have_header 'Message-ID', "" - end end describe 'that are new with a description' do @@ -179,6 +193,7 @@ describe Notify do subject { Notify.reassigned_issue_email(recipient.id, issue.id, previous_assignee.id, current_user) } it_behaves_like 'a multiple recipients email' + it_behaves_like 'an answer to an existing thread', 'issue' it 'is sent as the author' do sender = subject.header[:from].addrs[0] @@ -201,16 +216,14 @@ describe Notify do it 'contains a link to the issue' do should have_body_text /#{project_issue_path project, issue}/ end - - it 'has the correct reference set' do - should have_header 'References', "" - end end describe 'status changed' do let(:status) { 'closed' } subject { Notify.issue_status_changed_email(recipient.id, issue.id, status, current_user) } + it_behaves_like 'an answer to an existing thread', 'issue' + it 'is sent as the author' do sender = subject.header[:from].addrs[0] sender.display_name.should eq(current_user.name) @@ -232,10 +245,6 @@ describe Notify do it 'contains a link to the issue' do should have_body_text /#{project_issue_path project, issue}/ end - - it 'has the correct reference set' do - should have_header 'References', "" - end end end @@ -249,6 +258,7 @@ describe Notify do subject { Notify.new_merge_request_email(merge_request.assignee_id, merge_request.id) } it_behaves_like 'an assignee email' + it_behaves_like 'an email starting a new thread', 'merge_request' it 'has the correct subject' do should have_subject /#{merge_request.title} \(##{merge_request.iid}\)/ @@ -283,6 +293,7 @@ describe Notify do subject { Notify.reassigned_merge_request_email(recipient.id, merge_request.id, previous_assignee.id, current_user.id) } it_behaves_like 'a multiple recipients email' + it_behaves_like 'an answer to an existing thread', 'merge_request' it 'is sent as the author' do sender = subject.header[:from].addrs[0] @@ -311,6 +322,7 @@ describe Notify do subject { Notify.merged_merge_request_email(recipient.id, merge_request.id, merge_author.id) } it_behaves_like 'a multiple recipients email' + it_behaves_like 'an answer to an existing thread', 'merge_request' it 'is sent as the merge author' do sender = subject.header[:from].addrs[0] @@ -329,10 +341,6 @@ describe Notify do it 'contains a link to the merge request' do should have_body_text /#{project_merge_request_path project, merge_request}/ end - - it 'has the correct reference set' do - should have_header 'References', "" - end end end end @@ -426,6 +434,7 @@ describe Notify do subject { Notify.note_commit_email(recipient.id, note.id) } it_behaves_like 'a note email' + it_behaves_like 'an answer to an existing thread', 'commits' it 'has the correct subject' do should have_subject /#{commit.title} \(#{commit.short_id}\)/ @@ -444,6 +453,7 @@ describe Notify do subject { Notify.note_merge_request_email(recipient.id, note.id) } it_behaves_like 'a note email' + it_behaves_like 'an answer to an existing thread', 'merge_request' it 'has the correct subject' do should have_subject /#{merge_request.title} \(##{merge_request.iid}\)/ @@ -462,6 +472,7 @@ describe Notify do subject { Notify.note_issue_email(recipient.id, note.id) } it_behaves_like 'a note email' + it_behaves_like 'an answer to an existing thread', 'issue' it 'has the correct subject' do should have_subject /#{issue.title} \(##{issue.iid}\)/ @@ -574,7 +585,7 @@ describe Notify do end it 'is sent to recipient' do - should deliver_to 'devs@company.name' + should cc_to 'devs@company.name' end it 'has the correct subject' do From d65bf4605e561b58d3bb8ddba0ffb335e3a4c768 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 10 Jun 2014 19:22:39 +0300 Subject: [PATCH 280/360] Fix milestone reopen Signed-off-by: Dmitriy Zaporozhets --- app/services/milestones/reopen_service.rb | 2 +- app/services/milestones/update_service.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/services/milestones/reopen_service.rb b/app/services/milestones/reopen_service.rb index ff1ba23bdb..573f9ee5c2 100644 --- a/app/services/milestones/reopen_service.rb +++ b/app/services/milestones/reopen_service.rb @@ -1,7 +1,7 @@ module Milestones class ReopenService < Milestones::BaseService def execute(milestone) - if milestone.reopen + if milestone.activate event_service.reopen_milestone(milestone, current_user) end diff --git a/app/services/milestones/update_service.rb b/app/services/milestones/update_service.rb index 69254a7967..307e96a2b3 100644 --- a/app/services/milestones/update_service.rb +++ b/app/services/milestones/update_service.rb @@ -1,10 +1,10 @@ module Milestones class UpdateService < Milestones::BaseService def execute(milestone) - state = params.delete('state_event') + state = params.delete('state_event') || params.delete(:state_event) case state - when 'reopen' + when 'activate' Milestones::ReopenService.new(project, current_user, {}).execute(milestone) when 'close' Milestones::CloseService.new(project, current_user, {}).execute(milestone) From f6ee55aabd31c624d5bca71bca5c6ed152d844d0 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 10 Jun 2014 19:23:02 +0300 Subject: [PATCH 281/360] Fix issue/mr close/reopen via API Signed-off-by: Dmitriy Zaporozhets --- app/services/issues/update_service.rb | 2 +- app/services/merge_requests/update_service.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/services/issues/update_service.rb b/app/services/issues/update_service.rb index f69370bedd..b4a742b003 100644 --- a/app/services/issues/update_service.rb +++ b/app/services/issues/update_service.rb @@ -1,7 +1,7 @@ module Issues class UpdateService < Issues::BaseService def execute(issue) - state = params.delete('state_event') + state = params.delete('state_event') || params.delete(:state_event) case state when 'reopen' diff --git a/app/services/merge_requests/update_service.rb b/app/services/merge_requests/update_service.rb index 60d470a060..f1aa8b7393 100644 --- a/app/services/merge_requests/update_service.rb +++ b/app/services/merge_requests/update_service.rb @@ -10,7 +10,7 @@ module MergeRequests params.delete(:source_project_id) params.delete(:target_project_id) - state = params.delete('state_event') + state = params.delete('state_event') || params.delete(:state_event) case state when 'reopen' From 1c23333f344205f97fc909af724ed88c2ee45c2b Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 10 Jun 2014 20:59:26 +0300 Subject: [PATCH 282/360] Align issue box content and mr widgets vertically Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/generic/issue_box.scss | 11 +++++------ app/assets/stylesheets/sections/merge_requests.scss | 4 ++++ .../projects/merge_requests/show/_commits.html.haml | 2 +- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/app/assets/stylesheets/generic/issue_box.scss b/app/assets/stylesheets/generic/issue_box.scss index 3cb64d69a9..c468980f64 100644 --- a/app/assets/stylesheets/generic/issue_box.scss +++ b/app/assets/stylesheets/generic/issue_box.scss @@ -56,23 +56,22 @@ .state { border-bottom: 1px solid #DDD; - padding: 10px 25px; + padding: 10px 15px; } .title { - font-size: 26px; + font-size: 28px; font-weight: normal; line-height: 1.5; margin: 0; color: #333; - padding-bottom: 0; - padding: 15px 25px; + padding: 10px 15px; } .context { border: none; border-top: 1px solid #eee; - padding: 15px 25px; + padding: 10px 15px; // Reset text align for children .text-right > * { text-align: left; } @@ -88,7 +87,7 @@ } .description { - padding: 0 25px 15px 25px; + padding: 0 15px 10px 15px; } .title, .context, .description { diff --git a/app/assets/stylesheets/sections/merge_requests.scss b/app/assets/stylesheets/sections/merge_requests.scss index 5bff00f376..debbec4cb9 100644 --- a/app/assets/stylesheets/sections/merge_requests.scss +++ b/app/assets/stylesheets/sections/merge_requests.scss @@ -118,3 +118,7 @@ .merge-request-show-labels .label { padding: 6px 10px; } + +.mr-commits .commit { + padding: 10px 15px; +} diff --git a/app/views/projects/merge_requests/show/_commits.html.haml b/app/views/projects/merge_requests/show/_commits.html.haml index e62ab9d9d3..92a7bb927e 100644 --- a/app/views/projects/merge_requests/show/_commits.html.haml +++ b/app/views/projects/merge_requests/show/_commits.html.haml @@ -3,7 +3,7 @@ .panel-heading %i.icon-list Commits (#{@commits.count}) - .commits + .commits.mr-commits - if @commits.count > 8 %ul.first-commits.well-list - @commits.first(8).each do |commit| From de55d7aa577e52315866f605a08c43e547877eec Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 10 Jun 2014 20:59:51 +0300 Subject: [PATCH 283/360] issue-box content can be shown on sm devices easily Signed-off-by: Dmitriy Zaporozhets --- app/views/projects/issues/_issue_context.html.haml | 4 ++-- app/views/projects/merge_requests/show/_context.html.haml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/views/projects/issues/_issue_context.html.haml b/app/views/projects/issues/_issue_context.html.haml index 425dcb45dd..d7987f43fb 100644 --- a/app/views/projects/issues/_issue_context.html.haml +++ b/app/views/projects/issues/_issue_context.html.haml @@ -1,6 +1,6 @@ = form_for [@project, @issue], remote: true, html: {class: 'edit-issue inline-update'} do |f| .row - .col-md-6 + .col-sm-6 %strong.append-right-10 Assignee: @@ -11,7 +11,7 @@ - else None - .col-md-6.text-right + .col-sm-6.text-right %strong.append-right-10 Milestone: - if can?(current_user, :modify_issue, @issue) diff --git a/app/views/projects/merge_requests/show/_context.html.haml b/app/views/projects/merge_requests/show/_context.html.haml index 5c6734fd24..ab00b34242 100644 --- a/app/views/projects/merge_requests/show/_context.html.haml +++ b/app/views/projects/merge_requests/show/_context.html.haml @@ -1,6 +1,6 @@ = form_for [@project, @merge_request], remote: true, html: {class: 'edit-merge_request inline-update'} do |f| .row - .col-md-6 + .col-sm-6 %strong.append-right-10 Assignee: @@ -11,7 +11,7 @@ - else None - .col-md-6.text-right + .col-sm-6.text-right %strong.append-right-10 Milestone: - if can?(current_user, :modify_merge_request, @merge_request) From 8aac4fadba2c50d2a1b855c893fba31038cc15d8 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 10 Jun 2014 21:57:05 +0300 Subject: [PATCH 284/360] Small ui fixes Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/sections/issues.scss | 2 +- app/views/projects/merge_requests/_new_submit.html.haml | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/app/assets/stylesheets/sections/issues.scss b/app/assets/stylesheets/sections/issues.scss index 949c528bdb..495a7cb311 100644 --- a/app/assets/stylesheets/sections/issues.scss +++ b/app/assets/stylesheets/sections/issues.scss @@ -27,7 +27,7 @@ display: none; position: absolute; top: 10px; - right: 2px; + right: 15px; } &:hover { diff --git a/app/views/projects/merge_requests/_new_submit.html.haml b/app/views/projects/merge_requests/_new_submit.html.haml index 01bc10421b..34a30975e0 100644 --- a/app/views/projects/merge_requests/_new_submit.html.haml +++ b/app/views/projects/merge_requests/_new_submit.html.haml @@ -24,10 +24,9 @@ .light = f.label :description, "Description" = f.text_area :description, class: "form-control js-gfm-input markdown-area", rows: 10 - .col-sm-12.hint + .clearfix.hint .pull-left Description is parsed with #{link_to "GitLab Flavored Markdown", help_page_path("markdown", "markdown"), target: '_blank'}. .pull-right Attach images (JPG, PNG, GIF) by dragging & dropping or #{link_to "selecting them", '#', class: 'markdown-selector' }. - .clearfix .error-alert .form-group .issue-assignee @@ -37,7 +36,7 @@ %div = project_users_select_tag('merge_request[assignee_id]', placeholder: 'Select a user', class: 'custom-form-control', selected: @merge_request.assignee_id, project_id: @merge_request.target_project_id)   - = link_to 'Assign to me', '#', class: 'btn btn-small assign-to-me-link' + = link_to 'Assign to me', '#', class: 'btn assign-to-me-link' .form-group .issue-milestone = f.label :milestone_id do From 1f5891e99183f1b20ced08d75dd44c9a01c48094 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 10 Jun 2014 22:01:56 +0300 Subject: [PATCH 285/360] Use more compact bordered-list for commits page Signed-off-by: Dmitriy Zaporozhets --- app/views/projects/commits/_commits.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/projects/commits/_commits.html.haml b/app/views/projects/commits/_commits.html.haml index e3411b62eb..77f795f23f 100644 --- a/app/views/projects/commits/_commits.html.haml +++ b/app/views/projects/commits/_commits.html.haml @@ -6,6 +6,6 @@ %span= day.stamp("28 Aug, 2010") %p= pluralize(commits.count, 'commit') .col-md-10 - %ul.well-list + %ul.bordered-list = render commits, project: @project %hr.lists-separator From 587502390b3afa423a10f98f7568a26352cb0976 Mon Sep 17 00:00:00 2001 From: Marvin Frick Date: Fri, 9 May 2014 14:26:19 +0200 Subject: [PATCH 286/360] fixes gitlab.com issue #229 Changes .js.coffe files to not use a hardcoded path to `no_avatar.png` but instead stick with the asset pipeline. renames coffee.erb back to coffee --- app/assets/javascripts/project_users_select.js.coffee | 2 +- app/assets/javascripts/users_select.js.coffee | 2 +- app/helpers/application_helper.rb | 2 +- spec/helpers/application_helper_spec.rb | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/assets/javascripts/project_users_select.js.coffee b/app/assets/javascripts/project_users_select.js.coffee index a7fec96040..382f9b3799 100644 --- a/app/assets/javascripts/project_users_select.js.coffee +++ b/app/assets/javascripts/project_users_select.js.coffee @@ -43,7 +43,7 @@ avatar = avatar.replace('%{hash}', md5(user.email)) avatar = avatar.replace('%{size}', '24') else - avatar = gon.relative_url_root + "/assets/no_avatar.png" + avatar = gon.relative_url_root + "#{image_path('no_avatar.png')}" if user.id == '' avatarMarkup = '' diff --git a/app/assets/javascripts/users_select.js.coffee b/app/assets/javascripts/users_select.js.coffee index cab9f6271e..da66a4ba7f 100644 --- a/app/assets/javascripts/users_select.js.coffee +++ b/app/assets/javascripts/users_select.js.coffee @@ -7,7 +7,7 @@ $ -> avatar = avatar.replace('%{hash}', md5(user.email)) avatar = avatar.replace('%{size}', '24') else - avatar = gon.relative_url_root + "/assets/no_avatar.png" + avatar = gon.relative_url_root + "#{image_path('no_avatar.png')}" "
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 198ca76545..32010701e4 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -71,7 +71,7 @@ module ApplicationHelper size = 40 if size.nil? || size <= 0 if !Gitlab.config.gravatar.enabled || user_email.blank? - '/assets/no_avatar.png' + image_path('no_avatar.png') else gravatar_url = request.ssl? || gitlab_config.https ? Gitlab.config.gravatar.ssl_url : Gitlab.config.gravatar.plain_url user_email.strip! diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb index 10c5617d24..6401ec0710 100644 --- a/spec/helpers/application_helper_spec.rb +++ b/spec/helpers/application_helper_spec.rb @@ -79,11 +79,11 @@ describe ApplicationHelper do it "should return a generic avatar path when Gravatar is disabled" do Gitlab.config.gravatar.stub(:enabled).and_return(false) - gravatar_icon(user_email).should == '/assets/no_avatar.png' + gravatar_icon(user_email).should match('no_avatar.png') end it "should return a generic avatar path when email is blank" do - gravatar_icon('').should == '/assets/no_avatar.png' + gravatar_icon('').should match('no_avatar.png') end it "should return default gravatar url" do From d2d99521b62677acaf6904914e844bbf17cbc697 Mon Sep 17 00:00:00 2001 From: Sytse Sijbrandij Date: Wed, 11 Jun 2014 10:37:48 +0200 Subject: [PATCH 287/360] Clarify the master branch release instructions. --- doc/release/master.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/release/master.md b/doc/release/master.md index bed5692d0a..19070b46a0 100644 --- a/doc/release/master.md +++ b/doc/release/master.md @@ -1,8 +1,10 @@ # How to push GitLab CE master branch to all remotes. -Distribution to other repo's is done by the lead developer if there is no rush. +The source code of GitLab is available on multiple servers (with GitLab.com as the canonical source). +Synchronization between the repo's is done by the lead developer if there is no rush. This happens a few times per workday on average. -If a GitLab B.V. person wants to do it here are the instructions. +If somebody else with access to all repo's wants to do it the instructions are below. +This is just to distribute changes, not to make them. ## Add this to `.bashrc` or [your dotfiles](https://github.com/dosire/dotfiles/commit/52803ce3ac60d57632164b7713ff0041e86fa26c) From e57fdc1190af582544154b77f0271ef9f206bc47 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Wed, 11 Jun 2014 13:04:30 +0200 Subject: [PATCH 288/360] Remove email_validator gem and allow apostrophe as a valid character in email. --- Gemfile | 3 --- Gemfile.lock | 3 --- lib/gitlab/email_validator.rb | 21 +++++++++++++++++++++ 3 files changed, 21 insertions(+), 6 deletions(-) create mode 100644 lib/gitlab/email_validator.rb diff --git a/Gemfile b/Gemfile index 5b45b8bdcc..719d65a2eb 100644 --- a/Gemfile +++ b/Gemfile @@ -50,9 +50,6 @@ gem "grape", "~> 0.6.1" gem "grape-entity", "~> 0.4.2" gem 'rack-cors', require: 'rack/cors' -# Email validation -gem "email_validator", "~> 1.4.0", :require => 'email_validator/strict' - # Format dates and times # based on human-friendly examples gem "stamp" diff --git a/Gemfile.lock b/Gemfile.lock index 0d13ed5884..9e4dd35965 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -110,8 +110,6 @@ GEM email_spec (1.5.0) launchy (~> 2.1) mail (~> 2.2) - email_validator (1.4.0) - activemodel emoji (1.0.1) json enumerize (0.7.0) @@ -591,7 +589,6 @@ DEPENDENCIES diffy (~> 3.0.3) dropzonejs-rails email_spec - email_validator (~> 1.4.0) enumerize factory_girl_rails ffaker diff --git a/lib/gitlab/email_validator.rb b/lib/gitlab/email_validator.rb new file mode 100644 index 0000000000..0a67ebcd79 --- /dev/null +++ b/lib/gitlab/email_validator.rb @@ -0,0 +1,21 @@ +# Based on https://github.com/balexand/email_validator +# +# Extended to use only strict mode with following allowed characters: +# ' - apostrophe +# +# See http://www.remote.org/jochen/mail/info/chars.html +# +class EmailValidator < ActiveModel::EachValidator + @@default_options = {} + + def self.default_options + @@default_options + end + + def validate_each(record, attribute, value) + options = @@default_options.merge(self.options) + unless value =~ /\A\s*([-a-z0-9+._']{1,64})@((?:[-a-z0-9]+\.)+[a-z]{2,})\s*\z/i + record.errors.add(attribute, options[:message] || :invalid) + end + end +end From dd86ce3f062ed84d90aa51ab5aee4cfcce24cda5 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 11 Jun 2014 14:09:45 +0300 Subject: [PATCH 289/360] Sort issues in milestone Signed-off-by: Dmitriy Zaporozhets --- app/assets/javascripts/milestone.js.coffee | 16 ++++++++++++++++ .../projects/milestones_controller.rb | 12 +++++++++++- app/views/projects/milestones/_issue.html.haml | 2 +- app/views/projects/milestones/_issues.html.haml | 2 +- config/routes.rb | 6 +++++- 5 files changed, 34 insertions(+), 4 deletions(-) diff --git a/app/assets/javascripts/milestone.js.coffee b/app/assets/javascripts/milestone.js.coffee index 4a2c5068ba..3418832a9c 100644 --- a/app/assets/javascripts/milestone.js.coffee +++ b/app/assets/javascripts/milestone.js.coffee @@ -11,6 +11,18 @@ class Milestone new Flash("Issue update failed", 'alert') dataType: "json" + @sortIssues: (data) -> + sort_issues_url = location.href + "/sort_issues" + + $.ajax + type: "PUT" + url: sort_issues_url + data: data + success: (data) -> + if data.saved != true + new Flash("Issues update failed", 'alert') + dataType: "json" + @updateMergeRequest: (li, merge_request_url, data) -> $.ajax type: "PUT" @@ -31,6 +43,10 @@ class Milestone $("#issues-list-unassigned, #issues-list-ongoing, #issues-list-closed").sortable( connectWith: ".issues-sortable-list", dropOnEmpty: true, + update: (event, ui) -> + data = $(this).sortable("serialize") + Milestone.sortIssues(data) + receive: (event, ui) -> new_state = $(this).data('state') issue_id = ui.item.data('iid') diff --git a/app/controllers/projects/milestones_controller.rb b/app/controllers/projects/milestones_controller.rb index 227cc1dfba..139470237d 100644 --- a/app/controllers/projects/milestones_controller.rb +++ b/app/controllers/projects/milestones_controller.rb @@ -1,6 +1,6 @@ class Projects::MilestonesController < Projects::ApplicationController before_filter :module_enabled - before_filter :milestone, only: [:edit, :update, :destroy, :show] + before_filter :milestone, only: [:edit, :update, :destroy, :show, :sort_issues] # Allow read any milestone before_filter :authorize_read_milestone! @@ -72,6 +72,16 @@ class Projects::MilestonesController < Projects::ApplicationController end end + def sort_issues + @issues = @milestone.issues.where(id: params['sortable_issue']) + @issues.each do |issue| + issue.position = params['sortable_issue'].index(issue.id.to_s) + 1 + issue.save + end + + render json: { saved: true } + end + protected def milestone diff --git a/app/views/projects/milestones/_issue.html.haml b/app/views/projects/milestones/_issue.html.haml index fe93164a70..7c993e01c2 100644 --- a/app/views/projects/milestones/_issue.html.haml +++ b/app/views/projects/milestones/_issue.html.haml @@ -1,4 +1,4 @@ -%li{ class: 'issue-row', 'data-iid' => issue.iid, 'data-url' => project_issue_path(@project, issue) } +%li{ id: dom_id(issue, 'sortable'), class: 'issue-row', 'data-iid' => issue.iid, 'data-url' => project_issue_path(@project, issue) } %span.str-truncated = link_to [@project, issue] do %span.cgray ##{issue.iid} diff --git a/app/views/projects/milestones/_issues.html.haml b/app/views/projects/milestones/_issues.html.haml index 9dbcab19a2..95a4a9296c 100644 --- a/app/views/projects/milestones/_issues.html.haml +++ b/app/views/projects/milestones/_issues.html.haml @@ -1,6 +1,6 @@ .panel.panel-default .panel-heading= title %ul{ class: "well-list issues-sortable-list", id: "issues-list-#{id}", "data-state" => id } - - issues.each do |issue| + - issues.sort_by(&:position).each do |issue| = render 'issue', issue: issue %li.light Drag and drop available diff --git a/config/routes.rb b/config/routes.rb index 67ff66757e..c38b5c42a7 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -278,7 +278,11 @@ Gitlab::Application.routes.draw do end resources :team, controller: 'team_members', only: [:index] - resources :milestones, except: [:destroy], constraints: {id: /\d+/} + resources :milestones, except: [:destroy], constraints: {id: /\d+/} do + member do + put :sort_issues + end + end resources :labels, only: [:index] do collection do From f43e41973f912588d7af23a5575ede94a88d3a5d Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Wed, 11 Jun 2014 13:22:56 +0200 Subject: [PATCH 290/360] Test for the apostrophe in the email --- lib/{gitlab => }/email_validator.rb | 0 spec/models/user_spec.rb | 11 +++++++++++ 2 files changed, 11 insertions(+) rename lib/{gitlab => }/email_validator.rb (100%) diff --git a/lib/gitlab/email_validator.rb b/lib/email_validator.rb similarity index 100% rename from lib/gitlab/email_validator.rb rename to lib/email_validator.rb diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 34a5bcfb4a..4e0ebb584d 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -83,11 +83,17 @@ describe User do user = build(:user, email: 'info@example.com') expect(user).to be_valid end + it 'accepts info+test@example.com' do user = build(:user, email: 'info+test@example.com') expect(user).to be_valid end + it "accepts o'reilly@example.com" do + user = build(:user, email: "o'reilly@example.com") + expect(user).to be_valid + end + it 'rejects test@test@example.com' do user = build(:user, email: 'test@test@example.com') expect(user).to be_invalid @@ -97,6 +103,11 @@ describe User do user = build(:user, email: 'mailto:test@example.com') expect(user).to be_invalid end + + it "rejects lol!'+=?><#$%^&*()@gmail.com" do + user = build(:user, email: "lol!'+=?><#$%^&*()@gmail.com") + expect(user).to be_invalid + end end end From f2db4a18b96f5e0918dad3ba3cf3744779fc7036 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 11 Jun 2014 16:39:55 +0300 Subject: [PATCH 291/360] Bump gitlab-grit Signed-off-by: Dmitriy Zaporozhets --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 9e4dd35965..013804b999 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -164,7 +164,7 @@ GEM multi_json gitlab-grack (2.0.0.pre) rack (~> 1.5.1) - gitlab-grit (2.6.7) + gitlab-grit (2.6.8) charlock_holmes (~> 0.6) diff-lcs (~> 1.1) mime-types (~> 1.15) From 0b00b3dac3ec31924dae821c0fccc08598161762 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 11 Jun 2014 17:11:52 +0300 Subject: [PATCH 292/360] Add sorting to merge requests on milestone page Signed-off-by: Dmitriy Zaporozhets --- app/assets/javascripts/milestone.js.coffee | 16 ++++++++++++++++ .../projects/milestones_controller.rb | 12 +++++++++++- .../projects/milestones/_merge_request.html.haml | 2 +- .../milestones/_merge_requests.html.haml | 2 +- config/routes.rb | 1 + ...140611135229_add_position_to_merge_request.rb | 5 +++++ db/schema.rb | 11 ++++++----- 7 files changed, 41 insertions(+), 8 deletions(-) create mode 100644 db/migrate/20140611135229_add_position_to_merge_request.rb diff --git a/app/assets/javascripts/milestone.js.coffee b/app/assets/javascripts/milestone.js.coffee index 3418832a9c..97a71b9d33 100644 --- a/app/assets/javascripts/milestone.js.coffee +++ b/app/assets/javascripts/milestone.js.coffee @@ -23,6 +23,18 @@ class Milestone new Flash("Issues update failed", 'alert') dataType: "json" + @sortMergeRequests: (data) -> + sort_mr_url = location.href + "/sort_merge_requests" + + $.ajax + type: "PUT" + url: sort_mr_url + data: data + success: (data) -> + if data.saved != true + new Flash("MR update failed", 'alert') + dataType: "json" + @updateMergeRequest: (li, merge_request_url, data) -> $.ajax type: "PUT" @@ -71,6 +83,10 @@ class Milestone $("#merge_requests-list-unassigned, #merge_requests-list-ongoing, #merge_requests-list-closed").sortable( connectWith: ".merge_requests-sortable-list", dropOnEmpty: true, + update: (event, ui) -> + data = $(this).sortable("serialize") + Milestone.sortMergeRequests(data) + receive: (event, ui) -> new_state = $(this).data('state') merge_request_id = ui.item.data('iid') diff --git a/app/controllers/projects/milestones_controller.rb b/app/controllers/projects/milestones_controller.rb index 139470237d..c38c77d6b8 100644 --- a/app/controllers/projects/milestones_controller.rb +++ b/app/controllers/projects/milestones_controller.rb @@ -1,6 +1,6 @@ class Projects::MilestonesController < Projects::ApplicationController before_filter :module_enabled - before_filter :milestone, only: [:edit, :update, :destroy, :show, :sort_issues] + before_filter :milestone, only: [:edit, :update, :destroy, :show, :sort_issues, :sort_merge_requests] # Allow read any milestone before_filter :authorize_read_milestone! @@ -82,6 +82,16 @@ class Projects::MilestonesController < Projects::ApplicationController render json: { saved: true } end + def sort_merge_requests + @merge_requests = @milestone.merge_requests.where(id: params['sortable_merge_request']) + @merge_requests.each do |merge_request| + merge_request.position = params['sortable_merge_request'].index(merge_request.id.to_s) + 1 + merge_request.save + end + + render json: { saved: true } + end + protected def milestone diff --git a/app/views/projects/milestones/_merge_request.html.haml b/app/views/projects/milestones/_merge_request.html.haml index 4787da51e6..d630c4518d 100644 --- a/app/views/projects/milestones/_merge_request.html.haml +++ b/app/views/projects/milestones/_merge_request.html.haml @@ -1,4 +1,4 @@ -%li{ class: 'mr-row', 'data-iid' => merge_request.iid, 'data-url' => project_merge_request_path(@project, merge_request) } +%li{ id: dom_id(merge_request, 'sortable'), class: 'mr-row', 'data-iid' => merge_request.iid, 'data-url' => project_merge_request_path(@project, merge_request) } %span.str-truncated = link_to [@project, merge_request] do %span.cgray ##{merge_request.iid} diff --git a/app/views/projects/milestones/_merge_requests.html.haml b/app/views/projects/milestones/_merge_requests.html.haml index 18c4660183..521bfa7850 100644 --- a/app/views/projects/milestones/_merge_requests.html.haml +++ b/app/views/projects/milestones/_merge_requests.html.haml @@ -1,6 +1,6 @@ .panel.panel-default .panel-heading= title %ul{ class: "well-list merge_requests-sortable-list", id: "merge_requests-list-#{id}", "data-state" => id } - - merge_requests.each do |merge_request| + - merge_requests.sort_by(&:position).each do |merge_request| = render 'merge_request', merge_request: merge_request %li.light Drag and drop available diff --git a/config/routes.rb b/config/routes.rb index c38b5c42a7..34ee8d2d79 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -281,6 +281,7 @@ Gitlab::Application.routes.draw do resources :milestones, except: [:destroy], constraints: {id: /\d+/} do member do put :sort_issues + put :sort_merge_requests end end diff --git a/db/migrate/20140611135229_add_position_to_merge_request.rb b/db/migrate/20140611135229_add_position_to_merge_request.rb new file mode 100644 index 0000000000..d5fdecd0c3 --- /dev/null +++ b/db/migrate/20140611135229_add_position_to_merge_request.rb @@ -0,0 +1,5 @@ +class AddPositionToMergeRequest < ActiveRecord::Migration + def change + add_column :merge_requests, :position, :integer, default: 0 + end +end diff --git a/db/schema.rb b/db/schema.rb index 93837337af..345b6fd3b6 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: 20140502125220) do +ActiveRecord::Schema.define(version: 20140611135229) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -121,9 +121,9 @@ ActiveRecord::Schema.define(version: 20140502125220) do add_index "merge_request_diffs", ["merge_request_id"], name: "index_merge_request_diffs_on_merge_request_id", unique: true, using: :btree create_table "merge_requests", force: true do |t| - t.string "target_branch", null: false - t.string "source_branch", null: false - t.integer "source_project_id", null: false + t.string "target_branch", null: false + t.string "source_branch", null: false + t.integer "source_project_id", null: false t.integer "author_id" t.integer "assignee_id" t.string "title" @@ -132,9 +132,10 @@ ActiveRecord::Schema.define(version: 20140502125220) do t.integer "milestone_id" t.string "state" t.string "merge_status" - t.integer "target_project_id", null: false + t.integer "target_project_id", null: false t.integer "iid" t.text "description" + t.integer "position", default: 0 end add_index "merge_requests", ["assignee_id"], name: "index_merge_requests_on_assignee_id", using: :btree From 314e4736e485ef00092ff7248503b439fac5c490 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Wed, 11 Jun 2014 17:06:28 +0200 Subject: [PATCH 293/360] Strip apostrophe from email generated usernames. --- lib/gitlab/ldap/user.rb | 4 +++- lib/gitlab/oauth/user.rb | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/gitlab/ldap/user.rb b/lib/gitlab/ldap/user.rb index 01d86430f0..be3fcc4f03 100644 --- a/lib/gitlab/ldap/user.rb +++ b/lib/gitlab/ldap/user.rb @@ -50,7 +50,9 @@ module Gitlab # we look for user by extracting part of their email if !user && email && ldap_conf['allow_username_or_email_login'] uname = email.partition('@').first - user = model.find_by(username: uname) + # Strip apostrophes since they are disallowed as part of username + username = uname.gsub("'", "") + user = model.find_by(username: username) end user diff --git a/lib/gitlab/oauth/user.rb b/lib/gitlab/oauth/user.rb index d154bd8600..c5be884a89 100644 --- a/lib/gitlab/oauth/user.rb +++ b/lib/gitlab/oauth/user.rb @@ -39,7 +39,9 @@ module Gitlab # So we use part of email as username for new user # For LDAP, username is already set to the user's # uid/userid/sAMAccountName. - user.username = email.match(/^[^@]*/)[0] + email_username = email.match(/^[^@]*/)[0] + # Strip apostrophes since they are disallowed as part of username + user.username = email_username.gsub("'", "") end user.save! From 4594ca888610758ba916e1b2f36cdf92b1bdae41 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 11 Jun 2014 19:13:05 +0300 Subject: [PATCH 294/360] Bump gitlab_git Signed-off-by: Dmitriy Zaporozhets --- Gemfile.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 013804b999..3fcea78e1e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -175,7 +175,7 @@ GEM mime-types (~> 1.19) gitlab_emoji (0.0.1.1) emoji (~> 1.0.1) - gitlab_git (5.8.0) + gitlab_git (5.9.0) activesupport (~> 4.0) charlock_holmes (~> 0.6) gitlab-grit (~> 2.6) @@ -534,7 +534,7 @@ GEM eventmachine (>= 0.12.8) http_parser.rb (~> 0.5.1) simple_oauth (~> 0.1.4) - tzinfo (1.2.0) + tzinfo (1.2.1) thread_safe (~> 0.1) uglifier (2.3.2) execjs (>= 0.3.0) From e740a00ed659221929a79e580634424423690514 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 11 Jun 2014 22:08:39 +0300 Subject: [PATCH 295/360] Prevent commit page error if cant collect branches where commit exists Signed-off-by: Dmitriy Zaporozhets --- app/controllers/projects/commit_controller.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/controllers/projects/commit_controller.rb b/app/controllers/projects/commit_controller.rb index c56df65dcb..860ab40829 100644 --- a/app/controllers/projects/commit_controller.rb +++ b/app/controllers/projects/commit_controller.rb @@ -12,7 +12,12 @@ class Projects::CommitController < Projects::ApplicationController return git_not_found! unless @commit @line_notes = project.notes.for_commit_id(commit.id).inline - @branches = project.repository.branch_names_contains(commit.id) + + @branches = begin + project.repository.branch_names_contains(commit.id) + rescue Grit::Git::GitTimeout + [] + end begin @suppress_diff = true if commit.diff_suppress? && !params[:force_show_diff] From afa4a075e463103cd7148bc97db21421a0718a8a Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 11 Jun 2014 22:22:58 +0300 Subject: [PATCH 296/360] Show spinner on network graph while it loading Signed-off-by: Dmitriy Zaporozhets --- app/helpers/application_helper.rb | 7 +++++-- app/views/projects/network/show.html.haml | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 32010701e4..13120d2e58 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -226,8 +226,11 @@ module ApplicationHelper GitHub::Markup.render(file_name, file_content).html_safe end - def spinner(text = nil) - content_tag :div, class: 'loading hide' do + def spinner(text = nil, visible = false) + css_class = "loading" + css_class << " hide" unless visible + + content_tag :div, class: css_class do content_tag(:i, nil, class: 'icon-spinner icon-spin') + text end end diff --git a/app/views/projects/network/show.html.haml b/app/views/projects/network/show.html.haml index da0cfa84c2..37bc0a4c6b 100644 --- a/app/views/projects/network/show.html.haml +++ b/app/views/projects/network/show.html.haml @@ -3,7 +3,7 @@ .tip You can move around the graph by using the arrow keys. .network-graph - = spinner + = spinner nil, true :javascript new Network({ From 5b2193555b69f82f2efdadaf62ada1e9c3c2d77a Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 11 Jun 2014 22:53:42 +0300 Subject: [PATCH 297/360] Describe unicorn timeout value in git over http Signed-off-by: Dmitriy Zaporozhets --- config/unicorn.rb.example | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/config/unicorn.rb.example b/config/unicorn.rb.example index f6c0f09b51..e88a452233 100644 --- a/config/unicorn.rb.example +++ b/config/unicorn.rb.example @@ -34,6 +34,20 @@ listen "/home/git/gitlab/tmp/sockets/gitlab.socket", :backlog => 64 listen "127.0.0.1:8080", :tcp_nopush => true # nuke workers after 30 seconds instead of 60 seconds (the default) +# +# NOTICE: git push over http depends on this value. +# If you want be able to push huge amount of data to git repository over http +# you will have to increase this value too. +# +# Example of output if you try to push 1GB repo to GitLab over http. +# -> git push http://gitlab.... master +# +# error: RPC failed; result=18, HTTP code = 200 +# fatal: The remote end hung up unexpectedly +# fatal: The remote end hung up unexpectedly +# +# For more information see http://stackoverflow.com/a/21682112/752049 +# timeout 30 # feel free to point this anywhere accessible on the filesystem From 7ed935b6765ed1e9de810cfdf8ac9f6eb3fb741d Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 11 Jun 2014 23:13:31 +0300 Subject: [PATCH 298/360] Use gitlab_git to get commit_count in repo. It allows get commits count for git repos with 100k+ commits Signed-off-by: Dmitriy Zaporozhets --- Gemfile | 2 +- Gemfile.lock | 4 ++-- app/models/repository.rb | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Gemfile b/Gemfile index 719d65a2eb..6ef2a48018 100644 --- a/Gemfile +++ b/Gemfile @@ -30,7 +30,7 @@ gem 'omniauth-github' # Extracting information from a git repository # Provide access to Gitlab::Git library -gem "gitlab_git", '~> 5.8' +gem "gitlab_git", '~> 6.0' # Ruby/Rack Git Smart-HTTP Server Handler gem 'gitlab-grack', '~> 2.0.0.pre', require: 'grack' diff --git a/Gemfile.lock b/Gemfile.lock index 3fcea78e1e..133fc693f0 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -175,7 +175,7 @@ GEM mime-types (~> 1.19) gitlab_emoji (0.0.1.1) emoji (~> 1.0.1) - gitlab_git (5.9.0) + gitlab_git (6.0.0) activesupport (~> 4.0) charlock_holmes (~> 0.6) gitlab-grit (~> 2.6) @@ -601,7 +601,7 @@ DEPENDENCIES gitlab-grack (~> 2.0.0.pre) gitlab-linguist (~> 3.0.0) gitlab_emoji (~> 0.0.1.1) - gitlab_git (~> 5.8) + gitlab_git (~> 6.0) gitlab_meta (= 6.0) gitlab_omniauth-ldap (= 1.0.4) gollum-lib (~> 3.0.0) diff --git a/app/models/repository.rb b/app/models/repository.rb index f6e44a5248..00a1032b6c 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -106,7 +106,7 @@ class Repository def commit_count Rails.cache.fetch(cache_key(:commit_count)) do begin - raw_repository.raw.commit_count(self.root_ref) + raw_repository.commit_count(self.root_ref) rescue 0 end From 56f0f6aba399d85c6e99e69c57a18a040bad4cf3 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 11 Jun 2014 23:37:21 +0300 Subject: [PATCH 299/360] Use same 30 seconds satellite timeout for all actions Signed-off-by: Dmitriy Zaporozhets --- lib/gitlab/satellite/files/file_action.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/gitlab/satellite/files/file_action.rb b/lib/gitlab/satellite/files/file_action.rb index 7701a6d5d6..6446b14568 100644 --- a/lib/gitlab/satellite/files/file_action.rb +++ b/lib/gitlab/satellite/files/file_action.rb @@ -4,7 +4,7 @@ module Gitlab attr_accessor :file_path, :ref def initialize(user, project, ref, file_path) - super user, project, git_timeout: 10.seconds + super user, project @file_path = file_path @ref = ref end From 61c2a2d39a3a73761e862818b73940510eb80b80 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 11 Jun 2014 23:43:05 +0300 Subject: [PATCH 300/360] More items in CHANGELOG Signed-off-by: Dmitriy Zaporozhets --- CHANGELOG | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 900c7a1103..e5c1e324e6 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -26,6 +26,11 @@ v 7.0.0 - UI improvements for mobile devices - Improve diff rendering performance - Drag-n-drop for issues and merge requests between states at milestone page + - Fix '0 commits' message for huge repositories on project home page + - Prevent 500 error page when visit commit page from large repo + - Add notice about huge push over http to unicorn config + - File action in satellites uses default 30 seconds timeout instead of old 10 seconds one + - Overall performance improvements v 6.9.2 - Revert the commit that broke the LDAP user filter @@ -790,4 +795,4 @@ v 0.8.0 - stability - security fixes - increased test coverage - - email notification \ No newline at end of file + - email notification From 90bfe286a694e2af9de49dcb3b32360132249a48 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Thu, 12 Jun 2014 09:28:34 +0200 Subject: [PATCH 301/360] Skip init script checks on omnibus-gitlab Omnibus-gitlab does not use the init script. --- CHANGELOG | 1 + lib/tasks/gitlab/check.rake | 14 ++++++++++++++ 2 files changed, 15 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index e5c1e324e6..435cc668f1 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -31,6 +31,7 @@ v 7.0.0 - Add notice about huge push over http to unicorn config - File action in satellites uses default 30 seconds timeout instead of old 10 seconds one - Overall performance improvements + - Skip init script check on omnibus-gitlab v 6.9.2 - Revert the commit that broke the LDAP user filter diff --git a/lib/tasks/gitlab/check.rake b/lib/tasks/gitlab/check.rake index 00af8d1029..34116568e9 100644 --- a/lib/tasks/gitlab/check.rake +++ b/lib/tasks/gitlab/check.rake @@ -123,6 +123,11 @@ namespace :gitlab do def check_init_script_exists print "Init script exists? ... " + if omnibus_gitlab? + puts 'skipped (omnibus-gitlab has no init script)'.magenta + return + end + script_path = "/etc/init.d/gitlab" if File.exists?(script_path) @@ -142,6 +147,11 @@ namespace :gitlab do def check_init_script_up_to_date print "Init script up-to-date? ... " + if omnibus_gitlab? + puts 'skipped (omnibus-gitlab has no init script)'.magenta + return + end + recipe_path = Rails.root.join("lib/support/init.d/", "gitlab") script_path = "/etc/init.d/gitlab" @@ -823,4 +833,8 @@ namespace :gitlab do fix_and_rerun end end + + def omnibus_gitlab? + Dir.pwd == '/opt/gitlab/embedded/service/gitlab-rails' + end end From fcb0b76c32b3512ead419a4451e9cc632270fc89 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 12 Jun 2014 12:01:54 +0300 Subject: [PATCH 302/360] Load last commit for files per 10 items. Signed-off-by: Dmitriy Zaporozhets --- app/controllers/projects/refs_controller.rb | 20 +++++++++++++++++--- app/views/projects/refs/logs_tree.js.haml | 10 ++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/app/controllers/projects/refs_controller.rb b/app/controllers/projects/refs_controller.rb index 7b8026cff9..8834a99508 100644 --- a/app/controllers/projects/refs_controller.rb +++ b/app/controllers/projects/refs_controller.rb @@ -31,9 +31,23 @@ class Projects::RefsController < Projects::ApplicationController end def logs_tree - contents = tree.entries - @logs = contents.map do |content| - file = params[:path] ? File.join(params[:path], content.name) : content.name + @offset = if params[:offset].present? + params[:offset].to_i + else + 0 + end + + @limit = 10 + + @path = params[:path] + + contents = [] + contents += tree.trees + contents += tree.blobs + contents += tree.submodules + + @logs = contents[@offset, @limit].to_a.map do |content| + file = @path ? File.join(@path, content.name) : content.name last_commit = @repo.last_commit_for_path(@commit.id, file) { file_name: content.name, diff --git a/app/views/projects/refs/logs_tree.js.haml b/app/views/projects/refs/logs_tree.js.haml index e7343e0997..948a21aa81 100644 --- a/app/views/projects/refs/logs_tree.js.haml +++ b/app/views/projects/refs/logs_tree.js.haml @@ -7,3 +7,13 @@ var row = $("table.table_#{@hex_path} tr.file_#{hexdigest(file_name)}"); row.find("td.tree_time_ago").html('#{escape_javascript time_ago_with_tooltip(commit.committed_date)}'); row.find("td.tree_commit").html('#{escape_javascript render("projects/tree/tree_commit_column", commit: commit)}'); + +- if @logs.present? + :plain + var current_url = location.href.replace(/\/?$/, '/'); + var log_url = '#{project_tree_url(@project, tree_join(@ref, @path || '/'))}'.replace(/\/?$/, '/'); + if(current_url == log_url) { + // Load 10 more commit log for each file in tree + // if we still on the same page + ajaxGet('#{logs_file_project_ref_path(@project, @ref, @path || '/', offset: (@offset + @limit))}'); + } From 6e2a75df8ef0ea623c42c8cb6afc75690c011c5a Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 12 Jun 2014 16:16:29 +0300 Subject: [PATCH 303/360] Dont truncate project names on group page Signed-off-by: Dmitriy Zaporozhets --- app/views/groups/_projects.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/groups/_projects.html.haml b/app/views/groups/_projects.html.haml index a6ca41877a..2ebff21b81 100644 --- a/app/views/groups/_projects.html.haml +++ b/app/views/groups/_projects.html.haml @@ -16,6 +16,6 @@ = visibility_level_icon(project.visibility_level) %span.str-truncated %span.project-name - = truncate(project.name, length: 25) + = project.name %span.arrow %i.icon-angle-right From 8e2752f4595db07197cacbf8c352e51b5268b71b Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Thu, 12 Jun 2014 10:42:38 +0200 Subject: [PATCH 304/360] Be more selective when killing stray Sidekiqs Avoid the background_jobs script killing every process with 'sidekiq' in its argument string (e.g. 'rake gitlab:sidekiq start') by also catching the number (2) in 'sidekiq 2.14'. --- CHANGELOG | 1 + bin/background_jobs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 435cc668f1..2e4736a080 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -32,6 +32,7 @@ v 7.0.0 - File action in satellites uses default 30 seconds timeout instead of old 10 seconds one - Overall performance improvements - Skip init script check on omnibus-gitlab + - Be more selective when killing stray Sidekiqs v 6.9.2 - Revert the commit that broke the LDAP user filter diff --git a/bin/background_jobs b/bin/background_jobs index e0140e9689..c7ba4398cf 100755 --- a/bin/background_jobs +++ b/bin/background_jobs @@ -18,7 +18,7 @@ function stop function killall { - pkill -u $gitlab_user -f sidekiq + pkill -u $gitlab_user -f 'sidekiq [0-9]' } function restart From 11728851bf0b1b06e14858b08b1afcec44ec3d46 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 12 Jun 2014 21:36:38 +0300 Subject: [PATCH 305/360] Fix blob highlight tests Signed-off-by: Dmitriy Zaporozhets --- features/project/source/multiselect_blob.feature | 5 ++--- features/steps/shared/paths.rb | 4 ++++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/features/project/source/multiselect_blob.feature b/features/project/source/multiselect_blob.feature index 3038c0814a..0fdfe7ce93 100644 --- a/features/project/source/multiselect_blob.feature +++ b/features/project/source/multiselect_blob.feature @@ -2,8 +2,7 @@ Feature: Project Multiselect Blob Background: Given I sign in as a user And I own project "Shop" - And I visit project source page - And I click on "Gemfile.lock" file in repo + And I visit "Gemfile.lock" file in repo @javascript Scenario: I click line 1 in file @@ -83,4 +82,4 @@ Feature: Project Multiselect Blob And I go forward in history And I go forward in history Then I should see "L1-5" as URI fragment - And I should see lines 1-5 highlighted \ No newline at end of file + And I should see lines 1-5 highlighted diff --git a/features/steps/shared/paths.rb b/features/steps/shared/paths.rb index d36ff7e388..449f2f9c5e 100644 --- a/features/steps/shared/paths.rb +++ b/features/steps/shared/paths.rb @@ -264,6 +264,10 @@ module SharedPaths visit project_blob_path(@project, File.join(ValidCommit::ID, ValidCommit::BLOB_FILE_PATH)) end + step 'I visit "Gemfile.lock" file in repo' do + visit project_blob_path(@project, File.join(root_ref, 'Gemfile.lock')) + end + step 'I visit project source page for "8470d70"' do visit project_tree_path(@project, "8470d70") end From 1f3a69c1d197254edb620032fc83ff668b649fa5 Mon Sep 17 00:00:00 2001 From: skv-headless Date: Thu, 12 Jun 2014 22:39:08 +0400 Subject: [PATCH 306/360] fix double check for all issues --- app/assets/javascripts/issues.js.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/javascripts/issues.js.coffee b/app/assets/javascripts/issues.js.coffee index e2f1bc743f..54de93a4e0 100644 --- a/app/assets/javascripts/issues.js.coffee +++ b/app/assets/javascripts/issues.js.coffee @@ -38,7 +38,7 @@ initChecks: -> $(".check_all_issues").click -> - $(".selected_issue").attr "checked", @checked + $(".selected_issue").prop("checked", @checked) Issues.checkChanged() $(".selected_issue").bind "change", Issues.checkChanged From c827af21d3548f98c809550b471bbb3f5a344076 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 12 Jun 2014 21:49:02 +0300 Subject: [PATCH 307/360] Remove unnecessary padding Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/sections/commits.scss | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/assets/stylesheets/sections/commits.scss b/app/assets/stylesheets/sections/commits.scss index 855bb4ea01..e2503a8a16 100644 --- a/app/assets/stylesheets/sections/commits.scss +++ b/app/assets/stylesheets/sections/commits.scss @@ -140,8 +140,6 @@ * COMMIT ROW */ li.commit { - padding: 8px; - .commit-row-title { font-size: 14px; margin-bottom: 2px; From 98416ec9ab805b0afb994972e073b743b8204312 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 12 Jun 2014 21:49:45 +0300 Subject: [PATCH 308/360] Show proper message for new MR when satellite fails Signed-off-by: Dmitriy Zaporozhets --- .../projects/merge_requests_controller.rb | 12 ++++++-- .../merge_requests/_new_compare.html.haml | 29 +++++++++++-------- 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index 6ab353d222..e15e1be2c6 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -74,9 +74,17 @@ class Projects::MergeRequestsController < Projects::ApplicationController @merge_request.source_branch ) + @compare_failed = false @commits = compare_action.commits - @commits.map! { |commit| Commit.new(commit) } - @commit = @commits.first + + if @commits + @commits.map! { |commit| Commit.new(commit) } + @commit = @commits.first + else + # false value because failed to get commits from satellite + @commits = [] + @compare_failed = true + end @diffs = compare_action.diffs @merge_request.title = @merge_request.source_branch.titleize.humanize diff --git a/app/views/projects/merge_requests/_new_compare.html.haml b/app/views/projects/merge_requests/_new_compare.html.haml index a8b774a3cd..f8f14a71a1 100644 --- a/app/views/projects/merge_requests/_new_compare.html.haml +++ b/app/views/projects/merge_requests/_new_compare.html.haml @@ -33,18 +33,23 @@ %div= msg - if @merge_request.source_branch.present? && @merge_request.target_branch.present? - .light-well - %center - %h4 - There isn't anything to merge. - %p.slead - - if @merge_request.source_branch == @merge_request.target_branch - You'll need to use different branch names to get a valid comparison. - - else - %span.label-branch #{@merge_request.source_branch} - and - %span.label-branch #{@merge_request.target_branch} - are the same. + - if @compare_failed + .alert.alert-danger + %h4 Compare failed + %p We can't compare selected branches. It may be because of huge diff or satellite timeout. Please try again or select different branches. + - else + .light-well + %center + %h4 + There isn't anything to merge. + %p.slead + - if @merge_request.source_branch == @merge_request.target_branch + You'll need to use different branch names to get a valid comparison. + - else + %span.label-branch #{@merge_request.source_branch} + and + %span.label-branch #{@merge_request.target_branch} + are the same. %hr From 1bde927750b60d17334e188b70959059f3b00060 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 12 Jun 2014 22:08:54 +0300 Subject: [PATCH 309/360] Restyle git tags page Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/sections/projects.scss | 5 ----- app/views/projects/tags/_tag.html.haml | 15 ++++++--------- app/views/projects/tags/index.html.haml | 14 ++++++++------ app/views/projects/tree/_tree.html.haml | 2 +- 4 files changed, 15 insertions(+), 21 deletions(-) diff --git a/app/assets/stylesheets/sections/projects.scss b/app/assets/stylesheets/sections/projects.scss index 9fbed704ba..71f5f1663c 100644 --- a/app/assets/stylesheets/sections/projects.scss +++ b/app/assets/stylesheets/sections/projects.scss @@ -179,11 +179,6 @@ ul.nav.nav-projects-tabs { font-weight: normal; } -.new-tag-btn { - position: relative; - top: -5px; -} - .public-projects .repo-info { color: #777; diff --git a/app/views/projects/tags/_tag.html.haml b/app/views/projects/tags/_tag.html.haml index 67d771c970..9ed737b181 100644 --- a/app/views/projects/tags/_tag.html.haml +++ b/app/views/projects/tags/_tag.html.haml @@ -5,18 +5,15 @@ %i.icon-tag = tag.name .pull-right - %small.cdark - %i.icon-calendar - #{time_ago_with_tooltip(commit.committed_date)} - %p.prepend-left-20 - = link_to commit.short_id(8), project_commit_path(@project, commit), class: "monospace" - – - = link_to_gfm truncate(commit.title, length: 70), project_commit_path(@project, commit.id), class: "cdark" - - %span.pull-right - if can? current_user, :download_code, @project = render 'projects/repositories/download_archive', ref: tag.name, btn_class: 'btn-grouped btn-group-small' - if can?(current_user, :admin_project, @project) = link_to project_tag_path(@project, tag.name), class: 'btn btn-small btn-remove remove-row grouped', method: :delete, data: { confirm: 'Removed tag cannot be restored. Are you sure?'}, remote: true do %i.icon-trash + - if commit + %ul.list-unstyled + = render 'projects/commits/inline_commit', commit: commit, project: @project + - else + %p + Cant find HEAD commit for this tag diff --git a/app/views/projects/tags/index.html.haml b/app/views/projects/tags/index.html.haml index 08122fb884..dc3188d43b 100644 --- a/app/views/projects/tags/index.html.haml +++ b/app/views/projects/tags/index.html.haml @@ -1,12 +1,14 @@ = render "projects/commits/head" -- if can? current_user, :push_code, @project - .pull-right - = link_to new_project_tag_path(@project), class: 'btn btn-create new-tag-btn' do - %i.icon-add-sign - New tag +%h3.page-title + Git Tags + - if can? current_user, :push_code, @project + .pull-right + = link_to new_project_tag_path(@project), class: 'btn btn-create new-tag-btn' do + %i.icon-add-sign + New tag -%p +%p.light Tags give the ability to mark specific points in history as being important %hr diff --git a/app/views/projects/tree/_tree.html.haml b/app/views/projects/tree/_tree.html.haml index dbb74a1caf..fe572260e0 100644 --- a/app/views/projects/tree/_tree.html.haml +++ b/app/views/projects/tree/_tree.html.haml @@ -12,7 +12,7 @@ %li = link_to project_new_tree_path(@project, @id), title: 'New file', id: 'new-file-link' do %small - %i.icon-plus.light + %i.icon-plus %div#tree-content-holder.tree-content-holder %table#tree-slider{class: "table_#{@hex_path} tree-table" } From 6c6cdd23ff8241fd2f8c52143f102c9b914f5233 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 12 Jun 2014 22:24:19 +0300 Subject: [PATCH 310/360] Prevent timeout for Commits#stats page for huge repos Signed-off-by: Dmitriy Zaporozhets --- app/views/projects/repositories/stats.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/projects/repositories/stats.html.haml b/app/views/projects/repositories/stats.html.haml index fd35397857..70db27d644 100644 --- a/app/views/projects/repositories/stats.html.haml +++ b/app/views/projects/repositories/stats.html.haml @@ -5,7 +5,7 @@ %hr %p %b Total commits: - %span= @stats.commits_count + %span= @repository.commit_count %p %b Total files in #{@repository.root_ref}: %span= @stats.files_count From afe47e26f5961c5578ef28a79c7dc0ca43db76dd Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 12 Jun 2014 22:58:59 +0300 Subject: [PATCH 311/360] Add autolink to project/group description render Signed-off-by: Dmitriy Zaporozhets --- Gemfile | 3 +++ Gemfile.lock | 3 +++ app/views/groups/show.html.haml | 5 +++-- app/views/projects/_home_panel.html.haml | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index 6ef2a48018..ef0adb5e2b 100644 --- a/Gemfile +++ b/Gemfile @@ -13,6 +13,9 @@ gem "rails", "~> 4.1.0" gem "protected_attributes" gem 'rails-observers' +# Make links from text +gem 'rails_autolink', '~> 1.1' + # Default values for AR models gem "default_value_for", "~> 3.0.0" diff --git a/Gemfile.lock b/Gemfile.lock index 133fc693f0..3bea962f6a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -367,6 +367,8 @@ GEM sprockets-rails (~> 2.0) rails-observers (0.1.2) activemodel (~> 4.0) + rails_autolink (1.1.6) + rails (> 3.1) rails_best_practices (1.14.4) activesupport awesome_print @@ -641,6 +643,7 @@ DEPENDENCIES rack-mini-profiler rails (~> 4.1.0) rails-observers + rails_autolink (~> 1.1) rails_best_practices raphael-rails (~> 2.1.2) rb-fsevent diff --git a/app/views/groups/show.html.haml b/app/views/groups/show.html.haml index 17475288a8..06183dd74a 100644 --- a/app/views/groups/show.html.haml +++ b/app/views/groups/show.html.haml @@ -5,7 +5,7 @@ = link_to dashboard_path, class: 'btn btn-tiny' do ← To dashboard   - %span.cgray + %span.cgray Currently you are only seeing events from the = @group.name group @@ -23,7 +23,8 @@ %h3.page-title = @group.name - if @group.description.present? - %p= @group.description + %p + = auto_link @group.description, link: :urls = render "projects", projects: @projects - if current_user .prepend-top-20 diff --git a/app/views/projects/_home_panel.html.haml b/app/views/projects/_home_panel.html.haml index b24fd5a851..3851fd6c15 100644 --- a/app/views/projects/_home_panel.html.haml +++ b/app/views/projects/_home_panel.html.haml @@ -17,7 +17,7 @@ .col-md-8 .project-home-desc - if @project.description.present? - = @project.description + = auto_link @project.description, link: :urls - if can?(current_user, :admin_project, @project) – %strong= link_to 'Edit', edit_project_path From 8761dd2a6fb2e19556fbfaa30ab211c1f09f3e29 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Thu, 12 Jun 2014 16:01:23 +0200 Subject: [PATCH 312/360] Check LDAP user filter during sign-in --- CHANGELOG | 1 + app/controllers/omniauth_callbacks_controller.rb | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 2e4736a080..7279b7c8c0 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -33,6 +33,7 @@ v 7.0.0 - Overall performance improvements - Skip init script check on omnibus-gitlab - Be more selective when killing stray Sidekiqs + - Check LDAP user filter during sign-in v 6.9.2 - Revert the commit that broke the LDAP user filter diff --git a/app/controllers/omniauth_callbacks_controller.rb b/app/controllers/omniauth_callbacks_controller.rb index 7131e0fe18..0c87fe0d9a 100644 --- a/app/controllers/omniauth_callbacks_controller.rb +++ b/app/controllers/omniauth_callbacks_controller.rb @@ -20,7 +20,15 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController # if the authentication to LDAP was successful. @user = Gitlab::LDAP::User.find_or_create(oauth) @user.remember_me = true if @user.persisted? - sign_in_and_redirect(@user) + + gitlab_ldap_access do |access| + if access.allowed?(@user) + sign_in_and_redirect(@user) + else + flash[:alert] = "Access denied for your LDAP account." + redirect_to new_user_session_path + end + end end private From 1355ede49d02e2a7b1715a3ed6bd7389bfedf6bc Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 13 Jun 2014 14:24:54 +0300 Subject: [PATCH 313/360] Wipe wall notes feature Signed-off-by: Dmitriy Zaporozhets --- CHANGELOG | 1 + app/assets/javascripts/dispatcher.js.coffee | 2 - app/assets/javascripts/wall.js.coffee | 85 -------------------- app/assets/stylesheets/sections/wall.scss | 55 ------------- app/controllers/projects/walls_controller.rb | 20 ----- app/helpers/events_helper.rb | 2 - app/helpers/projects_helper.rb | 2 +- app/helpers/search_helper.rb | 1 - app/mailers/emails/notes.rb | 9 --- app/models/event.rb | 4 - app/models/note.rb | 6 -- app/models/project.rb | 5 +- app/observers/note_observer.rb | 5 +- app/services/notification_service.rb | 1 - app/services/projects/create_service.rb | 1 - app/views/layouts/nav/_project.html.haml | 4 - app/views/notify/note_wall_email.html.haml | 1 - app/views/notify/note_wall_email.text.erb | 9 --- app/views/projects/edit.html.haml | 7 -- app/views/projects/walls/show.html.haml | 23 ------ config/gitlab.yml.example | 1 - config/initializers/1_settings.rb | 1 - config/routes.rb | 6 -- doc/api/notes.md | 63 +-------------- doc/api/projects.md | 5 -- doc/markdown/markdown.md | 1 - doc/permissions/permissions.md | 1 - doc/workflow/project_features.md | 6 -- lib/api/entities.rb | 2 +- lib/api/notes.rb | 49 ----------- lib/api/projects.rb | 4 - 31 files changed, 7 insertions(+), 375 deletions(-) delete mode 100644 app/assets/javascripts/wall.js.coffee delete mode 100644 app/assets/stylesheets/sections/wall.scss delete mode 100644 app/controllers/projects/walls_controller.rb delete mode 100644 app/views/notify/note_wall_email.html.haml delete mode 100644 app/views/notify/note_wall_email.text.erb delete mode 100644 app/views/projects/walls/show.html.haml diff --git a/CHANGELOG b/CHANGELOG index 2e4736a080..a1e9c80e1e 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -33,6 +33,7 @@ v 7.0.0 - Overall performance improvements - Skip init script check on omnibus-gitlab - Be more selective when killing stray Sidekiqs + - Remove wall feature (no data loss - you can take it from database) v 6.9.2 - Revert the commit that broke the LDAP user filter diff --git a/app/assets/javascripts/dispatcher.js.coffee b/app/assets/javascripts/dispatcher.js.coffee index 6518c380bd..ff68b520ad 100644 --- a/app/assets/javascripts/dispatcher.js.coffee +++ b/app/assets/javascripts/dispatcher.js.coffee @@ -34,8 +34,6 @@ class Dispatcher new Activities() when 'projects:new', 'projects:edit' new Project() - when 'projects:walls:show' - new Wall(project_id) when 'projects:teams:members:index' new TeamMembers() when 'groups:members' diff --git a/app/assets/javascripts/wall.js.coffee b/app/assets/javascripts/wall.js.coffee deleted file mode 100644 index 4cc11331ac..0000000000 --- a/app/assets/javascripts/wall.js.coffee +++ /dev/null @@ -1,85 +0,0 @@ -class Wall - constructor: (project_id) -> - @project_id = project_id - @note_ids = [] - @getContent() - @initRefresh() - @initForm() - - # - # Gets an initial set of notes. - # - getContent: -> - Api.notes @project_id, (notes) => - $.each notes, (i, note) => - # render note if it not present in loaded list - # or skip if rendered - if $.inArray(note.id, @note_ids) == -1 - @note_ids.push(note.id) - @renderNote(note) - @scrollDown() - $("abbr.timeago").timeago() - - initRefresh: -> - setInterval => - @refresh() - , 10000 - - refresh: -> - @getContent() - - scrollDown: -> - notes = $('ul.notes') - $('body, html').scrollTop(notes.height()) - - initForm: -> - form = $('.wall-note-form') - form.find("#target_type").val('wall') - - form.on 'ajax:success', => - @refresh() - form.find(".js-note-text").val("").trigger("input") - - form.on 'ajax:complete', -> - form.find(".js-comment-button").removeAttr('disabled') - form.find(".js-comment-button").removeClass('disabled') - - form.on "click", ".js-choose-note-attachment-button", -> - form.find(".js-note-attachment-input").click() - - form.on "change", ".js-note-attachment-input", -> - filename = $(this).val().replace(/^.*[\\\/]/, '') - form.find(".js-attachment-filename").text(filename) - - form.find('.note_text').keydown (e) -> - if e.ctrlKey && e.keyCode == 13 - form.find('.js-comment-button').submit() - - form.show() - - renderNote: (note) -> - template = @noteTemplate() - template = template.replace('{{author_name}}', note.author.name) - template = template.replace(/{{created_at}}/g, note.created_at) - template = template.replace('{{text}}', simpleFormat(note.body)) - - if note.attachment - file = '' + note.attachment + '' - else - file = '' - template = template.replace('{{file}}', file) - - - $('ul.notes').append(template) - - noteTemplate: -> - return '
  • - {{author_name}} - - {{text}} - {{file}} - - {{created_at}} -
  • ' - -@Wall = Wall diff --git a/app/assets/stylesheets/sections/wall.scss b/app/assets/stylesheets/sections/wall.scss deleted file mode 100644 index 3705afdb87..0000000000 --- a/app/assets/stylesheets/sections/wall.scss +++ /dev/null @@ -1,55 +0,0 @@ -.wall-page { - .wall-note-form { - @extend .col-md-12; - - margin: 0; - height: 140px; - background: #F9F9F9; - position: fixed; - bottom: 0px; - padding: 3px; - padding-bottom: 25px; - border: 1px solid #DDD; - } - - .notes { - margin-bottom: 160px; - background: #FFE; - border: 1px solid #EED; - - > li { - @extend .clearfix; - border-bottom: 1px solid #EED; - padding: 10px; - } - - .wall-author { - color: #666; - float: left; - font-size: 12px; - width: 120px; - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden; - } - - .wall-text { - border-left: 1px solid #CCC; - margin-left: 10px; - padding-left: 10px; - float: left; - width: 75%; - } - - .wall-file { - margin-left: 8px; - background: #EEE; - } - - abbr { - float: right; - color: #AAA; - border: none; - } - } -} diff --git a/app/controllers/projects/walls_controller.rb b/app/controllers/projects/walls_controller.rb deleted file mode 100644 index 834215a147..0000000000 --- a/app/controllers/projects/walls_controller.rb +++ /dev/null @@ -1,20 +0,0 @@ -class Projects::WallsController < Projects::ApplicationController - before_filter :module_enabled - - respond_to :js, :html - - def show - @note = @project.notes.new - - respond_to do |format| - format.html - end - end - - protected - - def module_enabled - return render_404 unless @project.wall_enabled - end -end - diff --git a/app/helpers/events_helper.rb b/app/helpers/events_helper.rb index 929f9a9c38..d3904e16c1 100644 --- a/app/helpers/events_helper.rb +++ b/app/helpers/events_helper.rb @@ -109,8 +109,6 @@ module EventsHelper "#{event.note_target_type} ##{truncate event.note_target_iid}" end end - elsif event.wall_note? - link_to 'wall', project_wall_path(event.project) else content_tag :strong do "(deleted)" diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index ef0460f872..ba4c7068e9 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -139,7 +139,7 @@ module ProjectsHelper nav_tabs << :settings end - [:issues, :wiki, :wall, :snippets].each do |feature| + [:issues, :wiki, :snippets].each do |feature| nav_tabs << feature if project.send :"#{feature}_enabled" end diff --git a/app/helpers/search_helper.rb b/app/helpers/search_helper.rb index a4471507da..ecd8d3994d 100644 --- a/app/helpers/search_helper.rb +++ b/app/helpers/search_helper.rb @@ -61,7 +61,6 @@ module SearchHelper { label: "#{prefix} - Milestones", url: project_milestones_path(@project) }, { label: "#{prefix} - Snippets", url: project_snippets_path(@project) }, { label: "#{prefix} - Team", url: project_team_index_path(@project) }, - { label: "#{prefix} - Wall", url: project_wall_path(@project) }, { label: "#{prefix} - Wiki", url: project_wikis_path(@project) }, ] else diff --git a/app/mailers/emails/notes.rb b/app/mailers/emails/notes.rb index 7848d34ab2..acc6d03b5e 100644 --- a/app/mailers/emails/notes.rb +++ b/app/mailers/emails/notes.rb @@ -32,14 +32,5 @@ module Emails cc: recipient(recipient_id), subject: subject("#{@merge_request.title} (##{@merge_request.iid})")) end - - def note_wall_email(recipient_id, note_id) - @note = Note.find(note_id) - @project = @note.project - @target_url = project_wall_url(@note.project, anchor: "note_#{@note.id}") - mail(from: sender(@note.author_id), - cc: recipient(recipient_id), - subject: subject("Note on wall")) - end end end diff --git a/app/models/event.rb b/app/models/event.rb index cf88e9f4af..b88635ccb5 100644 --- a/app/models/event.rb +++ b/app/models/event.rb @@ -286,10 +286,6 @@ class Event < ActiveRecord::Base end.to_s end - def wall_note? - target.noteable_type.blank? - end - def note_target_type if target.noteable_type.present? target.noteable_type.titleize diff --git a/app/models/note.rb b/app/models/note.rb index dc8b968c3d..659cd75207 100644 --- a/app/models/note.rb +++ b/app/models/note.rb @@ -251,10 +251,6 @@ class Note < ActiveRecord::Base for_merge_request? && for_diff_line? end - def for_wall? - noteable_type.blank? - end - # override to return commits, which are not active record def noteable if for_commit? @@ -295,8 +291,6 @@ class Note < ActiveRecord::Base def noteable_type_name if noteable_type.present? noteable_type.downcase - else - "wall" end end diff --git a/app/models/project.rb b/app/models/project.rb index f92cc40642..e251c777d8 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -31,7 +31,6 @@ class Project < ActiveRecord::Base default_value_for :archived, false default_value_for :issues_enabled, true - default_value_for :wall_enabled, true default_value_for :merge_requests_enabled, true default_value_for :wiki_enabled, true default_value_for :snippets_enabled, true @@ -39,7 +38,7 @@ class Project < ActiveRecord::Base ActsAsTaggableOn.strict_case_match = true attr_accessible :name, :path, :description, :issues_tracker, :label_list, - :issues_enabled, :wall_enabled, :merge_requests_enabled, :snippets_enabled, :issues_tracker_id, + :issues_enabled, :merge_requests_enabled, :snippets_enabled, :issues_tracker_id, :wiki_enabled, :visibility_level, :import_url, :last_activity_at, as: [:default, :admin] attr_accessible :namespace_id, :creator_id, as: :admin @@ -98,7 +97,7 @@ class Project < ActiveRecord::Base exclusion: { in: Gitlab::Blacklist.path }, format: { with: Gitlab::Regex.path_regex, message: "only letters, digits & '_' '-' '.' allowed. Letter or digit should be first" } - validates :issues_enabled, :wall_enabled, :merge_requests_enabled, + validates :issues_enabled, :merge_requests_enabled, :wiki_enabled, inclusion: { in: [true, false] } validates :issues_tracker_id, length: { maximum: 255 }, allow_blank: true validates :namespace, presence: true diff --git a/app/observers/note_observer.rb b/app/observers/note_observer.rb index 9bb1f0f7b9..bb0b0876ec 100644 --- a/app/observers/note_observer.rb +++ b/app/observers/note_observer.rb @@ -3,12 +3,9 @@ class NoteObserver < BaseObserver notification.new_note(note) # Skip system notes, like status changes and cross-references. - # Skip wall notes to prevent spamming of dashboard - if note.noteable_type.present? && !note.system + unless note.system event_service.leave_note(note, note.author) - end - unless note.system? # Create a cross-reference note if this Note contains GFM that names an # issue, merge request, or commit. note.references.each do |mentioned| diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index 3547552df8..650b6008db 100644 --- a/app/services/notification_service.rb +++ b/app/services/notification_service.rb @@ -106,7 +106,6 @@ class NotificationService # TODO: split on methods and refactor # def new_note(note) - # ignore wall messages return true unless note.noteable_type.present? # ignore gitlab service messages diff --git a/app/services/projects/create_service.rb b/app/services/projects/create_service.rb index 7d322f25e4..3d2b9bf487 100644 --- a/app/services/projects/create_service.rb +++ b/app/services/projects/create_service.rb @@ -19,7 +19,6 @@ module Projects default_opts = { issues_enabled: default_features.issues, wiki_enabled: default_features.wiki, - wall_enabled: default_features.wall, snippets_enabled: default_features.snippets, merge_requests_enabled: default_features.merge_requests, visibility_level: default_features.visibility_level diff --git a/app/views/layouts/nav/_project.html.haml b/app/views/layouts/nav/_project.html.haml index d7d330e2a6..dd48ff6ce3 100644 --- a/app/views/layouts/nav/_project.html.haml +++ b/app/views/layouts/nav/_project.html.haml @@ -36,10 +36,6 @@ = nav_link(controller: :wikis) do = link_to 'Wiki', project_wiki_path(@project, :home) - - if project_nav_tab? :wall - = nav_link(controller: :walls) do - = link_to 'Wall', project_wall_path(@project) - - if project_nav_tab? :snippets = nav_link(controller: :snippets) do = link_to 'Snippets', project_snippets_path(@project) diff --git a/app/views/notify/note_wall_email.html.haml b/app/views/notify/note_wall_email.html.haml deleted file mode 100644 index 2fa2f78466..0000000000 --- a/app/views/notify/note_wall_email.html.haml +++ /dev/null @@ -1 +0,0 @@ -= render 'note_message' diff --git a/app/views/notify/note_wall_email.text.erb b/app/views/notify/note_wall_email.text.erb deleted file mode 100644 index ee0dc3db1d..0000000000 --- a/app/views/notify/note_wall_email.text.erb +++ /dev/null @@ -1,9 +0,0 @@ -New message on the project wall <%= @note.project %> - -<%= url_for(project_wall_url(@note.project, anchor: "note_#{@note.id}")) %> - - -<%= @note.author_name %> - -<%= @note.note %> - diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml index 59dcf3a6ff..adc7316820 100644 --- a/app/views/projects/edit.html.haml +++ b/app/views/projects/edit.html.haml @@ -73,13 +73,6 @@ = f.check_box :wiki_enabled %span.descr Pages for project documentation - .form-group - = f.label :wall_enabled, "Wall", class: 'control-label' - .col-sm-10 - .checkbox - = f.check_box :wall_enabled - %span.descr Simple chat system for broadcasting inside project - .form-group = f.label :snippets_enabled, "Snippets", class: 'control-label' .col-sm-10 diff --git a/app/views/projects/walls/show.html.haml b/app/views/projects/walls/show.html.haml deleted file mode 100644 index 3e3c7c4f8d..0000000000 --- a/app/views/projects/walls/show.html.haml +++ /dev/null @@ -1,23 +0,0 @@ -%div.wall-page - %ul.notes - - - if can? current_user, :write_note, @project - .note-form-holder - = form_for [@project, @note], remote: true, html: { multipart: true, id: nil, class: "new_note wall-note-form" }, authenticity_token: true do |f| - = note_target_fields - .note_text_and_preview - = f.text_area :note, size: 255, class: 'note_text js-note-text js-gfm-input turn-on' - .note-form-actions - .buttons - = f.submit 'Add Comment', class: "btn comment-btn btn-grouped js-comment-button" - - .note-form-option - %a.choose-btn.btn.btn-small.js-choose-note-attachment-button - %i.icon-paper-clip - %span Choose File ... -   - %span.file_name.js-attachment-filename File name... - = f.file_field :attachment, class: "js-note-attachment-input hidden" - - .hint.pull-right CTRL + Enter to send message - .clearfix diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example index 6f33256a2b..50a1a78b50 100644 --- a/config/gitlab.yml.example +++ b/config/gitlab.yml.example @@ -73,7 +73,6 @@ production: &base issues: true merge_requests: true wiki: true - wall: false snippets: false visibility_level: "private" # can be "private" | "internal" | "public" diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb index 18c628223a..de7c0990c0 100644 --- a/config/initializers/1_settings.rb +++ b/config/initializers/1_settings.rb @@ -95,7 +95,6 @@ Settings.gitlab['default_projects_features'] ||= {} Settings.gitlab.default_projects_features['issues'] = true if Settings.gitlab.default_projects_features['issues'].nil? Settings.gitlab.default_projects_features['merge_requests'] = true if Settings.gitlab.default_projects_features['merge_requests'].nil? Settings.gitlab.default_projects_features['wiki'] = true if Settings.gitlab.default_projects_features['wiki'].nil? -Settings.gitlab.default_projects_features['wall'] = false if Settings.gitlab.default_projects_features['wall'].nil? Settings.gitlab.default_projects_features['snippets'] = false if Settings.gitlab.default_projects_features['snippets'].nil? Settings.gitlab.default_projects_features['visibility_level'] = Settings.send(:verify_constant, Gitlab::VisibilityLevel, Settings.gitlab.default_projects_features['visibility_level'], Gitlab::VisibilityLevel::PRIVATE) Settings.gitlab['repository_downloads_path'] = File.absolute_path(Settings.gitlab['repository_downloads_path'] || 'tmp/repositories', Rails.root) diff --git a/config/routes.rb b/config/routes.rb index 34ee8d2d79..746e532a0e 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -209,12 +209,6 @@ Gitlab::Application.routes.draw do end end - resource :wall, only: [:show], constraints: {id: /\d+/} do - member do - get 'notes' - end - end - resource :repository, only: [:show] do member do get "stats" diff --git a/doc/api/notes.md b/doc/api/notes.md index 6d140643fc..e7f19965a3 100644 --- a/doc/api/notes.md +++ b/doc/api/notes.md @@ -1,67 +1,6 @@ # Notes -Notes can be wall notes or comments on snippets, issues or merge requests. - -## Wall - -### List project wall notes - -Get a list of project wall notes. - -``` -GET /projects/:id/notes -``` - -Parameters: - -+ `id` (required) - The ID of a project - -```json -[ - { - "id": 522, - "body": "The solution is rather tricky", - "attachment": null, - "author": { - "id": 1, - "username": "john_smith", - "email": "john@example.com", - "name": "John Smith", - "state": "active", - "created_at": "2012-05-23T08:00:58Z" - }, - "created_at": "2012-11-27T19:16:44Z" - } -] -``` - -### Get single wall note - -Returns a single wall note. - -``` -GET /projects/:id/notes/:note_id -``` - -Parameters: - -+ `id` (required) - The ID of a project -+ `note_id` (required) - The ID of a wall note - - -### Create new wall note - -Creates a new wall note. - -``` -POST /projects/:id/notes -``` - -Parameters: - -+ `id` (required) - The ID of a project -+ `body` (required) - The content of a note - +Notes are comments on snippets, issues or merge requests. ## Issues diff --git a/doc/api/projects.md b/doc/api/projects.md index ae2b8365e8..d32af678fc 100644 --- a/doc/api/projects.md +++ b/doc/api/projects.md @@ -30,7 +30,6 @@ GET /projects "path_with_namespace": "diaspora/diaspora-client", "issues_enabled": true, "merge_requests_enabled": true, - "wall_enabled": false, "wiki_enabled": true, "snippets_enabled": false, "created_at": "2013-09-30T13: 46: 02Z", @@ -66,7 +65,6 @@ GET /projects "path_with_namespace": "brightbox/puppet", "issues_enabled": true, "merge_requests_enabled": true, - "wall_enabled": false, "wiki_enabled": true, "snippets_enabled": false, "created_at": "2013-09-30T13:46:02Z", @@ -136,7 +134,6 @@ Parameters: "path_with_namespace": "diaspora/diaspora-project-site", "issues_enabled": true, "merge_requests_enabled": true, - "wall_enabled": false, "wiki_enabled": true, "snippets_enabled": false, "created_at": "2013-09-30T13: 46: 02Z", @@ -252,7 +249,6 @@ Parameters: + `namespace_id` (optional) - namespace for the new project (defaults to user) + `description` (optional) - short project description + `issues_enabled` (optional) -+ `wall_enabled` (optional) + `merge_requests_enabled` (optional) + `wiki_enabled` (optional) + `snippets_enabled` (optional) @@ -276,7 +272,6 @@ Parameters: + `description` (optional) - short project description + `default_branch` (optional) - 'master' by default + `issues_enabled` (optional) -+ `wall_enabled` (optional) + `merge_requests_enabled` (optional) + `wiki_enabled` (optional) + `snippets_enabled` (optional) diff --git a/doc/markdown/markdown.md b/doc/markdown/markdown.md index 0d0a08d50d..64f571b435 100644 --- a/doc/markdown/markdown.md +++ b/doc/markdown/markdown.md @@ -48,7 +48,6 @@ You can use GFM in - commit messages - comments -- wall posts - issues - merge requests - milestones diff --git a/doc/permissions/permissions.md b/doc/permissions/permissions.md index 9ddf56d046..e01b02212b 100644 --- a/doc/permissions/permissions.md +++ b/doc/permissions/permissions.md @@ -13,7 +13,6 @@ If a user is a GitLab administrator they receive all permissions. |---------------------------------------|---------|------------|-------------|----------|--------| | Create new issue | ✓ | ✓ | ✓ | ✓ | ✓ | | Leave comments | ✓ | ✓ | ✓ | ✓ | ✓ | -| Write on project wall | ✓ | ✓ | ✓ | ✓ | ✓ | | Pull project code | | ✓ | ✓ | ✓ | ✓ | | Download project | | ✓ | ✓ | ✓ | ✓ | | Create code snippets | | ✓ | ✓ | ✓ | ✓ | diff --git a/doc/workflow/project_features.md b/doc/workflow/project_features.md index 6ed9c1127a..48e86ee3ef 100644 --- a/doc/workflow/project_features.md +++ b/doc/workflow/project_features.md @@ -26,12 +26,6 @@ This is a separate system for documentation, built right into GitLab. It is source controlled and is very convenient if you don't want to keep you documentation in your source code, but you do want to keep it in your GitLab project. -## Wall - -For simple, project specific conversations, the wall can be used. - -It's very lightweight and simple and works well if you're not interested in using issues, but still want to occasionally communicate within a project. - ## Snippets Snippets are little bits of code or text. diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 6bad6c74bc..f15fe185ae 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -48,7 +48,7 @@ module API expose :owner, using: Entities::UserBasic, unless: ->(project, options) { project.group } expose :name, :name_with_namespace expose :path, :path_with_namespace - expose :issues_enabled, :merge_requests_enabled, :wall_enabled, :wiki_enabled, :snippets_enabled, :created_at, :last_activity_at + expose :issues_enabled, :merge_requests_enabled, :wiki_enabled, :snippets_enabled, :created_at, :last_activity_at expose :namespace expose :forked_from_project, using: Entities::ForkedFromProject, :if => lambda{ | project, options | project.forked? } end diff --git a/lib/api/notes.rb b/lib/api/notes.rb index cb2bc76447..413faf0cf2 100644 --- a/lib/api/notes.rb +++ b/lib/api/notes.rb @@ -6,55 +6,6 @@ module API NOTEABLE_TYPES = [Issue, MergeRequest, Snippet] resource :projects do - # Get a list of project wall notes - # - # Parameters: - # id (required) - The ID of a project - # Example Request: - # GET /projects/:id/notes - get ":id/notes" do - @notes = user_project.notes.common - - # Get recent notes if recent = true - @notes = @notes.order('id DESC') if params[:recent] - - present paginate(@notes), with: Entities::Note - end - - # Get a single project wall note - # - # Parameters: - # id (required) - The ID of a project - # note_id (required) - The ID of a note - # Example Request: - # GET /projects/:id/notes/:note_id - get ":id/notes/:note_id" do - @note = user_project.notes.common.find(params[:note_id]) - present @note, with: Entities::Note - end - - # Create a new project wall note - # - # Parameters: - # id (required) - The ID of a project - # body (required) - The content of a note - # Example Request: - # POST /projects/:id/notes - post ":id/notes" do - required_attributes! [:body] - - @note = user_project.notes.new(note: params[:body]) - @note.author = current_user - - if @note.save - present @note, with: Entities::Note - else - # :note is exposed as :body, but :note is set on error - bad_request!(:note) if @note.errors[:note].any? - not_found! - end - end - NOTEABLE_TYPES.each do |noteable_type| noteables_str = noteable_type.to_s.underscore.pluralize noteable_id_str = "#{noteable_type.to_s.underscore}_id" diff --git a/lib/api/projects.rb b/lib/api/projects.rb index 9d290c75ba..9a7f22b536 100644 --- a/lib/api/projects.rb +++ b/lib/api/projects.rb @@ -71,7 +71,6 @@ module API # name (required) - name for new project # description (optional) - short project description # issues_enabled (optional) - # wall_enabled (optional) # merge_requests_enabled (optional) # wiki_enabled (optional) # snippets_enabled (optional) @@ -86,7 +85,6 @@ module API :path, :description, :issues_enabled, - :wall_enabled, :merge_requests_enabled, :wiki_enabled, :snippets_enabled, @@ -114,7 +112,6 @@ module API # description (optional) - short project description # default_branch (optional) - 'master' by default # issues_enabled (optional) - # wall_enabled (optional) # merge_requests_enabled (optional) # wiki_enabled (optional) # snippets_enabled (optional) @@ -129,7 +126,6 @@ module API :description, :default_branch, :issues_enabled, - :wall_enabled, :merge_requests_enabled, :wiki_enabled, :snippets_enabled, From d593c98fcbd34789068a72c9386f69a152107139 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 13 Jun 2014 14:29:26 +0300 Subject: [PATCH 314/360] Delete wall notes tests Signed-off-by: Dmitriy Zaporozhets --- features/project/active_tab.feature | 5 -- features/project/wall.feature | 16 ------ features/steps/project/wall.rb | 18 ------- features/steps/shared/paths.rb | 8 --- .../security/project/internal_access_spec.rb | 11 ---- .../security/project/private_access_spec.rb | 11 ---- .../security/project/public_access_spec.rb | 11 ---- spec/mailers/notify_spec.rb | 16 ------ spec/requests/api/notes_spec.rb | 50 ------------------- spec/requests/api/projects_spec.rb | 2 - spec/routing/project_routing_spec.rb | 5 -- spec/services/projects/create_service_spec.rb | 2 - 12 files changed, 155 deletions(-) delete mode 100644 features/project/wall.feature delete mode 100644 features/steps/project/wall.rb diff --git a/features/project/active_tab.feature b/features/project/active_tab.feature index 48c217fbea..ce90a08668 100644 --- a/features/project/active_tab.feature +++ b/features/project/active_tab.feature @@ -35,11 +35,6 @@ Feature: Project active tab Then the active main tab should be Merge Requests And no other main tabs should be active - Scenario: On Project Wall - Given I visit my project's wall page - Then the active main tab should be Wall - And no other main tabs should be active - Scenario: On Project Wiki Given I visit my project's wiki page Then the active main tab should be Wiki diff --git a/features/project/wall.feature b/features/project/wall.feature deleted file mode 100644 index c38d046a85..0000000000 --- a/features/project/wall.feature +++ /dev/null @@ -1,16 +0,0 @@ -Feature: Project Wall - In order to use Project Wall - A user should be able to read and write messages - - Background: - Given I sign in as a user - And I own project "Shop" - And I visit project "Shop" wall page - - @javascript - Scenario: Write comment - Given I write new comment "my special test message" - Then I should see project wall note "my special test message" - - Then I visit project "Shop" wall page - And I should see project wall note "my special test message" diff --git a/features/steps/project/wall.rb b/features/steps/project/wall.rb deleted file mode 100644 index 7c61580eb2..0000000000 --- a/features/steps/project/wall.rb +++ /dev/null @@ -1,18 +0,0 @@ -class ProjectWall < Spinach::FeatureSteps - include SharedAuthentication - include SharedProject - include SharedNote - include SharedPaths - - - Given 'I write new comment "my special test message"' do - within(".wall-note-form") do - fill_in "note[note]", with: "my special test message" - click_button "Add Comment" - end - end - - Then 'I should see project wall note "my special test message"' do - page.should have_content "my special test message" - end -end diff --git a/features/steps/shared/paths.rb b/features/steps/shared/paths.rb index 449f2f9c5e..2090b64205 100644 --- a/features/steps/shared/paths.rb +++ b/features/steps/shared/paths.rb @@ -204,10 +204,6 @@ module SharedPaths visit project_merge_requests_path(@project) end - step "I visit my project's wall page" do - visit project_wall_path(@project) - end - step "I visit my project's wiki page" do visit project_wiki_path(@project, :home) end @@ -319,10 +315,6 @@ module SharedPaths visit project_team_index_path(project) end - step 'I visit project "Shop" wall page' do - visit project_wall_path(project) - end - step 'I visit project wiki page' do visit project_wiki_path(@project, :home) end diff --git a/spec/features/security/project/internal_access_spec.rb b/spec/features/security/project/internal_access_spec.rb index eb8422df59..f86b3db32e 100644 --- a/spec/features/security/project/internal_access_spec.rb +++ b/spec/features/security/project/internal_access_spec.rb @@ -87,17 +87,6 @@ describe "Internal Project Access", feature: true do it { should be_denied_for :visitor } end - describe "GET /:project_path/wall" do - subject { project_wall_path(project) } - - it { should be_allowed_for master } - it { should be_allowed_for reporter } - it { should be_allowed_for :admin } - it { should be_allowed_for guest } - it { should be_allowed_for :user } - it { should be_denied_for :visitor } - end - describe "GET /:project_path/blob" do before do commit = project.repository.commit diff --git a/spec/features/security/project/private_access_spec.rb b/spec/features/security/project/private_access_spec.rb index 186ad35046..a27361f4d1 100644 --- a/spec/features/security/project/private_access_spec.rb +++ b/spec/features/security/project/private_access_spec.rb @@ -87,17 +87,6 @@ describe "Private Project Access", feature: true do it { should be_denied_for :visitor } end - describe "GET /:project_path/wall" do - subject { project_wall_path(project) } - - it { should be_allowed_for master } - it { should be_allowed_for reporter } - it { should be_allowed_for :admin } - it { should be_denied_for guest } - it { should be_denied_for :user } - it { should be_denied_for :visitor } - end - describe "GET /:project_path/blob" do before do commit = project.repository.commit diff --git a/spec/features/security/project/public_access_spec.rb b/spec/features/security/project/public_access_spec.rb index f5d1cf7b97..f114965bd4 100644 --- a/spec/features/security/project/public_access_spec.rb +++ b/spec/features/security/project/public_access_spec.rb @@ -92,17 +92,6 @@ describe "Public Project Access", feature: true do it { should be_denied_for :visitor } end - describe "GET /:project_path/wall" do - subject { project_wall_path(project) } - - it { should be_allowed_for master } - it { should be_allowed_for reporter } - it { should be_allowed_for :admin } - it { should be_allowed_for guest } - it { should be_allowed_for :user } - it { should be_allowed_for :visitor } - end - describe "GET /:project_path/blob" do before do commit = project.repository.commit diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb index 32ba6c9b86..453bf2b3e9 100644 --- a/spec/mailers/notify_spec.rb +++ b/spec/mailers/notify_spec.rb @@ -410,22 +410,6 @@ describe Notify do end end - describe 'on a project wall' do - let(:note_on_the_wall_path) { project_wall_path(project, anchor: "note_#{note.id}") } - - subject { Notify.note_wall_email(recipient.id, note.id) } - - it_behaves_like 'a note email' - - it 'has the correct subject' do - should have_subject /#{project.name}/ - end - - it 'contains a link to the wall note' do - should have_body_text /#{note_on_the_wall_path}/ - end - end - describe 'on a commit' do let(:commit) { project.repository.commit } diff --git a/spec/requests/api/notes_spec.rb b/spec/requests/api/notes_spec.rb index 81576f7c23..1179618347 100644 --- a/spec/requests/api/notes_spec.rb +++ b/spec/requests/api/notes_spec.rb @@ -13,58 +13,8 @@ describe API::API, api: true do let!(:issue_note) { create(:note, noteable: issue, project: project, author: user) } let!(:merge_request_note) { create(:note, noteable: merge_request, project: project, author: user) } let!(:snippet_note) { create(:note, noteable: snippet, project: project, author: user) } - let!(:wall_note) { create(:note, project: project, author: user) } before { project.team << [user, :reporter] } - describe "GET /projects/:id/notes" do - context "when unauthenticated" do - it "should return authentication error" do - get api("/projects/#{project.id}/notes") - response.status.should == 401 - end - end - - context "when authenticated" do - it "should return project wall notes" do - get api("/projects/#{project.id}/notes", user) - response.status.should == 200 - json_response.should be_an Array - json_response.first['body'].should == wall_note.note - end - end - end - - describe "GET /projects/:id/notes/:note_id" do - it "should return a wall note by id" do - get api("/projects/#{project.id}/notes/#{wall_note.id}", user) - response.status.should == 200 - json_response['body'].should == wall_note.note - end - - it "should return a 404 error if note not found" do - get api("/projects/#{project.id}/notes/123", user) - response.status.should == 404 - end - end - - describe "POST /projects/:id/notes" do - it "should create a new wall note" do - post api("/projects/#{project.id}/notes", user), body: 'hi!' - response.status.should == 201 - json_response['body'].should == 'hi!' - end - - it "should return 401 unauthorized error" do - post api("/projects/#{project.id}/notes") - response.status.should == 401 - end - - it "should return a 400 bad request if body is missing" do - post api("/projects/#{project.id}/notes", user) - response.status.should == 400 - end - end - describe "GET /projects/:id/noteable/:noteable_id/notes" do context "when noteable is an Issue" do it "should return an array of issue notes" do diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index 81e6abbb0d..43915d8684 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -126,7 +126,6 @@ describe API::API, api: true do project = attributes_for(:project, { description: Faker::Lorem.sentence, issues_enabled: false, - wall_enabled: false, merge_requests_enabled: false, wiki_enabled: false }) @@ -208,7 +207,6 @@ describe API::API, api: true do project = attributes_for(:project, { description: Faker::Lorem.sentence, issues_enabled: false, - wall_enabled: false, merge_requests_enabled: false, wiki_enabled: false }) diff --git a/spec/routing/project_routing_spec.rb b/spec/routing/project_routing_spec.rb index fa9762625d..4b2eb42c70 100644 --- a/spec/routing/project_routing_spec.rb +++ b/spec/routing/project_routing_spec.rb @@ -56,7 +56,6 @@ end # projects POST /projects(.:format) projects#create # new_project GET /projects/new(.:format) projects#new # fork_project POST /:id/fork(.:format) projects#fork -# wall_project GET /:id/wall(.:format) projects#wall # files_project GET /:id/files(.:format) projects#files # edit_project GET /:id/edit(.:format) projects#edit # project GET /:id(.:format) projects#show @@ -75,10 +74,6 @@ describe ProjectsController, "routing" do post("/gitlab/gitlabhq/fork").should route_to('projects#fork', id: 'gitlab/gitlabhq') end - it "to #wall" do - get("/gitlab/gitlabhq/wall").should route_to('projects/walls#show', project_id: 'gitlab/gitlabhq') - end - it "to #edit" do get("/gitlab/gitlabhq/edit").should route_to('projects#edit', id: 'gitlab/gitlabhq') end diff --git a/spec/services/projects/create_service_spec.rb b/spec/services/projects/create_service_spec.rb index 38aae452c3..0eac6bed74 100644 --- a/spec/services/projects/create_service_spec.rb +++ b/spec/services/projects/create_service_spec.rb @@ -65,7 +65,6 @@ describe Projects::CreateService do @settings.stub(:issues) { true } @settings.stub(:merge_requests) { true } @settings.stub(:wiki) { true } - @settings.stub(:wall) { true } @settings.stub(:snippets) { true } stub_const("Settings", Class.new) @restrictions = double("restrictions") @@ -108,7 +107,6 @@ describe Projects::CreateService do @settings.stub(:issues) { true } @settings.stub(:merge_requests) { true } @settings.stub(:wiki) { true } - @settings.stub(:wall) { true } @settings.stub(:snippets) { true } @settings.stub(:visibility_level) { Gitlab::VisibilityLevel::PRIVATE } stub_const("Settings", Class.new) From 59e1819561912cb38bf00a7a34de1ac9e85c3a35 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 13 Jun 2014 15:00:35 +0300 Subject: [PATCH 315/360] Apply soft diff limits to MergeRequest#new page Signed-off-by: Dmitriy Zaporozhets --- app/controllers/projects/merge_requests_controller.rb | 3 +++ app/views/projects/commits/_diffs.html.haml | 5 +++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index e15e1be2c6..f8447691d6 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -90,6 +90,9 @@ class Projects::MergeRequestsController < Projects::ApplicationController @merge_request.title = @merge_request.source_branch.titleize.humanize @target_project = @merge_request.target_project @target_repo = @target_project.repository + + diff_line_count = Commit::diff_line_count(@diffs) + @suppress_diff = Commit::diff_suppress?(@diffs, diff_line_count) end end diff --git a/app/views/projects/commits/_diffs.html.haml b/app/views/projects/commits/_diffs.html.haml index 466085139f..ed95a30bc7 100644 --- a/app/views/projects/commits/_diffs.html.haml +++ b/app/views/projects/commits/_diffs.html.haml @@ -6,12 +6,13 @@ %p To preserve performance the diff is not shown. - if current_controller?(:commit) or current_controller?(:merge_requests) - Please, download the diff as - if current_controller?(:commit) + Please, download the diff as = link_to "plain diff", project_commit_path(@project, @commit, format: :diff), class: "underlined-link" or = link_to "email patch", project_commit_path(@project, @commit, format: :patch), class: "underlined-link" - - else + - elsif @merge_request && @merge_request.persisted? + Please, download the diff as = link_to "plain diff", project_merge_request_path(@project, @merge_request, format: :diff), class: "underlined-link" or = link_to "email patch", project_merge_request_path(@project, @merge_request, format: :patch), class: "underlined-link" From 76e2564018a28f79817dfd7c1e83ab2fc0bb58bc Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 13 Jun 2014 15:10:58 +0300 Subject: [PATCH 316/360] Recommend setup git 2.0 for installation docs Signed-off-by: Dmitriy Zaporozhets --- doc/install/installation.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/install/installation.md b/doc/install/installation.md index ed54b41e61..394a22d218 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -56,7 +56,7 @@ Make sure you have the right version of Git installed # Install Git sudo apt-get install -y git-core - # Make sure Git is version 1.7.10 or higher, for example 1.7.12 or 1.9.3 + # Make sure Git is version 1.7.10 or higher, for example 1.7.12 or 2.0.0 git --version Is the system packaged Git too old? Remove it and compile from source. @@ -69,8 +69,8 @@ Is the system packaged Git too old? Remove it and compile from source. # Download and compile from source cd /tmp - curl --progress https://www.kernel.org/pub/software/scm/git/git-1.9.3.tar.gz | tar xz - cd git-1.9.3/ + curl --progress https://www.kernel.org/pub/software/scm/git/git-2.0.0.tar.gz | tar xz + cd git-2.0.0/ make prefix=/usr/local all # Install into /usr/local/bin From d3d0775acde8dbbb887665c3c52009d76e906d10 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 13 Jun 2014 15:18:23 +0300 Subject: [PATCH 317/360] Exclude info rows from milestone sorting items Signed-off-by: Dmitriy Zaporozhets --- app/assets/javascripts/milestone.js.coffee | 2 ++ app/views/projects/milestones/_issues.html.haml | 2 +- app/views/projects/milestones/_merge_requests.html.haml | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/milestone.js.coffee b/app/assets/javascripts/milestone.js.coffee index 97a71b9d33..5cbddd3a20 100644 --- a/app/assets/javascripts/milestone.js.coffee +++ b/app/assets/javascripts/milestone.js.coffee @@ -55,6 +55,7 @@ class Milestone $("#issues-list-unassigned, #issues-list-ongoing, #issues-list-closed").sortable( connectWith: ".issues-sortable-list", dropOnEmpty: true, + items: "li:not(.ui-sort-disabled)", update: (event, ui) -> data = $(this).sortable("serialize") Milestone.sortIssues(data) @@ -83,6 +84,7 @@ class Milestone $("#merge_requests-list-unassigned, #merge_requests-list-ongoing, #merge_requests-list-closed").sortable( connectWith: ".merge_requests-sortable-list", dropOnEmpty: true, + items: "li:not(.ui-sort-disabled)", update: (event, ui) -> data = $(this).sortable("serialize") Milestone.sortMergeRequests(data) diff --git a/app/views/projects/milestones/_issues.html.haml b/app/views/projects/milestones/_issues.html.haml index 95a4a9296c..6e4df75a3d 100644 --- a/app/views/projects/milestones/_issues.html.haml +++ b/app/views/projects/milestones/_issues.html.haml @@ -3,4 +3,4 @@ %ul{ class: "well-list issues-sortable-list", id: "issues-list-#{id}", "data-state" => id } - issues.sort_by(&:position).each do |issue| = render 'issue', issue: issue - %li.light Drag and drop available + %li.light.ui-sort-disabled Drag and drop available diff --git a/app/views/projects/milestones/_merge_requests.html.haml b/app/views/projects/milestones/_merge_requests.html.haml index 521bfa7850..00889a5eb2 100644 --- a/app/views/projects/milestones/_merge_requests.html.haml +++ b/app/views/projects/milestones/_merge_requests.html.haml @@ -3,4 +3,4 @@ %ul{ class: "well-list merge_requests-sortable-list", id: "merge_requests-list-#{id}", "data-state" => id } - merge_requests.sort_by(&:position).each do |merge_request| = render 'merge_request', merge_request: merge_request - %li.light Drag and drop available + %li.light.ui-sort-disabled Drag and drop available From 273093a9b4e5970d7ed8b9bb6e16dee9f5ce2b70 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 13 Jun 2014 15:35:20 +0300 Subject: [PATCH 318/360] Small ui fix Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/sections/merge_requests.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/assets/stylesheets/sections/merge_requests.scss b/app/assets/stylesheets/sections/merge_requests.scss index debbec4cb9..12044db670 100644 --- a/app/assets/stylesheets/sections/merge_requests.scss +++ b/app/assets/stylesheets/sections/merge_requests.scss @@ -21,11 +21,11 @@ .merge-request .merge-request-tabs{ border-bottom: 2px solid $border_primary; - margin-bottom: 20px; + margin: 20px 0; li { a { - padding: 18px 40px; + padding: 15px 40px; font-size: 14px; margin-bottom: -2px; border-bottom: 2px solid $border_primary; From d5b0f29c4a3a9d7da849d91a16f70bd494831da7 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 13 Jun 2014 17:11:46 +0300 Subject: [PATCH 319/360] Move gravatar url compose to separate service Signed-off-by: Dmitriy Zaporozhets --- app/services/gravatar_service.rb | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 app/services/gravatar_service.rb diff --git a/app/services/gravatar_service.rb b/app/services/gravatar_service.rb new file mode 100644 index 0000000000..a69c7c7837 --- /dev/null +++ b/app/services/gravatar_service.rb @@ -0,0 +1,28 @@ +class GravatarService + def execute(email, size = nil) + if gravatar_config.enabled && email.present? + size = 40 if size.nil? || size <= 0 + + sprintf gravatar_url, + hash: Digest::MD5.hexdigest(email.strip.downcase), + size: size, + email: email.strip + end + end + + def gitlab_config + Gitlab.config.gitlab + end + + def gravatar_config + Gitlab.config.gravatar + end + + def gravatar_url + if gitlab_config.https + gravatar_config.ssl_url + else + gravatar_config.plain_url + end + end +end From ae564c97d48bf728745c57720734cb40378fd90f Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 13 Jun 2014 17:46:48 +0300 Subject: [PATCH 320/360] Dont expose user email via API To prevent leaking of users info we reduce amount of user information retrieved via API for normal users. What user can get via API: * if not admin: only id, state, name, username and avatar_url * if admin: all user information * about himself: all informaion Signed-off-by: Dmitriy Zaporozhets --- .../project_users_select.js.coffee | 8 ++--- app/assets/javascripts/users_select.js.coffee | 8 ++--- app/controllers/application_controller.rb | 3 +- app/helpers/application_helper.rb | 18 +++++----- app/models/user.rb | 8 +++++ lib/api/entities.rb | 33 +++++++++---------- lib/api/internal.rb | 1 - lib/api/projects.rb | 2 +- lib/api/users.rb | 18 +++++++--- spec/requests/api/users_spec.rb | 4 +-- 10 files changed, 54 insertions(+), 49 deletions(-) diff --git a/app/assets/javascripts/project_users_select.js.coffee b/app/assets/javascripts/project_users_select.js.coffee index 382f9b3799..cfbcd5108c 100644 --- a/app/assets/javascripts/project_users_select.js.coffee +++ b/app/assets/javascripts/project_users_select.js.coffee @@ -37,13 +37,9 @@ projectUserFormatResult: (user) -> if user.avatar_url - avatar = gon.relative_url_root + user.avatar_url - else if gon.gravatar_enabled - avatar = gon.gravatar_url - avatar = avatar.replace('%{hash}', md5(user.email)) - avatar = avatar.replace('%{size}', '24') + avatar = user.avatar_url else - avatar = gon.relative_url_root + "#{image_path('no_avatar.png')}" + avatar = gon.default_avatar_url if user.id == '' avatarMarkup = '' diff --git a/app/assets/javascripts/users_select.js.coffee b/app/assets/javascripts/users_select.js.coffee index da66a4ba7f..86318bd7d9 100644 --- a/app/assets/javascripts/users_select.js.coffee +++ b/app/assets/javascripts/users_select.js.coffee @@ -1,13 +1,9 @@ $ -> userFormatResult = (user) -> if user.avatar_url - avatar = gon.relative_url_root + user.avatar_url - else if gon.gravatar_enabled - avatar = gon.gravatar_url - avatar = avatar.replace('%{hash}', md5(user.email)) - avatar = avatar.replace('%{size}', '24') + avatar = user.avatar_url else - avatar = gon.relative_url_root + "#{image_path('no_avatar.png')}" + avatar = gon.default_avatar_url "
    diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 685d41a552..603e89a5e2 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -164,9 +164,8 @@ class ApplicationController < ActionController::Base def add_gon_variables gon.default_issues_tracker = Project.issues_tracker.default_value gon.api_version = API::API.version - gon.gravatar_url = request.ssl? || Gitlab.config.gitlab.https ? Gitlab.config.gravatar.ssl_url : Gitlab.config.gravatar.plain_url gon.relative_url_root = Gitlab.config.gitlab.relative_url_root - gon.gravatar_enabled = Gitlab.config.gravatar.enabled + gon.default_avatar_url = URI::join(Gitlab.config.gitlab.url, ActionController::Base.helpers.image_path('no_avatar.png')).to_s if current_user gon.current_user_id = current_user.id diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 13120d2e58..c3d89eb1b8 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -60,23 +60,21 @@ module ApplicationHelper def avatar_icon(user_email = '', size = nil) user = User.find_by(email: user_email) - if user && user.avatar.present? - user.avatar.url + + if user + user.avatar_url(size) || default_avatar else gravatar_icon(user_email, size) end end def gravatar_icon(user_email = '', size = nil) - size = 40 if size.nil? || size <= 0 + GravatarService.new.execute(user_email, size) || + default_avatar + end - if !Gitlab.config.gravatar.enabled || user_email.blank? - image_path('no_avatar.png') - else - gravatar_url = request.ssl? || gitlab_config.https ? Gitlab.config.gravatar.ssl_url : Gitlab.config.gravatar.plain_url - user_email.strip! - sprintf gravatar_url, hash: Digest::MD5.hexdigest(user_email.downcase), size: size, email: user_email - end + def default_avatar + image_path('no_avatar.png') end def last_commit(project) diff --git a/app/models/user.rb b/app/models/user.rb index 0fbc9284dd..6ad337c57a 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -482,4 +482,12 @@ class User < ActiveRecord::Base def public_profile? authorized_projects.public_only.any? end + + def avatar_url(size = nil) + if avatar.present? + URI::join(Gitlab.config.gitlab.url, avatar.url).to_s + else + GravatarService.new.execute(email) + end + end end diff --git a/lib/api/entities.rb b/lib/api/entities.rb index f15fe185ae..b190646a1e 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -1,28 +1,27 @@ module API module Entities - class User < Grape::Entity - expose :id, :username, :email, :name, :bio, :skype, :linkedin, :twitter, :website_url, - :theme_id, :color_scheme_id, :state, :created_at, :extern_uid, :provider - expose :is_admin?, as: :is_admin - expose :can_create_group?, as: :can_create_group - expose :can_create_project?, as: :can_create_project - - expose :avatar_url do |user, options| - if user.avatar.present? - user.avatar.url - end - end - end - class UserSafe < Grape::Entity expose :name, :username end - class UserBasic < Grape::Entity - expose :id, :username, :email, :name, :state, :created_at + class UserBasic < UserSafe + expose :id, :state, :avatar_url end - class UserLogin < User + class User < UserBasic + expose :created_at + expose :is_admin?, as: :is_admin + expose :bio, :skype, :linkedin, :twitter, :website_url + end + + class UserFull < User + expose :email + expose :theme_id, :color_scheme_id, :extern_uid, :provider + expose :can_create_group?, as: :can_create_group + expose :can_create_project?, as: :can_create_project + end + + class UserLogin < UserFull expose :private_token end diff --git a/lib/api/internal.rb b/lib/api/internal.rb index 06c66ba0b3..5850892df0 100644 --- a/lib/api/internal.rb +++ b/lib/api/internal.rb @@ -59,4 +59,3 @@ module API end end end - diff --git a/lib/api/projects.rb b/lib/api/projects.rb index 9a7f22b536..732c969d7e 100644 --- a/lib/api/projects.rb +++ b/lib/api/projects.rb @@ -209,7 +209,7 @@ module API @users = User.where(id: user_project.team.users.map(&:id)) @users = @users.search(params[:search]) if params[:search].present? @users = paginate @users - present @users, with: Entities::User + present @users, with: Entities::UserBasic end # Get a project labels diff --git a/lib/api/users.rb b/lib/api/users.rb index 6ed2740c33..92dbe97f0a 100644 --- a/lib/api/users.rb +++ b/lib/api/users.rb @@ -13,7 +13,12 @@ module API @users = @users.active if params[:active].present? @users = @users.search(params[:search]) if params[:search].present? @users = paginate @users - present @users, with: Entities::User + + if current_user.is_admin? + present @users, with: Entities::UserFull + else + present @users, with: Entities::UserBasic + end end # Get a single user @@ -24,7 +29,12 @@ module API # GET /users/:id get ":id" do @user = User.find(params[:id]) - present @user, with: Entities::User + + if current_user.is_admin? + present @user, with: Entities::UserFull + else + present @user, with: Entities::UserBasic + end end # Create user. Available only for admin @@ -53,7 +63,7 @@ module API admin = attrs.delete(:admin) user.admin = admin unless admin.nil? if user.save - present user, with: Entities::User + present user, with: Entities::UserFull else not_found! end @@ -87,7 +97,7 @@ module API admin = attrs.delete(:admin) user.admin = admin unless admin.nil? if user.update_attributes(attrs, as: :admin) - present user, with: Entities::User + present user, with: Entities::UserFull else not_found! end diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb index a6d300b099..c4728431ec 100644 --- a/spec/requests/api/users_spec.rb +++ b/spec/requests/api/users_spec.rb @@ -20,7 +20,7 @@ describe API::API, api: true do get api("/users", user) response.status.should == 200 json_response.should be_an Array - json_response.first['email'].should == user.email + json_response.first['username'].should == user.username end end end @@ -29,7 +29,7 @@ describe API::API, api: true do it "should return a user by id" do get api("/users/#{user.id}", user) response.status.should == 200 - json_response['email'].should == user.email + json_response['username'].should == user.username end it "should return a 401 if unauthenticated" do From a7345e368a92396c04e9cd8d1a9c1ed2ed50d15e Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 13 Jun 2014 18:02:42 +0300 Subject: [PATCH 321/360] Fix gravatar size and update docs for new users API Signed-off-by: Dmitriy Zaporozhets --- app/models/user.rb | 2 +- doc/api/users.md | 53 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/app/models/user.rb b/app/models/user.rb index 6ad337c57a..2352f8c050 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -487,7 +487,7 @@ class User < ActiveRecord::Base if avatar.present? URI::join(Gitlab.config.gitlab.url, avatar.url).to_s else - GravatarService.new.execute(email) + GravatarService.new.execute(email, size) end end end diff --git a/doc/api/users.md b/doc/api/users.md index 94af37629f..4ddbf73977 100644 --- a/doc/api/users.md +++ b/doc/api/users.md @@ -6,6 +6,34 @@ Get a list of users. This function takes pagination parameters `page` and `per_page` to restrict the list of users. +### For normal users: + +``` +GET /users +``` + +```json +[ + { + "id": 1, + "username": "john_smith", + "name": "John Smith", + "state": "active", + "avatar_url": "http://localhost:3000/uploads/user/avatar/1/cd8.jpeg", + }, + { + "id": 2, + "username": "jack_smith", + "name": "Jack Smith", + "state": "blocked", + "avatar_url": "http://gravatar.com/../e32131cd8.jpeg", + } +] +``` + + +### For admins: + ``` GET /users ``` @@ -29,6 +57,7 @@ GET /users "theme_id": 1, "color_scheme_id": 2, "is_admin": false, + "avatar_url": "http://localhost:3000/uploads/user/avatar/1/cd8.jpeg", "can_create_group": true }, { @@ -48,6 +77,7 @@ GET /users "theme_id": 1, "color_scheme_id": 3, "is_admin": false, + "avatar_url": "http://localhost:3000/uploads/user/avatar/1/cd8.jpeg", "can_create_group": true, "can_create_project": true } @@ -62,6 +92,29 @@ Also see `def search query` in `app/models/user.rb`. Get a single user. +#### For user: + +``` +GET /users/:id +``` + +Parameters: + +- `id` (required) - The ID of a user + +```json +{ + "id": 1, + "username": "john_smith", + "name": "John Smith", + "state": "active", + "avatar_url": "http://localhost:3000/uploads/user/avatar/1/cd8.jpeg", +} +``` + + +#### For admin: + ``` GET /users/:id ``` From 3f1ece26909f90e538a50cd724b64da28f0b7308 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Fri, 13 Jun 2014 16:19:08 +0200 Subject: [PATCH 322/360] Detect closing issues in Merge Request description --- CHANGELOG | 1 + app/models/commit.rb | 14 +------------- app/models/merge_request.rb | 4 +++- lib/gitlab/closing_issue_extractor.rb | 16 ++++++++++++++++ spec/models/merge_request_spec.rb | 8 ++++++++ 5 files changed, 29 insertions(+), 14 deletions(-) create mode 100644 lib/gitlab/closing_issue_extractor.rb diff --git a/CHANGELOG b/CHANGELOG index 4a299827c1..b677c9bca0 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -35,6 +35,7 @@ v 7.0.0 - Be more selective when killing stray Sidekiqs - Check LDAP user filter during sign-in - Remove wall feature (no data loss - you can take it from database) + - Detect issues closed by Merge Request description v 6.9.2 - Revert the commit that broke the LDAP user filter diff --git a/app/models/commit.rb b/app/models/commit.rb index 81875e1be2..82876e1044 100644 --- a/app/models/commit.rb +++ b/app/models/commit.rb @@ -111,22 +111,10 @@ class Commit description.present? end - # Regular expression that identifies commit message clauses that trigger issue closing. - def issue_closing_regex - @issue_closing_regex ||= Regexp.new(Gitlab.config.gitlab.issue_closing_pattern) - end - # Discover issues should be closed when this commit is pushed to a project's # default branch. def closes_issues project - md = issue_closing_regex.match(safe_message) - if md - extractor = Gitlab::ReferenceExtractor.new - extractor.analyze(md[0]) - extractor.issues_for(project) - else - [] - end + Gitlab::ClosingIssueExtractor.closed_by_message_in_project(safe_message, project) end # Mentionable override. diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index a501870115..bfea209bf6 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -220,7 +220,9 @@ class MergeRequest < ActiveRecord::Base # Return the set of issues that will be closed if this merge request is accepted. def closes_issues if target_branch == project.default_branch - commits.map { |c| c.closes_issues(project) }.flatten.uniq.sort_by(&:id) + issues = commits.flat_map { |c| c.closes_issues(project) } + issues += Gitlab::ClosingIssueExtractor.closed_by_message_in_project(description, project) + issues.uniq.sort_by(&:id) else [] end diff --git a/lib/gitlab/closing_issue_extractor.rb b/lib/gitlab/closing_issue_extractor.rb new file mode 100644 index 0000000000..90f1370c20 --- /dev/null +++ b/lib/gitlab/closing_issue_extractor.rb @@ -0,0 +1,16 @@ +module Gitlab + module ClosingIssueExtractor + ISSUE_CLOSING_REGEX = Regexp.new(Gitlab.config.gitlab.issue_closing_pattern) + + def self.closed_by_message_in_project(message, project) + md = ISSUE_CLOSING_REGEX.match(message) + if md + extractor = Gitlab::ReferenceExtractor.new + extractor.analyze(md[0]) + extractor.issues_for(project) + else + [] + end + end + end +end diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index 81a48699cd..1148df87ab 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -105,6 +105,14 @@ describe MergeRequest do subject.closes_issues.should be_empty end + + it 'detects issues mentioned in the description' do + issue2 = create(:issue, project: subject.project) + subject.description = "Closes ##{issue2.iid}" + subject.project.stub(default_branch: subject.target_branch) + + subject.closes_issues.should include(issue2) + end end it_behaves_like 'an editable mentionable' do From 2af8ace1dc49e5ff59be01c2063139a3244b9cee Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 13 Jun 2014 18:40:37 +0300 Subject: [PATCH 323/360] Small UI fixes Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/generic/files.scss | 2 +- app/assets/stylesheets/sections/tree.scss | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/app/assets/stylesheets/generic/files.scss b/app/assets/stylesheets/generic/files.scss index 9e4207965f..5aeccfe1d1 100644 --- a/app/assets/stylesheets/generic/files.scss +++ b/app/assets/stylesheets/generic/files.scss @@ -16,7 +16,7 @@ text-shadow: 0 1px 1px #fff; margin: 0; text-align: left; - padding: 9px 10px; + padding: 10px 15px; .options { float: right; diff --git a/app/assets/stylesheets/sections/tree.scss b/app/assets/stylesheets/sections/tree.scss index c019b62672..d0e03d5b66 100644 --- a/app/assets/stylesheets/sections/tree.scss +++ b/app/assets/stylesheets/sections/tree.scss @@ -157,6 +157,8 @@ margin-bottom: 10px; .commit { + padding: 10px 15px; + .commit-row-title { font-size: 13px; From d69853585415c1fa89a9e39e4f2e0853412b047b Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Fri, 13 Jun 2014 14:38:10 +0200 Subject: [PATCH 324/360] Add a test for issue sentence generation --- app/helpers/merge_requests_helper.rb | 4 ++++ .../merge_requests/show/_state_widget.html.haml | 2 +- spec/helpers/merge_requests_helper.rb | 12 ++++++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 spec/helpers/merge_requests_helper.rb diff --git a/app/helpers/merge_requests_helper.rb b/app/helpers/merge_requests_helper.rb index f3c3d43771..cc63db2035 100644 --- a/app/helpers/merge_requests_helper.rb +++ b/app/helpers/merge_requests_helper.rb @@ -42,4 +42,8 @@ module MergeRequestsHelper "Branches: #{@merge_request.source_branch} #{separator} #{@merge_request.target_branch}" end end + + def issues_sentence(issues) + issues.map { |i| "##{i.iid}" }.to_sentence + end end diff --git a/app/views/projects/merge_requests/show/_state_widget.html.haml b/app/views/projects/merge_requests/show/_state_widget.html.haml index bff5b36821..c30310f125 100644 --- a/app/views/projects/merge_requests/show/_state_widget.html.haml +++ b/app/views/projects/merge_requests/show/_state_widget.html.haml @@ -37,5 +37,5 @@ %i.icon-ok Accepting this merge request will close #{@closes_issues.size == 1 ? 'issue' : 'issues'} = succeed '.' do - != gfm(@closes_issues.map { |i| "##{i.iid}" }.to_sentence) + != gfm(issues_sentence(@closes_issues)) diff --git a/spec/helpers/merge_requests_helper.rb b/spec/helpers/merge_requests_helper.rb new file mode 100644 index 0000000000..5a317c4886 --- /dev/null +++ b/spec/helpers/merge_requests_helper.rb @@ -0,0 +1,12 @@ +require 'spec_helper' + +describe MergeRequestsHelper do + describe :issues_sentence do + subject { issues_sentence(issues) } + let(:issues) do + [build(:issue, iid: 1), build(:issue, iid: 2), build(:issue, iid: 3)] + end + + it { should eq('#1, #2, and #3') } + end +end From e8f222e39c5f7124bd604246c8d2502181760888 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 13 Jun 2014 19:35:21 +0300 Subject: [PATCH 325/360] Fix helper specs Signed-off-by: Dmitriy Zaporozhets --- spec/helpers/application_helper_spec.rb | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb index 6401ec0710..6a11414a02 100644 --- a/spec/helpers/application_helper_spec.rb +++ b/spec/helpers/application_helper_spec.rb @@ -67,10 +67,9 @@ describe ApplicationHelper do end it "should call gravatar_icon when no avatar is present" do - user = create(:user) + user = create(:user, email: 'test@example.com') user.save! - allow(self).to receive(:gravatar_icon).and_return('gravatar_method_called') - avatar_icon(user.email).to_s.should == "gravatar_method_called" + avatar_icon(user.email).to_s.should == "http://www.gravatar.com/avatar/55502f40dc8b7c769880b10874abc9d0?s=40&d=mm" end end @@ -87,12 +86,12 @@ describe ApplicationHelper do end it "should return default gravatar url" do - allow(self).to receive(:request).and_return(double(:ssl? => false)) + Gitlab.config.gitlab.stub(https: false) gravatar_icon(user_email).should match('http://www.gravatar.com/avatar/b58c6f14d292556214bd64909bcdb118') end it "should use SSL when appropriate" do - allow(self).to receive(:request).and_return(double(:ssl? => true)) + Gitlab.config.gitlab.stub(https: true) gravatar_icon(user_email).should match('https://secure.gravatar.com') end From 8ff171f62849d5e418847c1751a802f93604cc61 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 13 Jun 2014 19:39:12 +0300 Subject: [PATCH 326/360] Fix api specs Signed-off-by: Dmitriy Zaporozhets --- spec/requests/api/notes_spec.rb | 4 ++-- spec/requests/api/project_members_spec.rb | 12 ++++++------ spec/requests/api/projects_spec.rb | 6 +++--- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/spec/requests/api/notes_spec.rb b/spec/requests/api/notes_spec.rb index 1179618347..2875db04ee 100644 --- a/spec/requests/api/notes_spec.rb +++ b/spec/requests/api/notes_spec.rb @@ -93,7 +93,7 @@ describe API::API, api: true do post api("/projects/#{project.id}/issues/#{issue.id}/notes", user), body: 'hi!' response.status.should == 201 json_response['body'].should == 'hi!' - json_response['author']['email'].should == user.email + json_response['author']['username'].should == user.username end it "should return a 400 bad request error if body not given" do @@ -112,7 +112,7 @@ describe API::API, api: true do post api("/projects/#{project.id}/snippets/#{snippet.id}/notes", user), body: 'hi!' response.status.should == 201 json_response['body'].should == 'hi!' - json_response['author']['email'].should == user.email + json_response['author']['username'].should == user.username end it "should return a 400 bad request error if body not given" do diff --git a/spec/requests/api/project_members_spec.rb b/spec/requests/api/project_members_spec.rb index ec2d6e8509..032f850010 100644 --- a/spec/requests/api/project_members_spec.rb +++ b/spec/requests/api/project_members_spec.rb @@ -21,7 +21,7 @@ describe API::API, api: true do response.status.should == 200 json_response.should be_an Array json_response.count.should == 2 - json_response.map { |u| u['email'] }.should include user.email + json_response.map { |u| u['username'] }.should include user.username end it "finds team members with query string" do @@ -29,7 +29,7 @@ describe API::API, api: true do response.status.should == 200 json_response.should be_an Array json_response.count.should == 1 - json_response.first['email'].should == user.email + json_response.first['username'].should == user.username end it "should return a 404 error if id not found" do @@ -44,7 +44,7 @@ describe API::API, api: true do it "should return project team member" do get api("/projects/#{project.id}/members/#{user.id}", user) response.status.should == 200 - json_response['email'].should == user.email + json_response['username'].should == user.username json_response['access_level'].should == UsersProject::MASTER end @@ -62,7 +62,7 @@ describe API::API, api: true do }.to change { UsersProject.count }.by(1) response.status.should == 201 - json_response['email'].should == user2.email + json_response['username'].should == user2.username json_response['access_level'].should == UsersProject::DEVELOPER end @@ -75,7 +75,7 @@ describe API::API, api: true do }.not_to change { UsersProject.count }.by(1) response.status.should == 201 - json_response['email'].should == user2.email + json_response['username'].should == user2.username json_response['access_level'].should == UsersProject::DEVELOPER end @@ -101,7 +101,7 @@ describe API::API, api: true do it "should update project team member" do put api("/projects/#{project.id}/members/#{user3.id}", user), access_level: UsersProject::MASTER response.status.should == 200 - json_response['email'].should == user3.email + json_response['username'].should == user3.username json_response['access_level'].should == UsersProject::MASTER end diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index 43915d8684..415735091c 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -37,7 +37,7 @@ describe API::API, api: true do response.status.should == 200 json_response.should be_an Array json_response.first['name'].should == project.name - json_response.first['owner']['email'].should == user.email + json_response.first['owner']['username'].should == user.username end end end @@ -65,7 +65,7 @@ describe API::API, api: true do response.status.should == 200 json_response.should be_an Array json_response.first['name'].should == project.name - json_response.first['owner']['email'].should == user.email + json_response.first['owner']['username'].should == user.username end end end @@ -270,7 +270,7 @@ describe API::API, api: true do get api("/projects/#{project.id}", user) response.status.should == 200 json_response['name'].should == project.name - json_response['owner']['email'].should == user.email + json_response['owner']['username'].should == user.username end it "should return a project by path name" do From 47d6f70528dd4b41739c0a6767f74a8a40d9aaaa Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 13 Jun 2014 19:42:17 +0300 Subject: [PATCH 327/360] Add /api/users test for admin role. Updated CHANGELOG Signed-off-by: Dmitriy Zaporozhets --- CHANGELOG | 1 + spec/requests/api/users_spec.rb | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 4a299827c1..c353c3b770 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -35,6 +35,7 @@ v 7.0.0 - Be more selective when killing stray Sidekiqs - Check LDAP user filter during sign-in - Remove wall feature (no data loss - you can take it from database) + - Dont expose user emails via API unless you are admin v 6.9.2 - Revert the commit that broke the LDAP user filter diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb index c4728431ec..c3eec56d13 100644 --- a/spec/requests/api/users_spec.rb +++ b/spec/requests/api/users_spec.rb @@ -23,6 +23,17 @@ describe API::API, api: true do json_response.first['username'].should == user.username end end + + context "when admin" do + it "should return an array of users" do + get api("/users", admin) + response.status.should == 200 + json_response.should be_an Array + json_response.first.keys.should include 'email' + json_response.first.keys.should include 'extern_uid' + json_response.first.keys.should include 'can_create_project' + end + end end describe "GET /users/:id" do From eb7845682d3e9f66694ce6a5a97765fda898a4d2 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 13 Jun 2014 20:21:48 +0300 Subject: [PATCH 328/360] Improve files/snippets action buttons Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/generic/files.scss | 2 +- app/assets/stylesheets/sections/tree.scss | 9 --------- app/models/ability.rb | 6 +++++- app/views/projects/blob/_actions.html.haml | 6 +++--- app/views/projects/snippets/_blob.html.haml | 15 +++++++++------ app/views/snippets/_blob.html.haml | 16 +++++++++------- app/views/snippets/show.html.haml | 4 ++-- 7 files changed, 29 insertions(+), 29 deletions(-) diff --git a/app/assets/stylesheets/generic/files.scss b/app/assets/stylesheets/generic/files.scss index 5aeccfe1d1..1412277ffb 100644 --- a/app/assets/stylesheets/generic/files.scss +++ b/app/assets/stylesheets/generic/files.scss @@ -20,7 +20,7 @@ .options { float: right; - margin-top: -5px; + margin-top: -3px; } .left-options { diff --git a/app/assets/stylesheets/sections/tree.scss b/app/assets/stylesheets/sections/tree.scss index d0e03d5b66..18a5f6204f 100644 --- a/app/assets/stylesheets/sections/tree.scss +++ b/app/assets/stylesheets/sections/tree.scss @@ -117,15 +117,6 @@ } } -.tree-btn-group { - top: 2px; - - .btn { - margin-right: 0px; - padding: 2px 10px; - } -} - .tree-download-holder .btn { padding: 4px 12px; } diff --git a/app/models/ability.rb b/app/models/ability.rb index c60aa2d622..234578b5e1 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -236,7 +236,11 @@ class Ability :"modify_#{name}", ] else - subject.respond_to?(:project) ? project_abilities(user, subject.project) : [] + if subject.respond_to?(:project) + project_abilities(user, subject.project) + else + [] + end end end end diff --git a/app/views/projects/blob/_actions.html.haml b/app/views/projects/blob/_actions.html.haml index 2f82bfe52f..cabef3c19f 100644 --- a/app/views/projects/blob/_actions.html.haml +++ b/app/views/projects/blob/_actions.html.haml @@ -14,6 +14,6 @@ = link_to "blame", project_blame_path(@project, @id), class: "btn btn-small" unless @blob.empty? = link_to "history", project_commits_path(@project, @id), class: "btn btn-small" - - if allowed_tree_edit? - = link_to '#modal-remove-blob', class: "remove-blob btn btn-small btn-remove", "data-toggle" => "modal" do - remove +- if allowed_tree_edit? + = link_to '#modal-remove-blob', class: "remove-blob btn btn-small btn-remove", "data-toggle" => "modal" do + remove diff --git a/app/views/projects/snippets/_blob.html.haml b/app/views/projects/snippets/_blob.html.haml index af326a1a99..c6350cb7d1 100644 --- a/app/views/projects/snippets/_blob.html.haml +++ b/app/views/projects/snippets/_blob.html.haml @@ -1,10 +1,13 @@ .file-holder .file-title %i.icon-file - %strong= @snippet.file_name - %span.options - .btn-group.tree-btn-group.pull-right - - if can?(current_user, :admin_project_snippet, @project) || @snippet.author == current_user - = link_to "Edit", edit_project_snippet_path(@project, @snippet), class: "btn btn-tiny", title: 'Edit Snippet' - = link_to "Raw", raw_project_snippet_path(@project, @snippet), class: "btn btn-tiny", target: "_blank" + %span.file_name + = @snippet.file_name + .options + .btn-group + - if can?(current_user, :modify_project_snippet, @snippet) + = link_to "edit", edit_project_snippet_path(@project, @snippet), class: "btn btn-small", title: 'Edit Snippet' + = link_to "raw", raw_project_snippet_path(@project, @snippet), class: "btn btn-small", target: "_blank" + - if can?(current_user, :admin_project_snippet, @snippet) + = link_to "remove", project_snippet_path(@project, @snippet), method: :delete, data: { confirm: "Are you sure?" }, class: "btn btn-small btn-remove", title: 'Delete Snippet' = render 'snippets/blob_content' diff --git a/app/views/snippets/_blob.html.haml b/app/views/snippets/_blob.html.haml index 15867f071e..4a907011ad 100644 --- a/app/views/snippets/_blob.html.haml +++ b/app/views/snippets/_blob.html.haml @@ -1,11 +1,13 @@ .file-holder .file-title %i.icon-file - %strong= @snippet.file_name - %span.options - .btn-group.tree-btn-group.pull-right - - if @snippet.author == current_user - = link_to "Edit", edit_snippet_path(@snippet), class: "btn btn-tiny", title: 'Edit Snippet' - = link_to "Delete", snippet_path(@snippet), method: :delete, data: { confirm: "Are you sure?" }, class: "btn btn-tiny", title: 'Delete Snippet' - = link_to "Raw", raw_snippet_path(@snippet), class: "btn btn-tiny", target: "_blank" + %span.file_name + = @snippet.file_name + .options + .btn-group + - if can?(current_user, :modify_personal_snippet, @snippet) + = link_to "edit", edit_snippet_path(@snippet), class: "btn btn-small", title: 'Edit Snippet' + = link_to "raw", raw_snippet_path(@snippet), class: "btn btn-small", target: "_blank" + - if can?(current_user, :admin_personal_snippet, @snippet) + = link_to "remove", snippet_path(@snippet), method: :delete, data: { confirm: "Are you sure?" }, class: "btn btn-small btn-remove", title: 'Delete Snippet' = render 'snippets/blob_content' diff --git a/app/views/snippets/show.html.haml b/app/views/snippets/show.html.haml index a680e5eb5b..655ff947d2 100644 --- a/app/views/snippets/show.html.haml +++ b/app/views/snippets/show.html.haml @@ -7,9 +7,9 @@ private .pull-right - = link_to new_snippet_path, class: "btn btn-new btn-small", title: "New Snippet" do + = link_to new_snippet_path, class: "btn btn-new", title: "New Snippet" do Add new snippet - +%hr .append-bottom-20 .pull-right From 8b6dd9d4a802eeba5fa4f7e10d738a2af5e87d98 Mon Sep 17 00:00:00 2001 From: Job van der Voort Date: Sat, 14 Jun 2014 11:17:11 +0200 Subject: [PATCH 329/360] responsive sidebar --- Gemfile | 3 ++ Gemfile.lock | 3 ++ app/assets/javascripts/application.js.coffee | 1 + app/assets/javascripts/sidebar.js.coffee | 27 +++++++++++++++++ app/assets/stylesheets/application.scss | 5 ++++ app/assets/stylesheets/generic/sidebar.scss | 31 ++++++++++++++++++++ app/views/dashboard/show.html.haml | 5 +++- 7 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 app/assets/javascripts/sidebar.js.coffee create mode 100644 app/assets/stylesheets/generic/sidebar.scss diff --git a/Gemfile b/Gemfile index ef0adb5e2b..928b766f16 100644 --- a/Gemfile +++ b/Gemfile @@ -156,6 +156,9 @@ gem "rack-attack" # Ace editor gem 'ace-rails-ap' +# Semantic UI Sass for Sidebar +gem 'semantic-ui-sass', '~> 0.16.1.0' + gem "sass-rails", '~> 4.0.2' gem "coffee-rails" gem "uglifier" diff --git a/Gemfile.lock b/Gemfile.lock index 3bea962f6a..896e6fdebe 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -452,6 +452,8 @@ GEM activesupport (>= 3.1, < 4.2) select2-rails (3.5.2) thor (~> 0.14) + semantic-ui-sass (0.16.1.0) + sass (~> 3.2) settingslogic (2.0.9) sexp_processor (4.4.0) shoulda-matchers (2.1.0) @@ -656,6 +658,7 @@ DEPENDENCIES sdoc seed-fu select2-rails + semantic-ui-sass (~> 0.16.1.0) settingslogic shoulda-matchers (~> 2.1.0) sidekiq (= 2.17.0) diff --git a/app/assets/javascripts/application.js.coffee b/app/assets/javascripts/application.js.coffee index 35e4355466..9bcd8f0a17 100644 --- a/app/assets/javascripts/application.js.coffee +++ b/app/assets/javascripts/application.js.coffee @@ -30,6 +30,7 @@ #= require nprogress #= require nprogress-turbolinks #= require dropzone +#= require semantic-ui/sidebar #= require_tree . window.slugify = (text) -> diff --git a/app/assets/javascripts/sidebar.js.coffee b/app/assets/javascripts/sidebar.js.coffee new file mode 100644 index 0000000000..71e29d9ce0 --- /dev/null +++ b/app/assets/javascripts/sidebar.js.coffee @@ -0,0 +1,27 @@ +responsive_resize = -> + current_width = $(window).width() + if current_width < 985 + $('.side').addClass("ui right wide sidebar") + else + $('.side').removeClass("ui right wide sidebar") + +$ -> + responsive_resize() + + $('.ui.sidebar') + .sidebar() + + $('.sidebar-expand-button').click -> + $('.ui.sidebar') + .sidebar({overlay: true}) + .sidebar('toggle') + + # Hide sidebar on click outside of sidebar + $(document).mouseup (e) -> + container = $(".ui.sidebar") + container.sidebar "hide" if not container.is(e.target) and container.has(e.target).length is 0 + return + +$(window).resize -> + responsive_resize() + return diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index 630d2aa429..7d058ad771 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -51,3 +51,8 @@ * Styles for JS behaviors. */ @import "behaviors.scss"; + +/** +* Styles for responsive sidebar +*/ +@import "semantic-ui/modules/sidebar" diff --git a/app/assets/stylesheets/generic/sidebar.scss b/app/assets/stylesheets/generic/sidebar.scss new file mode 100644 index 0000000000..46f829b67b --- /dev/null +++ b/app/assets/stylesheets/generic/sidebar.scss @@ -0,0 +1,31 @@ +.ui.sidebar { + z-index: 1000 !important; + background: #fff; + padding: 10px; + border-left: 1px solid #e1e1e1; + width: 285px; +} + +.sidebar-expand-button { + background: #fff; + color: #555; + padding: 10px 15px; + border: 1px solid #E1E1E1; + border-right: 0; + border-radius: 3px; + position: fixed; + top: 108px; + right: 0px; + margin-right: 0; + cursor: pointer; + transition: all 0.4s; + -moz-transition: all 0.4s; + -webkit-transition: all 0.4s; + + + &:hover { + background: #ddd; + color: #333; + padding-right: 25px; + } +} diff --git a/app/views/dashboard/show.html.haml b/app/views/dashboard/show.html.haml index e5b7fbf097..cf6119672d 100644 --- a/app/views/dashboard/show.html.haml +++ b/app/views/dashboard/show.html.haml @@ -2,8 +2,11 @@ .dashboard.row .activities.col-md-8 = render 'activities' - .side.col-md-4.hidden-sm.hidden-xs + .side.col-md-4 = render 'sidebar' + .sidebar-expand-button.hidden-lg.hidden-md + %i.icon-list.icon-2x + - else = render "zero_authorized_projects" From d718209b47022abe8a28a7267cd40569bd7ec06a Mon Sep 17 00:00:00 2001 From: Job van der Voort Date: Sat, 14 Jun 2014 11:18:00 +0200 Subject: [PATCH 330/360] responsive sidebar on dashboard --- app/assets/javascripts/sidebar.js.coffee | 6 ++++-- app/assets/stylesheets/generic/sidebar.scss | 6 ++---- app/views/dashboard/show.html.haml | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/app/assets/javascripts/sidebar.js.coffee b/app/assets/javascripts/sidebar.js.coffee index 71e29d9ce0..13b3c8a18b 100644 --- a/app/assets/javascripts/sidebar.js.coffee +++ b/app/assets/javascripts/sidebar.js.coffee @@ -1,11 +1,12 @@ responsive_resize = -> current_width = $(window).width() if current_width < 985 - $('.side').addClass("ui right wide sidebar") + $('.responsive-side').addClass("ui right wide sidebar") else - $('.side').removeClass("ui right wide sidebar") + $('.responsive-side').removeClass("ui right wide sidebar") $ -> + # Depending on window size, set the sidebar offscreen. responsive_resize() $('.ui.sidebar') @@ -22,6 +23,7 @@ $ -> container.sidebar "hide" if not container.is(e.target) and container.has(e.target).length is 0 return +# On resize, check if sidebar should be offscreen. $(window).resize -> responsive_resize() return diff --git a/app/assets/stylesheets/generic/sidebar.scss b/app/assets/stylesheets/generic/sidebar.scss index 46f829b67b..eab80ee72b 100644 --- a/app/assets/stylesheets/generic/sidebar.scss +++ b/app/assets/stylesheets/generic/sidebar.scss @@ -7,12 +7,11 @@ } .sidebar-expand-button { - background: #fff; + background: #f9f9f9; color: #555; - padding: 10px 15px; + padding: 9px 12px 6px 14px; border: 1px solid #E1E1E1; border-right: 0; - border-radius: 3px; position: fixed; top: 108px; right: 0px; @@ -22,7 +21,6 @@ -moz-transition: all 0.4s; -webkit-transition: all 0.4s; - &:hover { background: #ddd; color: #333; diff --git a/app/views/dashboard/show.html.haml b/app/views/dashboard/show.html.haml index cf6119672d..9fd32cdc69 100644 --- a/app/views/dashboard/show.html.haml +++ b/app/views/dashboard/show.html.haml @@ -2,7 +2,7 @@ .dashboard.row .activities.col-md-8 = render 'activities' - .side.col-md-4 + .side.col-md-4.responsive-side = render 'sidebar' .sidebar-expand-button.hidden-lg.hidden-md From 600f4c68940160556b0a4c6ecf18c40dd6ad94d5 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sat, 14 Jun 2014 12:36:31 +0300 Subject: [PATCH 331/360] Fix snippet dev fixtures Signed-off-by: Dmitriy Zaporozhets --- db/fixtures/development/12_snippets.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/db/fixtures/development/12_snippets.rb b/db/fixtures/development/12_snippets.rb index dced270626..ff91e8430a 100644 --- a/db/fixtures/development/12_snippets.rb +++ b/db/fixtures/development/12_snippets.rb @@ -1,8 +1,8 @@ Gitlab::Seeder.quiet do contents = [ - `curl https://gist.github.com/randx/4275756/raw/da2f262920c96d1a970d48bf2e99147954b1f4bd/glus1204.sh`, - `curl https://gist.github.com/randx/3754594/raw/11026a295e6ef3a151c635707a3e1e8e15fc4725/gitlab_setup.sh `, - `curl https://gist.github.com/randx/3065552/raw/29fbd09f4605a5ea22a5a9095e35fd1938dea4d6/gistfile1.sh`, + `curl https://gist.githubusercontent.com/randx/4275756/raw/da2f262920c96d1a970d48bf2e99147954b1f4bd/glus1204.sh`, + `curl https://gist.githubusercontent.com/randx/3754594/raw/11026a295e6ef3a151c635707a3e1e8e15fc4725/gitlab_setup.sh`, + `curl https://gist.githubusercontent.com/randx/3065552/raw/29fbd09f4605a5ea22a5a9095e35fd1938dea4d6/gistfile1.sh`, ] (1..50).each do |i| From 9be5425a887d96aaf603dd537d36f410eb663e4f Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sat, 14 Jun 2014 12:36:46 +0300 Subject: [PATCH 332/360] Refactor snippets views Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/sections/snippets.scss | 3 + app/views/projects/snippets/_blob.html.haml | 13 ----- app/views/projects/snippets/edit.html.haml | 5 +- app/views/projects/snippets/new.html.haml | 5 +- app/views/projects/snippets/show.html.haml | 34 +++++++++-- .../snippets/_blob.html.haml} | 0 .../snippets/_form.html.haml | 33 +++++++---- app/views/snippets/_blob.html.haml | 13 ----- app/views/snippets/_form.html.haml | 58 ------------------- app/views/snippets/edit.html.haml | 5 +- app/views/snippets/new.html.haml | 5 +- app/views/snippets/show.html.haml | 14 ++++- features/project/snippets.feature | 1 - features/snippets/snippets.feature | 1 - features/steps/project/snippets.rb | 2 +- features/steps/snippets/snippets.rb | 2 +- 16 files changed, 87 insertions(+), 107 deletions(-) delete mode 100644 app/views/projects/snippets/_blob.html.haml rename app/views/{snippets/_blob_content.html.haml => shared/snippets/_blob.html.haml} (100%) rename app/views/{projects => shared}/snippets/_form.html.haml (55%) delete mode 100644 app/views/snippets/_blob.html.haml delete mode 100644 app/views/snippets/_form.html.haml diff --git a/app/assets/stylesheets/sections/snippets.scss b/app/assets/stylesheets/sections/snippets.scss index 84404b6ee3..d79591d991 100644 --- a/app/assets/stylesheets/sections/snippets.scss +++ b/app/assets/stylesheets/sections/snippets.scss @@ -3,3 +3,6 @@ padding-top: 0; } +.snippet-form-holder .file-holder .file-title { + padding: 2px; +} diff --git a/app/views/projects/snippets/_blob.html.haml b/app/views/projects/snippets/_blob.html.haml deleted file mode 100644 index c6350cb7d1..0000000000 --- a/app/views/projects/snippets/_blob.html.haml +++ /dev/null @@ -1,13 +0,0 @@ -.file-holder - .file-title - %i.icon-file - %span.file_name - = @snippet.file_name - .options - .btn-group - - if can?(current_user, :modify_project_snippet, @snippet) - = link_to "edit", edit_project_snippet_path(@project, @snippet), class: "btn btn-small", title: 'Edit Snippet' - = link_to "raw", raw_project_snippet_path(@project, @snippet), class: "btn btn-small", target: "_blank" - - if can?(current_user, :admin_project_snippet, @snippet) - = link_to "remove", project_snippet_path(@project, @snippet), method: :delete, data: { confirm: "Are you sure?" }, class: "btn btn-small btn-remove", title: 'Delete Snippet' - = render 'snippets/blob_content' diff --git a/app/views/projects/snippets/edit.html.haml b/app/views/projects/snippets/edit.html.haml index e28b7d4937..f6a5bf9e4f 100644 --- a/app/views/projects/snippets/edit.html.haml +++ b/app/views/projects/snippets/edit.html.haml @@ -1 +1,4 @@ -= render "projects/snippets/form", url: project_snippet_path(@project, @snippet) +%h3.page-title + Edit snippet +%hr += render "shared/snippets/form", url: project_snippet_path(@project, @snippet) diff --git a/app/views/projects/snippets/new.html.haml b/app/views/projects/snippets/new.html.haml index 460af34f67..10f684b631 100644 --- a/app/views/projects/snippets/new.html.haml +++ b/app/views/projects/snippets/new.html.haml @@ -1 +1,4 @@ -= render "projects/snippets/form", url: project_snippets_path(@project, @snippet) +%h3.page-title + New snippet +%hr += render "shared/snippets/form", url: project_snippets_path(@project, @snippet) diff --git a/app/views/projects/snippets/show.html.haml b/app/views/projects/snippets/show.html.haml index ac32f4866b..e4fdbd868c 100644 --- a/app/views/projects/snippets/show.html.haml +++ b/app/views/projects/snippets/show.html.haml @@ -1,11 +1,37 @@ %h3.page-title = @snippet.title - %small.pull-right + .pull-right + = link_to new_project_snippet_path(@project), class: "btn btn-new", title: "New Snippet" do + Add new snippet + +%hr + +.append-bottom-20 + .pull-right = "##{@snippet.id}" %span.light by - = image_tag avatar_icon(@snippet.author_email), class: "avatar avatar-inline s16" - = @snippet.author_name -%div= render 'projects/snippets/blob' + = link_to user_path(@snippet.author) do + = image_tag avatar_icon(@snippet.author_email), class: "avatar avatar-inline s16" + = @snippet.author_name + + .back-link + = link_to project_snippets_path(@project) do + ← project snippets + +.file-holder + .file-title + %i.icon-file + %span.file_name + = @snippet.file_name + .options + .btn-group + - if can?(current_user, :modify_project_snippet, @snippet) + = link_to "edit", edit_project_snippet_path(@project, @snippet), class: "btn btn-small", title: 'Edit Snippet' + = link_to "raw", raw_project_snippet_path(@project, @snippet), class: "btn btn-small", target: "_blank" + - if can?(current_user, :admin_project_snippet, @snippet) + = link_to "remove", project_snippet_path(@project, @snippet), method: :delete, data: { confirm: "Are you sure?" }, class: "btn btn-small btn-remove", title: 'Delete Snippet' + = render 'shared/snippets/blob' + %div#notes= render "projects/notes/notes_with_form" diff --git a/app/views/snippets/_blob_content.html.haml b/app/views/shared/snippets/_blob.html.haml similarity index 100% rename from app/views/snippets/_blob_content.html.haml rename to app/views/shared/snippets/_blob.html.haml diff --git a/app/views/projects/snippets/_form.html.haml b/app/views/shared/snippets/_form.html.haml similarity index 55% rename from app/views/projects/snippets/_form.html.haml rename to app/views/shared/snippets/_form.html.haml index 866346990d..49ea8460e7 100644 --- a/app/views/projects/snippets/_form.html.haml +++ b/app/views/shared/snippets/_form.html.haml @@ -1,9 +1,6 @@ -%h3.page-title - = @snippet.new_record? ? "New Snippet" : "Edit Snippet ##{@snippet.id}" -%hr .snippet-form-holder - = form_for [@project, @snippet], as: :project_snippet, url: url, html: {class: "form-horizontal snippet-form"} do |f| - -if @snippet.errors.any? + = form_for @snippet, url: url, html: { class: "form-horizontal snippet-form" } do |f| + - if @snippet.errors.any? .alert.alert-danger %ul - @snippet.errors.full_messages.each do |msg| @@ -12,6 +9,23 @@ .form-group = f.label :title, class: 'control-label' .col-sm-10= f.text_field :title, placeholder: "Example Snippet", class: 'form-control', required: true + + - unless @snippet.respond_to?(:project) + .form-group + = f.label "Access", class: 'control-label' + .col-sm-10 + = f.label :private_true, class: 'radio-label' do + = f.radio_button :private, true + %span + %strong Private + (only you can see this snippet) + %br + = f.label :private_false, class: 'radio-label' do + = f.radio_button :private, false + %span + %strong Public + (GitLab users can see this snippet) + .form-group .file-editor = f.label :file_name, "File", class: 'control-label' @@ -29,14 +43,13 @@ - else = f.submit 'Save', class: "btn-save btn" - - unless @snippet.new_record? - .pull-right.prepend-left-20 - = link_to 'Remove snippet', project_snippet_path(@project, @snippet), data: { confirm: 'Are you sure?' }, method: :delete, class: "btn pull-right btn-remove delete-snippet prepend-left-10", id: "destroy_snippet_#{@snippet.id}" - = link_to "Cancel", project_snippets_path(@project), class: "btn btn-cancel" + - if @snippet.respond_to?(:project) + = link_to "Cancel", project_snippets_path(@project), class: "btn btn-cancel" + - else + = link_to "Cancel", snippets_path(@project), class: "btn btn-cancel" :javascript var editor = ace.edit("editor"); $(".snippet-form-holder form").submit(function(){ $(".snippet-file-content").val(editor.getValue()); }); - diff --git a/app/views/snippets/_blob.html.haml b/app/views/snippets/_blob.html.haml deleted file mode 100644 index 4a907011ad..0000000000 --- a/app/views/snippets/_blob.html.haml +++ /dev/null @@ -1,13 +0,0 @@ -.file-holder - .file-title - %i.icon-file - %span.file_name - = @snippet.file_name - .options - .btn-group - - if can?(current_user, :modify_personal_snippet, @snippet) - = link_to "edit", edit_snippet_path(@snippet), class: "btn btn-small", title: 'Edit Snippet' - = link_to "raw", raw_snippet_path(@snippet), class: "btn btn-small", target: "_blank" - - if can?(current_user, :admin_personal_snippet, @snippet) - = link_to "remove", snippet_path(@snippet), method: :delete, data: { confirm: "Are you sure?" }, class: "btn btn-small btn-remove", title: 'Delete Snippet' - = render 'snippets/blob_content' diff --git a/app/views/snippets/_form.html.haml b/app/views/snippets/_form.html.haml deleted file mode 100644 index d466dc1af1..0000000000 --- a/app/views/snippets/_form.html.haml +++ /dev/null @@ -1,58 +0,0 @@ -%h3.page-title - = @snippet.new_record? ? "New Snippet" : "Edit Snippet ##{@snippet.id}" -%hr -.snippet-form-holder - = form_for @snippet, as: :personal_snippet, url: url, html: { class: "form-horizontal snippet-form" } do |f| - -if @snippet.errors.any? - .alert.alert-danger - %ul - - @snippet.errors.full_messages.each do |msg| - %li= msg - - .form-group - = f.label :title, class: 'control-label' - .col-sm-10= f.text_field :title, placeholder: "Example Snippet", class: 'form-control', required: true - .form-group - = f.label "Access", class: 'control-label' - .col-sm-10 - = f.label :private_true, class: 'radio-label' do - = f.radio_button :private, true - %span - %strong Private - (only you can see this snippet) - %br - = f.label :private_false, class: 'radio-label' do - = f.radio_button :private, false - %span - %strong Public - (GitLab users can see this snippet) - - .form-group - .file-editor - = f.label :file_name, "File", class: 'control-label' - .col-sm-10 - .file-holder.snippet - .file-title - = f.text_field :file_name, placeholder: "example.rb", class: 'form-control snippet-file-name', required: true - .file-content.code - %pre#editor= @snippet.content - = f.hidden_field :content, class: 'snippet-file-content' - - .form-actions - - if @snippet.new_record? - = f.submit 'Create snippet', class: "btn-create btn" - - else - = f.submit 'Save', class: "btn-save btn" - - - unless @snippet.new_record? - .pull-right.prepend-left-20 - = link_to 'Remove', snippet_path(@snippet), data: { confirm: 'Removed snippet cannot be restored! Are you sure?'}, method: :delete, class: "btn btn-remove delete-snippet", id: "destroy_snippet_#{@snippet.id}" - = link_to "Cancel", snippets_path(@project), class: "btn btn-cancel" - - -:javascript - var editor = ace.edit("editor"); - $(".snippet-form-holder form").submit(function(){ - $(".snippet-file-content").val(editor.getValue()); - }); - diff --git a/app/views/snippets/edit.html.haml b/app/views/snippets/edit.html.haml index 1b88a85faf..7042d07d5e 100644 --- a/app/views/snippets/edit.html.haml +++ b/app/views/snippets/edit.html.haml @@ -1 +1,4 @@ -= render "snippets/form", url: snippet_path(@snippet) +%h3.page-title + Edit snippet +%hr += render "shared/snippets/form", url: snippet_path(@snippet) diff --git a/app/views/snippets/new.html.haml b/app/views/snippets/new.html.haml index 90e0a1f79d..694d705831 100644 --- a/app/views/snippets/new.html.haml +++ b/app/views/snippets/new.html.haml @@ -1 +1,4 @@ -= render "snippets/form", url: snippets_path(@snippet) +%h3.page-title + New snippet +%hr += render "shared/snippets/form", url: snippets_path(@snippet) diff --git a/app/views/snippets/show.html.haml b/app/views/snippets/show.html.haml index 655ff947d2..1d2e3d5ae4 100644 --- a/app/views/snippets/show.html.haml +++ b/app/views/snippets/show.html.haml @@ -28,4 +28,16 @@ = link_to snippets_path do ← discover snippets -%div= render 'blob' +.file-holder + .file-title + %i.icon-file + %span.file_name + = @snippet.file_name + .options + .btn-group + - if can?(current_user, :modify_personal_snippet, @snippet) + = link_to "edit", edit_snippet_path(@snippet), class: "btn btn-small", title: 'Edit Snippet' + = link_to "raw", raw_snippet_path(@snippet), class: "btn btn-small", target: "_blank" + - if can?(current_user, :admin_personal_snippet, @snippet) + = link_to "remove", snippet_path(@snippet), method: :delete, data: { confirm: "Are you sure?" }, class: "btn btn-small btn-remove", title: 'Delete Snippet' + = render 'shared/snippets/blob' diff --git a/features/project/snippets.feature b/features/project/snippets.feature index dfaa02663a..77e42a1a38 100644 --- a/features/project/snippets.feature +++ b/features/project/snippets.feature @@ -30,6 +30,5 @@ Feature: Project Snippets Scenario: I destroy "Snippet one" Given I visit snippet page "Snippet one" - And I click link "Edit" And I click link "Remove Snippet" Then I should not see "Snippet one" in snippets diff --git a/features/snippets/snippets.feature b/features/snippets/snippets.feature index 3ee8720ddd..38216dd5b7 100644 --- a/features/snippets/snippets.feature +++ b/features/snippets/snippets.feature @@ -24,6 +24,5 @@ Feature: Snippets Feature Scenario: I destroy "Personal snippet one" Given I visit snippet page "Personal snippet one" - And I click link "Edit" And I click link "Destroy" Then I should not see "Personal snippet one" in snippets diff --git a/features/steps/project/snippets.rb b/features/steps/project/snippets.rb index c3a76bea26..feae535fbe 100644 --- a/features/steps/project/snippets.rb +++ b/features/steps/project/snippets.rb @@ -48,7 +48,7 @@ class ProjectSnippets < Spinach::FeatureSteps end And 'I click link "Remove Snippet"' do - click_link "Remove snippet" + click_link "remove" end And 'I submit new snippet "Snippet three"' do diff --git a/features/steps/snippets/snippets.rb b/features/steps/snippets/snippets.rb index fed54659eb..040b5390a5 100644 --- a/features/steps/snippets/snippets.rb +++ b/features/steps/snippets/snippets.rb @@ -19,7 +19,7 @@ class SnippetsFeature < Spinach::FeatureSteps end And 'I click link "Destroy"' do - click_link "Remove" + click_link "remove" end And 'I submit new snippet "Personal snippet three"' do From 054d68a3e9092f21d407dc39b784dece8c935bfe Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sat, 14 Jun 2014 12:58:08 +0300 Subject: [PATCH 333/360] Improve MR message for huge diffs Signed-off-by: Dmitriy Zaporozhets --- app/controllers/projects/merge_requests_controller.rb | 1 + app/views/projects/commits/_diffs.html.haml | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index f8447691d6..1abedc1f27 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -93,6 +93,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController diff_line_count = Commit::diff_line_count(@diffs) @suppress_diff = Commit::diff_suppress?(@diffs, diff_line_count) + @force_suppress_diff = @suppress_diff end end diff --git a/app/views/projects/commits/_diffs.html.haml b/app/views/projects/commits/_diffs.html.haml index ed95a30bc7..3d7b597414 100644 --- a/app/views/projects/commits/_diffs.html.haml +++ b/app/views/projects/commits/_diffs.html.haml @@ -11,12 +11,13 @@ = link_to "plain diff", project_commit_path(@project, @commit, format: :diff), class: "underlined-link" or = link_to "email patch", project_commit_path(@project, @commit, format: :patch), class: "underlined-link" + instead. - elsif @merge_request && @merge_request.persisted? Please, download the diff as = link_to "plain diff", project_merge_request_path(@project, @merge_request, format: :diff), class: "underlined-link" or = link_to "email patch", project_merge_request_path(@project, @merge_request, format: :patch), class: "underlined-link" - instead. + instead. - unless @force_suppress_diff %p If you still want to see the diff From 0b7f83ad7e0444f6514898359a415a731f9ee8ff Mon Sep 17 00:00:00 2001 From: Cyril Rohr Date: Thu, 12 Jun 2014 20:41:33 +0100 Subject: [PATCH 334/360] Enable CentOS packaging. --- .pkgr.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.pkgr.yml b/.pkgr.yml index 09cb83783d..97d78b6ef6 100644 --- a/.pkgr.yml +++ b/.pkgr.yml @@ -17,3 +17,10 @@ targets: - libicu52 - libpcre3 - git + centos-6: + build_dependencies: + - libicu-devel + dependencies: + - libicu + - pcre + - git From 9c843041faf000a76bd2b542f594c061dab45c3a Mon Sep 17 00:00:00 2001 From: Job van der Voort Date: Sat, 14 Jun 2014 14:32:41 +0200 Subject: [PATCH 335/360] add responsive sidebar to issues, milestones and MRs --- app/assets/javascripts/sidebar.js.coffee | 2 ++ app/assets/stylesheets/generic/sidebar.scss | 22 ++++++++++++++++++- app/views/dashboard/issues.html.haml | 4 +++- app/views/dashboard/merge_requests.html.haml | 4 +++- app/views/dashboard/show.html.haml | 2 +- app/views/groups/issues.html.haml | 4 +++- app/views/groups/merge_requests.html.haml | 4 +++- app/views/projects/issues/index.html.haml | 4 +++- .../projects/merge_requests/index.html.haml | 4 +++- app/views/projects/milestones/index.html.haml | 4 +++- app/views/shared/_filter.html.haml | 2 +- app/views/shared/_project_filter.html.haml | 2 +- 12 files changed, 47 insertions(+), 11 deletions(-) diff --git a/app/assets/javascripts/sidebar.js.coffee b/app/assets/javascripts/sidebar.js.coffee index 13b3c8a18b..e4a8cc6a4b 100644 --- a/app/assets/javascripts/sidebar.js.coffee +++ b/app/assets/javascripts/sidebar.js.coffee @@ -2,8 +2,10 @@ responsive_resize = -> current_width = $(window).width() if current_width < 985 $('.responsive-side').addClass("ui right wide sidebar") + $('.responsive-side-left').addClass("ui left sidebar") else $('.responsive-side').removeClass("ui right wide sidebar") + $('.responsive-side-left').removeClass("ui left sidebar") $ -> # Depending on window size, set the sidebar offscreen. diff --git a/app/assets/stylesheets/generic/sidebar.scss b/app/assets/stylesheets/generic/sidebar.scss index eab80ee72b..7d93db3cf9 100644 --- a/app/assets/stylesheets/generic/sidebar.scss +++ b/app/assets/stylesheets/generic/sidebar.scss @@ -2,10 +2,19 @@ z-index: 1000 !important; background: #fff; padding: 10px; - border-left: 1px solid #e1e1e1; width: 285px; } +.ui.left.sidebar { + border-right: 1px solid #e1e1e1; + border-left: 0; +} + +.ui.right.sidebar { + border-left: 1px solid #e1e1e1; + border-right: 0; +} + .sidebar-expand-button { background: #f9f9f9; color: #555; @@ -27,3 +36,14 @@ padding-right: 25px; } } + +.left.sidebar-expand-button { + left: 0px; + right: auto; + border: 1px solid #E1E1E1; + border-left: 0; + &:hover { + padding-right: 14px; + padding-left: 25px; + } +} diff --git a/app/views/dashboard/issues.html.haml b/app/views/dashboard/issues.html.haml index af627588ad..670755b899 100755 --- a/app/views/dashboard/issues.html.haml +++ b/app/views/dashboard/issues.html.haml @@ -7,7 +7,9 @@ %hr .row - .col-md-3 + .left.sidebar-expand-button.hidden-lg.hidden-md + %i.icon-list.icon-2x + .col-md-3.responsive-side-left = render 'shared/filter', entity: 'issue' .col-md-9 = render 'shared/issues' diff --git a/app/views/dashboard/merge_requests.html.haml b/app/views/dashboard/merge_requests.html.haml index 550a93e178..0a87eedaec 100755 --- a/app/views/dashboard/merge_requests.html.haml +++ b/app/views/dashboard/merge_requests.html.haml @@ -7,7 +7,9 @@ List all merge requests from all projects you have access to. %hr .row - .col-md-3 + .left.sidebar-expand-button.hidden-lg.hidden-md + %i.icon-list.icon-2x + .col-md-3.responsive-side-left = render 'shared/filter', entity: 'merge_request' .col-md-9 = render 'shared/merge_requests' diff --git a/app/views/dashboard/show.html.haml b/app/views/dashboard/show.html.haml index 9fd32cdc69..b81eed7600 100644 --- a/app/views/dashboard/show.html.haml +++ b/app/views/dashboard/show.html.haml @@ -2,7 +2,7 @@ .dashboard.row .activities.col-md-8 = render 'activities' - .side.col-md-4.responsive-side + .side.col-md-4.left.responsive-side = render 'sidebar' .sidebar-expand-button.hidden-lg.hidden-md diff --git a/app/views/groups/issues.html.haml b/app/views/groups/issues.html.haml index 4b11d91dc9..7c6042b8ba 100644 --- a/app/views/groups/issues.html.haml +++ b/app/views/groups/issues.html.haml @@ -11,7 +11,9 @@ %hr .row - .col-md-3 + .left.sidebar-expand-button.hidden-lg.hidden-md + %i.icon-list.icon-2x + .col-md-3.responsive-side-left = render 'shared/filter', entity: 'issue' .col-md-9 = render 'shared/issues' diff --git a/app/views/groups/merge_requests.html.haml b/app/views/groups/merge_requests.html.haml index 209130ec44..817790f06c 100644 --- a/app/views/groups/merge_requests.html.haml +++ b/app/views/groups/merge_requests.html.haml @@ -10,7 +10,9 @@ To see all merge requests you should visit #{link_to 'dashboard', merge_requests_dashboard_path} page. %hr .row - .col-md-3 + .left.sidebar-expand-button.hidden-lg.hidden-md + %i.icon-list.icon-2x + .col-md-3.responsive-side-left = render 'shared/filter', entity: 'merge_request' .col-md-9 = render 'shared/merge_requests' diff --git a/app/views/projects/issues/index.html.haml b/app/views/projects/issues/index.html.haml index 51a8c911af..e527b7bc2c 100644 --- a/app/views/projects/issues/index.html.haml +++ b/app/views/projects/issues/index.html.haml @@ -1,6 +1,8 @@ = render "head" .row - .col-md-3 + .left.sidebar-expand-button.hidden-lg.hidden-md + %i.icon-list.icon-2x + .col-md-3.responsive-side-left = render 'shared/project_filter', project_entities_path: project_issues_path(@project), labels: true, redirect: 'issues' .col-md-9.issues-holder diff --git a/app/views/projects/merge_requests/index.html.haml b/app/views/projects/merge_requests/index.html.haml index 232d398c53..919efc5fa1 100644 --- a/app/views/projects/merge_requests/index.html.haml +++ b/app/views/projects/merge_requests/index.html.haml @@ -7,7 +7,9 @@ %span (#{@merge_requests.total_count}) %hr .row - .col-md-3 + .left.sidebar-expand-button.hidden-lg.hidden-md + %i.icon-list.icon-2x + .col-md-3.responsive-side-left = render 'shared/project_filter', project_entities_path: project_merge_requests_path(@project), labels: true, redirect: 'merge_requests' .col-md-9 diff --git a/app/views/projects/milestones/index.html.haml b/app/views/projects/milestones/index.html.haml index 15635b299f..4b44d68a91 100644 --- a/app/views/projects/milestones/index.html.haml +++ b/app/views/projects/milestones/index.html.haml @@ -8,7 +8,9 @@ New Milestone .row - .col-md-3.hidden-sm + .left.sidebar-expand-button.hidden-lg.hidden-md + %i.icon-list.icon-2x + .col-md-3.responsive-side-left %ul.nav.nav-pills.nav-stacked %li{class: ("active" if (params[:f] == "active" || !params[:f]))} = link_to project_milestones_path(@project, f: "active") do diff --git a/app/views/shared/_filter.html.haml b/app/views/shared/_filter.html.haml index 0becf531cc..19ecc458e2 100644 --- a/app/views/shared/_filter.html.haml +++ b/app/views/shared/_filter.html.haml @@ -1,4 +1,4 @@ -.side-filters.hidden-xs.hidden-sm +.side-filters = form_tag filter_path(entity), method: 'get' do - if current_user %fieldset.scope-filter diff --git a/app/views/shared/_project_filter.html.haml b/app/views/shared/_project_filter.html.haml index 7936a038be..743b4fba54 100644 --- a/app/views/shared/_project_filter.html.haml +++ b/app/views/shared/_project_filter.html.haml @@ -1,4 +1,4 @@ -.side-filters.hidden-xs.hidden-sm +.side-filters = form_tag project_entities_path, method: 'get' do - if current_user %fieldset From 6a7990c007f2349f3093aef3e70eaa8c092033c8 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sat, 14 Jun 2014 15:51:07 +0300 Subject: [PATCH 336/360] Remove garbage and apply wiki style Signed-off-by: Dmitriy Zaporozhets --- app/controllers/help_controller.rb | 11 ------ app/views/help/_api_layout.html.haml | 13 ------- app/views/help/_layout.html.haml | 6 --- app/views/help/api.html.haml | 14 ------- app/views/help/markdown.html.haml | 6 --- app/views/help/permissions.html.haml | 6 --- app/views/help/public_access.html.haml | 6 --- app/views/help/raketasks.html.haml | 52 -------------------------- app/views/help/security.html.haml | 15 -------- app/views/help/show.html.haml | 5 +-- app/views/help/ssh.html.haml | 6 --- app/views/help/system_hooks.html.haml | 6 --- app/views/help/web_hooks.html.haml | 6 --- app/views/help/workflow.html.haml | 6 --- 14 files changed, 2 insertions(+), 156 deletions(-) delete mode 100644 app/views/help/_api_layout.html.haml delete mode 100644 app/views/help/_layout.html.haml delete mode 100644 app/views/help/api.html.haml delete mode 100644 app/views/help/markdown.html.haml delete mode 100644 app/views/help/permissions.html.haml delete mode 100644 app/views/help/public_access.html.haml delete mode 100644 app/views/help/raketasks.html.haml delete mode 100644 app/views/help/security.html.haml delete mode 100644 app/views/help/ssh.html.haml delete mode 100644 app/views/help/system_hooks.html.haml delete mode 100644 app/views/help/web_hooks.html.haml delete mode 100644 app/views/help/workflow.html.haml diff --git a/app/controllers/help_controller.rb b/app/controllers/help_controller.rb index a4fcd4b29e..fc498559d6 100644 --- a/app/controllers/help_controller.rb +++ b/app/controllers/help_controller.rb @@ -2,17 +2,6 @@ class HelpController < ApplicationController def index end - def api - @category = params[:category] - @category = "README" if @category.blank? - - if File.exists?(Rails.root.join('doc', 'api', @category + '.md')) - render 'api' - else - not_found! - end - end - def show @category = params[:category] @file = params[:file] diff --git a/app/views/help/_api_layout.html.haml b/app/views/help/_api_layout.html.haml deleted file mode 100644 index af723f906d..0000000000 --- a/app/views/help/_api_layout.html.haml +++ /dev/null @@ -1,13 +0,0 @@ -.row - .col-md-3 - .append-bottom-20 - = link_to help_path, class: 'btn btn-small' do - %i.icon-angle-left - Back to help - %ul.nav.nav-pills.nav-stacked - - %w(README projects project_snippets repositories repository_files commits deploy_keys users groups session issues milestones merge_requests notes system_hooks).each do |file| - %li{class: file == @category ? 'active' : nil} - = link_to file.titleize, help_api_file_path(file) - - .col-md-9.pull-right - = yield diff --git a/app/views/help/_layout.html.haml b/app/views/help/_layout.html.haml deleted file mode 100644 index 93a746c60e..0000000000 --- a/app/views/help/_layout.html.haml +++ /dev/null @@ -1,6 +0,0 @@ -.row - .col-md-3 - %h3.page-title Help - .col-md-9 - .wiki - = yield diff --git a/app/views/help/api.html.haml b/app/views/help/api.html.haml deleted file mode 100644 index 3d2cf50b7f..0000000000 --- a/app/views/help/api.html.haml +++ /dev/null @@ -1,14 +0,0 @@ -= render layout: 'help/api_layout' do - %h3.page-title - %span.light API - %span - \/ - = @category.titleize - - .file-holder - .file-title - %i.icon-file - = @category - .file-content.wiki - = preserve do - = markdown File.read(Rails.root.join("doc", "api", "#{@category}.md")) diff --git a/app/views/help/markdown.html.haml b/app/views/help/markdown.html.haml deleted file mode 100644 index ec9d13f2d6..0000000000 --- a/app/views/help/markdown.html.haml +++ /dev/null @@ -1,6 +0,0 @@ -= render layout: 'help/layout' do - %h3.page-title GitLab Flavored Markdown - - .help_body - = preserve do - = markdown File.read(Rails.root.join("doc", "markdown", "markdown.md")) diff --git a/app/views/help/permissions.html.haml b/app/views/help/permissions.html.haml deleted file mode 100644 index 5d3ee4526f..0000000000 --- a/app/views/help/permissions.html.haml +++ /dev/null @@ -1,6 +0,0 @@ -= render layout: 'help/layout' do - %h3.page-title Permissions - - .help_body - = preserve do - = markdown File.read(Rails.root.join("doc", "permissions", "permissions.md")) diff --git a/app/views/help/public_access.html.haml b/app/views/help/public_access.html.haml deleted file mode 100644 index d1ec3f5d5c..0000000000 --- a/app/views/help/public_access.html.haml +++ /dev/null @@ -1,6 +0,0 @@ -= render layout: 'help/layout' do - %h3.page-title Public Access - - .help_body - = preserve do - = markdown File.read(Rails.root.join("doc", "public_access", "public_access.md")) diff --git a/app/views/help/raketasks.html.haml b/app/views/help/raketasks.html.haml deleted file mode 100644 index 61a3774a13..0000000000 --- a/app/views/help/raketasks.html.haml +++ /dev/null @@ -1,52 +0,0 @@ -= render layout: 'help/layout' do - %h3.page-title GitLab Rake Tasks - - %p.slead - GitLab provides some specific rake tasks to enable special features or perform maintenance tasks. - - %ul.nav.nav-tabs.log-tabs - %li.active - = link_to "Maintenance", "#maintenance", 'data-toggle' => 'tab' - %li - = link_to "User Management", "#user_management", 'data-toggle' => 'tab' - %li - = link_to "Backup & Restore", "#backup_restore", 'data-toggle' => 'tab' - %li - = link_to "Cleanup", "#cleanup", 'data-toggle' => 'tab' - - .tab-content - .tab-pane.active#maintenance - .file-holder - .file-title - %i.icon-file - Maintenance - .file-content.wiki - = preserve do - = markdown File.read(Rails.root.join("doc", "raketasks", "maintenance.md")) - - .tab-pane#user_management - .file-holder - .file-title - %i.icon-file - User Management - .file-content.wiki - = preserve do - = markdown File.read(Rails.root.join("doc", "raketasks", "user_management.md")) - - .tab-pane#cleanup - .file-holder - .file-title - %i.icon-file - Cleanup - .file-content.wiki - = preserve do - = markdown File.read(Rails.root.join("doc", "raketasks", "cleanup.md")) - - .tab-pane#backup_restore - .file-holder - .file-title - %i.icon-file - Backup & Restore - .file-content.wiki - = preserve do - = markdown File.read(Rails.root.join("doc", "raketasks", "backup_restore.md")) diff --git a/app/views/help/security.html.haml b/app/views/help/security.html.haml deleted file mode 100644 index 72f21e9f63..0000000000 --- a/app/views/help/security.html.haml +++ /dev/null @@ -1,15 +0,0 @@ -= render layout: 'help/layout' do - %h3.page-title Security - - %p.slead - If your GitLab instance is visible from the internet chances are it will be 'tested' by bots sooner or later. - %br - %br - %br - .file-holder - .file-title - %i.icon-file - Dealing with bruteforcing - .file-content.wiki - = preserve do - = markdown File.read(Rails.root.join("doc", "security", "rack_attack.md")) diff --git a/app/views/help/show.html.haml b/app/views/help/show.html.haml index e9fc6163c7..67f9cc41cf 100644 --- a/app/views/help/show.html.haml +++ b/app/views/help/show.html.haml @@ -1,3 +1,2 @@ -.col-md-12 - .documentation - = markdown File.read(Rails.root.join('doc', @category, @file + '.md')) +.documentation.wiki + = markdown File.read(Rails.root.join('doc', @category, @file + '.md')) diff --git a/app/views/help/ssh.html.haml b/app/views/help/ssh.html.haml deleted file mode 100644 index 75419c3dd0..0000000000 --- a/app/views/help/ssh.html.haml +++ /dev/null @@ -1,6 +0,0 @@ -= render layout: 'help/layout' do - %h3.page-title SSH Keys - - .help_body - = preserve do - = markdown File.read(Rails.root.join("doc", "ssh", "ssh.md")).gsub("$your_email", current_user.email) diff --git a/app/views/help/system_hooks.html.haml b/app/views/help/system_hooks.html.haml deleted file mode 100644 index e24f566121..0000000000 --- a/app/views/help/system_hooks.html.haml +++ /dev/null @@ -1,6 +0,0 @@ -= render layout: 'help/layout' do - %h3.page-title System hooks - - .help_body - = preserve do - = markdown File.read(Rails.root.join("doc", "system_hooks", "system_hooks.md")) diff --git a/app/views/help/web_hooks.html.haml b/app/views/help/web_hooks.html.haml deleted file mode 100644 index 9e2b54ab6e..0000000000 --- a/app/views/help/web_hooks.html.haml +++ /dev/null @@ -1,6 +0,0 @@ -= render layout: 'help/layout' do - %h3.page-title Project web hooks - - .help_body - = preserve do - = markdown File.read(Rails.root.join("doc", "web_hooks", "web_hooks.md")) diff --git a/app/views/help/workflow.html.haml b/app/views/help/workflow.html.haml deleted file mode 100644 index 47de4ad796..0000000000 --- a/app/views/help/workflow.html.haml +++ /dev/null @@ -1,6 +0,0 @@ -= render layout: 'help/layout' do - %h3.page-title Workflow - - .help_body - = preserve do - = markdown File.read(Rails.root.join("doc", "workflow", "workflow.md")) From 55795b7c297c08b4b3f7f6dc3ee98cd0d29c6748 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sat, 14 Jun 2014 19:02:16 +0300 Subject: [PATCH 337/360] Improve breadcrumbs Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/generic/common.scss | 6 ------ app/assets/stylesheets/gl_bootstrap.scss | 14 -------------- app/assets/stylesheets/sections/commits.scss | 11 +++++++---- app/assets/stylesheets/sections/projects.scss | 12 ++++++++++++ app/assets/stylesheets/sections/tree.scss | 4 ---- app/helpers/commits_helper.rb | 8 +++----- app/views/projects/commits/_head.html.haml | 8 -------- app/views/projects/commits/show.html.haml | 18 +++++++++++++----- app/views/projects/tree/_tree.html.haml | 2 +- app/views/projects/tree/show.html.haml | 2 +- 10 files changed, 37 insertions(+), 48 deletions(-) diff --git a/app/assets/stylesheets/generic/common.scss b/app/assets/stylesheets/generic/common.scss index 3b034b757b..da2c1b0cbd 100644 --- a/app/assets/stylesheets/generic/common.scss +++ b/app/assets/stylesheets/generic/common.scss @@ -59,12 +59,6 @@ pre { color: #FFF } -.breadcrumb > li + li:before { - content: "/"; - padding: 0; - color: #666; -} - .str-truncated { @include str-truncated; } diff --git a/app/assets/stylesheets/gl_bootstrap.scss b/app/assets/stylesheets/gl_bootstrap.scss index 6c244afa50..4271a7b310 100644 --- a/app/assets/stylesheets/gl_bootstrap.scss +++ b/app/assets/stylesheets/gl_bootstrap.scss @@ -199,20 +199,6 @@ $list-group-active-bg: $bg_style_color; color: #3c763d; } -// Breadcrumb -ul.breadcrumb { - background: white; - border: none; - li { - display: inline; - text-shadow: 0 1px 0 white - } - - a { - font-size: 16px; - } -} - /** * fix to keep tooltips position in top navigation bar * diff --git a/app/assets/stylesheets/sections/commits.scss b/app/assets/stylesheets/sections/commits.scss index e2503a8a16..ef8c5f089b 100644 --- a/app/assets/stylesheets/sections/commits.scss +++ b/app/assets/stylesheets/sections/commits.scss @@ -115,10 +115,6 @@ line-height: 2; } -.commit-breadcrumb { - padding: 0; -} - .commit-info-row { margin-bottom: 10px; .avatar { @@ -210,3 +206,10 @@ li.commit { } } } + +.commits-feed-holder { + float: right; + .btn { + padding: 4px 12px; + } +} diff --git a/app/assets/stylesheets/sections/projects.scss b/app/assets/stylesheets/sections/projects.scss index 71f5f1663c..34dd3448f5 100644 --- a/app/assets/stylesheets/sections/projects.scss +++ b/app/assets/stylesheets/sections/projects.scss @@ -239,3 +239,15 @@ ul.nav.nav-projects-tabs { .vs-private { color: $bg_success; } + +.breadcrumb.repo-breadcrumb { + padding: 2px 0; + background: white; + border: none; + font-size: 16px; + + > li + li:before { + padding: 0 3px; + color: #999; + } +} diff --git a/app/assets/stylesheets/sections/tree.scss b/app/assets/stylesheets/sections/tree.scss index 18a5f6204f..b08f94f55a 100644 --- a/app/assets/stylesheets/sections/tree.scss +++ b/app/assets/stylesheets/sections/tree.scss @@ -4,10 +4,6 @@ width: 100%; } - .breadcrumb { - padding: 2px 0; - } - .tree_progress { display: none; margin: 20px; diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb index c4abdbdabc..62aa683237 100644 --- a/app/helpers/commits_helper.rb +++ b/app/helpers/commits_helper.rb @@ -76,15 +76,13 @@ module CommitsHelper # Add the root project link and the arrow icon crumbs = content_tag(:li) do - content_tag(:span, nil, class: 'arrow') + - link_to(@project.name, project_commits_path(@project, @ref)) + link_to(@project.path, project_commits_path(@project, @ref)) end if @path parts = @path.split('/') parts.each_with_index do |part, i| - crumbs += content_tag(:span, ' / ', class: 'divider') crumbs += content_tag(:li) do # The text is just the individual part, but the link needs all the parts before it link_to part, project_commits_path(@project, tree_join(@ref, parts[0..i].join('/'))) @@ -195,11 +193,11 @@ module CommitsHelper def commit_person_link(commit, options = {}) source_name = commit.send "#{options[:source]}_name".to_sym source_email = commit.send "#{options[:source]}_email".to_sym - + user = User.find_for_commit(source_email, source_name) person_name = user.nil? ? source_name : user.name person_email = user.nil? ? source_email : user.email - + text = if options[:avatar] avatar = image_tag(avatar_icon(person_email, options[:size]), class: "avatar #{"s#{options[:size]}" if options[:size]}", width: options[:size], alt: "") %Q{#{avatar} #{person_name}} diff --git a/app/views/projects/commits/_head.html.haml b/app/views/projects/commits/_head.html.haml index 1bb4d9bfab..b636e8ffe1 100644 --- a/app/views/projects/commits/_head.html.haml +++ b/app/views/projects/commits/_head.html.haml @@ -1,6 +1,4 @@ %ul.nav.nav-tabs - %li= render partial: 'shared/ref_switcher', locals: {destination: 'commits'} - = nav_link(controller: [:commit, :commits]) do = link_to 'Commits', project_commits_path(@project, @repository.root_ref) = nav_link(controller: :compare) do @@ -19,9 +17,3 @@ = nav_link(controller: :repositories, action: :stats) do = link_to stats_project_repository_path(@project) do Stats - - - - if current_user && current_controller?(:commits) && current_user.private_token - %li.pull-right.hidden-sm - = link_to project_commits_path(@project, @ref, {format: :atom, private_token: current_user.private_token}), title: "Feed" do - %i.icon-rss diff --git a/app/views/projects/commits/show.html.haml b/app/views/projects/commits/show.html.haml index 3a4f304a25..482a845558 100644 --- a/app/views/projects/commits/show.html.haml +++ b/app/views/projects/commits/show.html.haml @@ -1,10 +1,18 @@ = render "head" -- if @path.present? - %ul.breadcrumb.commit-breadcrumb - %li.light - History for - = commits_breadcrumbs +.tree-ref-holder + = render 'shared/ref_switcher', destination: 'commits' + +- if current_user && current_user.private_token + .commits-feed-holder.hidden-xs.hidden-sm + = link_to project_commits_path(@project, @ref, {format: :atom, private_token: current_user.private_token}), title: "Feed", class: 'btn' do + %i.icon-rss + Commits feed + +%ul.breadcrumb.repo-breadcrumb + = commits_breadcrumbs + %li.active + commits %div{id: dom_id(@project)} #commits-list= render "commits" diff --git a/app/views/projects/tree/_tree.html.haml b/app/views/projects/tree/_tree.html.haml index fe572260e0..33cc40f475 100644 --- a/app/views/projects/tree/_tree.html.haml +++ b/app/views/projects/tree/_tree.html.haml @@ -1,4 +1,4 @@ -%ul.breadcrumb +%ul.breadcrumb.repo-breadcrumb %li = link_to project_tree_path(@project, @ref) do = @project.path diff --git a/app/views/projects/tree/show.html.haml b/app/views/projects/tree/show.html.haml index 1ef3020f35..fc4616da6e 100644 --- a/app/views/projects/tree/show.html.haml +++ b/app/views/projects/tree/show.html.haml @@ -3,7 +3,7 @@ - if can? current_user, :download_code, @project .tree-download-holder - = render 'projects/repositories/download_archive', ref: @ref, btn_class: 'btn-group-small pull-right hidden-xs', split_button: true + = render 'projects/repositories/download_archive', ref: @ref, btn_class: 'btn-group-small pull-right hidden-xs hidden-sm', split_button: true #tree-holder.tree-holder.clearfix = render "tree", tree: @tree From 951279b1a312db5d943c970d435bba5b29901375 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sat, 14 Jun 2014 19:09:36 +0300 Subject: [PATCH 338/360] Improve tree view for iPad Signed-off-by: Dmitriy Zaporozhets --- app/views/projects/tree/_tree.html.haml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/views/projects/tree/_tree.html.haml b/app/views/projects/tree/_tree.html.haml index 33cc40f475..84c3682d7a 100644 --- a/app/views/projects/tree/_tree.html.haml +++ b/app/views/projects/tree/_tree.html.haml @@ -20,9 +20,9 @@ %tr %th Name %th Last Update - %th.hidden-sm.hidden-xs - Last Commit - %span.last-commit + %th.hidden-xs + .pull-left Last Commit + .last-commit.hidden-sm.pull-left   %i.icon-angle-right   From 3637d244be046c145598777fce2488598d7ca6e8 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sat, 14 Jun 2014 19:35:45 +0300 Subject: [PATCH 339/360] Improve network UI Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/sections/graph.scss | 4 ++-- app/views/projects/network/_head.html.haml | 18 +++--------------- app/views/projects/network/show.html.haml | 13 +++++++++++-- 3 files changed, 16 insertions(+), 19 deletions(-) diff --git a/app/assets/stylesheets/sections/graph.scss b/app/assets/stylesheets/sections/graph.scss index 8a337a5e20..3d878d1e52 100644 --- a/app/assets/stylesheets/sections/graph.scss +++ b/app/assets/stylesheets/sections/graph.scss @@ -1,10 +1,10 @@ .project-network { border: 1px solid #CCC; - .tip { + .controls { color: #888; font-size: 14px; - padding: 10px; + padding: 5px; border-bottom: 1px solid #bbb; background: #EEE; } diff --git a/app/views/projects/network/_head.html.haml b/app/views/projects/network/_head.html.haml index d61ff789b6..415c98ec6a 100644 --- a/app/views/projects/network/_head.html.haml +++ b/app/views/projects/network/_head.html.haml @@ -1,15 +1,3 @@ -.row.append-bottom-20 - .col-md-2.append-bottom-10 - = render partial: 'shared/ref_switcher', locals: {destination: 'graph'} - .col-md-10 - = form_tag project_network_path(@project, @id), method: :get, class: 'form-inline network-form' do |f| - = label_tag :extended_sha1 , "Looking for", class: 'light inline-label' - = text_field_tag :extended_sha1, @options[:extended_sha1], placeholder: "Input an extended SHA1 syntax", class: "search-input form-control input-mx-250" - = button_tag type: 'submit', class: 'btn btn-success' do - %i.icon-search - - .inline.prepend-left-20 - .checkbox.light - = label_tag :filter_ref do - = check_box_tag :filter_ref, 1, @options[:filter_ref] - %span Begin with the selected commit +.append-bottom-20 + = render partial: 'shared/ref_switcher', locals: {destination: 'graph'} + .pull-right.visible-lg.light You can move around the graph by using the arrow keys. diff --git a/app/views/projects/network/show.html.haml b/app/views/projects/network/show.html.haml index 37bc0a4c6b..5310822823 100644 --- a/app/views/projects/network/show.html.haml +++ b/app/views/projects/network/show.html.haml @@ -1,7 +1,16 @@ = render "head" .project-network - .tip - You can move around the graph by using the arrow keys. + .controls + = form_tag project_network_path(@project, @id), method: :get, class: 'form-inline network-form' do |f| + = text_field_tag :extended_sha1, @options[:extended_sha1], placeholder: "Input an extended SHA1 syntax", class: "search-input form-control input-mx-250" + = button_tag type: 'submit', class: 'btn btn-success' do + %i.icon-search + .inline.prepend-left-20 + .checkbox.light + = label_tag :filter_ref do + = check_box_tag :filter_ref, 1, @options[:filter_ref] + %span Begin with the selected commit + .network-graph = spinner nil, true From 869809a1cf33dc19cf22119301cea42af5f5e45a Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sat, 14 Jun 2014 19:41:32 +0300 Subject: [PATCH 340/360] Remove failing test on travis+pg Signed-off-by: Dmitriy Zaporozhets --- features/steps/project/browse_commits.rb | 4 ---- spec/features/notes_on_merge_requests_spec.rb | 15 --------------- 2 files changed, 19 deletions(-) diff --git a/features/steps/project/browse_commits.rb b/features/steps/project/browse_commits.rb index d667b58240..bd944dee61 100644 --- a/features/steps/project/browse_commits.rb +++ b/features/steps/project/browse_commits.rb @@ -45,11 +45,7 @@ class ProjectBrowseCommits < Spinach::FeatureSteps Then 'I see breadcrumb links' do page.should have_selector('ul.breadcrumb') - page.should have_selector('ul.breadcrumb span.divider', count: 3) page.should have_selector('ul.breadcrumb a', count: 4) - - find('ul.breadcrumb li:nth-child(2) a')['href'].should match(/#{@project.path_with_namespace}\/commits\/master\z/) - find('ul.breadcrumb li:last a')['href'].should match(%r{master/app/models/project\.rb\z}) end Then 'I see commits stats' do diff --git a/spec/features/notes_on_merge_requests_spec.rb b/spec/features/notes_on_merge_requests_spec.rb index 7f1da3cffd..3fe1184966 100644 --- a/spec/features/notes_on_merge_requests_spec.rb +++ b/spec/features/notes_on_merge_requests_spec.rb @@ -32,21 +32,6 @@ describe "On a merge request", js: true, feature: true do within(".js-main-target-form") { should have_css(".js-note-preview-button", visible: true) } end end - - describe "with preview" do - before do - within(".js-main-target-form") do - fill_in "note[note]", with: "This is awesome" - find(".js-note-preview-button").trigger("click") - end - end - - it 'should have text and visible edit button' do - within(".js-main-target-form") { should have_css(".js-note-preview", text: "This is awesome", visible: true) } - within(".js-main-target-form") { should have_css(".js-note-preview-button", visible: false) } - within(".js-main-target-form") { should have_css(".js-note-write-button", visible: true) } - end - end end describe "when posting a note" do From 52b7fa248a8670a86764c4786f4a34b072992715 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sat, 14 Jun 2014 19:55:26 +0300 Subject: [PATCH 341/360] Darker color for page title Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/main/mixins.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/stylesheets/main/mixins.scss b/app/assets/stylesheets/main/mixins.scss index cf6d5ba933..93faf5ced6 100644 --- a/app/assets/stylesheets/main/mixins.scss +++ b/app/assets/stylesheets/main/mixins.scss @@ -117,7 +117,7 @@ } @mixin page-title { - color: #555; + color: #333; line-height: 1.5; font-weight: normal; margin-top: 0px; From 56cb6d889910a2c4b6420c190c235b6e8a0324bb Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sat, 14 Jun 2014 19:58:54 +0300 Subject: [PATCH 342/360] Fix help css Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/sections/help.scss | 2 +- app/views/help/index.html.haml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/assets/stylesheets/sections/help.scss b/app/assets/stylesheets/sections/help.scss index 94cef187d1..90ed98ba25 100644 --- a/app/assets/stylesheets/sections/help.scss +++ b/app/assets/stylesheets/sections/help.scss @@ -1,4 +1,4 @@ -.documentation { +.documentation-index { h1 { margin: 0; } diff --git a/app/views/help/index.html.haml b/app/views/help/index.html.haml index 258a468f7b..a89ccde792 100644 --- a/app/views/help/index.html.haml +++ b/app/views/help/index.html.haml @@ -34,7 +34,7 @@ = link_to "shortcuts", '#', onclick: "new Shortcuts()" .col-md-8 - .panel.panel-default.documentation + .panel.panel-default.documentation-index .panel-heading Documentation .panel-body = preserve do From 72f0a6b286e6a11addc70249643a96fd5b0559c1 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sat, 14 Jun 2014 20:01:56 +0300 Subject: [PATCH 343/360] Fix blob breadcrumb Signed-off-by: Dmitriy Zaporozhets --- 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 b0cac828f3..87574d4648 100644 --- a/app/views/projects/blob/_blob.html.haml +++ b/app/views/projects/blob/_blob.html.haml @@ -1,4 +1,4 @@ -%ul.breadcrumb +%ul.breadcrumb.repo-breadcrumb %li %i.icon-angle-right = link_to project_tree_path(@project, @ref) do From 9e21e96b2a4fdd0485946dfe7ef85b7475ee00a4 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sat, 14 Jun 2014 20:33:12 +0300 Subject: [PATCH 344/360] Fix dashboard "show more project" link padding Signed-off-by: Dmitriy Zaporozhets --- app/views/dashboard/_projects.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/dashboard/_projects.html.haml b/app/views/dashboard/_projects.html.haml index f2cd57504c..5a49bf0c6b 100644 --- a/app/views/dashboard/_projects.html.haml +++ b/app/views/dashboard/_projects.html.haml @@ -19,7 +19,7 @@ %li.bottom %span.light #{@projects_limit} of #{pluralize(@projects_count, 'project')} displayed. - .pull-right.append-right-10 + .pull-right = link_to projects_dashboard_path do Show all %i.icon-angle-right From b48bb4a77ceb3fec8a361a6836eb6feba71c84c9 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sat, 14 Jun 2014 20:35:40 +0300 Subject: [PATCH 345/360] Change mode for view files Signed-off-by: Dmitriy Zaporozhets --- app/views/dashboard/issues.html.haml | 0 app/views/dashboard/merge_requests.html.haml | 0 2 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 app/views/dashboard/issues.html.haml mode change 100755 => 100644 app/views/dashboard/merge_requests.html.haml diff --git a/app/views/dashboard/issues.html.haml b/app/views/dashboard/issues.html.haml old mode 100755 new mode 100644 diff --git a/app/views/dashboard/merge_requests.html.haml b/app/views/dashboard/merge_requests.html.haml old mode 100755 new mode 100644 From d29bb23a6896c1c660fe27d1a9bd5dbfde94bf52 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sat, 14 Jun 2014 22:54:56 +0300 Subject: [PATCH 346/360] Update gitlab-grit to newer version with normal diff collection. Show if file mode was changed Signed-off-by: Dmitriy Zaporozhets --- Gemfile.lock | 2 +- app/assets/stylesheets/sections/diff.scss | 11 +++++++---- app/helpers/commits_helper.rb | 4 ++++ app/views/projects/commits/_diffs.html.haml | 3 +-- app/views/projects/commits/_text_file.html.haml | 3 +++ 5 files changed, 16 insertions(+), 7 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 896e6fdebe..a9a23f7439 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -164,7 +164,7 @@ GEM multi_json gitlab-grack (2.0.0.pre) rack (~> 1.5.1) - gitlab-grit (2.6.8) + gitlab-grit (2.6.9) charlock_holmes (~> 0.6) diff-lcs (~> 1.1) mime-types (~> 1.15) diff --git a/app/assets/stylesheets/sections/diff.scss b/app/assets/stylesheets/sections/diff.scss index 24d997c9fc..f4926e2f52 100644 --- a/app/assets/stylesheets/sections/diff.scss +++ b/app/assets/stylesheets/sections/diff.scss @@ -11,7 +11,6 @@ > span { font-family: $monospace_font; - font-size: 14px; line-height: 2; } @@ -19,9 +18,7 @@ float: right; .btn { - background-color: #EEE; - color: #666; - font-weight: bolder; + background-color: #FFF; } } @@ -32,6 +29,7 @@ .file-mode { font-family: $monospace_font; + margin-left: 10px; } } .diff-content { @@ -51,6 +49,11 @@ } } + .file-mode-changed { + padding: 10px; + color: #777; + } + table { width: 100%; font-family: $monospace_font; diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb index 62aa683237..4d27cf2851 100644 --- a/app/helpers/commits_helper.rb +++ b/app/helpers/commits_helper.rb @@ -216,4 +216,8 @@ module CommitsHelper link_to(text.html_safe, user_path(user), options) end end + + def diff_file_mode_changed?(diff) + diff.a_mode && diff.b_mode && diff.a_mode != diff.b_mode + end end diff --git a/app/views/projects/commits/_diffs.html.haml b/app/views/projects/commits/_diffs.html.haml index 3d7b597414..a62f50776f 100644 --- a/app/views/projects/commits/_diffs.html.haml +++ b/app/views/projects/commits/_diffs.html.haml @@ -42,7 +42,6 @@ .files - unless @suppress_diff - diffs.each_with_index do |diff, i| - - next if diff.diff.empty? - file = project.repository.blob_at(@commit.id, diff.new_path) - file = project.repository.blob_at(@commit.parent_id, diff.old_path) unless file - next unless file @@ -58,7 +57,7 @@ %span.commit-short-id= @commit.short_id(6) - else %span= diff.new_path - - if diff.a_mode && diff.b_mode && diff.a_mode != diff.b_mode + - if diff_file_mode_changed?(diff) %span.file-mode= "#{diff.a_mode} → #{diff.b_mode}" .diff-btn-group diff --git a/app/views/projects/commits/_text_file.html.haml b/app/views/projects/commits/_text_file.html.haml index 74a68b1bf8..8ced413329 100644 --- a/app/views/projects/commits/_text_file.html.haml +++ b/app/views/projects/commits/_text_file.html.haml @@ -22,3 +22,6 @@ - unless comments.empty? = render "projects/notes/diff_notes_with_reply", notes: comments, line: line +- if diff.diff.blank? && diff_file_mode_changed?(diff) + .file-mode-changed + File mode changed From 204fee4f41cafedbb30d4c68793985a9e3ea84e4 Mon Sep 17 00:00:00 2001 From: Job van der Voort Date: Sat, 14 Jun 2014 22:44:23 +0200 Subject: [PATCH 347/360] move all sidebars to one side for improved UX; add button in head of projects/issues and milestones instead of tab on side of screen to prevent overlapping of content --- app/assets/javascripts/sidebar.js.coffee | 5 --- app/assets/stylesheets/generic/sidebar.scss | 35 +++++++++---------- app/views/dashboard/issues.html.haml | 4 +-- app/views/dashboard/merge_requests.html.haml | 4 +-- app/views/dashboard/show.html.haml | 2 +- app/views/groups/issues.html.haml | 4 +-- app/views/groups/merge_requests.html.haml | 4 +-- app/views/projects/issues/_head.html.haml | 7 ++++ app/views/projects/issues/index.html.haml | 4 +-- .../projects/merge_requests/index.html.haml | 4 +-- app/views/projects/milestones/index.html.haml | 4 +-- 11 files changed, 38 insertions(+), 39 deletions(-) diff --git a/app/assets/javascripts/sidebar.js.coffee b/app/assets/javascripts/sidebar.js.coffee index e4a8cc6a4b..c084d730d6 100644 --- a/app/assets/javascripts/sidebar.js.coffee +++ b/app/assets/javascripts/sidebar.js.coffee @@ -2,18 +2,13 @@ responsive_resize = -> current_width = $(window).width() if current_width < 985 $('.responsive-side').addClass("ui right wide sidebar") - $('.responsive-side-left').addClass("ui left sidebar") else $('.responsive-side').removeClass("ui right wide sidebar") - $('.responsive-side-left').removeClass("ui left sidebar") $ -> # Depending on window size, set the sidebar offscreen. responsive_resize() - $('.ui.sidebar') - .sidebar() - $('.sidebar-expand-button').click -> $('.ui.sidebar') .sidebar({overlay: true}) diff --git a/app/assets/stylesheets/generic/sidebar.scss b/app/assets/stylesheets/generic/sidebar.scss index 7d93db3cf9..f6311ef74e 100644 --- a/app/assets/stylesheets/generic/sidebar.scss +++ b/app/assets/stylesheets/generic/sidebar.scss @@ -5,17 +5,19 @@ width: 285px; } -.ui.left.sidebar { - border-right: 1px solid #e1e1e1; - border-left: 0; -} - .ui.right.sidebar { border-left: 1px solid #e1e1e1; border-right: 0; } .sidebar-expand-button { + cursor: pointer; + transition: all 0.4s; + -moz-transition: all 0.4s; + -webkit-transition: all 0.4s; +} + +.fixed.sidebar-expand-button { background: #f9f9f9; color: #555; padding: 9px 12px 6px 14px; @@ -25,11 +27,6 @@ top: 108px; right: 0px; margin-right: 0; - cursor: pointer; - transition: all 0.4s; - -moz-transition: all 0.4s; - -webkit-transition: all 0.4s; - &:hover { background: #ddd; color: #333; @@ -37,13 +34,13 @@ } } -.left.sidebar-expand-button { - left: 0px; - right: auto; - border: 1px solid #E1E1E1; - border-left: 0; - &:hover { - padding-right: 14px; - padding-left: 25px; - } +.btn.btn-default.sidebar-expand-button { + margin-left: 12px; + display: inline-block !important; +} + +@media (min-width: 767px) { +.btn.btn-default.sidebar-expand-button { + display: none!important; + } } diff --git a/app/views/dashboard/issues.html.haml b/app/views/dashboard/issues.html.haml index 670755b899..9888da2f7f 100755 --- a/app/views/dashboard/issues.html.haml +++ b/app/views/dashboard/issues.html.haml @@ -7,9 +7,9 @@ %hr .row - .left.sidebar-expand-button.hidden-lg.hidden-md + .fixed.sidebar-expand-button.hidden-lg.hidden-md %i.icon-list.icon-2x - .col-md-3.responsive-side-left + .col-md-3.responsive-side = render 'shared/filter', entity: 'issue' .col-md-9 = render 'shared/issues' diff --git a/app/views/dashboard/merge_requests.html.haml b/app/views/dashboard/merge_requests.html.haml index 0a87eedaec..ee3bec2849 100755 --- a/app/views/dashboard/merge_requests.html.haml +++ b/app/views/dashboard/merge_requests.html.haml @@ -7,9 +7,9 @@ List all merge requests from all projects you have access to. %hr .row - .left.sidebar-expand-button.hidden-lg.hidden-md + .fixed.sidebar-expand-button.hidden-lg.hidden-md %i.icon-list.icon-2x - .col-md-3.responsive-side-left + .col-md-3.responsive-side = render 'shared/filter', entity: 'merge_request' .col-md-9 = render 'shared/merge_requests' diff --git a/app/views/dashboard/show.html.haml b/app/views/dashboard/show.html.haml index b81eed7600..306b71717e 100644 --- a/app/views/dashboard/show.html.haml +++ b/app/views/dashboard/show.html.haml @@ -5,7 +5,7 @@ .side.col-md-4.left.responsive-side = render 'sidebar' - .sidebar-expand-button.hidden-lg.hidden-md + .fixed.sidebar-expand-button.hidden-lg.hidden-md %i.icon-list.icon-2x - else diff --git a/app/views/groups/issues.html.haml b/app/views/groups/issues.html.haml index 7c6042b8ba..0eec2d6be0 100644 --- a/app/views/groups/issues.html.haml +++ b/app/views/groups/issues.html.haml @@ -11,9 +11,9 @@ %hr .row - .left.sidebar-expand-button.hidden-lg.hidden-md + .fixed.sidebar-expand-button.hidden-lg.hidden-md %i.icon-list.icon-2x - .col-md-3.responsive-side-left + .col-md-3.responsive-side = render 'shared/filter', entity: 'issue' .col-md-9 = render 'shared/issues' diff --git a/app/views/groups/merge_requests.html.haml b/app/views/groups/merge_requests.html.haml index 817790f06c..71adb2c551 100644 --- a/app/views/groups/merge_requests.html.haml +++ b/app/views/groups/merge_requests.html.haml @@ -10,9 +10,9 @@ To see all merge requests you should visit #{link_to 'dashboard', merge_requests_dashboard_path} page. %hr .row - .left.sidebar-expand-button.hidden-lg.hidden-md + .fixed.sidebar-expand-button.hidden-lg.hidden-md %i.icon-list.icon-2x - .col-md-3.responsive-side-left + .col-md-3.responsive-side = render 'shared/filter', entity: 'merge_request' .col-md-9 = render 'shared/merge_requests' diff --git a/app/views/projects/issues/_head.html.haml b/app/views/projects/issues/_head.html.haml index f1e866c8e9..716ea7cefe 100644 --- a/app/views/projects/issues/_head.html.haml +++ b/app/views/projects/issues/_head.html.haml @@ -9,6 +9,11 @@ = nav_link(controller: :labels) do = link_to 'Labels', project_labels_path(@project), class: "tab" + - if current_controller?(:milestones) + %li.pull-right + %button.btn.btn-default.sidebar-expand-button + %i.icon.icon-list + - if current_controller?(:issues) - if current_user %li @@ -17,6 +22,8 @@ %li.pull-right .pull-right + %button.btn.btn-default.sidebar-expand-button + %i.icon.icon-list = form_tag project_issues_path(@project), 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, nil, { placeholder: 'Filter by title or description', class: 'form-control issue_search search-text-input input-mn-300' } diff --git a/app/views/projects/issues/index.html.haml b/app/views/projects/issues/index.html.haml index e527b7bc2c..2e66d05956 100644 --- a/app/views/projects/issues/index.html.haml +++ b/app/views/projects/issues/index.html.haml @@ -1,8 +1,8 @@ = render "head" .row - .left.sidebar-expand-button.hidden-lg.hidden-md + .fixed.fixed.sidebar-expand-button.hidden-lg.hidden-md.hidden-xs %i.icon-list.icon-2x - .col-md-3.responsive-side-left + .col-md-3.responsive-side = render 'shared/project_filter', project_entities_path: project_issues_path(@project), labels: true, redirect: 'issues' .col-md-9.issues-holder diff --git a/app/views/projects/merge_requests/index.html.haml b/app/views/projects/merge_requests/index.html.haml index 919efc5fa1..4bb803eb6d 100644 --- a/app/views/projects/merge_requests/index.html.haml +++ b/app/views/projects/merge_requests/index.html.haml @@ -7,9 +7,9 @@ %span (#{@merge_requests.total_count}) %hr .row - .left.sidebar-expand-button.hidden-lg.hidden-md + .fixed.sidebar-expand-button.hidden-lg.hidden-md %i.icon-list.icon-2x - .col-md-3.responsive-side-left + .col-md-3.responsive-side = render 'shared/project_filter', project_entities_path: project_merge_requests_path(@project), labels: true, redirect: 'merge_requests' .col-md-9 diff --git a/app/views/projects/milestones/index.html.haml b/app/views/projects/milestones/index.html.haml index 4b44d68a91..f0e48a5177 100644 --- a/app/views/projects/milestones/index.html.haml +++ b/app/views/projects/milestones/index.html.haml @@ -8,9 +8,9 @@ New Milestone .row - .left.sidebar-expand-button.hidden-lg.hidden-md + .fixed.sidebar-expand-button.hidden-lg.hidden-md.hidden-xs %i.icon-list.icon-2x - .col-md-3.responsive-side-left + .col-md-3.responsive-side %ul.nav.nav-pills.nav-stacked %li{class: ("active" if (params[:f] == "active" || !params[:f]))} = link_to project_milestones_path(@project, f: "active") do From d74bf464d38da126bbc44ab39bac4b9e2adb12b4 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sun, 15 Jun 2014 09:40:24 +0300 Subject: [PATCH 348/360] Postgres requires not-null value for boolean field Signed-off-by: Dmitriy Zaporozhets --- app/models/project.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/models/project.rb b/app/models/project.rb index e251c777d8..762b540b7a 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -33,6 +33,7 @@ class Project < ActiveRecord::Base default_value_for :issues_enabled, true default_value_for :merge_requests_enabled, true default_value_for :wiki_enabled, true + default_value_for :wall_enabled, false default_value_for :snippets_enabled, true ActsAsTaggableOn.strict_case_match = true From e6722cb1786f7765228c2ac81f337ec5d09f9d19 Mon Sep 17 00:00:00 2001 From: Alex Elman Date: Wed, 11 Jun 2014 11:37:29 -0500 Subject: [PATCH 349/360] Provide better email subject lines from email on push service If one commit is pushed, display the commit message in the subject line. Otherwise display the number of commits pushed to the repository. --- CHANGELOG | 1 + app/mailers/emails/projects.rb | 4 +++- spec/mailers/notify_spec.rb | 4 ++-- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 8fa1fb000a..1b17bcac32 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -37,6 +37,7 @@ v 7.0.0 - Remove wall feature (no data loss - you can take it from database) - Dont expose user emails via API unless you are admin - Detect issues closed by Merge Request description + - Better email subject lines from email on push service (Alex Elman) v 6.9.2 - Revert the commit that broke the LDAP user filter diff --git a/app/mailers/emails/projects.rb b/app/mailers/emails/projects.rb index 6017d9192e..64878568ef 100644 --- a/app/mailers/emails/projects.rb +++ b/app/mailers/emails/projects.rb @@ -25,13 +25,15 @@ module Emails @branch = branch if @commits.length > 1 @target_url = project_compare_url(@project, from: @commits.first, to: @commits.last) + @subject = "#{@commits.length} new commits pushed to repository" else @target_url = project_commit_url(@project, @commits.first) + @subject = @commits.first.title end mail(from: sender(author_id), cc: recipient, - subject: subject("New push to repository")) + subject: subject(@subject)) end end end diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb index 453bf2b3e9..ab26b290d7 100644 --- a/spec/mailers/notify_spec.rb +++ b/spec/mailers/notify_spec.rb @@ -537,7 +537,7 @@ describe Notify do end it 'has the correct subject' do - should have_subject /New push to repository/ + should have_subject /#{commits.length} new commits pushed to repository/ end it 'includes commits list' do @@ -573,7 +573,7 @@ describe Notify do end it 'has the correct subject' do - should have_subject /New push to repository/ + should have_subject /#{commits.first.title}/ end it 'includes commits list' do From 89ed1e09bba6c0fe5d259510f2b91de730c9675d Mon Sep 17 00:00:00 2001 From: Sytse Sijbrandij Date: Mon, 16 Jun 2014 10:52:21 +0200 Subject: [PATCH 350/360] Clean up the readme. --- README.md | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 166e1187bf..152c3c0e2b 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,11 @@ # GitLab -## Self hosted Git management software +## Open source software to collaborate on code ![logo](https://gitlab.com/gitlab-org/gitlab-ce/raw/master/public/gitlab_logo.png) ![animated-screenshots](https://gist.github.com/fnkr/2f9badd56bfe0ed04ee7/raw/4f48806fbae97f556c2f78d8c2d299c04500cb0d/compiled.gif) -## Open source software to collaborate on code - - Manage Git repositories with fine grained access controls that keep your code secure - Perform code reviews and enhance collaboration with merge requests - Each project can also have an issue tracker and a wiki @@ -29,15 +27,27 @@ - [![PullReview stats](https://www.pullreview.com/gitlab/gitlab-org/gitlab-ce/badges/master.svg?)](https://www.pullreview.com/gitlab.gitlab.com/gitlab-org/gitlab-ce/reviews/master) -### Resources +## Website -- [www.gitlab.com](https://www.gitlab.com/) includes information about [subscriptions](https://www.gitlab.com/subscription/), [consultancy](https://www.gitlab.com/consultancy/), the [community](https://www.gitlab.com/community/) and the [hosted GitLab.com](https://www.gitlab.com/gitlab-com/). +On [www.gitlab.com](https://www.gitlab.com/) you can find more information about: -- [GitLab Enterprise Edition](https://www.gitlab.com/gitlab-ee/) offers additional features aimed at larger organizations. +- [Subscriptions](https://www.gitlab.com/subscription/) +- [Consultancy](https://www.gitlab.com/consultancy/) +- [Community](https://www.gitlab.com/community/) +- [Hosted GitLab.com](https://www.gitlab.com/gitlab-com/) use GitLab as a free service +- [GitLab Enterprise Edition](https://www.gitlab.com/gitlab-ee/) with additional features aimed at larger organizations. +- [GitLab CI](https://www.gitlab.com/gitlab-ci/) a continuous integration (CI) server that is easy to integrate with GitLab. -- [GitLab CI](https://www.gitlab.com/gitlab-ci/) is a continuous integration (CI) server that is easy to integrate with GitLab. +## Third-party applications -- Unofficial third-party [iPhone app](http://gitlabcontrol.com/), [Android app](https://play.google.com/store/apps/details?id=com.bd.gitlab&hl=en), [command line client](https://github.com/drewblessing/gitlab-cli), [Ruby API wrapper](https://github.com/NARKOZ/gitlab) and [Chrome app](https://chrome.google.com/webstore/detail/chrome-gitlab-notifier/eageapgbnjicdjjihgclpclilenjbobi) for GitLab. +Access GitLab from multiple platforms with applications below. +These applications are maintained by contributors, GitLab B.V. does not offer support for them. + +- [iPhone app](http://gitlabcontrol.com/) +- [Android app](https://play.google.com/store/apps/details?id=com.bd.gitlab&hl=en) +- [Chrome app](https://chrome.google.com/webstore/detail/chrome-gitlab-notifier/eageapgbnjicdjjihgclpclilenjbobi) +- [Command line client](https://github.com/drewblessing/gitlab-cli) +- [Ruby API wrapper](https://github.com/NARKOZ/gitlab) ## Requirements From 8d240fb0e76f6333a51b1e9eaffb9196d2e4557a Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 16 Jun 2014 12:17:34 +0300 Subject: [PATCH 351/360] Show/hide issue assignee avatar depends on drag-n-drop column in milestone view Signed-off-by: Dmitriy Zaporozhets --- app/assets/javascripts/milestone.js.coffee | 7 +++++++ app/controllers/projects/issues_controller.rb | 1 + app/views/projects/milestones/_issue.html.haml | 4 ++-- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/milestone.js.coffee b/app/assets/javascripts/milestone.js.coffee index 5cbddd3a20..ea01c318d4 100644 --- a/app/assets/javascripts/milestone.js.coffee +++ b/app/assets/javascripts/milestone.js.coffee @@ -6,6 +6,13 @@ class Milestone data: data success: (data) -> if data.saved == true + if data.assignee_avatar_url + img_tag = $('') + img_tag.attr('src', data.assignee_avatar_url) + img_tag.addClass('avatar s16') + $(li).find('.assignee-icon').html(img_tag) + else + $(li).find('.assignee-icon').html('') $(li).effect 'highlight' else new Flash("Issue update failed", 'alert') diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb index 6c6fc7e077..ddea8901f9 100644 --- a/app/controllers/projects/issues_controller.rb +++ b/app/controllers/projects/issues_controller.rb @@ -90,6 +90,7 @@ class Projects::IssuesController < Projects::ApplicationController format.json do render json: { saved: @issue.valid?, + assignee_avatar_url: @issue.assignee.try(:avatar_url) } end end diff --git a/app/views/projects/milestones/_issue.html.haml b/app/views/projects/milestones/_issue.html.haml index 7c993e01c2..08ccd0cdc8 100644 --- a/app/views/projects/milestones/_issue.html.haml +++ b/app/views/projects/milestones/_issue.html.haml @@ -3,7 +3,7 @@ = link_to [@project, issue] do %span.cgray ##{issue.iid} = link_to_gfm issue.title, [@project, issue] - - if issue.assignee - .pull-right + .pull-right.assignee-icon + - if issue.assignee = image_tag avatar_icon(issue.assignee.email, 16), class: "avatar s16" From 4ea7b192d4de3b670829b817914f26c943cc286c Mon Sep 17 00:00:00 2001 From: Sytse Sijbrandij Date: Mon, 16 Jun 2014 12:08:23 +0200 Subject: [PATCH 352/360] Use same size headers. Add PullReview. Mention shell guide as created by us. --- CONTRIBUTING.md | 5 ++--- README.md | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ee17f1d6cc..3b6212c960 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -110,8 +110,7 @@ For examples of feedback on merge requests please look at already [closed merge 1. [Rails](https://github.com/bbatsov/rails-style-guide) 1. [Testing](https://github.com/thoughtbot/guides/tree/master/style#testing) 1. [CoffeeScript](https://github.com/thoughtbot/guides/tree/master/style#coffeescript) -1. [Shell commands](doc/development/shell_commands.md) +1. [Shell commands](doc/development/shell_commands.md) created by GitLab contributors to enhance security 1. [Markdown](http://www.cirosantilli.com/markdown-styleguide) -This is also the style used by linting tools such as [Rubocop](https://github.com/bbatsov/rubocop) -and [Hound CI](https://houndci.com). +This is also the style used by linting tools such as [Rubocop](https://github.com/bbatsov/rubocop), PullReview[https://www.pullreview.com/] and [Hound CI](https://houndci.com). diff --git a/README.md b/README.md index 152c3c0e2b..07c5c61e93 100644 --- a/README.md +++ b/README.md @@ -83,13 +83,13 @@ or by directly calling the script: Please login with `root` / `5iveL!fe`. -### Install a development environment +## Install a development environment We recommend setting up your development environment with [the cookbook](https://gitlab.com/gitlab-org/cookbook-gitlab/blob/master/README.md#installation). If you do not use the cookbook you might need to copy the example development unicorn configuration file cp config/unicorn.rb.example.development config/unicorn.rb -### Run in development mode +## Run in development mode Start it with [Foreman](https://github.com/ddollar/foreman) From 0014326ded8164bbbd12f8411c622d4ee9a1952f Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 16 Jun 2014 14:26:38 +0300 Subject: [PATCH 353/360] Small UI fix Signed-off-by: Dmitriy Zaporozhets --- app/views/projects/_home_panel.html.haml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/projects/_home_panel.html.haml b/app/views/projects/_home_panel.html.haml index 3851fd6c15..81bb0e20a3 100644 --- a/app/views/projects/_home_panel.html.haml +++ b/app/views/projects/_home_panel.html.haml @@ -14,7 +14,7 @@ = render "shared/clone_panel" .project-home-extra.row - .col-md-8 + .col-md-7 .project-home-desc - if @project.description.present? = auto_link @project.description, link: :urls @@ -23,7 +23,7 @@ %strong= link_to 'Edit', edit_project_path - unless empty_repo - .col-md-4 + .col-md-5 .project-home-links = link_to pluralize(number_with_delimiter(@repository.commit_count), 'commit'), project_commits_path(@project, @ref || @repository.root_ref) = link_to pluralize(number_with_delimiter(@repository.branch_names.count), 'branch'), project_branches_path(@project) From a6549118b51b95e16cf8342cc35b5126dfba1c88 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 16 Jun 2014 17:23:38 +0300 Subject: [PATCH 354/360] Dont install production gems for travis Signed-off-by: Dmitriy Zaporozhets --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index c90bba8dee..8bb2da5e51 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,6 +17,8 @@ env: - TASK=jasmine:ci DB=postgresql before_install: - sudo apt-get install libicu-dev -y +install: + - "bundle install --deployment --without production" branches: only: - 'master' From 3e3396365d6b477a06584b7149f1b816996ac4b1 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 16 Jun 2014 17:25:45 +0300 Subject: [PATCH 355/360] Update gitlab_meta gem Signed-off-by: Dmitriy Zaporozhets --- Gemfile | 2 +- Gemfile.lock | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index 928b766f16..c64213479f 100644 --- a/Gemfile +++ b/Gemfile @@ -243,5 +243,5 @@ group :test do end group :production do - gem "gitlab_meta", '6.0' + gem "gitlab_meta", '7.0' end diff --git a/Gemfile.lock b/Gemfile.lock index a9a23f7439..6c27b6e373 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -181,7 +181,7 @@ GEM gitlab-grit (~> 2.6) gitlab-linguist (~> 3.0) rugged (~> 0.19.0) - gitlab_meta (6.0) + gitlab_meta (7.0) gitlab_omniauth-ldap (1.0.4) net-ldap (~> 0.3.1) omniauth (~> 1.0) @@ -606,7 +606,7 @@ DEPENDENCIES gitlab-linguist (~> 3.0.0) gitlab_emoji (~> 0.0.1.1) gitlab_git (~> 6.0) - gitlab_meta (= 6.0) + gitlab_meta (= 7.0) gitlab_omniauth-ldap (= 1.0.4) gollum-lib (~> 3.0.0) gon (~> 5.0.0) From 085a93d4a513dd661d57f2a9a5141e2c6b5680a2 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 16 Jun 2014 22:31:15 +0300 Subject: [PATCH 356/360] Replace ok with circle for boolean icon Signed-off-by: Dmitriy Zaporozhets --- app/helpers/icons_helper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/helpers/icons_helper.rb b/app/helpers/icons_helper.rb index 53d4a8f2e6..f0f771b4ba 100644 --- a/app/helpers/icons_helper.rb +++ b/app/helpers/icons_helper.rb @@ -1,7 +1,7 @@ module IconsHelper def boolean_to_icon(value) if value.to_s == "true" - content_tag :i, nil, class: 'icon-ok cgreen' + content_tag :i, nil, class: 'icon-circle cgreen' else content_tag :i, nil, class: 'icon-off clgray' end From 7be80fd89954a248527ca9be4bb9d9c320390811 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 17 Jun 2014 09:27:50 +0300 Subject: [PATCH 357/360] Enable identicon for gravatar by default Signed-off-by: Dmitriy Zaporozhets --- CHANGELOG | 1 + config/gitlab.yml.example | 4 ++-- config/initializers/1_settings.rb | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 1b17bcac32..495d20e8b0 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -38,6 +38,7 @@ v 7.0.0 - Dont expose user emails via API unless you are admin - Detect issues closed by Merge Request description - Better email subject lines from email on push service (Alex Elman) + - Enable identicon for gravatar be default v 6.9.2 - Revert the commit that broke the LDAP user filter diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example index 50a1a78b50..806984e8d4 100644 --- a/config/gitlab.yml.example +++ b/config/gitlab.yml.example @@ -114,8 +114,8 @@ production: &base gravatar: enabled: true # Use user avatar image from Gravatar.com (default: true) # gravatar urls: possible placeholders: %{hash} %{size} %{email} - # plain_url: "http://..." # default: http://www.gravatar.com/avatar/%{hash}?s=%{size}&d=mm - # ssl_url: "https://..." # default: https://secure.gravatar.com/avatar/%{hash}?s=%{size}&d=mm + # plain_url: "http://..." # default: http://www.gravatar.com/avatar/%{hash}?s=%{size}&d=identicon + # ssl_url: "https://..." # default: https://secure.gravatar.com/avatar/%{hash}?s=%{size}&d=identicon # # 2. Auth settings diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb index de7c0990c0..f55e69c08f 100644 --- a/config/initializers/1_settings.rb +++ b/config/initializers/1_settings.rb @@ -104,8 +104,8 @@ Settings.gitlab['repository_downloads_path'] = File.absolute_path(Settings.gitla # Settings['gravatar'] ||= Settingslogic.new({}) Settings.gravatar['enabled'] = true if Settings.gravatar['enabled'].nil? -Settings.gravatar['plain_url'] ||= 'http://www.gravatar.com/avatar/%{hash}?s=%{size}&d=mm' -Settings.gravatar['ssl_url'] ||= 'https://secure.gravatar.com/avatar/%{hash}?s=%{size}&d=mm' +Settings.gravatar['plain_url'] ||= 'http://www.gravatar.com/avatar/%{hash}?s=%{size}&d=identicon' +Settings.gravatar['ssl_url'] ||= 'https://secure.gravatar.com/avatar/%{hash}?s=%{size}&d=identicon' # # GitLab Shell From e44e2316c3e223955847859492f6f9bd7974e50e Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 17 Jun 2014 09:40:48 +0300 Subject: [PATCH 358/360] Change gravatar tests to identicon Signed-off-by: Dmitriy Zaporozhets --- spec/helpers/application_helper_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb index 6a11414a02..053a1fe22f 100644 --- a/spec/helpers/application_helper_spec.rb +++ b/spec/helpers/application_helper_spec.rb @@ -69,7 +69,7 @@ describe ApplicationHelper do it "should call gravatar_icon when no avatar is present" do user = create(:user, email: 'test@example.com') user.save! - avatar_icon(user.email).to_s.should == "http://www.gravatar.com/avatar/55502f40dc8b7c769880b10874abc9d0?s=40&d=mm" + avatar_icon(user.email).to_s.should == "http://www.gravatar.com/avatar/55502f40dc8b7c769880b10874abc9d0?s=40&d=identicon" end end From 216e5fca0c83a3c52dbd03d8a6f091e93f0e16c9 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 17 Jun 2014 11:30:51 +0300 Subject: [PATCH 359/360] Fix 500 on appearance page Signed-off-by: Dmitriy Zaporozhets --- app/views/admin/appearances/_form.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/admin/appearances/_form.html.haml b/app/views/admin/appearances/_form.html.haml index 0313ffd559..e54dc3c675 100644 --- a/app/views/admin/appearances/_form.html.haml +++ b/app/views/admin/appearances/_form.html.haml @@ -13,7 +13,7 @@ .col-sm-10 = f.text_area :description, class: "form-control", rows: 10 .hint - Description parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}. + Description parsed with #{link_to "GitLab Flavored Markdown", help_page_path('markdown', 'markdown'), target: '_blank'}. .form-group = f.label :logo, class: 'control-label' .col-sm-10 From 30654f8d83933cfff242814e06399e6be779d9cf Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 17 Jun 2014 12:14:17 +0300 Subject: [PATCH 360/360] remove duplicate steps Signed-off-by: Dmitriy Zaporozhets --- .../steps/project/project_browse_branches.rb | 51 ------------------- 1 file changed, 51 deletions(-) delete mode 100644 features/steps/project/project_browse_branches.rb diff --git a/features/steps/project/project_browse_branches.rb b/features/steps/project/project_browse_branches.rb deleted file mode 100644 index 30c8cef80c..0000000000 --- a/features/steps/project/project_browse_branches.rb +++ /dev/null @@ -1,51 +0,0 @@ -class ProjectBrowseBranches < Spinach::FeatureSteps - include SharedAuthentication - include SharedProject - include SharedPaths - - step 'I should see "Shop" recent branches list' do - page.should have_content "Branches" - page.should have_content "master" - end - - step 'I click link "All"' do - click_link "All" - end - - step 'I should see "Shop" all branches list' do - page.should have_content "Branches" - page.should have_content "master" - end - - step 'I click link "Protected"' do - click_link "Protected" - end - - step 'I should see "Shop" protected branches list' do - within ".protected-branches-list" do - page.should have_content "stable" - page.should_not have_content "master" - end - end - - step 'project "Shop" has protected branches' do - project = Project.find_by(name: "Shop") - project.protected_branches.create(name: "stable") - end - - step 'I click new branch link' do - click_link "New branch" - end - - step 'I submit new branch form' do - fill_in 'branch_name', with: 'deploy_keys' - fill_in 'ref', with: 'master' - click_button 'Create branch' - end - - step 'I should see new branch created' do - within '.all-branches' do - page.should have_content 'deploy_keys' - end - end -end