diff options
183 files changed, 1844 insertions, 1564 deletions
diff --git a/CHANGELOG b/CHANGELOG index 8b14594c5f2..25868e0a4bf 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,11 @@ v 7.2.0 - Explore page - Add project stars (Ciro Santilli) + - Log Sidekiq arguments + - Fix cpu usage issue in Firefox + - Better labels: colors, ability to rename and remove + - Improve the way merge request collects diffs + - Improve compare page for large diffs v 7.1.0 - Remove observers @@ -79,16 +79,20 @@ gem "six" gem "seed-fu" # Markdown to HTML -gem "redcarpet", "~> 2.2.2" gem "github-markup" -gem "org-ruby" # For rendering .org files + +# Required markup gems by github-markdown +gem 'redcarpet', '~> 2.2.2' +gem 'RedCloth' +gem 'rdoc', '~>3.6' +gem 'org-ruby', '= 0.9.1' +gem 'creole', '~>0.3.6' +gem 'wikicloth', '=0.8.1' +gem 'asciidoctor', '= 0.1.4' # Diffs gem 'diffy', '~> 3.0.3' -# Asciidoc to HTML -gem "asciidoctor" - # Application server group :unicorn do gem "unicorn", '~> 4.6.3' diff --git a/Gemfile.lock b/Gemfile.lock index fe85e9ec9ea..c77d20debd9 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,6 +1,7 @@ GEM remote: https://rubygems.org/ specs: + RedCloth (4.2.9) ace-rails-ap (2.0.1) actionmailer (4.1.1) actionpack (= 4.1.1) @@ -86,6 +87,7 @@ GEM thor crack (0.4.1) safe_yaml (~> 0.9.0) + creole (0.3.8) d3_rails (3.1.10) railties (>= 3.1.0) daemons (1.1.9) @@ -121,6 +123,7 @@ GEM eventmachine (1.0.3) excon (0.32.1) execjs (2.0.2) + expression_parser (0.9.0) factory_girl (4.3.0) activesupport (>= 3.0.0) factory_girl_rails (4.3.0) @@ -176,7 +179,7 @@ GEM mime-types (~> 1.19) gitlab_emoji (0.0.1.1) emoji (~> 1.0.1) - gitlab_git (6.0.1) + gitlab_git (6.1.0) activesupport (~> 4.0) charlock_holmes (~> 0.6) gitlab-grit (~> 2.6) @@ -241,7 +244,7 @@ GEM json (~> 1.8) multi_xml (>= 0.5.2) httpauth (0.2.0) - i18n (0.6.9) + i18n (0.6.11) ice_nine (0.10.0) jasmine (2.0.2) jasmine-core (~> 2.0.0) @@ -320,7 +323,7 @@ GEM omniauth-twitter (1.0.1) multi_json (~> 1.3) omniauth-oauth (~> 1.0) - org-ruby (0.9.6) + org-ruby (0.9.1) rubypants (>= 0.2.0) orm_adapter (0.5.0) pg (0.15.1) @@ -413,6 +416,7 @@ GEM require_all (1.3.2) rest-client (1.6.7) mime-types (>= 1.16) + rinku (1.7.3) rouge (1.3.3) rspec (2.14.1) rspec-core (~> 2.14.0) @@ -563,6 +567,10 @@ GEM addressable (>= 2.2.7) crack (>= 0.3.2) websocket-driver (0.3.3) + wikicloth (0.8.1) + builder + expression_parser + rinku xpath (2.0.0) nokogiri (~> 1.3) @@ -570,10 +578,11 @@ PLATFORMS ruby DEPENDENCIES + RedCloth ace-rails-ap acts-as-taggable-on annotate (~> 2.6.0.beta2) - asciidoctor + asciidoctor (= 0.1.4) awesome_print better_errors binding_of_caller @@ -583,6 +592,7 @@ DEPENDENCIES coffee-rails colored coveralls + creole (~> 0.3.6) d3_rails (~> 3.1.4) database_cleaner default_value_for (~> 3.0.0) @@ -632,7 +642,7 @@ DEPENDENCIES omniauth-github omniauth-google-oauth2 omniauth-twitter - org-ruby + org-ruby (= 0.9.1) pg poltergeist (~> 1.5.1) pry @@ -646,6 +656,7 @@ DEPENDENCIES raphael-rails (~> 2.1.2) rb-fsevent rb-inotify + rdoc (~> 3.6) redcarpet (~> 2.2.2) redis-rails request_store @@ -682,3 +693,4 @@ DEPENDENCIES unicorn-worker-killer version_sorter webmock + wikicloth (= 0.8.1) diff --git a/README.md b/README.md index bcee4e064fa..f5f7a8aad49 100644 --- a/README.md +++ b/README.md @@ -81,7 +81,7 @@ 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 @@ -1 +1 @@ -7.1.0 +7.2.0.pre diff --git a/app/assets/javascripts/markdown_area.js.coffee b/app/assets/javascripts/markdown_area.js.coffee index 1449735fae9..bee2785562d 100644 --- a/app/assets/javascripts/markdown_area.js.coffee +++ b/app/assets/javascripts/markdown_area.js.coffee @@ -20,6 +20,9 @@ $(document).ready -> $(".div-dropzone-hover").append iconPicture $(".div-dropzone").append divSpinner $(".div-dropzone-spinner").append iconSpinner + $(".div-dropzone-spinner").css + "opacity": 0 + "display": "none" dropzone = $(".div-dropzone").dropzone( url: project_image_path_upload @@ -66,13 +69,17 @@ $(document).ready -> return sending: -> - $(".div-dropzone-spinner").css "opacity", 0.7 + $(".div-dropzone-spinner").css + "opacity": 0.7 + "display": "inherit" return complete: -> $(".dz-preview").remove() $(".markdown-area").trigger "input" - $(".div-dropzone-spinner").css "opacity", 0 + $(".div-dropzone-spinner").css + "opacity": 0 + "display": "none" return ) @@ -163,10 +170,14 @@ $(document).ready -> val + url + "\n" showSpinner = (e) -> - $(".div-dropzone-spinner").css "opacity", 0.7 + $(".div-dropzone-spinner").css + "opacity": 0.7 + "display": "inherit" closeSpinner = -> - $(".div-dropzone-spinner").css "opacity", 0 + $(".div-dropzone-spinner").css + "opacity": 0 + "display": "none" showError = (message) -> checkIfMsgExists = $(".error-alert").children().length diff --git a/app/assets/stylesheets/sections/issues.scss b/app/assets/stylesheets/sections/issues.scss index 495a7cb3113..a7fa715d2e0 100644 --- a/app/assets/stylesheets/sections/issues.scss +++ b/app/assets/stylesheets/sections/issues.scss @@ -63,26 +63,10 @@ @media (min-width: 800px) { .issues_bulk_update .select2-container { min-width: 120px; } } @media (min-width: 1200px) { .issues_bulk_update .select2-container { min-width: 160px; } } -.issues-holder { - .issues_filters { - } - - .issues_bulk_update { - margin: 0; - form { - float:left; - } - - .update_selected_issues { - margin-left: 4px; - } - - .select2-container .select2-choice { - height: 32px; - line-height: 28px; - color: #444 !important; - font-weight: 500; - } +.issues_bulk_update { + .select2-container .select2-choice { + color: #444 !important; + font-weight: 500; } } @@ -110,7 +94,7 @@ } } -.issue-show-labels .label { +.issue-show-labels .color-label { padding: 6px 10px; } diff --git a/app/assets/stylesheets/sections/labels.scss b/app/assets/stylesheets/sections/labels.scss new file mode 100644 index 00000000000..d1590e42fcb --- /dev/null +++ b/app/assets/stylesheets/sections/labels.scss @@ -0,0 +1,21 @@ +.suggest-colors { + margin-top: 5px; + a { + @include border-radius(4px); + width: 30px; + height: 30px; + display: inline-block; + margin-right: 10px; + } +} + +.manage-labels-list { + .label { + padding: 9px; + font-size: 14px; + } +} + +.color-label { + padding: 3px 4px; +} diff --git a/app/assets/stylesheets/sections/merge_requests.scss b/app/assets/stylesheets/sections/merge_requests.scss index 12044db6702..3db6da2a9f9 100644 --- a/app/assets/stylesheets/sections/merge_requests.scss +++ b/app/assets/stylesheets/sections/merge_requests.scss @@ -1,6 +1,6 @@ -/** - * MR -> show: Automerge widget + /** + * MR -> show: Automerge widget * */ .automerge_widget { @@ -48,10 +48,10 @@ .label-branch { @include border-radius(4px); - padding: 2px 4px; + padding: 3px 4px; border: none; - background: #555; - color: #fff; + background: $hover; + color: #333; font-family: $monospace_font; font-weight: normal; overflow: hidden; diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb index 233b91680f6..5aff526d1b5 100644 --- a/app/controllers/dashboard_controller.rb +++ b/app/controllers/dashboard_controller.rb @@ -46,11 +46,11 @@ class DashboardController < ApplicationController @projects = @projects.where(namespace_id: Group.find_by(name: params[:group])) if params[:group].present? @projects = @projects.where(visibility_level: params[:visibility_level]) if params[:visibility_level].present? @projects = @projects.includes(:namespace) - @projects = @projects.tagged_with(params[:label]) if params[:label].present? + @projects = @projects.tagged_with(params[:tag]) if params[:tag].present? @projects = @projects.sort(@sort = params[:sort]) @projects = @projects.page(params[:page]).per(30) - @labels = current_user.authorized_projects.tags_on(:labels) + @tags = current_user.authorized_projects.tags_on(:tags) @groups = current_user.authorized_groups end diff --git a/app/controllers/profiles/passwords_controller.rb b/app/controllers/profiles/passwords_controller.rb index 0d93f5cbfdf..1191ce47eba 100644 --- a/app/controllers/profiles/passwords_controller.rb +++ b/app/controllers/profiles/passwords_controller.rb @@ -11,6 +11,11 @@ class Profiles::PasswordsController < ApplicationController end def create + unless @user.valid_password?(user_params[:current_password]) + redirect_to new_profile_password_path, alert: 'You must provide a valid current password' + return + end + new_password = user_params[:password] new_password_confirmation = user_params[:password_confirmation] diff --git a/app/controllers/projects/compare_controller.rb b/app/controllers/projects/compare_controller.rb index eae96396574..7a671e8455d 100644 --- a/app/controllers/projects/compare_controller.rb +++ b/app/controllers/projects/compare_controller.rb @@ -8,14 +8,21 @@ class Projects::CompareController < Projects::ApplicationController end def show - compare = Gitlab::Git::Compare.new(@repository.raw_repository, params[:from], params[:to], MergeRequestDiff::COMMITS_SAFE_SIZE) + base_ref = params[:from] + head_ref = params[:to] - @commits = compare.commits - @commit = compare.commit - @diffs = compare.diffs - @refs_are_same = compare.same - @line_notes = [] - @diff_timeout = compare.timeout + compare_result = CompareService.new.execute( + current_user, + @project, + head_ref, + @project, + base_ref + ) + + @commits = compare_result.commits + @diffs = compare_result.diffs + @commit = @commits.last + @line_notes = [] end def create diff --git a/app/controllers/projects/hooks_controller.rb b/app/controllers/projects/hooks_controller.rb index 268e19f26ee..c8269ed99ce 100644 --- a/app/controllers/projects/hooks_controller.rb +++ b/app/controllers/projects/hooks_controller.rb @@ -24,7 +24,12 @@ class Projects::HooksController < Projects::ApplicationController end def test - TestHookService.new.execute(hook, current_user) + if !@project.empty_repo? + TestHookService.new.execute(hook, current_user) + flash[:notice] = 'Hook successfully executed.' + else + flash[:alert] = 'Hook execution failed. Ensure the project has commits.' + end redirect_to :back end diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb index 4dc9384c996..bde90466ea1 100644 --- a/app/controllers/projects/issues_controller.rb +++ b/app/controllers/projects/issues_controller.rb @@ -152,7 +152,7 @@ class Projects::IssuesController < Projects::ApplicationController def issue_params params.require(:issue).permit( :title, :assignee_id, :position, :description, - :milestone_id, :label_list, :state_event + :milestone_id, :state_event, label_ids: [] ) end end diff --git a/app/controllers/projects/labels_controller.rb b/app/controllers/projects/labels_controller.rb index 30fcb64cbb2..d049012f6d8 100644 --- a/app/controllers/projects/labels_controller.rb +++ b/app/controllers/projects/labels_controller.rb @@ -1,12 +1,38 @@ class Projects::LabelsController < Projects::ApplicationController before_filter :module_enabled - + before_filter :label, only: [:edit, :update, :destroy] before_filter :authorize_labels! + before_filter :authorize_admin_labels!, except: [:index] respond_to :js, :html def index - @labels = @project.issues_labels + @labels = @project.labels.order_by_name.page(params[:page]).per(20) + end + + def new + @label = @project.labels.new + end + + def create + @label = @project.labels.create(label_params) + + if @label.valid? + redirect_to project_labels_path(@project) + else + render 'new' + end + end + + def edit + end + + def update + if @label.update_attributes(label_params) + redirect_to project_labels_path(@project) + else + render 'edit' + end end def generate @@ -21,6 +47,12 @@ class Projects::LabelsController < Projects::ApplicationController end end + def destroy + @label.destroy + + redirect_to project_labels_path(@project), notice: 'Label was removed' + end + protected def module_enabled @@ -28,4 +60,16 @@ class Projects::LabelsController < Projects::ApplicationController return render_404 end end + + def label_params + params.require(:label).permit(:title, :color) + end + + def label + @label = @project.labels.find(params[:id]) + end + + def authorize_admin_labels! + return render_404 unless can?(current_user, :admin_label, @project) + end end diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index fcc6384e27c..8dca0400693 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -70,7 +70,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController @target_project = merge_request.target_project @source_project = merge_request.source_project @commits = @merge_request.compare_commits - @commit = @merge_request.compare_base_commit + @commit = @merge_request.compare_commits.last @diffs = @merge_request.compare_diffs @note_counts = Note.where(commit_id: @commits.map(&:id)). group(:commit_id).count @@ -242,7 +242,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController params.require(:merge_request).permit( :title, :assignee_id, :source_project_id, :source_branch, :target_project_id, :target_branch, :milestone_id, - :state_event, :description, :label_list + :state_event, :description, label_ids: [] ) end end diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 1b1b0eb7ad1..f23afaf28fa 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -196,7 +196,7 @@ class ProjectsController < ApplicationController def project_params params.require(:project).permit( - :name, :path, :description, :issues_tracker, :label_list, + :name, :path, :description, :issues_tracker, :tag_list, :issues_enabled, :merge_requests_enabled, :snippets_enabled, :issues_tracker_id, :default_branch, :wiki_enabled, :visibility_level, :import_url, :last_activity_at, :namespace_id ) diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index f7d5ca08c05..1bdba75c5e7 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -1,7 +1,7 @@ class SessionsController < Devise::SessionsController def new - redirect_url = if request.referer.present? + redirect_path = if request.referer.present? && (params['redirect_to_referer'] == 'yes') referer_uri = URI(request.referer) if referer_uri.host == Gitlab.config.gitlab.host referer_uri.path @@ -12,7 +12,11 @@ class SessionsController < Devise::SessionsController request.fullpath end - store_location_for(:redirect, redirect_url) + # Prevent a 'you are already signed in' message directly after signing: + # we should never redirect to '/users/sign_in' after signing in successfully. + unless redirect_path == '/users/sign_in' + store_location_for(:redirect, redirect_path) + end super end diff --git a/app/finders/base_finder.rb b/app/finders/base_finder.rb index 7150bb2e31b..ec5f5919d7e 100644 --- a/app/finders/base_finder.rb +++ b/app/finders/base_finder.rb @@ -125,7 +125,13 @@ class BaseFinder def by_label(items) if params[:label_name].present? - items = items.tagged_with(params[:label_name]) + label_names = params[:label_name].split(",") + + item_ids = LabelLink.joins(:label). + where('labels.title in (?)', label_names). + where(target_type: klass.name).pluck(:target_id) + + items = items.where(id: item_ids) end items diff --git a/app/helpers/gitlab_markdown_helper.rb b/app/helpers/gitlab_markdown_helper.rb index c112e98508c..e4aa90154fb 100644 --- a/app/helpers/gitlab_markdown_helper.rb +++ b/app/helpers/gitlab_markdown_helper.rb @@ -179,7 +179,11 @@ module GitlabMarkdownHelper if @commit @commit.id elsif @repository && !@repository.empty? - @repository.head_commit.sha + if @ref + @repository.commit(@ref).try(:sha) + else + @repository.head_commit.sha + end end end diff --git a/app/helpers/labels_helper.rb b/app/helpers/labels_helper.rb index 4d20b827a0d..37f3832e54f 100644 --- a/app/helpers/labels_helper.rb +++ b/app/helpers/labels_helper.rb @@ -1,28 +1,37 @@ module LabelsHelper - def issue_label_names - @project.issues_labels.map(&:name) + def project_label_names + @project.labels.pluck(:title) end - def labels_autocomplete_source - labels = @project.issues_labels - labels = labels.map{ |l| { label: l.name, value: l.name } } - labels.to_json + def render_colored_label(label) + label_color = label.color || "#428bca" + text_color = text_color_for_bg(label_color) + + content_tag :span, class: 'label color-label', style: "background:#{label_color};color:#{text_color}" do + label.name + end + end + + def suggested_colors + [ + '#d9534f', + '#f0ad4e', + '#428bca', + '#5cb85c', + '#34495e', + '#7f8c8d', + '#8e44ad', + '#FFECDB' + ] end - def label_css_class(name) - klass = Gitlab::IssuesLabels + def text_color_for_bg(bg_color) + r, g, b = bg_color.slice(1,7).scan(/.{2}/).map(&:hex) - case name.downcase - when *klass.warning_labels - 'label-warning' - when *klass.neutral_labels - 'label-primary' - when *klass.positive_labels - 'label-success' - when *klass.important_labels - 'label-danger' + if (r + g + b) > 500 + "#333" else - 'label-info' + "#FFF" end end end diff --git a/app/helpers/tree_helper.rb b/app/helpers/tree_helper.rb index 2d82b6a0b47..bde2a60faa9 100644 --- a/app/helpers/tree_helper.rb +++ b/app/helpers/tree_helper.rb @@ -44,8 +44,8 @@ module TreeHelper # # Returns boolean def markup?(filename) - filename.downcase.end_with?(*%w(.textile .rdoc .org .creole - .mediawiki .rst .adoc .asciidoc .pod)) + filename.downcase.end_with?(*%w(.textile .rdoc .org .creole .wiki .mediawiki + .rst .adoc .asciidoc .asc)) end def gitlab_markdown?(filename) diff --git a/app/models/ability.rb b/app/models/ability.rb index d33ca41118a..f1d57de63bb 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -142,6 +142,7 @@ class Ability :write_wiki, :modify_issue, :admin_issue, + :admin_label, :push_code ] end diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb index 9a227fcef59..517e4548624 100644 --- a/app/models/concerns/issuable.rb +++ b/app/models/concerns/issuable.rb @@ -13,6 +13,8 @@ module Issuable belongs_to :assignee, class_name: "User" belongs_to :milestone has_many :notes, as: :noteable, dependent: :destroy + has_many :label_links, as: :target, dependent: :destroy + has_many :labels, through: :label_links validates :author, presence: true validates :title, presence: true, length: { within: 0..255 } @@ -131,4 +133,15 @@ module Issuable object_attributes: self.attributes } end + + def label_names + labels.order('title ASC').pluck(:title) + end + + def add_labels_by_names(label_names) + label_names.each do |label_name| + label = project.labels.find_or_create_by(title: label_name.strip) + self.labels << label + end + end end diff --git a/app/models/issue.rb b/app/models/issue.rb index b5a72d535d9..92a8ff9b677 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -32,9 +32,6 @@ class Issue < ActiveRecord::Base scope :of_group, ->(group) { where(project_id: group.project_ids) } scope :of_user_team, ->(team) { where(project_id: team.project_ids, assignee_id: team.member_ids) } - - acts_as_taggable_on :labels - scope :cared, ->(user) { where(assignee_id: user) } scope :open_for, ->(user) { opened.assigned_to(user) } diff --git a/app/models/label.rb b/app/models/label.rb new file mode 100644 index 00000000000..ce982579675 --- /dev/null +++ b/app/models/label.rb @@ -0,0 +1,21 @@ +class Label < ActiveRecord::Base + belongs_to :project + has_many :label_links, dependent: :destroy + has_many :issues, through: :label_links, source: :target, source_type: 'Issue' + + validates :color, format: { with: /\A\#[0-9A-Fa-f]{6}+\Z/ }, allow_blank: true + validates :project, presence: true + + # Dont allow '?', '&', and ',' for label titles + validates :title, presence: true, format: { with: /\A[^&\?,&]*\z/ } + + scope :order_by_name, -> { reorder("labels.title ASC") } + + def name + title + end + + def open_issues_count + issues.opened.count + end +end diff --git a/app/models/label_link.rb b/app/models/label_link.rb new file mode 100644 index 00000000000..47bd6eaf35f --- /dev/null +++ b/app/models/label_link.rb @@ -0,0 +1,7 @@ +class LabelLink < ActiveRecord::Base + belongs_to :target, polymorphic: true + belongs_to :label + + validates :target, presence: true + validates :label, presence: true +end diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 686add63bbf..b5705ef151d 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -44,12 +44,9 @@ class MergeRequest < ActiveRecord::Base # Temporary fields to store compare vars # when creating new merge request - attr_accessor :can_be_created, :compare_failed, :compare_base_commit, + attr_accessor :can_be_created, :compare_failed, :compare_commits, :compare_diffs - ActsAsTaggableOn.strict_case_match = true - acts_as_taggable_on :labels - state_machine :state, initial: :opened do event :close do transition [:reopened, :opened] => :closed diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb index d3c07555b0c..248fa18353e 100644 --- a/app/models/merge_request_diff.rb +++ b/app/models/merge_request_diff.rb @@ -83,11 +83,7 @@ class MergeRequestDiff < ActiveRecord::Base # Collect array of Git::Commit objects # between target and source branches def unmerged_commits - commits = if merge_request.for_fork? - compare_action.commits - else - repository.commits_between(target_branch, source_branch) - end + commits = compare_result.commits if commits.present? commits = Commit.decorate(commits). @@ -147,12 +143,7 @@ class MergeRequestDiff < ActiveRecord::Base # Collect array of Git::Diff objects # between target and source branches def unmerged_diffs - diffs = if merge_request.for_fork? - compare_action.diffs - else - Gitlab::Git::Diff.between(repository, source_branch, target_branch) - end - + diffs = compare_result.diffs diffs ||= [] diffs rescue Gitlab::Git::Diff::TimeoutError => ex @@ -166,13 +157,13 @@ class MergeRequestDiff < ActiveRecord::Base private - def compare_action - Gitlab::Satellite::CompareAction.new( + def compare_result + @compare_result ||= CompareService.new.execute( merge_request.author, + merge_request.source_project, + merge_request.source_branch, merge_request.target_project, merge_request.target_branch, - merge_request.source_project, - merge_request.source_branch ) end end diff --git a/app/models/project.rb b/app/models/project.rb index 73a2b42492e..a24eae7d26b 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -41,8 +41,7 @@ class Project < ActiveRecord::Base default_value_for :snippets_enabled, gitlab_config_features.snippets ActsAsTaggableOn.strict_case_match = true - - acts_as_taggable_on :labels, :issues_default_labels + acts_as_taggable_on :tags attr_accessor :new_default_branch @@ -71,6 +70,7 @@ class Project < ActiveRecord::Base # Merge requests from source project should be kept when source project was removed has_many :fork_merge_requests, foreign_key: "source_project_id", class_name: MergeRequest has_many :issues, -> { order "state DESC, created_at DESC" }, dependent: :destroy + has_many :labels, dependent: :destroy has_many :services, dependent: :destroy has_many :events, dependent: :destroy has_many :milestones, dependent: :destroy @@ -282,13 +282,6 @@ class Project < ActiveRecord::Base self.id end - # Tags are shared by issues and merge requests - def issues_labels - @issues_labels ||= (issues_default_labels + - merge_requests.tags_on(:labels) + - issues.tags_on(:labels)).uniq.sort_by(&:name) - end - def issue_exists?(issue_id) if used_default_issues_tracker? self.issues.where(iid: issue_id).first.present? @@ -501,6 +494,7 @@ class Project < ActiveRecord::Base end def rename_repo + path_was = previous_changes['path'].first old_path_with_namespace = File.join(namespace_dir, path_was) new_path_with_namespace = File.join(namespace_dir, path) diff --git a/app/models/repository.rb b/app/models/repository.rb index 2ff70c248dc..e970c449a73 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -10,8 +10,11 @@ class Repository nil end + # Return absolute path to repository def path_to_repo - @path_to_repo ||= File.join(Gitlab.config.gitlab_shell.repos_path, path_with_namespace + ".git") + @path_to_repo ||= File.expand_path( + File.join(Gitlab.config.gitlab_shell.repos_path, path_with_namespace + ".git") + ) end def exists? @@ -263,4 +266,20 @@ class Repository contributor end end + + def blob_for_diff(commit, diff) + file = blob_at(commit.id, diff.new_path) + + unless file + file = prev_blob_for_diff(commit, diff) + end + + file + end + + def prev_blob_for_diff(commit, diff) + if commit.parent_id + blob_at(commit.parent_id, diff.old_path) + end + end end diff --git a/app/services/compare_service.rb b/app/services/compare_service.rb new file mode 100644 index 00000000000..c5e04702914 --- /dev/null +++ b/app/services/compare_service.rb @@ -0,0 +1,27 @@ +# Compare 2 branches for one repo or between repositories +# and return Gitlab::CompareResult object that responds to commits and diffs +class CompareService + def execute(current_user, source_project, source_branch, target_project, target_branch) + # Try to compare branches to get commits list and diffs + # + # Note: Use satellite only when need to compare between to repos + # because satellites are slower then operations on bare repo + if target_project == source_project + Gitlab::CompareResult.new( + Gitlab::Git::Compare.new( + target_project.repository.raw_repository, + target_branch, + source_branch, + ) + ) + else + Gitlab::Satellite::CompareAction.new( + current_user, + target_project, + target_branch, + source_project, + source_branch + ).result + end + end +end diff --git a/app/services/files/update_service.rb b/app/services/files/update_service.rb index c631f28749c..a0f40154db0 100644 --- a/app/services/files/update_service.rb +++ b/app/services/files/update_service.rb @@ -33,7 +33,7 @@ module Files if created_successfully success else - error("Your changes could not be committed, because the file has been changed") + error("Your changes could not be committed. Maybe the file was changed by another process or there was nothing to commit?") end end end diff --git a/app/services/issues/create_service.rb b/app/services/issues/create_service.rb index 6d05d417f1b..d5c17906a55 100644 --- a/app/services/issues/create_service.rb +++ b/app/services/issues/create_service.rb @@ -1,10 +1,12 @@ module Issues class CreateService < Issues::BaseService def execute - issue = project.issues.new(params) + label_params = params[:label_ids] + issue = project.issues.new(params.except(:label_ids)) issue.author = current_user if issue.save + issue.update_attributes(label_ids: label_params) notification_service.new_issue(issue, current_user) event_service.open_issue(issue, current_user) issue.create_cross_references!(issue.project, current_user) diff --git a/app/services/merge_requests/build_service.rb b/app/services/merge_requests/build_service.rb index 466ed1c1760..1475973e543 100644 --- a/app/services/merge_requests/build_service.rb +++ b/app/services/merge_requests/build_service.rb @@ -19,27 +19,25 @@ module MergeRequests # Generate suggested MR title based on source branch name merge_request.title = merge_request.source_branch.titleize.humanize - # Try to compare branches to get commits list and diffs - compare_action = Gitlab::Satellite::CompareAction.new( + compare_result = CompareService.new.execute( current_user, + merge_request.source_project, + merge_request.source_branch, merge_request.target_project, merge_request.target_branch, - merge_request.source_project, - merge_request.source_branch ) - commits = compare_action.commits + commits = compare_result.commits # At this point we decide if merge request can be created # If we have at least one commit to merge -> creation allowed if commits.present? merge_request.compare_commits = Commit.decorate(commits) - merge_request.compare_base_commit = Commit.new(commits.first) merge_request.can_be_created = true merge_request.compare_failed = false # Try to collect diff for merge request. - diffs = compare_action.diffs + diffs = compare_result.diffs if diffs.present? merge_request.compare_diffs = diffs diff --git a/app/services/merge_requests/create_service.rb b/app/services/merge_requests/create_service.rb index d1bf827f3fc..ca8d80f6c0c 100644 --- a/app/services/merge_requests/create_service.rb +++ b/app/services/merge_requests/create_service.rb @@ -1,12 +1,14 @@ module MergeRequests class CreateService < MergeRequests::BaseService def execute - merge_request = MergeRequest.new(params) + label_params = params[:label_ids] + merge_request = MergeRequest.new(params.except(:label_ids)) merge_request.source_project = project merge_request.target_project ||= project merge_request.author = current_user if merge_request.save + merge_request.update_attributes(label_ids: label_params) event_service.open_mr(merge_request, current_user) notification_service.new_merge_request(merge_request, current_user) merge_request.create_cross_references!(merge_request.project, current_user) diff --git a/app/views/dashboard/_projects_filter.html.haml b/app/views/dashboard/_projects_filter.html.haml index 8c9893ba84f..e4fa2d59e8a 100644 --- a/app/views/dashboard/_projects_filter.html.haml +++ b/app/views/dashboard/_projects_filter.html.haml @@ -44,12 +44,12 @@ -- if @labels.present? +- if @tags.present? %fieldset - %legend Labels + %legend Tags %ul.nav.nav-pills.nav-stacked.nav-small - - @labels.each do |label| - %li{ class: (label.name == params[:label]) ? 'active' : 'light' } - = link_to projects_dashboard_filter_path(scope: params[:scope], label: label.name) do + - @tags.each do |tag| + %li{ class: (tag.name == params[:tag]) ? 'active' : 'light' } + = link_to projects_dashboard_filter_path(scope: params[:scope], tag: tag.name) do %i.icon-tag - = label.name + = tag.name diff --git a/app/views/dashboard/projects.html.haml b/app/views/dashboard/projects.html.haml index e1c9a5941e9..2714ebc53de 100644 --- a/app/views/dashboard/projects.html.haml +++ b/app/views/dashboard/projects.html.haml @@ -54,10 +54,10 @@ %span.label %i.icon-archive Archived - - project.labels.each do |label| + - project.tags.each do |tag| %span.label.label-info %i.icon-tag - = label.name + = tag.name - if project.description.present? %p= truncate project.description, length: 100 .last-activity diff --git a/app/views/layouts/_public_head_panel.html.haml b/app/views/layouts/_public_head_panel.html.haml index 5d7f72e6b31..945c66e2adf 100644 --- a/app/views/layouts/_public_head_panel.html.haml +++ b/app/views/layouts/_public_head_panel.html.haml @@ -13,10 +13,10 @@ %i.icon-reorder .pull-right.hidden-xs - = link_to "Sign in", new_session_path(:user), class: 'btn btn-sign-in btn-new' + = link_to "Sign in", new_session_path(:user, redirect_to_referer: 'yes'), class: 'btn btn-sign-in btn-new' .navbar-collapse.collapse %ul.nav.navbar-nav %li.visible-xs - = link_to "Sign in", new_session_path(:user) + = link_to "Sign in", new_session_path(:user, redirect_to_referer: 'yes') diff --git a/app/views/notify/repository_push_email.html.haml b/app/views/notify/repository_push_email.html.haml index bf358fe70a9..0358810afdc 100644 --- a/app/views/notify/repository_push_email.html.haml +++ b/app/views/notify/repository_push_email.html.haml @@ -25,6 +25,4 @@ %br - if @compare.timeout - %h5 To prevent performance issues changes are hidden -- elsif @compare.commits_over_limit? - %h5 Changes are not shown due to large amount of commits + %h5 Huge diff. To prevent performance issues changes are hidden diff --git a/app/views/notify/repository_push_email.text.haml b/app/views/notify/repository_push_email.text.haml index ac337c7628a..4d7c972a16a 100644 --- a/app/views/notify/repository_push_email.text.haml +++ b/app/views/notify/repository_push_email.text.haml @@ -23,5 +23,3 @@ Changes: \ - if @compare.timeout Huge diff. To prevent performance issues it was hidden -- elsif @compare.commits_over_limit? - Changes are not shown due to large amount of commits diff --git a/app/views/profiles/passwords/new.html.haml b/app/views/profiles/passwords/new.html.haml index b72232ee36b..aef7348fd20 100644 --- a/app/views/profiles/passwords/new.html.haml +++ b/app/views/profiles/passwords/new.html.haml @@ -12,6 +12,9 @@ %li= msg .form-group + = f.label :current_password, class: 'control-label' + .col-sm-10= f.password_field :current_password, required: true, class: 'form-control' + .form-group = f.label :password, class: 'control-label' .col-sm-10= f.password_field :password, required: true, class: 'form-control' .form-group diff --git a/app/views/projects/commits/_diff_file.html.haml b/app/views/projects/commits/_diff_file.html.haml index 45d1cd9c9a0..9cbcb84aead 100644 --- a/app/views/projects/commits/_diff_file.html.haml +++ b/app/views/projects/commits/_diff_file.html.haml @@ -1,5 +1,4 @@ -- file = project.repository.blob_at(@commit.id, diff.new_path) -- file = project.repository.blob_at(@commit.parent_id, diff.old_path) unless file +- file = project.repository.blob_for_diff(@commit, diff) - return unless file .diff-file{id: "diff-#{i}"} .diff-header{id: "file-path-#{hexdigest(diff.new_path || diff.old_path)}"} @@ -41,7 +40,7 @@ - else = render "projects/commits/text_file", diff: diff, index: i - elsif file.image? - - old_file = project.repository.blob_at(@commit.parent_id, diff.old_path) if @commit.parent_id + - old_file = project.repository.prev_blob_for_diff(@commit, diff) = render "projects/commits/image", diff: diff, old_file: old_file, file: file, index: i - else .nothing-here-block No preview for this file type diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml index 6eaa3e7559a..99b6d8ad288 100644 --- a/app/views/projects/edit.html.haml +++ b/app/views/projects/edit.html.haml @@ -33,12 +33,12 @@ %fieldset.features %legend - Labels: + Tags: .form-group - = f.label :label_list, "Labels", class: 'control-label' + = f.label :tag_list, "Tags", class: 'control-label' .col-sm-10 - = f.text_field :label_list, maxlength: 2000, class: "form-control" - %p.hint Separate labels with commas. + = f.text_field :tag_list, maxlength: 2000, class: "form-control" + %p.hint Separate tags with commas. %fieldset.features %legend diff --git a/app/views/projects/issues/_form.html.haml b/app/views/projects/issues/_form.html.haml index d29a7973100..b2a8e8e091e 100644 --- a/app/views/projects/issues/_form.html.haml +++ b/app/views/projects/issues/_form.html.haml @@ -3,15 +3,19 @@ %hr - if @repository.exists? && !@repository.empty? && @repository.contribution_guide && !@issue.persisted? - 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 <strong>#{link_to "guidelines for contribution", contribution_guide_url}</strong> to this repository.".html_safe + .row + .col-sm-10.col-sm-offset-2 + .alert.alert-info + = "Please review the <strong>#{link_to "guidelines for contribution", contribution_guide_url}</strong> to this repository.".html_safe = form_for [@project, @issue], html: { class: 'form-horizontal issue-form' } do |f| -if @issue.errors.any? - .alert.alert-danger - - @issue.errors.full_messages.each do |msg| - %span= msg - %br + .row + .col-sm-10.col-sm-offset-2 + .alert.alert-danger + - @issue.errors.full_messages.each do |msg| + %span= msg + %br .form-group = f.label :title, class: 'control-label' do %strong= 'Title *' @@ -44,14 +48,11 @@ .col-sm-10= f.select(:milestone_id, milestone_options(@issue), { include_blank: "Select milestone" }, {class: 'select2'}) .form-group - = f.label :label_list, class: 'control-label' do + = f.label :label_ids, class: 'control-label' do %i.icon-tag Labels .col-sm-10 - = f.text_field :label_list, maxlength: 2000, class: "form-control" - %p.hint Separate labels with commas. - - + = f.collection_select :label_ids, @project.labels.all, :id, :name, { selected: @issue.label_ids }, multiple: true, class: 'select2' .form-actions - if @issue.new_record? @@ -63,35 +64,6 @@ = link_to "Cancel", cancel_path, class: 'btn btn-cancel' :javascript - $("#issue_label_list") - .bind( "keydown", function( event ) { - if ( event.keyCode === $.ui.keyCode.TAB && - $( this ).data( "autocomplete" ).menu.active ) { - event.preventDefault(); - } - }) - .bind("click", function(event) { - $(this).autocomplete("search", ""); - }) - .autocomplete({ - minLength: 0, - source: function( request, response ) { - response( $.ui.autocomplete.filter( - #{raw labels_autocomplete_source}, extractLast( request.term ) ) ); - }, - focus: function() { - return false; - }, - select: function(event, ui) { - var terms = split( this.value ); - terms.pop(); - terms.push( ui.item.value ); - terms.push( "" ); - this.value = terms.join( ", " ); - return false; - } - }); - $('.assign-to-me-link').on('click', function(e){ $('#issue_assignee_id').val("#{current_user.id}").trigger("change"); e.preventDefault(); diff --git a/app/views/projects/issues/_issue.html.haml b/app/views/projects/issues/_issue.html.haml index 8d447da3ae9..db28b831182 100644 --- a/app/views/projects/issues/_issue.html.haml +++ b/app/views/projects/issues/_issue.html.haml @@ -31,9 +31,7 @@ .issue-labels - issue.labels.each do |label| - %span{class: "label #{label_css_class(label.name)}"} - %i.icon-tag - = label.name + = render_colored_label(label) .issue-actions - if can? current_user, :modify_issue, issue diff --git a/app/views/projects/issues/show.html.haml b/app/views/projects/issues/show.html.haml index 695eb225754..bd5f01ff6a7 100644 --- a/app/views/projects/issues/show.html.haml +++ b/app/views/projects/issues/show.html.haml @@ -68,9 +68,6 @@ .issue-show-labels.pull-right - @issue.labels.each do |label| - %span{class: "label #{label_css_class(label.name)}"} - %i.icon-tag - = label.name - + = render_colored_label(label) .voting_notes#notes= render "projects/notes/notes_with_form" diff --git a/app/views/projects/labels/_form.html.haml b/app/views/projects/labels/_form.html.haml new file mode 100644 index 00000000000..2a5c907febe --- /dev/null +++ b/app/views/projects/labels/_form.html.haml @@ -0,0 +1,49 @@ += form_for [@project, @label], html: { class: 'form-horizontal label-form' } do |f| + -if @label.errors.any? + .row + .col-sm-10.col-sm-offset-2 + .bs-callout.bs-callout-danger + - @label.errors.full_messages.each do |msg| + %span= msg + %br + + .form-group + = f.label :title, class: 'control-label' + .col-sm-10 + = f.text_field :title, class: "form-control", required: true + .form-group + = f.label :color, "Background Color", class: 'control-label' + .col-sm-10 + .input-group + .input-group-addon.label-color-preview + = f.text_field :color, placeholder: "#AA33EE", class: "form-control" + .help-block + 6 character hex values starting with a # sign. + %br + Or you can choose one of suggested colors below + + .suggest-colors + - suggested_colors.each do |color| + = link_to '#', style: "background-color: #{color}", data: { color: color } do + + + .form-actions + = f.submit 'Save', class: 'btn btn-save' + = link_to "Cancel", project_labels_path(@project), class: 'btn btn-cancel' + + +:coffeescript + updateColorPreview = -> + previewColor = $('input#label_color').val() + $('div.label-color-preview').css('background-color', previewColor) + + $('.suggest-colors a').on 'click', (e) -> + color = $(this).data("color") + $('input#label_color').val(color) + updateColorPreview() + e.preventDefault() + + $('input#label_color').on 'input', -> + updateColorPreview() + + updateColorPreview() diff --git a/app/views/projects/labels/_label.html.haml b/app/views/projects/labels/_label.html.haml index 6e1ca0d8f2f..725bf852078 100644 --- a/app/views/projects/labels/_label.html.haml +++ b/app/views/projects/labels/_label.html.haml @@ -1,13 +1,10 @@ -- frequency = @project.issues.tagged_with(label.name).count -%li - %span{class: "label #{label_css_class(label.name)}"} - %i.icon-tag - - if frequency.zero? - %span.light= label.name - - else - = label.name +%li{id: dom_id(label)} + = render_colored_label(label) .pull-right - - unless frequency.zero? - = link_to project_issues_path(label_name: label.name) do - = pluralize(frequency, 'issue') - = "»" + %strong.append-right-20 + = link_to project_issues_path(@project, label_name: label.name) do + = pluralize label.open_issues_count, 'open issue' + + - if can? current_user, :admin_label, @project + = link_to 'Edit', edit_project_label_path(@project, label), class: 'btn' + = link_to 'Remove', project_label_path(@project, label), class: 'btn btn-remove', method: :delete, data: {confirm: "Remove this label? Are you sure?"} diff --git a/app/views/projects/labels/edit.html.haml b/app/views/projects/labels/edit.html.haml new file mode 100644 index 00000000000..52435c5d892 --- /dev/null +++ b/app/views/projects/labels/edit.html.haml @@ -0,0 +1,8 @@ +%h3 + Edit label + %span.light #{@label.name} +.back-link + = link_to project_labels_path(@project) do + ← To labels list +%hr += render 'form' diff --git a/app/views/projects/labels/index.html.haml b/app/views/projects/labels/index.html.haml index 329cf9ceba8..075779a9c88 100644 --- a/app/views/projects/labels/index.html.haml +++ b/app/views/projects/labels/index.html.haml @@ -1,10 +1,17 @@ = render "projects/issues/head" +- if can? current_user, :admin_label, @project + = link_to new_project_label_path(@project), class: "pull-right btn btn-new" do + New label +%h3.page-title + Labels +%hr + - if @labels.present? - %ul.bordered-list.labels-table - - @labels.each do |label| - = render 'label', label: label + %ul.bordered-list.manage-labels-list + = render @labels + = paginate @labels, theme: 'gitlab' - else .light-well - .nothing-here-block Add first label to your issues or #{link_to 'generate', generate_project_labels_path(@project), method: :post} default set of labels + .nothing-here-block Create first label or #{link_to 'generate', generate_project_labels_path(@project), method: :post} default set of labels diff --git a/app/views/projects/labels/new.html.haml b/app/views/projects/labels/new.html.haml new file mode 100644 index 00000000000..850da0b192b --- /dev/null +++ b/app/views/projects/labels/new.html.haml @@ -0,0 +1,6 @@ +%h3 New label +.back-link + = link_to project_labels_path(@project) do + ← To labels list +%hr += render 'form' diff --git a/app/views/projects/merge_requests/_form.html.haml b/app/views/projects/merge_requests/_form.html.haml index 9ef232b5268..0af89b6e376 100644 --- a/app/views/projects/merge_requests/_form.html.haml +++ b/app/views/projects/merge_requests/_form.html.haml @@ -46,14 +46,12 @@ .col-sm-10= f.select(:milestone_id, milestone_options(@merge_request), { include_blank: "Select milestone" }, {class: 'select2'}) - - if @merge_request.persisted? # Only allow labels on edit to avoid fork vs upstream repo labels issue - .form-group - = f.label :label_list, class: 'control-label' do - %i.icon-tag - Labels - .col-sm-10 - = f.text_field :label_list, maxlength: 2000, class: "form-control" - %p.hint Separate labels with commas. + .form-group + = f.label :label_ids, class: 'control-label' do + %i.icon-tag + Labels + .col-sm-10 + = f.collection_select :label_ids, @merge_request.target_project.labels.all, :id, :name, { selected: @merge_request.label_ids }, multiple: true, class: 'select2' .form-actions - if @merge_request.new_record? @@ -74,33 +72,4 @@ e.preventDefault(); }); - $("#merge_request_label_list") - .bind( "keydown", function( event ) { - if ( event.keyCode === $.ui.keyCode.TAB && - $( this ).data( "autocomplete" ).menu.active ) { - event.preventDefault(); - } - }) - .bind("click", function(event) { - $(this).autocomplete("search", ""); - }) - .autocomplete({ - minLength: 0, - source: function( request, response ) { - response( $.ui.autocomplete.filter( - #{raw labels_autocomplete_source}, extractLast( request.term ) ) ); - }, - focus: function() { - return false; - }, - select: function(event, ui) { - var terms = split( this.value ); - terms.pop(); - terms.push( ui.item.value ); - terms.push( "" ); - this.value = terms.join( ", " ); - return false; - } - }); - window.project_image_path_upload = "#{upload_image_project_path @project}"; diff --git a/app/views/projects/merge_requests/_merge_request.html.haml b/app/views/projects/merge_requests/_merge_request.html.haml index c9a80ec22ef..7f5de232dcf 100644 --- a/app/views/projects/merge_requests/_merge_request.html.haml +++ b/app/views/projects/merge_requests/_merge_request.html.haml @@ -34,6 +34,4 @@ .merge-request-labels - merge_request.labels.each do |label| - %span{class: "label #{label_css_class(label.name)}"} - %i.icon-tag - = label.name + = render_colored_label(label) diff --git a/app/views/projects/merge_requests/_new_submit.html.haml b/app/views/projects/merge_requests/_new_submit.html.haml index 73d364b4f93..7c43d355987 100644 --- a/app/views/projects/merge_requests/_new_submit.html.haml +++ b/app/views/projects/merge_requests/_new_submit.html.haml @@ -2,11 +2,9 @@ New merge request %p.slead From - %strong.monospace - #{@merge_request.source_project_namespace}:#{@merge_request.source_branch} - into - %strong.monospace - #{@merge_request.target_project_namespace}:#{@merge_request.target_branch} + %strong.label-branch #{@merge_request.source_project_namespace}:#{@merge_request.source_branch} + %span into + %strong.label-branch #{@merge_request.target_project_namespace}:#{@merge_request.target_branch} %span.pull-right = link_to 'Change branches', new_project_merge_request_path(@project) @@ -43,6 +41,13 @@ %i.icon-time Milestone %div= f.select(:milestone_id, milestone_options(@merge_request), { include_blank: "Select milestone" }, {class: 'select2'}) + .form-group + = f.label :label_ids do + %i.icon-tag + Labels + %div + = f.collection_select :label_ids, @merge_request.target_project.labels.all, :id, :name, { selected: @merge_request.label_ids }, multiple: true, class: 'select2' + .panel-footer - if contribution_guide_url(@target_project) %p diff --git a/app/views/projects/merge_requests/show/_mr_title.html.haml b/app/views/projects/merge_requests/show/_mr_title.html.haml index 2c905413bc3..563a5244993 100644 --- a/app/views/projects/merge_requests/show/_mr_title.html.haml +++ b/app/views/projects/merge_requests/show/_mr_title.html.haml @@ -28,15 +28,13 @@ = link_to project_merge_requests_path(@project) do ← To merge requests - %span.prepend-left-20.monospace - -if @merge_request.for_fork? - %span - %strong - #{truncate(@merge_request.source_project_path, length: 25)}: - #{@merge_request.source_branch} - → - %span= @merge_request.target_branch + %span.prepend-left-20 + %span From + - if @merge_request.for_fork? + %strong.label-branch #{@merge_request.source_project_namespace}:#{@merge_request.source_branch} + %span into + %strong.label-branch #{@merge_request.target_project_namespace}:#{@merge_request.target_branch} - else - %span= @merge_request.source_branch - → - %span= @merge_request.target_branch + %strong.label-branch #{@merge_request.source_branch} + %span into + %strong.label-branch #{@merge_request.target_branch} diff --git a/app/views/projects/merge_requests/show/_participants.html.haml b/app/views/projects/merge_requests/show/_participants.html.haml index 0dabd965e52..007c111f7fb 100644 --- a/app/views/projects/merge_requests/show/_participants.html.haml +++ b/app/views/projects/merge_requests/show/_participants.html.haml @@ -5,7 +5,4 @@ .merge-request-show-labels.pull-right - @merge_request.labels.each do |label| - %span{class: "label #{label_css_class(label.name)}"} - %i.icon-tag - = label.name - + = render_colored_label(label) diff --git a/app/views/projects/protected_branches/index.html.haml b/app/views/projects/protected_branches/index.html.haml index a51a4cc224a..7925e800305 100644 --- a/app/views/projects/protected_branches/index.html.haml +++ b/app/views/projects/protected_branches/index.html.haml @@ -5,7 +5,7 @@ .bs-callout.bs-callout-info %p Protected branches designed to %ul - %li prevent push for all except #{link_to "masters", help_page_path("permissions", "permissions"), 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_page_path("permissions", "permissions"), class: "underlined-link"} diff --git a/app/views/shared/_project_filter.html.haml b/app/views/shared/_project_filter.html.haml index 38cb1208cdc..5e7d1c2c885 100644 --- a/app/views/shared/_project_filter.html.haml +++ b/app/views/shared/_project_filter.html.haml @@ -34,23 +34,26 @@ - if defined?(labels) %fieldset - %legend Labels + %legend + Labels + %small.pull-right + = link_to project_labels_path(@project), class: 'light' do + %i.icon-edit %ul.nav.nav-pills.nav-stacked.nav-small.labels-filter - - issue_label_names.each do |label_name| - %li{class: label_filter_class(label_name)} - = link_to labels_filter_path(label_name) do - %span{class: "label #{label_css_class(label_name)}"} - %i.icon-tag - = label_name - - if selected_label?(label_name) + - @project.labels.order_by_name.each do |label| + %li{class: label_filter_class(label.name)} + = link_to labels_filter_path(label.name) do + = render_colored_label(label) + - if selected_label?(label.name) .pull-right %i.icon-remove - - if issue_label_names.empty? - .light-well - Add first label to your issues - %br - or #{link_to 'generate', generate_project_labels_path(@project, redirect: redirect), method: :post} default set of labels + - if @project.labels.empty? + .light-well + Create first label at + = link_to 'labels page', project_labels_path(@project) + %br + or #{link_to 'generate', generate_project_labels_path(@project, redirect: redirect), method: :post} default set of labels %fieldset - if %w(state scope milestone_id assignee_id label_name).select { |k| params[k].present? }.any? diff --git a/app/workers/emails_on_push_worker.rb b/app/workers/emails_on_push_worker.rb index 5e81810cbdb..2947c8e3ecd 100644 --- a/app/workers/emails_on_push_worker.rb +++ b/app/workers/emails_on_push_worker.rb @@ -13,7 +13,7 @@ class EmailsOnPushWorker return true end - compare = Gitlab::Git::Compare.new(project.repository.raw_repository, before_sha, after_sha, MergeRequestDiff::COMMITS_SAFE_SIZE) + compare = Gitlab::Git::Compare.new(project.repository.raw_repository, before_sha, after_sha) # Do not send emails if git compare failed return false unless compare && compare.commits.present? diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example index dff709b66b8..7f31fb113c9 100644 --- a/config/gitlab.yml.example +++ b/config/gitlab.yml.example @@ -259,6 +259,12 @@ test: gitlab: host: localhost port: 80 + satellites: + path: tmp/tests/gitlab-satellites/ + gitlab_shell: + path: tmp/tests/gitlab-shell/ + repos_path: tmp/tests/repositories/ + hooks_path: tmp/tests/gitlab-shell/hooks/ issues_tracker: redmine: title: "Redmine" diff --git a/config/initializers/4_sidekiq.rb b/config/initializers/4_sidekiq.rb index c90d376273d..228b14cb526 100644 --- a/config/initializers/4_sidekiq.rb +++ b/config/initializers/4_sidekiq.rb @@ -12,6 +12,10 @@ Sidekiq.configure_server do |config| url: resque_url, namespace: 'resque:gitlab' } + + config.server_middleware do |chain| + chain.add Gitlab::SidekiqMiddleware::ArgumentsLogger + end end Sidekiq.configure_client do |config| diff --git a/config/routes.rb b/config/routes.rb index 3b34ad40297..261fbb50e38 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -297,7 +297,7 @@ Gitlab::Application.routes.draw do end end - resources :labels, only: [:index] do + resources :labels, constraints: {id: /\d+/} do collection do post :generate end diff --git a/db/fixtures/test/001_repo.rb b/db/fixtures/test/001_repo.rb index 281e3476df1..e69de29bb2d 100644 --- a/db/fixtures/test/001_repo.rb +++ b/db/fixtures/test/001_repo.rb @@ -1,36 +0,0 @@ -require 'fileutils' - -print "Unpacking seed repository..." - -SEED_REPO = 'seed_project.tar.gz' -REPO_PATH = Rails.root.join('tmp', 'repositories') - -# Make whatever directories we need to make -FileUtils.mkdir_p(REPO_PATH) - -# Copy the archive to the repo path -FileUtils.cp(Rails.root.join('spec', SEED_REPO), REPO_PATH) - -# chdir to the repo path -FileUtils.cd(REPO_PATH) do - # Extract the archive - `tar -xf #{SEED_REPO}` - - # Remove the copy - FileUtils.rm(SEED_REPO) -end -puts ' done.' -print "Creating seed satellite..." - -SATELLITE_PATH = Rails.root.join('tmp', 'satellite') -# Make directory -FileUtils.mkdir_p(SATELLITE_PATH) -# Clear any potential directory -FileUtils.rm_rf("#{SATELLITE_PATH}/gitlabhq") -# Chdir, clone from the seed -FileUtils.cd(SATELLITE_PATH) do - # Clone the satellite - - `git clone --quiet #{REPO_PATH}/gitlabhq #{SATELLITE_PATH}/gitlabhq` -end -puts ' done.' diff --git a/db/migrate/20140729134820_create_labels.rb b/db/migrate/20140729134820_create_labels.rb new file mode 100644 index 00000000000..3a4b6a152dc --- /dev/null +++ b/db/migrate/20140729134820_create_labels.rb @@ -0,0 +1,11 @@ +class CreateLabels < ActiveRecord::Migration + def change + create_table :labels do |t| + t.string :title + t.string :color + t.integer :project_id + + t.timestamps + end + end +end diff --git a/db/migrate/20140729140420_create_label_links.rb b/db/migrate/20140729140420_create_label_links.rb new file mode 100644 index 00000000000..2bfc4ae2094 --- /dev/null +++ b/db/migrate/20140729140420_create_label_links.rb @@ -0,0 +1,11 @@ +class CreateLabelLinks < ActiveRecord::Migration + def change + create_table :label_links do |t| + t.integer :label_id + t.integer :target_id + t.string :target_type + + t.timestamps + end + end +end diff --git a/db/migrate/20140729145339_migrate_project_tags.rb b/db/migrate/20140729145339_migrate_project_tags.rb new file mode 100644 index 00000000000..5760e4bfeaa --- /dev/null +++ b/db/migrate/20140729145339_migrate_project_tags.rb @@ -0,0 +1,9 @@ +class MigrateProjectTags < ActiveRecord::Migration + def up + ActsAsTaggableOn::Tagging.where(taggable_type: 'Project', context: 'labels').update_all(context: 'tags') + end + + def down + ActsAsTaggableOn::Tagging.where(taggable_type: 'Project', context: 'tags').update_all(context: 'labels') + end +end diff --git a/db/migrate/20140729152420_migrate_taggable_labels.rb b/db/migrate/20140729152420_migrate_taggable_labels.rb new file mode 100644 index 00000000000..0b844720ba1 --- /dev/null +++ b/db/migrate/20140729152420_migrate_taggable_labels.rb @@ -0,0 +1,27 @@ +class MigrateTaggableLabels < ActiveRecord::Migration + def up + taggings = ActsAsTaggableOn::Tagging.where(taggable_type: ['Issue', 'MergeRequest'], context: 'labels') + taggings.find_each(batch_size: 500) do |tagging| + create_label_from_tagging(tagging) + end + end + + def down + Label.destroy_all + LabelLink.destroy_all + end + + private + + def create_label_from_tagging(tagging) + target = tagging.taggable + label_name = tagging.tag.name + label = target.project.labels.find_or_create_by(title: label_name) + + if LabelLink.create(label: label, target: target) + print '.' + else + print 'F' + end + end +end diff --git a/db/migrate/20140730111702_add_index_to_labels.rb b/db/migrate/20140730111702_add_index_to_labels.rb new file mode 100644 index 00000000000..494241c873c --- /dev/null +++ b/db/migrate/20140730111702_add_index_to_labels.rb @@ -0,0 +1,7 @@ +class AddIndexToLabels < ActiveRecord::Migration + def change + add_index "labels", :project_id + add_index "label_links", :label_id + add_index "label_links", [:target_id, :target_type] + end +end diff --git a/db/schema.rb b/db/schema.rb index e4dcdf5bea2..9159556ac72 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: 20140625115202) do +ActiveRecord::Schema.define(version: 20140730111702) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -109,6 +109,27 @@ ActiveRecord::Schema.define(version: 20140625115202) do add_index "keys", ["user_id"], name: "index_keys_on_user_id", using: :btree + create_table "label_links", force: true do |t| + t.integer "label_id" + t.integer "target_id" + t.string "target_type" + t.datetime "created_at" + t.datetime "updated_at" + end + + add_index "label_links", ["label_id"], name: "index_label_links_on_label_id", using: :btree + add_index "label_links", ["target_id", "target_type"], name: "index_label_links_on_target_id_and_target_type", using: :btree + + create_table "labels", force: true do |t| + t.string "title" + t.string "color" + t.integer "project_id" + t.datetime "created_at" + t.datetime "updated_at" + end + + add_index "labels", ["project_id"], name: "index_labels_on_project_id", using: :btree + create_table "merge_request_diffs", force: true do |t| t.string "state" t.text "st_commits" diff --git a/doc/api/README.md b/doc/api/README.md index e91d3af59d7..a0a9ba6f4b6 100644 --- a/doc/api/README.md +++ b/doc/api/README.md @@ -132,14 +132,14 @@ When listing resources you can pass the following parameters: ## 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 entities: id and iid. The main difference between them is scope. Example: Issue: id: 46 iid: 5 -- 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 - is unique across all issues. It's used for any api call. +- iid - is unique only in scope of a 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 f695b48fe2f..090287133ce 100644 --- a/doc/api/branches.md +++ b/doc/api/branches.md @@ -174,7 +174,7 @@ 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 +- `ref` (required) - Create branch from commit SHA or existing branch ```json { diff --git a/doc/api/projects.md b/doc/api/projects.md index 56eee00ffe2..b8876e8e104 100644 --- a/doc/api/projects.md +++ b/doc/api/projects.md @@ -90,7 +90,7 @@ Parameters: #### List owned projects -Get a list of projects owned by the authenticated user. +Get a list of projects which are owned by the authenticated user. ``` GET /projects/owned @@ -106,7 +106,7 @@ GET /projects/all ### Get single project -Get a specific project, identified by project ID or NAMESPACE/PROJECT_NAME , which is owned by the authentication user. +Get a specific project, identified by project ID or NAMESPACE/PROJECT_NAME, which is owned by the authenticated user. If using namespaced projects call make sure that the NAMESPACE/PROJECT_NAME is URL-encoded, eg. `/api/v3/projects/diaspora%2Fdiaspora` (where `/` is represented by `%2F`). ``` @@ -167,7 +167,7 @@ Parameters: ### Get project events -Get a project events for specific project. +Get the events for the specified project. Sorted from newest to latest ``` @@ -241,7 +241,7 @@ Parameters: ### Create project -Creates new project owned by user. +Creates a new project owned by the authenticated user. ``` POST /projects @@ -263,7 +263,7 @@ Parameters: ### Create project for user -Creates a new project owned by user. Available only for admins. +Creates a new project owned by the specified user. Available only for admins. ``` POST /projects/user/:user_id @@ -286,7 +286,7 @@ Parameters: ## Remove project -Removes project with all resources(issues, merge requests etc) +Removes a project including all associated resources (issues, merge requests etc.) ``` DELETE /projects/:id @@ -301,7 +301,7 @@ Parameters: ### List project team members -Get a list of project team members. +Get a list of a project's team members. ``` GET /projects/:id/members @@ -358,7 +358,7 @@ Parameters: ### Edit project team member -Updates project team member to a specified access level. +Updates a project team member to a specified access level. ``` PUT /projects/:id/members/:user_id @@ -373,7 +373,7 @@ Parameters: ### Remove project team member -Removes user from project team. +Removes a user from a project team. ``` DELETE /projects/:id/members/:user_id @@ -394,7 +394,7 @@ rely on the returned JSON structure. ### List project hooks -Get list of project hooks. +Get a list of project hooks. ``` GET /projects/:id/hooks @@ -407,7 +407,7 @@ Parameters: ### Get project hook -Get a specific hook for project. +Get a specific hook for a project. ``` GET /projects/:id/hooks/:hook_id @@ -433,7 +433,7 @@ Parameters: ### Add project hook -Adds a hook to project. +Adds a hook to a specified project. ``` POST /projects/:id/hooks @@ -450,7 +450,7 @@ Parameters: ### Edit project hook -Edits a hook for project. +Edits a hook for a specified project. ``` PUT /projects/:id/hooks/:hook_id @@ -468,7 +468,7 @@ Parameters: ### Delete project hook -Removes a hook from project. This is an idempotent method and can be called multiple times. +Removes a hook from a project. This is an idempotent method and can be called multiple times. Either the hook is available or not. ``` @@ -595,7 +595,7 @@ Parameters: ## Admin fork relation -Allows modification of the forked relationship between existing projects. . Available only for admins. +Allows modification of the forked relationship between existing projects. Available only for admins. ### Create a forked from/to relation between existing projects. @@ -621,7 +621,7 @@ Parameter: ## Search for projects by name -Search for projects by name which are public or the calling user has access to +Search for projects by name which are accessible to the authenticated user. ``` GET /projects/search/:query diff --git a/doc/api/repositories.md b/doc/api/repositories.md index 2539e3edbf9..7d6164a0819 100644 --- a/doc/api/repositories.md +++ b/doc/api/repositories.md @@ -49,7 +49,7 @@ 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. ++ `ref` (required) - Create tag using commit SHA, another tag name, or branch name. ```json [ @@ -129,7 +129,7 @@ Parameters: ## Raw file content -Get the raw file contents for a file by commit sha and path. +Get the raw file contents for a file by commit SHA and path. ``` GET /projects/:id/repository/blobs/:sha @@ -144,7 +144,7 @@ Parameters: ## Raw blob content -Get the raw file contents for a blob by blob sha. +Get the raw file contents for a blob by blob SHA. ``` GET /projects/:id/repository/raw_blobs/:sha @@ -153,7 +153,7 @@ GET /projects/:id/repository/raw_blobs/:sha Parameters: + `id` (required) - The ID of a project -+ `sha` (required) - The blob sha ++ `sha` (required) - The blob SHA ## Get file archive @@ -166,7 +166,7 @@ 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 ++ `sha` (optional) - The commit SHA to download defaults to the tip of the default branch ## Compare branches, tags or commits @@ -177,15 +177,15 @@ 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 ++ `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: +Response: ```json diff --git a/doc/api/repository_files.md b/doc/api/repository_files.md index ae56b04b6ce..b53d60bceec 100644 --- a/doc/api/repository_files.md +++ b/doc/api/repository_files.md @@ -80,6 +80,15 @@ Parameters: - `content` (required) - New file content - `commit_message` (required) - Commit message +If the commit fails for any reason we return a 400 error with a non-specific +error message. Possible causes for a failed commit include: +- the `file_path` contained `/../` (attempted directory traversal); +- the new file contents were identical to the current file contents, i.e. the + user tried to make an empty commit; +- the branch was updated by a Git push while the file edit was in progress. + +Currently gitlab-shell has a boolean return code, preventing GitLab from specifying the error. + ## Delete existing file in repository ``` diff --git a/doc/development/architecture.md b/doc/development/architecture.md index 9d0d58b3db9..4624d9f60b6 100644 --- a/doc/development/architecture.md +++ b/doc/development/architecture.md @@ -22,7 +22,7 @@ To serve repositories over SSH there's an add-on application called gitlab-shell  -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. +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 incoming 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. @@ -38,7 +38,7 @@ To summarize here's the [directory structure of the `git` user home directory](. 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 @@ -53,28 +53,28 @@ See the README for more information. The GitLab init script starts and stops Unicorn and Sidekiq. ``` -/etc/init.d/gitlab +/etc/init.d/gitlab Usage: service gitlab {start|stop|restart|reload|status} ``` Redis (key-value store/non-persistent database) ``` -/etc/init.d/redis +/etc/init.d/redis Usage: /etc/init.d/redis {start|stop|status|restart|condrestart|try-restart} ``` SSH daemon ``` -/etc/init.d/sshd +/etc/init.d/sshd Usage: /etc/init.d/sshd {start|stop|restart|reload|force-reload|condrestart|try-restart|status} ``` Web server (one of the following) ``` -/etc/init.d/httpd +/etc/init.d/httpd Usage: httpd {start|stop|restart|condrestart|try-restart|force-reload|reload|status|fullstatus|graceful|help|configtest} $ /etc/init.d/nginx @@ -84,7 +84,7 @@ Usage: nginx {start|stop|restart|reload|force-reload|status|configtest} Persistent database (one of the following) ``` -/etc/init.d/mysqld +/etc/init.d/mysqld Usage: /etc/init.d/mysqld {start|stop|status|restart|condrestart|try-restart|reload|force-reload} $ /etc/init.d/postgresql diff --git a/doc/development/rake_tasks.md b/doc/development/rake_tasks.md index 9e75b3a6275..6d9ac161e91 100644 --- a/doc/development/rake_tasks.md +++ b/doc/development/rake_tasks.md @@ -2,7 +2,7 @@ ## Setup db with developer seeds: -Note that if your db user does not have advanced privilegies you must create db manually before run this command +Note that if your db user does not have advanced privileges you must create the db manually before running this command. ``` bundle exec rake setup @@ -10,7 +10,7 @@ bundle exec rake setup ## Run tests -This runs all test suite present in GitLab +This runs all test suites present in GitLab. ``` bundle exec rake test @@ -18,7 +18,7 @@ bundle exec rake test ## Generate searchable docs for source code -You can find results under `doc/code` directory +You can find results under the `doc/code` directory. ``` bundle exec rake gitlab:generate_docs diff --git a/doc/install/installation.md b/doc/install/installation.md index f3d21ac4482..e502a3ed82c 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -86,7 +86,7 @@ Then select 'Internet Site' and press enter to confirm the hostname. ## 2. Ruby -The use of ruby version managers such as [RVM](http://rvm.io/), [rbenv](https://github.com/sstephenson/rbenv) or [chruby](https://github.com/postmodern/chruby) with GitLab in production frequently leads to hard to diagnose problems. For example, GitLab Shell is called from OpenSSH and having a version manager can prevent pushing and pulling over SSH. Version managers are not supported and we stronly advise everyone to follow the instructions below to use a system ruby. +The use of ruby version managers such as [RVM](http://rvm.io/), [rbenv](https://github.com/sstephenson/rbenv) or [chruby](https://github.com/postmodern/chruby) with GitLab in production frequently leads to hard to diagnose problems. For example, GitLab Shell is called from OpenSSH and having a version manager can prevent pushing and pulling over SSH. Version managers are not supported and we strongly advise everyone to follow the instructions below to use a system ruby. Remove the old Ruby 1.8 if present @@ -107,7 +107,7 @@ Install the Bundler Gem: ## 3. System Users -Create a `git` user for Gitlab: +Create a `git` user for GitLab: sudo adduser --disabled-login --gecos 'GitLab' git @@ -232,9 +232,9 @@ We recommend using a PostgreSQL database. For MySQL check [MySQL setup guide](da ### Install GitLab shell -GitLab Shell is an ssh access and repository management software developed specially for GitLab. +GitLab Shell is an SSH access and repository management software developed specially for GitLab. - # Go to the Gitlab installation folder: + # Go to the GitLab installation folder: cd /home/git/gitlab # Run the installation task for gitlab-shell (replace `REDIS_URL` if needed): @@ -269,7 +269,7 @@ And if you are installing with a non-default folder or user copy and edit the de sudo cp lib/support/init.d/gitlab.default.example /etc/default/gitlab -If you installed gitlab in another directory or as a user other than the default you should change these settings in /etc/default/gitlab. Do not edit /etc/init.d/gitlab as it will be changed on upgrade. +If you installed GitLab in another directory or as a user other than the default you should change these settings in `/etc/default/gitlab`. Do not edit `/etc/init.d/gitlab as it will be changed on upgrade. Make GitLab start on boot: @@ -372,7 +372,7 @@ If you want to connect the Redis server via socket, then use the "unix:" URL sch ### Custom SSH Connection -If you are running SSH on a non-standard port, you must change the gitlab user's SSH config. +If you are running SSH on a non-standard port, you must change the GitLab user's SSH config. # Add to /home/git/.ssh/config host localhost # Give your setup a name (here: override localhost) @@ -380,11 +380,11 @@ If you are running SSH on a non-standard port, you must change the gitlab user's port 2222 # Your port number hostname 127.0.0.1; # Your server name or IP -You also need to change the corresponding options (e.g. ssh_user, ssh_host, admin_uri) in the `config\gitlab.yml` file. +You also need to change the corresponding options (e.g. `ssh_user`, `ssh_host`, `admin_uri`) in the `config\gitlab.yml` file. ### LDAP authentication -You can configure LDAP authentication in config/gitlab.yml. Please restart GitLab after editing this file. +You can configure LDAP authentication in `config/gitlab.yml`. Please restart GitLab after editing this file. ### Using Custom Omniauth Providers @@ -422,4 +422,4 @@ If you have successfully set up a provider that is not shipped with GitLab itsel 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. +While we can't officially support every possible authentication 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 46a98397aa3..938e48ddd74 100644 --- a/doc/install/requirements.md +++ b/doc/install/requirements.md @@ -51,11 +51,11 @@ We love [JRuby](http://jruby.org/) and [Rubinius](http://rubini.us/)) but GitLab ### Memory - 512MB is the absolute minimum but we do not recommend this amount of memory. -You will either need to configure a minimum swap of 256MB and this will only allow you to run one slow unicorn worker. -One unicorn worker will cause only git ssh access to work because the git http access requires two running workers. -It requires one worker to receive the user request and one worker for the authorization check. -Or if you use SSD you can configure 2GB of swap to use two Unicorn workers and have slow operation with http access. -- 1GB supports up to 100 users (with individual repositories under 250MB, otherwise git memory usage necessitates configuring swap space) +You will either need to configure 512MB or 1.5GB of swap space. +With 512MB of swap space you must configure only one unicorn worker. +With one unicorn worker only git over ssh access will work because the git over http access requires two running workers (one worker to receive the user request and one worker for the authorization check). +If you use SSD storage and configure 1.5GB of swap space you can use two Unicorn workers, this will allow http access but it will still be slow. +- 1GB supports up to 100 users (we highly recommend adding al least 1GB of swap space, this is a must if you have individual repositories under 250MB) - **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 @@ -63,6 +63,8 @@ Or if you use SSD you can configure 2GB of swap to use two Unicorn workers and h - 32GB supports up to 20,000 users - 64GB supports up to 40,000 users +Notice: The 25 workers of Sidekiq will show up as separate processes in your process overview (such as top or htop) but they share the same RAM allocation since Sidekiq is a multithreaded application. + ### 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. diff --git a/doc/integration/github.md b/doc/integration/github.md index b53a7c12857..714593d8266 100644 --- a/doc/integration/github.md +++ b/doc/integration/github.md @@ -37,7 +37,7 @@ To enable the GitHub OmniAuth provider you must register your application with G args: { scope: 'user:email' } } ``` -1. Change 'YOUR APP ID' to the client ID from the GitHub application page from step 7. +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. diff --git a/doc/markdown/markdown.md b/doc/markdown/markdown.md index 2565acb8eff..5627fd0659f 100644 --- a/doc/markdown/markdown.md +++ b/doc/markdown/markdown.md @@ -139,37 +139,38 @@ But let's throw in a <b>tag</b>. ## Emoji - Sometimes you want to be :cool: and add some :sparkles: to your :speech_balloon:. Well we have a :gift: for you: + Sometimes you want to be a :ninja: and add some :glowing_star: to your :speech_balloon:. Well we have a gift for you: - :exclamation: You can use emoji anywhere GFM is supported. :sunglasses: + :high_voltage_sign: You can use emoji anywhere GFM is supported. :victory_hand: - You can use it to point out a :bug: or warn about :monkey:patches. And if someone improves your really :snail: code, send them a :bouquet: or some :candy:. People will :heart: you for that. + You can use it to point out a :bug: or warn about :speak_no_evil_monkey: patches. And if someone improves your really :snail: code, send them some :cake:. People will :heart: you for that. - If you are :new: to this, don't be :fearful:. You can easily join the emoji :circus_tent:. All you need to do is to :book: up on the supported codes. + If you are new to this, don't be :fearful_face:. You can easily join the emoji :family:. All you need to do is to look up on the supported codes. - Consult the [Emoji Cheat Sheet](http://www.emoji-cheat-sheet.com/) for a list of all supported emoji codes. :thumbsup: + Consult the [Emoji Cheat Sheet](https://www.dropbox.com/s/b9xaqb977s6d8w1/cheat_sheet.pdf) for a list of all supported emoji codes. :thumbsup: -Sometimes you want to be :cool: and add some :sparkles: to your :speech_balloon:. Well we have a :gift: for you: +Sometimes you want to be a :ninja: and add some :glowing_star: to your :speech_balloon:. Well we have a gift for you: -:exclamation: You can use emoji anywhere GFM is supported. :sunglasses: +:high_voltage_sign: You can use emoji anywhere GFM is supported. :victory_hand: -You can use it to point out a :bug: or warn about :monkey:patches. And if someone improves your really :snail: code, send them a :bouquet: or some :candy:. People will :heart: you for that. +You can use it to point out a :bug: or warn about :speak_no_evil_monkey: patches. And if someone improves your really :snail: code, send them some :cake:. People will :heart: you for that. -If you are :new: to this, don't be :fearful:. You can easily join the emoji :circus_tent:. All you need to do is to :book: up on the supported codes. +If you are new to this, don't be :fearful_face:. You can easily join the emoji :family:. All you need to do is to look up on the supported codes. -Consult the [Emoji Cheat Sheet](http://www.emoji-cheat-sheet.com/) for a list of all supported emoji codes. :thumbsup: +Consult the [Emoji Cheat Sheet](https://www.dropbox.com/s/b9xaqb977s6d8w1/cheat_sheet.pdf) for a list of all supported emoji codes. :thumbsup: ## Special GitLab References GFM recognized special references. -You can easily reference e.g. a team member, an issue, or a commit within a project. +You can easily reference e.g. an issue, a commit, a team member or even the whole team 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 +- @all : for the whole team - #123 : for issues - !123 : for merge requests - $123 : for snippets diff --git a/doc/public_access/public_access.md b/doc/public_access/public_access.md index 9b117319eec..4712c387021 100644 --- a/doc/public_access/public_access.md +++ b/doc/public_access/public_access.md @@ -1,6 +1,6 @@ # Public access -Gitlab allows you to open selected projects to be accessed **publicly** or **internally**. +GitLab allows you to open selected projects to be accessed **publicly** or **internally**. Projects with either of these visibility levels will be listed in the [public access directory](/public). diff --git a/doc/raketasks/backup_restore.md b/doc/raketasks/backup_restore.md index a0e38067094..8200a8cf630 100644 --- a/doc/raketasks/backup_restore.md +++ b/doc/raketasks/backup_restore.md @@ -51,7 +51,7 @@ Deleting old backups... [SKIPPING] Please be informed that a backup does not store your configuration files. If you use Omnibus-GitLab please see the [instructions in the readme to backup your configuration](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/README.md#backup-and-restore-omnibus-gitlab-configuration). If you have a cookbook installation there should be a copy of your configuration in Chef. -If you have a manual installation please consider backing up your gitlab.yml file and any ssl keys and certificates. +If you have a manual installation please consider backing up your gitlab.yml file and any SSL keys and certificates. ## Restore a previously created backup diff --git a/doc/raketasks/maintenance.md b/doc/raketasks/maintenance.md index 9f5d21527c3..a0901cc4070 100644 --- a/doc/raketasks/maintenance.md +++ b/doc/raketasks/maintenance.md @@ -111,9 +111,9 @@ Redis version >= 2.0.0? ... yes Checking GitLab ... Finished ``` -## (Re-)Create satellite repos +## (Re-)Create satellite repositories -This will create satellite repos for all your projects. +This will create satellite repositories for all your projects. If necessary, remove the `tmp/repo_satellites` directory and rerun the command below. diff --git a/doc/release/monthly.md b/doc/release/monthly.md index f3201c3b628..09bdde81dcc 100644 --- a/doc/release/monthly.md +++ b/doc/release/monthly.md @@ -20,10 +20,12 @@ Any changes not yet added to the changelog are added by lead developer and in th 15th: * Update the changelog (#LINK) +* Triage the omnibus-gitlab milestone 16th: * Merge CE in to EE (#LINK) +* Close the omnibus-gitlab milestone 17th: @@ -43,7 +45,7 @@ Any changes not yet added to the changelog are added by lead developer and in th * Release CE and EE (#LINK) -23th: +23rd: * Prepare package for GitLab.com release (#LINK) @@ -71,9 +73,9 @@ The RC1 release comes with the task to update the installation and upgrade docs. 1. Create: CE update guide from previous version. Like `from-6-8-to-6.9` 1. Create: CE to EE update guide in EE repository for latest version. -1. Update: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/update/6.0-to-6.x.md to latest version. +1. Update: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/update/6.0-to-6.x.md to latest version. -It's best to copy paste the previous guide and make changes where necessary. +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? diff --git a/doc/release/security.md b/doc/release/security.md index f20d7e16222..da442de6ee1 100644 --- a/doc/release/security.md +++ b/doc/release/security.md @@ -59,7 +59,7 @@ XXX ### Credit -We want to thank XXX of XXX for the reponsible disclosure of this vulnerability. +We want to thank XXX of XXX for the responsible disclosure of this vulnerability. ## Email template diff --git a/doc/update/4.2-to-5.0.md b/doc/update/4.2-to-5.0.md index 230c1e88b23..27cc72c1cb6 100644 --- a/doc/update/4.2-to-5.0.md +++ b/doc/update/4.2-to-5.0.md @@ -7,6 +7,7 @@ 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 +- Self signed SSL certificates are not supported until GitLab 5.1 - **requires ruby1.9.3** ## 0. Stop gitlab @@ -66,7 +67,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 @@ -156,9 +157,13 @@ sudo -u git -H /home/git/gitlab-shell/bin/check # /home/git/.ssh/authorized_keys: OK -# Now check gitlab instance +# Now check GitLab instance 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** + +```bash +sudo userdel -r gitlab +``` diff --git a/doc/update/5.0-to-5.1.md b/doc/update/5.0-to-5.1.md index 628d8bc7dfa..b04f3065a17 100644 --- a/doc/update/5.0-to-5.1.md +++ b/doc/update/5.0-to-5.1.md @@ -69,3 +69,22 @@ mysql> \q ## 7. Start application sudo service gitlab start + +## 8. Check installation + + +```bash +# In 5-10 seconds lets check gitlab-shell +sudo -u git -H /home/git/gitlab-shell/bin/check + +# Example of success output +# Check GitLab API access: OK +# Check directories and files: +# /home/git/repositories: OK +# /home/git/.ssh/authorized_keys: OK + + +# Now check gitlab instance +sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production + +``` diff --git a/doc/update/5.1-to-6.0.md b/doc/update/5.1-to-6.0.md index d8484b2c650..123b3326ead 100644 --- a/doc/update/5.1-to-6.0.md +++ b/doc/update/5.1-to-6.0.md @@ -149,6 +149,12 @@ sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production 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. +Start rails console: + +``` +sudo -u git -H rails console production +``` + All project owners should have an owner: ``` diff --git a/doc/update/6.2-to-6.3.md b/doc/update/6.2-to-6.3.md index dfe2e551b36..345480c4d32 100644 --- a/doc/update/6.2-to-6.3.md +++ b/doc/update/6.2-to-6.3.md @@ -32,7 +32,7 @@ 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 <https://github.com/gitlabhq/gitlab-shell/blob/master/config.yml.example> ## 4. Install libs, migrations, etc. @@ -55,7 +55,7 @@ sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS ## 5. 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-2-stable:config/gitlab.yml.example 6-3-stable:config/gitlab.yml.example diff --git a/doc/update/6.6-to-6.7.md b/doc/update/6.6-to-6.7.md index 1e3b7da12d4..c3a749b9a92 100644 --- a/doc/update/6.6-to-6.7.md +++ b/doc/update/6.6-to-6.7.md @@ -18,7 +18,7 @@ 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-7-stable diff --git a/doc/update/6.8-to-6.9.md b/doc/update/6.8-to-6.9.md index 4a3e45ae5ee..b7305d082a5 100644 --- a/doc/update/6.8-to-6.9.md +++ b/doc/update/6.8-to-6.9.md @@ -20,7 +20,7 @@ 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-9-stable @@ -90,7 +90,7 @@ If all items are green, then congratulations upgrade is complete! ## Things went south? Revert to previous version (6.8) ### 1. Revert the code to the previous version -Follow the [`upgrade guide from 6.7 to 6.8`](6.7-to-6.8.md), except for the database migration +Follow the [`upgrade guide from 6.7 to 6.8`](6.7-to-6.8.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.9-to-7.0.md b/doc/update/6.9-to-7.0.md index 70a30a58687..806a714c49b 100644 --- a/doc/update/6.9-to-7.0.md +++ b/doc/update/6.9-to-7.0.md @@ -52,7 +52,7 @@ 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 7-0-stable @@ -103,7 +103,7 @@ sudo chmod +x /etc/init.d/gitlab 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. ``` -git diff 6-9-stable:config/gitlab.yml.example 7-0-stable:config/gitlab.yml.example +git diff origin/6-9-stable:config/gitlab.yml.example origin/7-0-stable:config/gitlab.yml.example ``` ### 7. Start application @@ -126,7 +126,7 @@ If all items are green, then congratulations upgrade is complete! ## Things went south? Revert to previous version (6.9) ### 1. Revert the code to the previous version -Follow the [`upgrade guide from 6.8 to 6.9`](6.8-to-6.9.md), except for the database migration +Follow the [`upgrade guide from 6.8 to 6.9`](6.8-to-6.9.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/7.0-to-7.1.md b/doc/update/7.0-to-7.1.md index 6864101f8c6..ba2d9a23a36 100644 --- a/doc/update/7.0-to-7.1.md +++ b/doc/update/7.0-to-7.1.md @@ -52,7 +52,7 @@ 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 7-1-stable @@ -126,7 +126,7 @@ If all items are green, then congratulations upgrade is complete! ## Things went south? Revert to previous version (7.0) ### 1. Revert the code to the previous version -Follow the [`upgrade guide from 6.9 to 7.0`](6.9-to-7.0.md), except for the database migration +Follow the [`upgrade guide from 6.9 to 7.0`](6.9-to-7.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/workflow/groups.md b/doc/workflow/groups.md index 611f871cf77..52bf611dc5e 100644 --- a/doc/workflow/groups.md +++ b/doc/workflow/groups.md @@ -21,7 +21,7 @@ When your group has been created you are presented with the group dashboard feed You can use the 'New project' button to add a project to the new group. -## Transfering an existing project into a group +## Transferring an existing project into a group You can transfer an existing project into a group you own from the project settings page. First scroll down to the 'Dangerous settings' and click 'Show them to me'. @@ -59,7 +59,7 @@ See [the GitLab Enterprise Edition documentation](http://doc.gitlab.com/ee/integ ## Allowing only admins to create groups By default, any GitLab user can create new groups. -This ability can be disabled for individual users from the admin panel. +This ability can be disabled for individual users from the admin panel. It is also possible to configure GitLab so that new users default to not being able to create groups: ``` diff --git a/doc/workflow/project_features.md b/doc/workflow/project_features.md index 48e86ee3ef5..a523b3facbe 100644 --- a/doc/workflow/project_features.md +++ b/doc/workflow/project_features.md @@ -16,7 +16,7 @@ They integrate deeply into GitLab and are easily referenced from anywhere by usi 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. +As with issues, it can be assigned; people, issues, etc. can be referenced; milestones attached. We see it as an integral part of working together on code and couldn't work without it. diff --git a/features/project/commits/commits.feature b/features/project/commits/commits.feature index cbe8b321507..7c6db3c465a 100644 --- a/features/project/commits/commits.feature +++ b/features/project/commits/commits.feature @@ -38,10 +38,6 @@ Feature: Project Browse commits Given I visit big commit page Then I see big commit warning - Scenario: I browse huge commit - Given I visit huge commit page - Then I see huge commit message - Scenario: I browse a commit with an image Given I visit a commit with an image that changed Then The diff links to both the previous and current image diff --git a/features/project/commits/user_lookup.feature b/features/project/commits/user_lookup.feature index aa347e24fe4..7b194ab9206 100644 --- a/features/project/commits/user_lookup.feature +++ b/features/project/commits/user_lookup.feature @@ -2,13 +2,14 @@ Feature: Project Browse Commits User Lookup Background: Given I sign in as a user And I own a project - And I have the user that authored the commits And I visit my project's commits page Scenario: I browse commit from list - Given I click on commit link - Then I see commit info + Given I have user with primary email + When I click on commit link + Then I see author based on primary email Scenario: I browse another commit from list - Given I click on another commit link - Then I see other commit info + Given I have user with secondary email + When I click on another commit link + Then I see author based on secondary email diff --git a/features/project/forked_merge_requests.feature b/features/project/forked_merge_requests.feature index 5832b729deb..7442145d87e 100644 --- a/features/project/forked_merge_requests.feature +++ b/features/project/forked_merge_requests.feature @@ -4,7 +4,6 @@ Feature: Project Forked Merge Requests And I am a member of project "Shop" And I have a project forked off of "Shop" called "Forked Shop" - @javascript Scenario: I submit new unassigned merge request to a forked project Given I visit project "Forked Shop" merge requests page And I click link "New Merge Request" diff --git a/features/project/hooks.feature b/features/project/hooks.feature index b158e07ad33..52e02a890dd 100644 --- a/features/project/hooks.feature +++ b/features/project/hooks.feature @@ -19,3 +19,8 @@ Feature: Project Hooks When I click test hook button Then hook should be triggered + Scenario: I test a hook on empty project + Given I own empty project with hook + And I visit project hooks page + When I click test hook button + Then I should see hook error message diff --git a/features/project/issues/filter_labels.feature b/features/project/issues/filter_labels.feature index 8df7a119e84..f4a0a7977cc 100644 --- a/features/project/issues/filter_labels.feature +++ b/features/project/issues/filter_labels.feature @@ -2,9 +2,10 @@ Feature: Project Filter Labels Background: Given I sign in as a user And I own project "Shop" - And project "Shop" has issue "Bugfix1" with tags: "bug", "feature" - And project "Shop" has issue "Bugfix2" with tags: "bug", "enhancement" - And project "Shop" has issue "Feature1" with tags: "feature" + And project "Shop" has labels: "bug", "feature", "enhancement" + And project "Shop" has issue "Bugfix1" with labels: "bug", "feature" + And project "Shop" has issue "Bugfix2" with labels: "bug", "enhancement" + And project "Shop" has issue "Feature1" with labels: "feature" Given I visit project "Shop" issues page Scenario: I should see project issues @@ -18,9 +19,12 @@ Feature: Project Filter Labels And I should see "Bugfix2" in issues list And I should not see "Feature1" in issues list - Scenario: I filter by two labels - Given I click link "bug" - And I click link "feature" - Then I should see "Bugfix1" in issues list - And I should not see "Bugfix2" in issues list - And I should not see "Feature1" in issues list + # TODO: make labels filter works according to this scanario + # right now it looks for label 1 OR label 2. Old behaviour (this test) was + # all issues that have both label 1 AND label 2 + #Scenario: I filter by two labels + #Given I click link "bug" + #And I click link "feature" + #Then I should see "Bugfix1" in issues list + #And I should not see "Bugfix2" in issues list + #And I should not see "Feature1" in issues list diff --git a/features/project/issues/issues.feature b/features/project/issues/issues.feature index 191e8dcbe7f..b2e6f1f9324 100644 --- a/features/project/issues/issues.feature +++ b/features/project/issues/issues.feature @@ -30,6 +30,13 @@ Feature: Project Issues And I submit new issue "500 error on profile" Then I should see issue "500 error on profile" + Scenario: I submit new unassigned issue with labels + Given project "Shop" has labels: "bug", "feature", "enhancement" + And I click link "New Issue" + And I submit new issue "500 error on profile" with label 'bug' + Then I should see issue "500 error on profile" + And I should see label 'bug' with issue + @javascript Scenario: I comment issue Given I visit issue page "Release 0.4" diff --git a/features/project/issues/labels.feature b/features/project/issues/labels.feature index e601a41bfc4..4a37b6dc9fa 100644 --- a/features/project/issues/labels.feature +++ b/features/project/issues/labels.feature @@ -2,9 +2,24 @@ Feature: Project Labels Background: Given I sign in as a user And I own project "Shop" - And project "Shop" have issues tags: "bug", "feature" + And project "Shop" has labels: "bug", "feature", "enhancement" Given I visit project "Shop" labels page - Scenario: I should see active milestones + Scenario: I should see labels list Then I should see label "bug" And I should see label "feature" + + Scenario: I create new label + Given I visit new label page + When I submit new label 'support' + Then I should see label 'support' + + Scenario: I edit label + Given I visit 'bug' label edit page + When I change label 'bug' to 'fix' + Then I should not see label 'bug' + Then I should see label 'fix' + + Scenario: I remove label + When I remove label 'bug' + Then I should not see label 'bug' diff --git a/features/project/merge_requests.feature b/features/project/merge_requests.feature index 6a2ba7e3b28..d4c71ba336e 100644 --- a/features/project/merge_requests.feature +++ b/features/project/merge_requests.feature @@ -52,27 +52,27 @@ Feature: Project Merge Requests Given project "Shop" have "Bug NS-05" open merge request with diffs inside And I visit merge request page "Bug NS-05" And I switch to the diff tab - And I leave a comment like "Line is wrong" on line 185 of the first file + And I leave a comment like "Line is wrong" on diff And I switch to the merge request's comments tab - Then I should see a discussion has started on line 185 + Then I should see a discussion has started on diff @javascript Scenario: I comment on a line of a commit in merge request Given project "Shop" have "Bug NS-05" open merge request with diffs inside And I visit merge request page "Bug NS-05" - And I click on the first commit in the merge request - And I leave a comment like "Line is wrong" on line 185 of the first file in commit + And I click on the commit in the merge request + And I leave a comment like "Line is wrong" on diff in commit And I switch to the merge request's comments tab - Then I should see a discussion has started on commit b1e6a9dbf1:L185 + Then I should see a discussion has started on commit diff @javascript Scenario: I comment on a commit in merge request Given project "Shop" have "Bug NS-05" open merge request with diffs inside And I visit merge request page "Bug NS-05" - And I click on the first commit in the merge request + And I click on the commit in the merge request And I leave a comment on the diff page in commit And I switch to the merge request's comments tab - Then I should see a discussion has started on commit b1e6a9dbf1 + Then I should see a discussion has started on commit @javascript Scenario: I accept merge request with custom commit message diff --git a/features/project/network.feature b/features/project/network.feature index 22beb1c50bc..8beb6043aff 100644 --- a/features/project/network.feature +++ b/features/project/network.feature @@ -12,28 +12,28 @@ Feature: Project Network Graph @javascript Scenario: I should switch "branch" and "tag" - When I switch ref to "stable" - Then page should select "stable" in select box - And page should have "stable" on graph - When I switch ref to "v2.1.0" - Then page should select "v2.1.0" in select box - And page should have "v2.1.0" on graph + When I switch ref to "feature" + Then page should select "feature" in select box + And page should have "feature" on graph + When I switch ref to "v1.0.0" + Then page should select "v1.0.0" in select box + And page should have "v1.0.0" on graph @javascript Scenario: I should looking for a commit by SHA - When I looking for a commit by SHA of "v2.1.0" + When I looking for a commit by SHA of "v1.0.0" Then page should have network graph And page should select "master" in select box - And page should have "v2.1.0" on graph + And page should have "v1.0.0" on graph @javascript Scenario: I should filter selected tag - When I switch ref to "v2.1.0" - Then page should have content not containing "v2.1.0" + When I switch ref to "v1.0.0" + Then page should have content not containing "v1.0.0" When click "Show only selected branch" checkbox - Then page should not have content not containing "v2.1.0" + Then page should not have content not containing "v1.0.0" When click "Show only selected branch" checkbox - Then page should have content not containing "v2.1.0" + Then page should have content not containing "v1.0.0" Scenario: I should fail to look for a commit When I look for a commit by ";" diff --git a/features/project/source/browse_files.feature b/features/project/source/browse_files.feature index 4af2cc83581..f8934da8de5 100644 --- a/features/project/source/browse_files.feature +++ b/features/project/source/browse_files.feature @@ -8,11 +8,11 @@ Feature: Project Browse files Then I should see files from repository Scenario: I browse files for specific ref - Given I visit project source page for "8470d70" - Then I should see files from repository for "8470d70" + Given I visit project source page for "6d39438" + Then I should see files from repository for "6d39438" Scenario: I browse file content - Given I click on "Gemfile.lock" file in repo + Given I click on ".gitignore" file in repo Then I should see it content Scenario: I browse raw file @@ -26,20 +26,20 @@ Feature: Project Browse files @javascript Scenario: I can edit file - Given I click on "Gemfile.lock" file in repo + Given I click on ".gitignore" file in repo And I click button "edit" Then I can edit code @javascript Scenario: I can see editing preview - Given I click on "Gemfile.lock" file in repo + Given I click on ".gitignore" file in repo And I click button "edit" And I edit code And I click link "Diff" Then I see diff Scenario: I can browse directory with Browse Dir - Given I click on app directory + Given I click on files directory And I click on history link Then I see Browse dir link diff --git a/features/project/source/git_blame.feature b/features/project/source/git_blame.feature index 3b20437a875..ae62c166c12 100644 --- a/features/project/source/git_blame.feature +++ b/features/project/source/git_blame.feature @@ -5,6 +5,6 @@ Feature: Project Browse git repo Given I visit project source page Scenario: I blame file - Given I click on "Gemfile.lock" file in repo + Given I click on ".gitignore" file in repo And I click blame button Then I should see git file blame diff --git a/features/project/source/markdown_render.feature b/features/project/source/markdown_render.feature index 970a9e57864..fce351317c6 100644 --- a/features/project/source/markdown_render.feature +++ b/features/project/source/markdown_render.feature @@ -2,7 +2,7 @@ Feature: Project markdown render Background: Given I sign in as a user And I own project "Delta" - Given I visit project source page + And I visit markdown branch # Tree README @@ -11,26 +11,26 @@ Feature: Project markdown render And I click on a relative link in README Then I should see the correct markdown - Scenario: I browse files from master branch - Then I should see files from repository in master + Scenario: I browse files from markdown branch + Then I should see files from repository in markdown And I should see rendered README which contains correct links And I click on Gitlab API in README Then I should see correct document rendered - Scenario: I view README in master branch - Then I should see files from repository in master + Scenario: I view README in markdown branch + Then I should see files from repository in markdown And I should see rendered README which contains correct links And I click on Rake tasks in README Then I should see correct directory rendered - Scenario: I view README in master branch to see reference links to directory - Then I should see files from repository in master + Scenario: I view README in markdown branch to see reference links to directory + Then I should see files from repository in markdown And I should see rendered README which contains correct links And I click on GitLab API doc directory in README Then I should see correct doc/api directory rendered - Scenario: I view README in master branch to see reference links to file - Then I should see files from repository in master + Scenario: I view README in markdown branch to see reference links to file + Then I should see files from repository in markdown And I should see rendered README which contains correct links And I click on Maintenance in README Then I should see correct maintenance file rendered @@ -41,19 +41,19 @@ Feature: Project markdown render # Blob - Scenario: I navigate to doc directory to view documentation in master + Scenario: I navigate to doc directory to view documentation in markdown And I navigate to the doc/api/README And I see correct file rendered And I click on users in doc/api/README Then I should see the correct document file - Scenario: I navigate to doc directory to view user doc in master + Scenario: I navigate to doc directory to view user doc in markdown And I navigate to the doc/api/README And I see correct file rendered And I click on raketasks in doc/api/README Then I should see correct directory rendered - Scenario: I navigate to doc directory to view user doc in master + Scenario: I navigate to doc directory to view user doc in markdown And I navigate to the doc/api/README And Header "GitLab API" should have correct id and link diff --git a/features/project/source/multiselect_blob.feature b/features/project/source/multiselect_blob.feature index 0fdfe7ce938..f60b646a8d9 100644 --- a/features/project/source/multiselect_blob.feature +++ b/features/project/source/multiselect_blob.feature @@ -2,7 +2,7 @@ Feature: Project Multiselect Blob Background: Given I sign in as a user And I own project "Shop" - And I visit "Gemfile.lock" file in repo + And I visit ".gitignore" file in repo @javascript Scenario: I click line 1 in file diff --git a/features/project/source/search_code.feature b/features/project/source/search_code.feature index 13f15cc922f..ad8a650d895 100644 --- a/features/project/source/search_code.feature +++ b/features/project/source/search_code.feature @@ -4,6 +4,6 @@ Feature: Project Search code And I own project "Shop" Given I visit project source page - Scenario: Search for term "Welcome to GitLab" - When I search for term "Welcome to GitLab" - Then I should see files from repository containing "Welcome to GitLab" + Scenario: Search for term "coffee" + When I search for term "coffee" + Then I should see files from repository containing "coffee" diff --git a/features/steps/dashboard/dashboard.rb b/features/steps/dashboard/dashboard.rb index 706c9babcee..84a480bd7f8 100644 --- a/features/steps/dashboard/dashboard.rb +++ b/features/steps/dashboard/dashboard.rb @@ -12,7 +12,7 @@ class Dashboard < Spinach::FeatureSteps end Then 'I should see last push widget' do - page.should have_content "You pushed to new_design" + page.should have_content "You pushed to fix" page.should have_link "Create Merge Request" end @@ -23,7 +23,7 @@ class Dashboard < Spinach::FeatureSteps Then 'I see prefilled new Merge Request page' do current_path.should == new_project_merge_request_path(@project) find("#merge_request_target_project_id").value.should == @project.id.to_s - find("#merge_request_source_branch").value.should == "new_design" + find("#merge_request_source_branch").value.should == "fix" find("#merge_request_target_branch").value.should == "master" end diff --git a/features/steps/explore/groups_feature.rb b/features/steps/explore/groups_feature.rb index 48486a83424..b529c5f8455 100644 --- a/features/steps/explore/groups_feature.rb +++ b/features/steps/explore/groups_feature.rb @@ -90,4 +90,3 @@ class Spinach::Features::ExploreGroupsFeature < Spinach::FeatureSteps ) end end - diff --git a/features/steps/help.rb b/features/steps/help.rb index 67054e14303..0d1c9c00376 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(2, '(Re-)Create satellite repos', 're-create-satellite-repos', '.documentation') + header_should_have_correct_id_and_link(2, '(Re-)Create satellite repositories', 're-create-satellite-repositories', '.documentation') end end diff --git a/features/steps/profile/profile.rb b/features/steps/profile/profile.rb index 879bcf41b40..5a7ac207314 100644 --- a/features/steps/profile/profile.rb +++ b/features/steps/profile/profile.rb @@ -145,6 +145,7 @@ class Profile < Spinach::FeatureSteps end step 'I submit new password' do + fill_in :user_current_password, with: '12345678' fill_in :user_password, with: '12345678' fill_in :user_password_confirmation, with: '12345678' click_button "Set new password" @@ -179,7 +180,7 @@ class Profile < Spinach::FeatureSteps @group.add_owner(current_user) @project = create(:project, namespace: @group) @event = create(:closed_issue_event, project: @project) - + @project.team << [current_user, :master] end diff --git a/features/steps/project/browse_commits.rb b/features/steps/project/browse_commits.rb index fe47a731915..37207aafebe 100644 --- a/features/steps/project/browse_commits.rb +++ b/features/steps/project/browse_commits.rb @@ -2,11 +2,12 @@ class ProjectBrowseCommits < Spinach::FeatureSteps include SharedAuthentication include SharedProject include SharedPaths + include RepoHelpers Then 'I see project commits' do commit = @project.repository.commit page.should have_content(@project.name) - page.should have_content(commit.message) + page.should have_content(commit.message[0..20]) page.should have_content(commit.id.to_s[0..5]) end @@ -19,21 +20,21 @@ class ProjectBrowseCommits < Spinach::FeatureSteps page.response_headers['Content-Type'].should have_content("application/atom+xml") page.body.should have_selector("title", text: "Recent commits to #{@project.name}") page.body.should have_selector("author email", text: commit.author_email) - page.body.should have_selector("entry summary", text: commit.description) + page.body.should have_selector("entry summary", text: commit.description[0..10]) end Given 'I click on commit link' do - visit project_commit_path(@project, ValidCommit::ID) + visit project_commit_path(@project, sample_commit.id) end Then 'I see commit info' do - page.should have_content ValidCommit::MESSAGE - page.should have_content "Showing 1 changed file" + page.should have_content sample_commit.message + page.should have_content "Showing #{sample_commit.files_changed_count} changed files" end And 'I fill compare fields with refs' do - fill_in "from", with: "8716fc78f3c65bbf7bcf7b574febd583bc5d2812" - fill_in "to", with: "bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a" + fill_in "from", with: sample_commit.parent_id + fill_in "to", with: sample_commit.id click_button "Compare" end @@ -56,30 +57,24 @@ class ProjectBrowseCommits < Spinach::FeatureSteps end Given 'I visit big commit page' do - visit project_commit_path(@project, BigCommits::BIG_COMMIT_ID) + Commit::DIFF_SAFE_FILES = 20 + visit project_commit_path(@project, sample_big_commit.id) end Then 'I see big commit warning' do - page.should have_content BigCommits::BIG_COMMIT_MESSAGE + page.should have_content sample_big_commit.message page.should have_content "Too many changes" - end - - Given 'I visit huge commit page' do - visit project_commit_path(@project, BigCommits::HUGE_COMMIT_ID) - end - - Then 'I see huge commit message' do - page.should have_content BigCommits::HUGE_COMMIT_MESSAGE + Commit::DIFF_SAFE_FILES = 100 end Given 'I visit a commit with an image that changed' do - visit project_commit_path(@project, 'cc1ba255d6c5ffdce87a357ba7ccc397a4f4026b') + visit project_commit_path(@project, sample_image_commit.id) end Then 'The diff links to both the previous and current image' do links = page.all('.two-up span div a') - links[0]['href'].should =~ %r{blob/bc3735004cb45cec5e0e4fa92710897a910a5957} - links[1]['href'].should =~ %r{blob/cc1ba255d6c5ffdce87a357ba7ccc397a4f4026b} + links[0]['href'].should =~ %r{blob/#{sample_image_commit.old_blob_id}} + links[1]['href'].should =~ %r{blob/#{sample_image_commit.new_blob_id}} end Given 'I click side-by-side diff button' do @@ -93,5 +88,4 @@ class ProjectBrowseCommits < Spinach::FeatureSteps Then 'I see inline diff button' do page.should have_content "Inline Diff" end - end diff --git a/features/steps/project/browse_commits_user_lookup.rb b/features/steps/project/browse_commits_user_lookup.rb index 328be373553..198ea29f28d 100644 --- a/features/steps/project/browse_commits_user_lookup.rb +++ b/features/steps/project/browse_commits_user_lookup.rb @@ -2,34 +2,47 @@ class ProjectBrowseCommitsUserLookup < Spinach::FeatureSteps include SharedAuthentication include SharedProject include SharedPaths - - Given 'I have the user that authored the commits' do - @user = create(:user, email: 'dmitriy.zaporozhets@gmail.com') - create(:email, { user: @user, email: 'dzaporozhets@sphereconsultinginc.com' }) - end Given 'I click on commit link' do - visit project_commit_path(@project, ValidCommit::ID) + visit project_commit_path(@project, sample_commit.id) end Given 'I click on another commit link' do - visit project_commit_path(@project, ValidCommitWithAltEmail::ID) + visit project_commit_path(@project, sample_commit.parent_id) + end + + step 'I have user with primary email' do + user_primary + end + + step 'I have user with secondary email' do + user_secondary end - Then 'I see commit info' do - page.should have_content ValidCommit::MESSAGE - check_author_link(ValidCommit::AUTHOR_EMAIL) + step 'I see author based on primary email' do + check_author_link(sample_commit.author_email, user_primary) end - - Then 'I see other commit info' do - page.should have_content ValidCommitWithAltEmail::MESSAGE - check_author_link(ValidCommitWithAltEmail::AUTHOR_EMAIL) + + step 'I see author based on secondary email' do + check_author_link(sample_commit.author_email, user_secondary) end - def check_author_link(email) + def check_author_link(email, user) author_link = find('.commit-author-link') - author_link['href'].should == user_path(@user) + author_link['href'].should == user_path(user) author_link['data-original-title'].should == email - find('.commit-author-name').text.should == @user.name + find('.commit-author-name').text.should == user.name + end + + def user_primary + @user_primary ||= create(:user, email: 'dmitriy.zaporozhets@gmail.com') + end + + def user_secondary + @user_secondary ||= begin + user = create(:user, email: 'dzaporozhets@example.com') + create(:email, { user: user, email: 'dmitriy.zaporozhets@gmail.com' }) + user + end end end diff --git a/features/steps/project/browse_files.rb b/features/steps/project/browse_files.rb index 7134050da69..6fd0c2c2ded 100644 --- a/features/steps/project/browse_files.rb +++ b/features/steps/project/browse_files.rb @@ -2,26 +2,26 @@ class ProjectBrowseFiles < Spinach::FeatureSteps include SharedAuthentication include SharedProject include SharedPaths + include RepoHelpers step 'I should see files from repository' do - page.should have_content "app" - page.should have_content "history" - page.should have_content "Gemfile" + page.should have_content "VERSION" + page.should have_content ".gitignore" + page.should have_content "LICENSE" end - step 'I should see files from repository for "8470d70"' do - current_path.should == project_tree_path(@project, "8470d70") - page.should have_content "app" - page.should have_content "history" - page.should have_content "Gemfile" + step 'I should see files from repository for "6d39438"' do + current_path.should == project_tree_path(@project, "6d39438") + page.should have_content ".gitignore" + page.should have_content "LICENSE" end - step 'I click on "Gemfile.lock" file in repo' do - click_link "Gemfile.lock" + step 'I click on ".gitignore" file in repo' do + click_link ".gitignore" end step 'I should see it content' do - page.should have_content "DEPENDENCIES" + page.should have_content "*.rbc" end step 'I click link "raw"' do @@ -29,7 +29,7 @@ class ProjectBrowseFiles < Spinach::FeatureSteps end step 'I should see raw file content' do - page.source.should == ValidCommit::BLOB_FILE + page.source.should == sample_blob.data end step 'I click button "edit"' do @@ -63,8 +63,8 @@ class ProjectBrowseFiles < Spinach::FeatureSteps page.should have_content "Commit message" end - step 'I click on app directory' do - click_link 'app' + step 'I click on files directory' do + click_link 'files' end step 'I click on history link' do diff --git a/features/steps/project/browse_git_repo.rb b/features/steps/project/browse_git_repo.rb index cd9a60f49cb..2c3017dd4e2 100644 --- a/features/steps/project/browse_git_repo.rb +++ b/features/steps/project/browse_git_repo.rb @@ -3,8 +3,8 @@ class ProjectBrowseGitRepo < Spinach::FeatureSteps include SharedProject include SharedPaths - Given 'I click on "Gemfile.lock" file in repo' do - click_link "Gemfile.lock" + Given 'I click on ".gitignore" file in repo' do + click_link ".gitignore" end And 'I click blame button' do @@ -12,8 +12,8 @@ class ProjectBrowseGitRepo < Spinach::FeatureSteps end Then 'I should see git file blame' do - page.should have_content "DEPENDENCIES" + page.should have_content "*.rb" page.should have_content "Dmitriy Zaporozhets" - page.should have_content "Moving to rails 3.2" + page.should have_content "Initial commit" end end diff --git a/features/steps/project/browse_tags.rb b/features/steps/project/browse_tags.rb index 0cbfa0d80aa..7c679911e00 100644 --- a/features/steps/project/browse_tags.rb +++ b/features/steps/project/browse_tags.rb @@ -5,6 +5,6 @@ class ProjectBrowseTags < Spinach::FeatureSteps Then 'I should see "Shop" all tags list' do page.should have_content "Tags" - page.should have_content "v1.2.1" + page.should have_content "v1.0.0" end end diff --git a/features/steps/project/filter_labels.rb b/features/steps/project/filter_labels.rb index 5926d69d6c7..9b31a6d9da2 100644 --- a/features/steps/project/filter_labels.rb +++ b/features/steps/project/filter_labels.rb @@ -3,68 +3,77 @@ class ProjectFilterLabels < Spinach::FeatureSteps include SharedProject include SharedPaths - Then 'I should see "bug" in labels filter' do + step 'I should see "bug" in labels filter' do within ".labels-filter" do page.should have_content "bug" end end - And 'I should see "feature" in labels filter' do + step 'I should see "feature" in labels filter' do within ".labels-filter" do page.should have_content "feature" end end - And 'I should see "enhancement" in labels filter' do + step 'I should see "enhancement" in labels filter' do within ".labels-filter" do page.should have_content "enhancement" end end - Then 'I should see "Bugfix1" in issues list' do + step 'I should see "Bugfix1" in issues list' do within ".issues-list" do page.should have_content "Bugfix1" end end - And 'I should see "Bugfix2" in issues list' do + step 'I should see "Bugfix2" in issues list' do within ".issues-list" do page.should have_content "Bugfix2" end end - And 'I should not see "Bugfix2" in issues list' do + step 'I should not see "Bugfix2" in issues list' do within ".issues-list" do page.should_not have_content "Bugfix2" end end - And 'I should not see "Feature1" in issues list' do + step 'I should not see "Feature1" in issues list' do within ".issues-list" do page.should_not have_content "Feature1" end end - Given 'I click link "bug"' do - click_link "bug" + step 'I click link "bug"' do + within ".labels-filter" do + click_link "bug" + end end - Given 'I click link "feature"' do - click_link "feature" + step 'I click link "feature"' do + within ".labels-filter" do + click_link "feature" + end end - And 'project "Shop" has issue "Bugfix1" with tags: "bug", "feature"' do + step 'project "Shop" has issue "Bugfix1" with labels: "bug", "feature"' do project = Project.find_by(name: "Shop") - create(:issue, title: "Bugfix1", project: project, label_list: ['bug', 'feature']) + issue = create(:issue, title: "Bugfix1", project: project) + issue.labels << project.labels.find_by(title: 'bug') + issue.labels << project.labels.find_by(title: 'feature') end - And 'project "Shop" has issue "Bugfix2" with tags: "bug", "enhancement"' do + step 'project "Shop" has issue "Bugfix2" with labels: "bug", "enhancement"' do project = Project.find_by(name: "Shop") - create(:issue, title: "Bugfix2", project: project, label_list: ['bug', 'enhancement']) + issue = create(:issue, title: "Bugfix2", project: project) + issue.labels << project.labels.find_by(title: 'bug') + issue.labels << project.labels.find_by(title: 'enhancement') end - And 'project "Shop" has issue "Feature1" with tags: "feature"' do + step 'project "Shop" has issue "Feature1" with labels: "feature"' do project = Project.find_by(name: "Shop") - create(:issue, title: "Feature1", project: project, label_list: 'feature') + issue = create(:issue, title: "Feature1", project: project) + issue.labels << project.labels.find_by(title: 'feature') end end diff --git a/features/steps/project/fork.rb b/features/steps/project/fork.rb index c00d9014b1d..93ceaa0ebb1 100644 --- a/features/steps/project/fork.rb +++ b/features/steps/project/fork.rb @@ -6,31 +6,23 @@ class ForkProject < Spinach::FeatureSteps step 'I click link "Fork"' do page.should have_content "Shop" page.should have_content "Fork" - Gitlab::Shell.any_instance.stub(:fork_repository).and_return(true) click_link "Fork" end step 'I am a member of project "Shop"' do - @project = Project.find_by(name: "Shop") - @project ||= create(:project, name: "Shop", group: create(:group)) + @project = create(:project, name: "Shop") @project.team << [@user, :reporter] end step 'I should see the forked project page' do page.should have_content "Project was successfully forked." - current_path.should include current_user.namespace.path - @forked_project = Project.find_by(namespace_id: current_user.namespace.path) end step 'I already have a project named "Shop" in my namespace' do - current_user.namespace ||= create(:namespace) - current_user.namespace.should_not be_nil - current_user.namespace.path.should_not be_nil @my_project = create(:project, name: "Shop", namespace: current_user.namespace) end step 'I should see a "Name has already been taken" warning' do page.should have_content "Name has already been taken" end - end diff --git a/features/steps/project/forked_merge_requests.rb b/features/steps/project/forked_merge_requests.rb index 3c497638d9c..6ec527df13d 100644 --- a/features/steps/project/forked_merge_requests.rb +++ b/features/steps/project/forked_merge_requests.rb @@ -9,18 +9,11 @@ class ProjectForkedMergeRequests < Spinach::FeatureSteps @project = Project.find_by(name: "Shop") @project ||= create(:project, name: "Shop") @project.team << [@user, :reporter] + @project.ensure_satellite_exists end step 'I have a project forked off of "Shop" called "Forked Shop"' do - @forking_user = @user - forked_project_link = build(:forked_project_link) - @forked_project = Project.find_by(name: "Forked Shop") - @forked_project ||= create(:project, name: "Forked Shop", forked_project_link: forked_project_link, creator_id: @forking_user.id , namespace: @forking_user.namespace) - - forked_project_link.forked_from_project = @project - forked_project_link.forked_to_project = @forked_project - @forked_project.team << [@forking_user , :master] - forked_project_link.save! + @forked_project = Projects::ForkService.new(@project, @user).execute end step 'I click link "New Merge Request"' do @@ -33,8 +26,8 @@ class ProjectForkedMergeRequests < Spinach::FeatureSteps current_path.should == project_merge_request_path(@project, @merge_request) @merge_request.title.should == "Merge Request On Forked Project" @merge_request.source_project.should == @forked_project - @merge_request.source_branch.should == "master" - @merge_request.target_branch.should == "stable" + @merge_request.source_branch.should == "fix" + @merge_request.target_branch.should == "master" page.should have_content @forked_project.path_with_namespace page.should have_content @project.path_with_namespace page.should have_content @merge_request.source_branch @@ -42,17 +35,11 @@ class ProjectForkedMergeRequests < Spinach::FeatureSteps end step 'I fill out a "Merge Request On Forked Project" merge request' do - select2 @forked_project.id, from: "#merge_request_source_project_id" - select2 @project.id, from: "#merge_request_target_project_id" - - find(:select, "merge_request_source_project_id", {}).value.should == @forked_project.id.to_s - find(:select, "merge_request_target_project_id", {}).value.should == @project.id.to_s - - select2 "master", from: "#merge_request_source_branch" - select2 "stable", from: "#merge_request_target_branch" + select @forked_project.path_with_namespace, from: "merge_request_source_project_id" + select @project.path_with_namespace, from: "merge_request_target_project_id" + select "fix", from: "merge_request_source_branch" + select "master", from: "merge_request_target_branch" - find(:select, "merge_request_source_branch", {}).value.should == 'master' - find(:select, "merge_request_target_branch", {}).value.should == 'stable' click_button "Compare branches" fill_in "merge_request_title", with: "Merge Request On Forked Project" @@ -101,8 +88,8 @@ class ProjectForkedMergeRequests < Spinach::FeatureSteps @merge_request = @project.merge_requests.last current_path.should == project_merge_request_path(@project, @merge_request) @merge_request.source_project.should == @forked_project - @merge_request.source_branch.should == "master" - @merge_request.target_branch.should == "stable" + @merge_request.source_branch.should == "fix" + @merge_request.target_branch.should == "master" page.should have_content @forked_project.path_with_namespace page.should have_content @project.path_with_namespace page.should have_content @merge_request.source_branch @@ -114,33 +101,6 @@ class ProjectForkedMergeRequests < Spinach::FeatureSteps page.should have_link "Create Merge Request" end - step 'project "Forked Shop" has push event' do - @forked_project = Project.find_by(name: "Forked Shop") - - data = { - before: "0000000000000000000000000000000000000000", - after: "0220c11b9a3e6c69dc8fd35321254ca9a7b98f7e", - ref: "refs/heads/new_design", - user_id: @user.id, - user_name: @user.name, - repository: { - name: @forked_project.name, - url: "localhost/rubinius", - description: "", - homepage: "localhost/rubinius", - private: true - } - } - - @event = Event.create( - project: @forked_project, - action: Event::PUSHED, - data: data, - author_id: @user.id - ) - end - - step 'I click link edit "Merge Request On Forked Project"' do find("#edit_merge_request").click end diff --git a/features/steps/project/hooks.rb b/features/steps/project/hooks.rb index 19ff3244543..30da589260d 100644 --- a/features/steps/project/hooks.rb +++ b/features/steps/project/hooks.rb @@ -8,31 +8,45 @@ class ProjectHooks < Spinach::FeatureSteps include RSpec::Mocks::ExampleMethods include WebMock::API - Given 'project has hook' do + step 'project has hook' do @hook = create(:project_hook, project: current_project) end - Then 'I should see project hook' do + step 'I own empty project with hook' do + @project = create(:empty_project, + name: 'Empty Project', namespace: @user.namespace) + @hook = create(:project_hook, project: current_project) + end + + step 'I should see project hook' do page.should have_content @hook.url end - When 'I submit new hook' do + step 'I submit new hook' do @url = Faker::Internet.uri("http") fill_in "hook_url", with: @url expect { click_button "Add Web Hook" }.to change(ProjectHook, :count).by(1) end - Then 'I should see newly created hook' do + step 'I should see newly created hook' do page.current_path.should == project_hooks_path(current_project) page.should have_content(@url) end - When 'I click test hook button' do + step 'I click test hook button' do stub_request(:post, @hook.url).to_return(status: 200) click_link 'Test Hook' end - Then 'hook should be triggered' do + step 'hook should be triggered' do page.current_path.should == project_hooks_path(current_project) + page.should have_selector '.flash-notice', + text: 'Hook successfully executed.' + end + + step 'I should see hook error message' do + page.should have_selector '.flash-alert', + text: 'Hook execution failed. '\ + 'Ensure the project has commits.' end end diff --git a/features/steps/project/issues.rb b/features/steps/project/issues.rb index d0b4aa6e080..557ea2fdca8 100644 --- a/features/steps/project/issues.rb +++ b/features/steps/project/issues.rb @@ -50,10 +50,22 @@ class ProjectIssues < Spinach::FeatureSteps click_button "Submit new issue" end + step 'I submit new issue "500 error on profile" with label \'bug\'' do + fill_in "issue_title", with: "500 error on profile" + select 'bug', from: "Labels" + click_button "Submit new issue" + end + Given 'I click link "500 error on profile"' do click_link "500 error on profile" end + step 'I should see label \'bug\' with issue' do + within '.issue-show-labels' do + page.should have_content 'bug' + end + end + Then 'I should see issue "500 error on profile"' do issue = Issue.find_by(title: "500 error on profile") page.should have_content issue.title diff --git a/features/steps/project/labels.rb b/features/steps/project/labels.rb index 0907cdb526f..3d9aa29299c 100644 --- a/features/steps/project/labels.rb +++ b/features/steps/project/labels.rb @@ -3,22 +3,59 @@ class ProjectLabels < Spinach::FeatureSteps include SharedProject include SharedPaths - Then 'I should see label "bug"' do - within ".labels-table" do + step 'I should see label "bug"' do + within ".manage-labels-list" do page.should have_content "bug" end end - And 'I should see label "feature"' do - within ".labels-table" do + step 'I should see label "feature"' do + within ".manage-labels-list" do page.should have_content "feature" end end - And 'project "Shop" have issues tags: "bug", "feature"' do - project = Project.find_by(name: "Shop") - ['bug', 'feature'].each do |label| - create(:issue, project: project, label_list: label) + step 'I visit \'bug\' label edit page' do + visit edit_project_label_path(project, bug_label) + end + + step 'I remove label \'bug\'' do + within "#label_#{bug_label.id}" do + click_link 'Remove' end end + + step 'I submit new label \'support\'' do + fill_in 'Title', with: 'support' + fill_in 'Background Color', with: '#F95610' + click_button 'Save' + end + + step 'I should not see label \'bug\'' do + within '.manage-labels-list' do + page.should_not have_content 'bug' + end + end + + step 'I should see label \'support\'' do + within '.manage-labels-list' do + page.should have_content 'support' + end + end + + step 'I change label \'bug\' to \'fix\'' do + fill_in 'Title', with: 'fix' + fill_in 'Background Color', with: '#F15610' + click_button 'Save' + end + + step 'I should see label \'fix\'' do + within '.manage-labels-list' do + page.should have_content 'fix' + end + end + + def bug_label + project.labels.find_or_create_by(title: 'bug') + end end diff --git a/features/steps/project/markdown_render.rb b/features/steps/project/markdown_render.rb index c94de283069..1885649891e 100644 --- a/features/steps/project/markdown_render.rb +++ b/features/steps/project/markdown_render.rb @@ -12,11 +12,10 @@ class Spinach::Features::ProjectMarkdownRender < Spinach::FeatureSteps @project.team << [@user, :master] end - Then 'I should see files from repository in master' do - current_path.should == project_tree_path(@project, "master") - page.should have_content "Gemfile" - page.should have_content "app" - page.should have_content "README" + Then 'I should see files from repository in markdown' do + current_path.should == project_tree_path(@project, "markdown") + page.should have_content "README.md" + page.should have_content "CHANGELOG" end And 'I should see rendered README which contains correct links' do @@ -34,7 +33,7 @@ class Spinach::Features::ProjectMarkdownRender < Spinach::FeatureSteps end Then 'I should see correct document rendered' do - current_path.should == project_blob_path(@project, "master/doc/api/README.md") + current_path.should == project_blob_path(@project, "markdown/doc/api/README.md") page.should have_content "All API requests require authentication" end @@ -43,7 +42,7 @@ class Spinach::Features::ProjectMarkdownRender < Spinach::FeatureSteps end Then 'I should see correct directory rendered' do - current_path.should == project_tree_path(@project, "master/doc/raketasks") + current_path.should == project_tree_path(@project, "markdown/doc/raketasks") page.should have_content "backup_restore.md" page.should have_content "maintenance.md" end @@ -53,7 +52,7 @@ class Spinach::Features::ProjectMarkdownRender < Spinach::FeatureSteps end Then 'I should see correct doc/api directory rendered' do - current_path.should == project_tree_path(@project, "master/doc/api") + current_path.should == project_tree_path(@project, "markdown/doc/api") page.should have_content "README.md" page.should have_content "users.md" end @@ -63,7 +62,7 @@ class Spinach::Features::ProjectMarkdownRender < Spinach::FeatureSteps end Then 'I should see correct maintenance file rendered' do - current_path.should == project_blob_path(@project, "master/doc/raketasks/maintenance.md") + current_path.should == project_blob_path(@project, "markdown/doc/raketasks/maintenance.md") page.should have_content "bundle exec rake gitlab:env:info RAILS_ENV=production" end @@ -86,7 +85,7 @@ class Spinach::Features::ProjectMarkdownRender < Spinach::FeatureSteps end And 'I see correct file rendered' do - current_path.should == project_blob_path(@project, "master/doc/api/README.md") + current_path.should == project_blob_path(@project, "markdown/doc/api/README.md") page.should have_content "Contents" page.should have_link "Users" page.should have_link "Rake tasks" @@ -97,7 +96,7 @@ class Spinach::Features::ProjectMarkdownRender < Spinach::FeatureSteps end Then 'I should see the correct document file' do - current_path.should == project_blob_path(@project, "master/doc/api/users.md") + current_path.should == project_blob_path(@project, "markdown/doc/api/users.md") page.should have_content "Get a list of users." end @@ -125,9 +124,8 @@ class Spinach::Features::ProjectMarkdownRender < Spinach::FeatureSteps Then 'I should see files from repository in markdown branch' do current_path.should == project_tree_path(@project, "markdown") - page.should have_content "Gemfile" - page.should have_content "app" - page.should have_content "README" + page.should have_content "README.md" + page.should have_content "CHANGELOG" end And 'I see correct file rendered in markdown branch' do @@ -256,8 +254,8 @@ class Spinach::Features::ProjectMarkdownRender < Spinach::FeatureSteps end Given 'I go directory which contains README file' do - visit project_tree_path(@project, "master/doc/api") - current_path.should == project_tree_path(@project, "master/doc/api") + visit project_tree_path(@project, "markdown/doc/api") + current_path.should == project_tree_path(@project, "markdown/doc/api") end And 'I click on a relative link in README' do @@ -265,7 +263,7 @@ class Spinach::Features::ProjectMarkdownRender < Spinach::FeatureSteps end Then 'I should see the correct markdown' do - current_path.should == project_blob_path(@project, "master/doc/api/users.md") + current_path.should == project_blob_path(@project, "markdown/doc/api/users.md") page.should have_content "List users" end diff --git a/features/steps/project/merge_requests.rb b/features/steps/project/merge_requests.rb index b0a6e530e8a..f0007a039e4 100644 --- a/features/steps/project/merge_requests.rb +++ b/features/steps/project/merge_requests.rb @@ -61,8 +61,8 @@ class ProjectMergeRequests < Spinach::FeatureSteps end step 'I submit new merge request "Wiki Feature"' do - select "master", from: "merge_request_source_branch" - select "notes_refactoring", from: "merge_request_target_branch" + select "fix", from: "merge_request_source_branch" + select "feature", from: "merge_request_target_branch" click_button "Compare branches" fill_in "merge_request_title", with: "Wiki Feature" click_button "Submit merge request" @@ -73,7 +73,7 @@ class ProjectMergeRequests < Spinach::FeatureSteps title: "Bug NS-04", source_project: project, target_project: project, - source_branch: 'stable', + source_branch: 'fix', target_branch: 'master', author: project.users.first, description: "# Description header" @@ -104,9 +104,9 @@ class ProjectMergeRequests < Spinach::FeatureSteps visit project_merge_request_path(project, merge_request) end - step 'I click on the first commit in the merge request' do - within '.first-commits' do - click_link merge_request.commits.first.short_id(8) + step 'I click on the commit in the merge request' do + within '.mr-commits' do + click_link sample_commit.id[0..8] end end @@ -116,36 +116,35 @@ class ProjectMergeRequests < Spinach::FeatureSteps end step 'I leave a comment on the diff page in commit' do - find('a[data-line-code="4735dfc552ad7bf15ca468adc3cad9d05b624490_185_185"]').click + click_diff_line(sample_commit.line_code) leave_comment "One comment to rule them all" end - step 'I leave a comment like "Line is wrong" on line 185 of the first file' do + step 'I leave a comment like "Line is wrong" on diff' do init_diff_note leave_comment "Line is wrong" end - step 'I leave a comment like "Line is wrong" on line 185 of the first file in commit' do - find('a[data-line-code="4735dfc552ad7bf15ca468adc3cad9d05b624490_185_185"]').click + step 'I leave a comment like "Line is wrong" on diff in commit' do + click_diff_line(sample_commit.line_code) leave_comment "Line is wrong" end - step 'I should see a discussion has started on line 185' do + step 'I should see a discussion has started on diff' do page.should have_content "#{current_user.name} started a discussion" - page.should have_content "app/assets/stylesheets/tree.scss" + page.should have_content sample_commit.line_code_path page.should have_content "Line is wrong" end - step 'I should see a discussion has started on commit b1e6a9dbf1:L185' do + step 'I should see a discussion has started on commit diff' do page.should have_content "#{current_user.name} started a discussion on commit" - page.should have_content "app/assets/stylesheets/tree.scss" + page.should have_content sample_commit.line_code_path page.should have_content "Line is wrong" end - step 'I should see a discussion has started on commit b1e6a9dbf1' do + step 'I should see a discussion has started on commit' do page.should have_content "#{current_user.name} started a discussion on commit" page.should have_content "One comment to rule them all" - page.should have_content "app/assets/stylesheets/tree.scss" end step 'merge request is mergeable' do @@ -162,6 +161,10 @@ class ProjectMergeRequests < Spinach::FeatureSteps end step 'I accept this merge request' do + Gitlab::Satellite::MergeAction.any_instance.stub( + merge!: true, + ) + click_button "Accept Merge Request" end @@ -248,7 +251,7 @@ class ProjectMergeRequests < Spinach::FeatureSteps end def init_diff_note - find('a[data-line-code="4735dfc552ad7bf15ca468adc3cad9d05b624490_172_185"]').click + click_diff_line(sample_commit.line_code) end def leave_comment(message) @@ -261,14 +264,18 @@ class ProjectMergeRequests < Spinach::FeatureSteps end def init_diff_note_first_file - find('a[data-line-code="a5cc2925ca8258af241be7e5b0381edf30266302_12_12"]').click + click_diff_line(sample_compare.changes[0][:line_code]) end def init_diff_note_second_file - find('a[data-line-code="8ec9a00bfd09b3190ac6b22251dbb1aa95a0579d_28_39"]').click + click_diff_line(sample_compare.changes[1][:line_code]) end def have_visible_content (text) have_css("*", text: text, visible: true) end + + def click_diff_line(code) + find("a[data-line-code='#{code}']").click + end end diff --git a/features/steps/project/multiselect_blob.rb b/features/steps/project/multiselect_blob.rb index 28df7bc9312..d4dc1186970 100644 --- a/features/steps/project/multiselect_blob.rb +++ b/features/steps/project/multiselect_blob.rb @@ -52,7 +52,7 @@ class ProjectMultiselectBlob < Spinach::FeatureSteps page.evaluate_script("window.history.forward()") end - step 'I click on "Gemfile.lock" file in repo' do - click_link "Gemfile.lock" + step 'I click on ".gitignore" file in repo' do + click_link ".gitignore" end end diff --git a/features/steps/project/network_graph.rb b/features/steps/project/network_graph.rb index 1c5cfcc6c68..9f5da288914 100644 --- a/features/steps/project/network_graph.rb +++ b/features/steps/project/network_graph.rb @@ -19,8 +19,8 @@ class ProjectNetworkGraph < Spinach::FeatureSteps page.should have_selector '.select2-chosen', text: "master" end - And 'page should select "v2.1.0" in select box' do - page.should have_selector '.select2-chosen', text: "v2.1.0" + And 'page should select "v1.0.0" in select box' do + page.should have_selector '.select2-chosen', text: "v1.0.0" end And 'page should have "master" on graph' do @@ -29,13 +29,13 @@ class ProjectNetworkGraph < Spinach::FeatureSteps end end - When 'I switch ref to "stable"' do - page.select 'stable', from: 'ref' + When 'I switch ref to "feature"' do + page.select 'feature', from: 'ref' sleep 2 end - When 'I switch ref to "v2.1.0"' do - page.select 'v2.1.0', from: 'ref' + When 'I switch ref to "v1.0.0"' do + page.select 'v1.0.0', from: 'ref' sleep 2 end @@ -44,43 +44,43 @@ class ProjectNetworkGraph < Spinach::FeatureSteps sleep 2 end - Then 'page should have content not containing "v2.1.0"' do + Then 'page should have content not containing "v1.0.0"' do within '.network-graph' do - page.should have_content 'cleaning' + page.should have_content 'Change some files' end end - Then 'page should not have content not containing "v2.1.0"' do + Then 'page should not have content not containing "v1.0.0"' do within '.network-graph' do - page.should_not have_content 'cleaning' + page.should_not have_content 'Change some files' end end - And 'page should select "stable" in select box' do - page.should have_selector '.select2-chosen', text: "stable" + And 'page should select "feature" in select box' do + page.should have_selector '.select2-chosen', text: "feature" end - And 'page should select "v2.1.0" in select box' do - page.should have_selector '.select2-chosen', text: "v2.1.0" + And 'page should select "v1.0.0" in select box' do + page.should have_selector '.select2-chosen', text: "v1.0.0" end - And 'page should have "stable" on graph' do + And 'page should have "feature" on graph' do within '.network-graph' do - page.should have_content 'stable' + page.should have_content 'feature' end end - When 'I looking for a commit by SHA of "v2.1.0"' do + When 'I looking for a commit by SHA of "v1.0.0"' do within ".network-form" do - fill_in 'extended_sha1', with: '98d6492' + fill_in 'extended_sha1', with: '6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9' find('button').click end sleep 2 end - And 'page should have "v2.1.0" on graph' do + And 'page should have "v1.0.0" on graph' do within '.network-graph' do - page.should have_content 'v2.1.0' + page.should have_content 'v1.0.0' end end diff --git a/features/steps/project/project.rb b/features/steps/project/project.rb index b6968152aaf..2ffa1a62978 100644 --- a/features/steps/project/project.rb +++ b/features/steps/project/project.rb @@ -33,18 +33,16 @@ class ProjectFeature < Spinach::FeatureSteps step 'I should see project "Shop" version' do within '.project-side' do - page.should have_content "Version: 2.2.0" + page.should have_content "Version: 6.7.0.pre" end end step 'change project default branch' do - select 'stable', from: 'project_default_branch' + select 'fix', from: 'project_default_branch' + click_button 'Save changes' end step 'I should see project default branch changed' do - # TODO: Uncomment this when we can do real gitlab-shell calls - # from spinach tests. Right now gitlab-shell calls are stubbed so this test - # will not pass - # find(:css, 'select#project_default_branch').value.should == 'stable' + find(:css, 'select#project_default_branch').value.should == 'fix' end end diff --git a/features/steps/project/search_code.rb b/features/steps/project/search_code.rb index d117b019a15..8d130a8ed0d 100644 --- a/features/steps/project/search_code.rb +++ b/features/steps/project/search_code.rb @@ -3,15 +3,14 @@ class ProjectSearchCode < Spinach::FeatureSteps include SharedProject include SharedPaths - When 'I search for term "Welcome to GitLab"' do - fill_in "search", with: "Welcome to GitLab" + When 'I search for term "coffee"' do + fill_in "search", with: "coffee" click_button "Go" click_link 'Repository Code' end - Then 'I should see files from repository containing "Welcome to GitLab"' do - page.should have_content "Welcome to GitLab" - page.should have_content "GitLab is a free project and repository management application" + Then 'I should see files from repository containing "coffee"' do + page.should have_content "coffee" + page.should have_content " CONTRIBUTING.md" end - end diff --git a/features/steps/shared/diff_note.rb b/features/steps/shared/diff_note.rb index 201642a086e..b107b083220 100644 --- a/features/steps/shared/diff_note.rb +++ b/features/steps/shared/diff_note.rb @@ -1,5 +1,6 @@ module SharedDiffNote include Spinach::DSL + include RepoHelpers Given 'I cancel the diff comment' do within(diff_file_selector) do @@ -19,8 +20,8 @@ module SharedDiffNote end Given 'I leave a diff comment like "Typo, please fix"' do - find('a[data-line-code="586fb7c4e1add2d4d24e27566ed7064680098646_29_14"]').click - within("#{diff_file_selector} form[rel$='586fb7c4e1add2d4d24e27566ed7064680098646_29_14']") do + click_diff_line(sample_commit.line_code) + within("#{diff_file_selector} form[rel$='#{sample_commit.line_code}']") do fill_in "note[note]", with: "Typo, please fix" find(".js-comment-button").trigger("click") sleep 0.05 @@ -28,28 +29,28 @@ module SharedDiffNote end Given 'I preview a diff comment text like "Should fix it :smile:"' do - find('a[data-line-code="586fb7c4e1add2d4d24e27566ed7064680098646_29_14"]').click - within("#{diff_file_selector} form[rel$='586fb7c4e1add2d4d24e27566ed7064680098646_29_14']") do + click_diff_line(sample_commit.line_code) + within("#{diff_file_selector} form[rel$='#{sample_commit.line_code}']") do fill_in "note[note]", with: "Should fix it :smile:" find(".js-note-preview-button").trigger("click") end end Given 'I preview another diff comment text like "DRY this up"' do - find('a[data-line-code="586fb7c4e1add2d4d24e27566ed7064680098646_57_41"]').click + click_diff_line(sample_commit.del_line_code) - within("#{diff_file_selector} form[rel$='586fb7c4e1add2d4d24e27566ed7064680098646_57_41']") do + within("#{diff_file_selector} form[rel$='#{sample_commit.del_line_code}']") do fill_in "note[note]", with: "DRY this up" find(".js-note-preview-button").trigger("click") end end Given 'I open a diff comment form' do - find('a[data-line-code="586fb7c4e1add2d4d24e27566ed7064680098646_29_14"]').click + click_diff_line(sample_commit.line_code) end Given 'I open another diff comment form' do - find('a[data-line-code="586fb7c4e1add2d4d24e27566ed7064680098646_57_41"]').click + click_diff_line(sample_commit.del_line_code) end Given 'I write a diff comment like ":-1: I don\'t like this"' do @@ -155,6 +156,10 @@ module SharedDiffNote end def diff_file_selector - ".diff-file" + ".diff-file:nth-of-type(1)" + end + + def click_diff_line(code) + find("a[data-line-code='#{code}']").click end end diff --git a/features/steps/shared/paths.rb b/features/steps/shared/paths.rb index ab1ae31ed74..4e97dba20b3 100644 --- a/features/steps/shared/paths.rb +++ b/features/steps/shared/paths.rb @@ -1,5 +1,6 @@ module SharedPaths include Spinach::DSL + include RepoHelpers step 'I visit new project page' do visit new_project_path @@ -257,15 +258,15 @@ module SharedPaths end step 'I visit blob file from repo' do - visit project_blob_path(@project, File.join(ValidCommit::ID, ValidCommit::BLOB_FILE_PATH)) + visit project_blob_path(@project, File.join(sample_commit.id, sample_blob.path)) end - step 'I visit "Gemfile.lock" file in repo' do - visit project_blob_path(@project, File.join(root_ref, 'Gemfile.lock')) + step 'I visit ".gitignore" file in repo' do + visit project_blob_path(@project, File.join(root_ref, '.gitignore')) end - step 'I visit project source page for "8470d70"' do - visit project_tree_path(@project, "8470d70") + step 'I visit project source page for "6d39438"' do + visit project_tree_path(@project, "6d39438") end step 'I visit project tags page' do @@ -273,7 +274,7 @@ module SharedPaths end step 'I visit project commit page' do - visit project_commit_path(@project, ValidCommit::ID) + visit project_commit_path(@project, sample_commit.id) end step 'I visit project "Shop" issues page' do @@ -289,6 +290,10 @@ module SharedPaths visit project_labels_path(project) end + step 'I visit new label page' do + visit new_project_label_path(project) + end + step 'I visit merge request page "Bug NS-04"' do mr = MergeRequest.find_by(title: "Bug NS-04") visit project_merge_request_path(mr.target_project, mr) diff --git a/features/steps/shared/project.rb b/features/steps/shared/project.rb index 1d894b33fbd..655840f447d 100644 --- a/features/steps/shared/project.rb +++ b/features/steps/shared/project.rb @@ -26,8 +26,8 @@ module SharedProject data = { before: "0000000000000000000000000000000000000000", - after: "0220c11b9a3e6c69dc8fd35321254ca9a7b98f7e", - ref: "refs/heads/new_design", + after: "6d394385cf567f80a8fd85055db1ab4c5295806f", + ref: "refs/heads/fix", user_id: @user.id, user_name: @user.name, repository: { @@ -49,7 +49,7 @@ module SharedProject Then 'I should see project "Shop" activity feed' do project = Project.find_by(name: "Shop") - page.should have_content "#{@user.name} pushed new branch new_design at #{project.name_with_namespace}" + page.should have_content "#{@user.name} pushed new branch fix at #{project.name_with_namespace}" end Then 'I should see project settings' do @@ -123,10 +123,6 @@ module SharedProject project.team << [user, :master] end - # ---------------------------------------- - # Empty projects - # ---------------------------------------- - step 'public empty project "Empty Public Project"' do create :empty_project, :public, name: "Empty Public Project" end @@ -135,4 +131,11 @@ module SharedProject project = Project.find_by(name: "Community") 2.times { create(:note_on_issue, project: project) } end + + step 'project "Shop" has labels: "bug", "feature", "enhancement"' do + project = Project.find_by(name: "Shop") + create(:label, project: project, title: 'bug') + create(:label, project: project, title: 'feature') + create(:label, project: project, title: 'enhancement') + end end diff --git a/features/support/env.rb b/features/support/env.rb index 3ab2ce0a3e6..22f28987fe3 100644 --- a/features/support/env.rb +++ b/features/support/env.rb @@ -15,7 +15,7 @@ require 'spinach/capybara' require 'sidekiq/testing/inline' -%w(valid_commit valid_commit_with_alt_email big_commits select2_helper test_env).each do |f| +%w(select2_helper test_env repo_helpers).each do |f| require Rails.root.join('spec', 'support', f) end @@ -39,7 +39,6 @@ Capybara.ignore_hidden_elements = false DatabaseCleaner.strategy = :truncation Spinach.hooks.before_scenario do - TestEnv.setup_stubs DatabaseCleaner.start end @@ -48,7 +47,7 @@ Spinach.hooks.after_scenario do end Spinach.hooks.before_run do - TestEnv.init(mailer: false, init_repos: true, repos: false) + TestEnv.init(mailer: false) RSpec::Mocks::setup self include FactoryGirl::Syntax::Methods diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 09fb97abf29..42715d2be3b 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -126,7 +126,7 @@ module API end class Issue < ProjectEntity - expose :label_list, as: :labels + expose :label_names, as: :labels expose :milestone, using: Entities::Milestone expose :assignee, :author, using: Entities::UserBasic end @@ -135,7 +135,7 @@ module API expose :target_branch, :source_branch, :upvotes, :downvotes expose :author, :assignee, using: Entities::UserBasic expose :source_project_id, :target_project_id - expose :label_list, as: :labels + expose :label_names, as: :labels end class SSHKey < Grape::Entity @@ -201,13 +201,13 @@ module API class Compare < Grape::Entity expose :commit, using: Entities::RepoCommit do |compare, options| - if compare.commit - Commit.new compare.commit - end + Commit.decorate(compare.commits).last end + expose :commits, using: Entities::RepoCommit do |compare, options| - Commit.decorate compare.commits + Commit.decorate(compare.commits) end + expose :diffs, using: Entities::RepoDiff do |compare, options| compare.diffs end diff --git a/lib/api/issues.rb b/lib/api/issues.rb index f50be3a815d..b29118b2fd8 100644 --- a/lib/api/issues.rb +++ b/lib/api/issues.rb @@ -50,10 +50,15 @@ module API post ":id/issues" do required_attributes! [:title] attrs = attributes_for_keys [:title, :description, :assignee_id, :milestone_id] - attrs[:label_list] = params[:labels] if params[:labels].present? + issue = ::Issues::CreateService.new(user_project, current_user, attrs).execute if issue.valid? + # Find or create labels and attach to issue + if params[:labels].present? + issue.add_labels_by_names(params[:labels].split(",")) + end + present issue, with: Entities::Issue else not_found! @@ -76,13 +81,16 @@ module API put ":id/issues/:issue_id" do issue = user_project.issues.find(params[:issue_id]) authorize! :modify_issue, issue - attrs = attributes_for_keys [:title, :description, :assignee_id, :milestone_id, :state_event] - attrs[:label_list] = params[:labels] if params[:labels].present? issue = ::Issues::UpdateService.new(user_project, current_user, attrs).execute(issue) if issue.valid? + # Find or create labels and attach to issue + if params[:labels].present? + issue.add_labels_by_names(params[:labels].split(",")) + end + present issue, with: Entities::Issue else not_found! diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb index fc1f1254a9e..acca7cb6bad 100644 --- a/lib/api/merge_requests.rb +++ b/lib/api/merge_requests.rb @@ -76,10 +76,14 @@ module API authorize! :write_merge_request, user_project required_attributes! [:source_branch, :target_branch, :title] attrs = attributes_for_keys [:source_branch, :target_branch, :assignee_id, :title, :target_project_id, :description] - attrs[:label_list] = params[:labels] if params[:labels].present? merge_request = ::MergeRequests::CreateService.new(user_project, current_user, attrs).execute if merge_request.valid? + # Find or create labels and attach to issue + if params[:labels].present? + merge_request.add_labels_by_names(params[:labels].split(",")) + end + present merge_request, with: Entities::MergeRequest else handle_merge_request_errors! merge_request.errors @@ -103,12 +107,16 @@ module API # put ":id/merge_request/:merge_request_id" do attrs = attributes_for_keys [:source_branch, :target_branch, :assignee_id, :title, :state_event, :description] - attrs[:label_list] = params[:labels] if params[:labels].present? merge_request = user_project.merge_requests.find(params[:merge_request_id]) authorize! :modify_merge_request, merge_request merge_request = ::MergeRequests::UpdateService.new(user_project, current_user, attrs).execute(merge_request) if merge_request.valid? + # Find or create labels and attach to issue + if params[:labels].present? + merge_request.add_labels_by_names(params[:labels].split(",")) + end + present merge_request, with: Entities::MergeRequest else handle_merge_request_errors! merge_request.errors diff --git a/lib/api/projects.rb b/lib/api/projects.rb index 27869e49f71..4c0766482f3 100644 --- a/lib/api/projects.rb +++ b/lib/api/projects.rb @@ -230,7 +230,7 @@ module API # Example Request: # GET /projects/:id/labels get ':id/labels' do - @labels = user_project.issues_labels + @labels = user_project.labels present @labels, with: Entities::Label end end diff --git a/lib/api/repositories.rb b/lib/api/repositories.rb index d091fa4f035..461ce4e59cf 100644 --- a/lib/api/repositories.rb +++ b/lib/api/repositories.rb @@ -147,7 +147,7 @@ module API 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) + compare = Gitlab::Git::Compare.new(user_project.repository.raw_repository, params[:from], params[:to]) present compare, with: Entities::Compare end diff --git a/lib/gitlab/compare_result.rb b/lib/gitlab/compare_result.rb new file mode 100644 index 00000000000..d72391dade5 --- /dev/null +++ b/lib/gitlab/compare_result.rb @@ -0,0 +1,9 @@ +module Gitlab + class CompareResult + attr_reader :commits, :diffs + + def initialize(compare) + @commits, @diffs = compare.commits, compare.diffs + end + end +end diff --git a/lib/gitlab/issues_labels.rb b/lib/gitlab/issues_labels.rb index bc49d27b521..0d34976736f 100644 --- a/lib/gitlab/issues_labels.rb +++ b/lib/gitlab/issues_labels.rb @@ -1,27 +1,27 @@ module Gitlab class IssuesLabels class << self - def important_labels - %w(bug critical confirmed) - end - - def warning_labels - %w(documentation support) - end - - def neutral_labels - %w(discussion suggestion) - end - - def positive_labels - %w(feature enhancement) - end - def generate(project) - labels = important_labels + warning_labels + neutral_labels + positive_labels + red = '#d9534f' + yellow = '#f0ad4e' + blue = '#428bca' + green = '#5cb85c' + + labels = [ + { title: "bug", color: red }, + { title: "critical", color: red }, + { title: "confirmed", color: red }, + { title: "documentation", color: yellow }, + { title: "support", color: yellow }, + { title: "discussion", color: blue }, + { title: "suggestion", color: blue }, + { title: "feature", color: green }, + { title: "enhancement", color: green } + ] - project.issues_default_label_list = labels - project.save + labels.each do |label| + project.labels.create(label) + end end end end diff --git a/lib/gitlab/satellite/compare_action.rb b/lib/gitlab/satellite/compare_action.rb index 9c9e69e3515..46c98a8f4ca 100644 --- a/lib/gitlab/satellite/compare_action.rb +++ b/lib/gitlab/satellite/compare_action.rb @@ -10,34 +10,16 @@ module Gitlab @source_project, @source_branch = source_project, source_branch end - # Only show what is new in the source branch compared to the target branch, not the other way around. - # The line below with merge_base is equivalent to diff with three dots (git diff branch1...branch2) - # From the git documentation: "git diff A...B" is equivalent to "git diff $(git-merge-base A B) B" - def diffs + # Compare 2 repositories and return Gitlab::CompareResult object + def result in_locked_and_timed_satellite do |target_repo| prepare_satellite!(target_repo) update_satellite_source_and_target!(target_repo) - common_commit = target_repo.git.native(:merge_base, default_options, ["origin/#{@target_branch}", "source/#{@source_branch}"]).strip - #this method doesn't take default options - diffs = target_repo.diff(common_commit, "source/#{@source_branch}") - diffs = diffs.map { |diff| Gitlab::Git::Diff.new(diff) } - diffs - end - rescue Grit::Git::CommandFailed => ex - raise BranchesWithoutParent - end - # Retrieve an array of commits between the source and the target - def commits - in_locked_and_timed_satellite do |target_repo| - prepare_satellite!(target_repo) - update_satellite_source_and_target!(target_repo) - commits = target_repo.commits_between("origin/#{@target_branch}", "source/#{@source_branch}") - commits = commits.map { |commit| Gitlab::Git::Commit.new(commit, nil) } - commits + Gitlab::CompareResult.new(compare(target_repo)) end rescue Grit::Git::CommandFailed => ex - handle_exception(ex) + raise BranchesWithoutParent end private @@ -46,10 +28,17 @@ module Gitlab def update_satellite_source_and_target!(target_repo) target_repo.remote_add('source', @source_project.repository.path_to_repo) target_repo.remote_fetch('source') - target_repo.git.checkout(default_options({b: true}), @target_branch, "origin/#{@target_branch}") rescue Grit::Git::CommandFailed => ex handle_exception(ex) end + + def compare(repo) + @compare ||= Gitlab::Git::Compare.new( + Gitlab::Git::Repository.new(repo.path), + "origin/#{@target_branch}", + "source/#{@source_branch}" + ) + end end end end diff --git a/lib/gitlab/satellite/merge_action.rb b/lib/gitlab/satellite/merge_action.rb index 6c32dfb3ad9..7c9b2294647 100644 --- a/lib/gitlab/satellite/merge_action.rb +++ b/lib/gitlab/satellite/merge_action.rb @@ -45,27 +45,30 @@ module Gitlab handle_exception(ex) end - # Get a raw diff of the source to the target def diff_in_satellite in_locked_and_timed_satellite do |merge_repo| prepare_satellite!(merge_repo) update_satellite_source_and_target!(merge_repo) - diff = merge_repo.git.native(:diff, default_options, "origin/#{merge_request.target_branch}", "source/#{merge_request.source_branch}") + + # Only show what is new in the source branch compared to the target branch, not the other way around. + # The line below with merge_base is equivalent to diff with three dots (git diff branch1...branch2) + # From the git documentation: "git diff A...B" is equivalent to "git diff $(git-merge-base A B) B" + common_commit = merge_repo.git.native(:merge_base, default_options, ["origin/#{merge_request.target_branch}", "source/#{merge_request.source_branch}"]).strip + merge_repo.git.native(:diff, default_options, common_commit, "source/#{merge_request.source_branch}") end rescue Grit::Git::CommandFailed => ex handle_exception(ex) end - # Only show what is new in the source branch compared to the target branch, not the other way around. - # The line below with merge_base is equivalent to diff with three dots (git diff branch1...branch2) - # From the git documentation: "git diff A...B" is equivalent to "git diff $(git-merge-base A B) B" def diffs_between_satellite in_locked_and_timed_satellite do |merge_repo| prepare_satellite!(merge_repo) update_satellite_source_and_target!(merge_repo) if merge_request.for_fork? + # Only show what is new in the source branch compared to the target branch, not the other way around. + # The line below with merge_base is equivalent to diff with three dots (git diff branch1...branch2) + # From the git documentation: "git diff A...B" is equivalent to "git diff $(git-merge-base A B) B" common_commit = merge_repo.git.native(:merge_base, default_options, ["origin/#{merge_request.target_branch}", "source/#{merge_request.source_branch}"]).strip - #this method doesn't take default options diffs = merge_repo.diff(common_commit, "source/#{merge_request.source_branch}") else raise "Attempt to determine diffs between for a non forked merge request in satellite MergeRequest.id:[#{merge_request.id}]" diff --git a/lib/gitlab/sidekiq_middleware/arguments_logger.rb b/lib/gitlab/sidekiq_middleware/arguments_logger.rb new file mode 100644 index 00000000000..7813091ec7b --- /dev/null +++ b/lib/gitlab/sidekiq_middleware/arguments_logger.rb @@ -0,0 +1,10 @@ +module Gitlab + module SidekiqMiddleware + class ArgumentsLogger + def call(worker, job, queue) + Sidekiq.logger.info "arguments: #{job['args']}" + yield + end + end + end +end diff --git a/lib/support/nginx/gitlab b/lib/support/nginx/gitlab index 36306eeb3a6..49306fb63da 100644 --- a/lib/support/nginx/gitlab +++ b/lib/support/nginx/gitlab @@ -20,9 +20,9 @@ upstream gitlab { } server { - listen *:80 default_server; # e.g., listen 192.168.1.1:80; In most cases *:80 is a good idea - server_name YOUR_SERVER_FQDN; # e.g., server_name source.example.com; - server_tokens off; # don't show the version number, a security best practice + listen *:80 default_server; + server_name YOUR_SERVER_FQDN; ## Replace this with something like gitlab.example.com + server_tokens off; ## Don't show the nginx version number, a security best practice root /home/git/gitlab/public; # Increase this if you want to upload large attachments diff --git a/lib/support/nginx/gitlab-ssl b/lib/support/nginx/gitlab-ssl index 22e923b377c..54a4a080a9f 100644 --- a/lib/support/nginx/gitlab-ssl +++ b/lib/support/nginx/gitlab-ssl @@ -3,33 +3,11 @@ ## ## Modified from nginx http version ## Modified from http://blog.phusion.nl/2012/04/21/tutorial-setting-up-gitlab-on-debian-6/ +## Modified from https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html ## -## 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" +## Lines starting with two hashes (##) are comments with information. +## Lines starting with one hash (#) are configuration parameters. +## The last category can be commented/uncommented to your liking. ## ################################## ## CHUNKED TRANSFER ## @@ -48,33 +26,41 @@ ## [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 - +## +################################### +## SSL file editing ## +################################### +## +## 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" +## +################################### +## SSL configuration ## +################################### +## 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; + listen *:80 default_server; + server_name YOUR_SERVER_FQDN; ## Replace this with something like gitlab.example.com + server_tokens off; ## Don't show the nginx version number, a security best practice + root /nowhere; ## root doesn't have to be a valid path since we are redirecting rewrite ^ https://$server_name$request_uri permanent; } server { listen 443 ssl; - ## Replace git.example.com with your FQDN. - server_name git.example.com; + server_name YOUR_SERVER_FQDN; ## Replace this with something like gitlab.example.com server_tokens off; root /home/git/gitlab/public; @@ -93,22 +79,7 @@ server { 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; diff --git a/lib/tasks/gitlab/shell.rake b/lib/tasks/gitlab/shell.rake index dfc90bb3339..ff27e6a3066 100644 --- a/lib/tasks/gitlab/shell.rake +++ b/lib/tasks/gitlab/shell.rake @@ -4,7 +4,8 @@ namespace :gitlab do task :install, [:tag, :repo] => :environment do |t, args| warn_user_is_not_gitlab - args.with_defaults(tag: "v1.9.3", repo: "https://gitlab.com/gitlab-org/gitlab-shell.git") + default_version = File.read(File.join(Rails.root, "GITLAB_SHELL_VERSION")).strip + args.with_defaults(tag: 'v' + default_version, repo: "https://gitlab.com/gitlab-org/gitlab-shell.git") user = Settings.gitlab.user home_dir = Settings.gitlab.user_home diff --git a/spec/controllers/blob_controller_spec.rb b/spec/controllers/blob_controller_spec.rb index 929f6d3b46d..11d748ca77f 100644 --- a/spec/controllers/blob_controller_spec.rb +++ b/spec/controllers/blob_controller_spec.rb @@ -44,8 +44,8 @@ describe Projects::BlobController do end context 'redirect to tree' do - let(:id) { 'master/doc' } - it { should redirect_to("/#{project.path_with_namespace}/tree/master/doc") } + let(:id) { 'markdown/doc' } + it { should redirect_to("/#{project.path_with_namespace}/tree/markdown/doc") } end end end diff --git a/spec/controllers/merge_requests_controller_spec.rb b/spec/controllers/merge_requests_controller_spec.rb index 1502bded97f..300527e4ff2 100644 --- a/spec/controllers/merge_requests_controller_spec.rb +++ b/spec/controllers/merge_requests_controller_spec.rb @@ -3,12 +3,11 @@ require 'spec_helper' describe Projects::MergeRequestsController do let(:project) { create(:project) } let(:user) { create(:user) } - let(:merge_request) { create(:merge_request_with_diffs, target_project: project, source_project: project, target_branch: "stable", source_branch: "master") } + let(:merge_request) { create(:merge_request_with_diffs, target_project: project, source_project: project) } before do sign_in(user) project.team << [user, :master] - Projects::MergeRequestsController.any_instance.stub(validates_merge_request: true, ) end describe "#show" do @@ -61,7 +60,7 @@ describe Projects::MergeRequestsController do it "should really be a git email patch with commit" do get :show, project_id: project.to_param, id: merge_request.iid, format: format - expect(response.body[0..100]).to start_with("From 6ea87c47f0f8a24ae031c3fff17bc913889ecd00") + expect(response.body[0..100]).to start_with("From #{merge_request.commits.last.id}") end it "should contain git diffs" do diff --git a/spec/controllers/tree_controller_spec.rb b/spec/controllers/tree_controller_spec.rb index b169c2a678f..8147fb0e6fb 100644 --- a/spec/controllers/tree_controller_spec.rb +++ b/spec/controllers/tree_controller_spec.rb @@ -26,7 +26,7 @@ describe Projects::TreeController do end context "valid branch, valid path" do - let(:id) { 'master/app/' } + let(:id) { 'master/encoding/' } it { should respond_with(:success) } end @@ -36,7 +36,7 @@ describe Projects::TreeController do end context "invalid branch, valid path" do - let(:id) { 'invalid-branch/app/' } + let(:id) { 'invalid-branch/encoding/' } it { should respond_with(:not_found) } end end diff --git a/spec/factories.rb b/spec/factories.rb index ad4c56986c3..03c87fcc6c5 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -27,51 +27,6 @@ FactoryGirl.define do factory :admin, traits: [:admin] end - factory :empty_project, class: 'Project' do - sequence(:name) { |n| "project#{n}" } - path { name.downcase.gsub(/\s/, '_') } - namespace - creator - snippets_enabled true - - trait :public do - visibility_level Gitlab::VisibilityLevel::PUBLIC - end - - trait :internal do - visibility_level Gitlab::VisibilityLevel::INTERNAL - end - - trait :private do - visibility_level Gitlab::VisibilityLevel::PRIVATE - end - end - - # Generates a test repository from the repository stored under `spec/seed_project.tar.gz`. - # Once you run `rake gitlab:setup`, you can see what the repository looks like under `tmp/repositories/gitlabhq`. - # In order to modify files in the repository, you must untar the seed, modify and remake the tar. - # Before recompressing, do not forget to `git checkout master`. - # After recompressing, you need to run `RAILS_ENV=test bundle exec rake gitlab:setup` to regenerate the seeds under tmp. - # - # If you want to modify the repository only for an specific type of tests, e.g., markdown tests, - # consider using a feature branch to reduce the chances of collision with other tests. - # Create a new commit, and use the same commit message that you will use for the change in the main repo. - # Changing the commig message and SHA of branch `master` may break tests. - factory :project, parent: :empty_project do - path { 'gitlabhq' } - - after :create do |project| - TestEnv.clear_repo_dir(project.namespace, project.path) - TestEnv.reset_satellite_dir - TestEnv.create_repo(project.namespace, project.path) - end - end - - factory :redmine_project, parent: :project do - issues_tracker { "redmine" } - issues_tracker_id { "project_name_in_redmine" } - end - factory :group do sequence(:name) { |n| "group#{n}" } path { name.downcase.gsub(/\s/, '_') } @@ -107,105 +62,6 @@ FactoryGirl.define do factory :reopened_issue, traits: [:reopened] end - factory :merge_request do - title - author - source_project factory: :project - target_project { source_project } - - # → git log stable..master --pretty=oneline - # b1e6a9dbf1c85e6616497a5e7bad9143a4bd0828 tree css fixes - # 8716fc78f3c65bbf7bcf7b574febd583bc5d2812 Added loading animation for notes - # cd5c4bac5042c5469dcdf7e7b2f768d3c6fd7088 notes count for wall - # 8470d70da67355c9c009e4401746b1d5410af2e3 notes controller refactored - # 1e689bfba39525ead225eaf611948cfbe8ac34cf fixed notes logic - # f0f14c8eaba69ebddd766498a9d0b0e79becd633 finished scss refactoring - # 3a4b4fb4cde7809f033822a171b9feae19d41fff Moving ui styles to one scss file, Added ui class to body - # 065c200c33f68c2bb781e35a43f9dc8138a893b5 removed unnecessary hr tags & titles - # 1e8b111be85df0db6c8000ef9a710bc0221eae83 Merge branch 'master' of github.com:gitlabhq/gitlabhq - # f403da73f5e62794a0447aca879360494b08f678 Fixed ajax loading image. Fixed wrong wording - # e6ea73c77600d413d370249b8e392734f7d1dbee Merge pull request #468 from bencevans/patch-1 - # 4a3c05b69355deee25767a74d0512ec4b510d4ef Merge pull request #470 from bgondy/patch-1 - # 0347fe2412eb51d3efeccc35210e9268bc765ac5 Update app/views/projects/team.html.haml - # 2b5c61bdece1f7eb2b901ceea7d364065cdf76ac Title for a link fixed - # 460eeb13b7560b40104044973ff933b1a6dbbcaa Increased count of notes loaded when visit wall page - # 21c141afb1c53a9180a99d2cca29ffa613eb7e3a Merge branch 'notes_refactoring' - # 292a41cbe295f16f7148913b31eb0fb91f3251c3 Fixed comments for snippets. Tests fixed - # d41d8ffb02fa74fd4571603548bd7e401ec99e0c Reply button, Comments for Merge Request diff - # b1a36b552be2a7a6bc57fbed6c52dc6ed82111f8 Merge pull request #466 from skroutz/no-rbenv - # db75dae913e8365453ca231f101b067314a7ea71 Merge pull request #465 from skroutz/branches_commit_link - # 75f040fbfe4b5af23ff004ad3207c3976df097a8 Don't enforce rbenv version - # e42fb4fda475370dcb0d8f8f1268bfdc7a0cc437 Fix broken commit link in branches page - # 215a01f63ccdc085f75a48f6f7ab6f2b15b5852c move notes login to one controller - # 81092c01984a481e312de10a28e3f1a6dda182a3 Status codes for errors, New error pages - # 7d279f9302151e3c8f4c5df9c5200a72799409b9 better error handling for not found resource, gitolite error - # 9e6d0710e927aa8ea834b8a9ae9f277be617ac7d Merge pull request #443 from CedricGatay/fix/incorrectLineNumberingInDiff - # 6ea87c47f0f8a24ae031c3fff17bc913889ecd00 Incorrect line numbering in diff - # - # → git log master..stable --pretty=oneline - # empty - - source_branch "master" - target_branch "stable" - - trait :with_diffs do - end - - trait :closed do - state :closed - end - - trait :reopened do - state :reopened - end - - trait :simple do - source_branch "simple_merge_request" - target_branch "master" - end - - factory :closed_merge_request, traits: [:closed] - factory :reopened_merge_request, traits: [:reopened] - factory :merge_request_with_diffs, traits: [:with_diffs] - end - - factory :note do - project - note "Note" - author - - factory :note_on_commit, traits: [:on_commit] - factory :note_on_commit_diff, traits: [:on_commit, :on_diff] - factory :note_on_issue, traits: [:on_issue], aliases: [:votable_note] - factory :note_on_merge_request, traits: [:on_merge_request] - factory :note_on_merge_request_diff, traits: [:on_merge_request, :on_diff] - - trait :on_commit do - project factory: :project - commit_id "bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a" - noteable_type "Commit" - end - - trait :on_diff do - line_code "0_184_184" - end - - trait :on_merge_request do - project factory: :project - noteable_id 1 - noteable_type "MergeRequest" - end - - trait :on_issue do - noteable_id 1 - noteable_type "Issue" - end - - trait :with_attachment do - attachment { fixture_file_upload(Rails.root + "spec/fixtures/dk.png", "`/png") } - end - end - factory :event do factory :closed_issue_event do project diff --git a/spec/factories/label_links.rb b/spec/factories/label_links.rb new file mode 100644 index 00000000000..d6b6f8581f6 --- /dev/null +++ b/spec/factories/label_links.rb @@ -0,0 +1,8 @@ +# Read about factories at https://github.com/thoughtbot/factory_girl + +FactoryGirl.define do + factory :label_link do + label + target factory: :issue + end +end diff --git a/spec/factories/labels.rb b/spec/factories/labels.rb new file mode 100644 index 00000000000..af9f3efa641 --- /dev/null +++ b/spec/factories/labels.rb @@ -0,0 +1,9 @@ +# Read about factories at https://github.com/thoughtbot/factory_girl + +FactoryGirl.define do + factory :label do + title "Bug" + color "#990000" + project + end +end diff --git a/spec/factories/merge_requests.rb b/spec/factories/merge_requests.rb new file mode 100644 index 00000000000..3319262c015 --- /dev/null +++ b/spec/factories/merge_requests.rb @@ -0,0 +1,47 @@ +FactoryGirl.define do + factory :merge_request do + title + author + source_project factory: :project + target_project { source_project } + + # → git log --pretty=oneline feature..master + # 5937ac0a7beb003549fc5fd26fc247adbce4a52e Add submodule from gitlab.com + # 570e7b2abdd848b95f2f578043fc23bd6f6fd24d Change some files + # 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9 More submodules + # d14d6c0abdd253381df51a723d58691b2ee1ab08 Remove ds_store files + # c1acaa58bbcbc3eafe538cb8274ba387047b69f8 Ignore DS files + # + # See also RepoHelpers.sample_compare + # + source_branch "master" + target_branch "feature" + + merge_status :can_be_merged + + trait :with_diffs do + end + + trait :conflict do + source_branch "feature_conflict" + target_branch "feature" + end + + trait :closed do + state :closed + end + + trait :reopened do + state :reopened + end + + trait :simple do + source_branch "feature" + target_branch "master" + end + + factory :closed_merge_request, traits: [:closed] + factory :reopened_merge_request, traits: [:reopened] + factory :merge_request_with_diffs, traits: [:with_diffs] + end +end diff --git a/spec/factories/notes.rb b/spec/factories/notes.rb new file mode 100644 index 00000000000..a55ccf289dd --- /dev/null +++ b/spec/factories/notes.rb @@ -0,0 +1,40 @@ +require_relative '../support/repo_helpers' + +FactoryGirl.define do + factory :note do + project + note "Note" + author + + factory :note_on_commit, traits: [:on_commit] + factory :note_on_commit_diff, traits: [:on_commit, :on_diff] + factory :note_on_issue, traits: [:on_issue], aliases: [:votable_note] + factory :note_on_merge_request, traits: [:on_merge_request] + factory :note_on_merge_request_diff, traits: [:on_merge_request, :on_diff] + + trait :on_commit do + project factory: :project + commit_id RepoHelpers.sample_commit.id + noteable_type "Commit" + end + + trait :on_diff do + line_code "0_184_184" + end + + trait :on_merge_request do + project factory: :project + noteable_id 1 + noteable_type "MergeRequest" + end + + trait :on_issue do + noteable_id 1 + noteable_type "Issue" + end + + trait :with_attachment do + attachment { fixture_file_upload(Rails.root + "spec/fixtures/dk.png", "`/png") } + end + end +end diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb new file mode 100644 index 00000000000..353d9d645ef --- /dev/null +++ b/spec/factories/projects.rb @@ -0,0 +1,44 @@ +FactoryGirl.define do + factory :empty_project, class: 'Project' do + sequence(:name) { |n| "project#{n}" } + path { name.downcase.gsub(/\s/, '_') } + namespace + creator + snippets_enabled true + + trait :public do + visibility_level Gitlab::VisibilityLevel::PUBLIC + end + + trait :internal do + visibility_level Gitlab::VisibilityLevel::INTERNAL + end + + trait :private do + visibility_level Gitlab::VisibilityLevel::PRIVATE + end + end + + # Generates a test repository from the repository stored under `spec/seed_project.tar.gz`. + # Once you run `rake gitlab:setup`, you can see what the repository looks like under `tmp/repositories/gitlabhq`. + # In order to modify files in the repository, you must untar the seed, modify and remake the tar. + # Before recompressing, do not forget to `git checkout master`. + # After recompressing, you need to run `RAILS_ENV=test bundle exec rake gitlab:setup` to regenerate the seeds under tmp. + # + # If you want to modify the repository only for an specific type of tests, e.g., markdown tests, + # consider using a feature branch to reduce the chances of collision with other tests. + # Create a new commit, and use the same commit message that you will use for the change in the main repo. + # Changing the commig message and SHA of branch `master` may break tests. + factory :project, parent: :empty_project do + path { 'gitlabhq' } + + after :create do |project| + TestEnv.copy_repo(project) + end + end + + factory :redmine_project, parent: :project do + issues_tracker { "redmine" } + issues_tracker_id { "project_name_in_redmine" } + end +end diff --git a/spec/features/notes_on_merge_requests_spec.rb b/spec/features/notes_on_merge_requests_spec.rb index 3fe11849660..47776ba7f3f 100644 --- a/spec/features/notes_on_merge_requests_spec.rb +++ b/spec/features/notes_on_merge_requests_spec.rb @@ -1,197 +1,209 @@ require 'spec_helper' -describe "On a merge request", js: true, feature: true do - let!(:merge_request) { create(:merge_request, :simple) } - let!(:project) { merge_request.source_project } - let!(:note) { create(:note_on_merge_request, :with_attachment, project: project) } - - before do - login_as :admin - visit project_merge_request_path(project, merge_request) - end +describe 'Comments' do + include RepoHelpers - subject { page } + describe "On a merge request", js: true, feature: true do + let!(:merge_request) { create(:merge_request) } + let!(:project) { merge_request.source_project } + let!(:note) { create(:note_on_merge_request, :with_attachment, project: project) } - describe "the note form" do - it 'should be valid' do - should have_css(".js-main-target-form", visible: true, count: 1) - find(".js-main-target-form input[type=submit]").value.should == "Add Comment" - within(".js-main-target-form") { should_not have_link("Cancel") } - within(".js-main-target-form") { should have_css(".js-note-preview-button", visible: false) } + before do + login_as :admin + visit project_merge_request_path(project, merge_request) end - describe "with text" do - before do - within(".js-main-target-form") do - fill_in "note[note]", with: "This is awesome" - end - end + subject { page } - it 'should have enable submit button and preview button' do - within(".js-main-target-form") { should_not have_css(".js-comment-button[disabled]") } - within(".js-main-target-form") { should have_css(".js-note-preview-button", visible: true) } + describe "the note form" do + it 'should be valid' do + should have_css(".js-main-target-form", visible: true, count: 1) + find(".js-main-target-form input[type=submit]").value.should == "Add Comment" + within(".js-main-target-form") { should_not have_link("Cancel") } + within(".js-main-target-form") { should have_css(".js-note-preview-button", visible: false) } end - end - end - describe "when posting a note" do - before do - within(".js-main-target-form") do - fill_in "note[note]", with: "This is awsome!" - find(".js-note-preview-button").trigger("click") - click_button "Add Comment" + describe "with text" do + before do + within(".js-main-target-form") do + fill_in "note[note]", with: "This is awesome" + end + end + + it 'should have enable submit button and preview button' do + within(".js-main-target-form") { should_not have_css(".js-comment-button[disabled]") } + within(".js-main-target-form") { should have_css(".js-note-preview-button", visible: true) } + end end end - it 'should be added and form reset' do - should have_content("This is awsome!") - within(".js-main-target-form") { should have_no_field("note[note]", with: "This is awesome!") } - within(".js-main-target-form") { should have_css(".js-note-preview", visible: false) } - within(".js-main-target-form") { should have_css(".js-note-text", visible: true) } - end - end + describe "when posting a note" do + before do + within(".js-main-target-form") do + fill_in "note[note]", with: "This is awsome!" + find(".js-note-preview-button").trigger("click") + click_button "Add Comment" + end + end - describe "when editing a note", js: true do - it "should contain the hidden edit form" do - within("#note_#{note.id}") { should have_css(".note-edit-form", visible: false) } + it 'should be added and form reset' do + should have_content("This is awsome!") + within(".js-main-target-form") { should have_no_field("note[note]", with: "This is awesome!") } + within(".js-main-target-form") { should have_css(".js-note-preview", visible: false) } + within(".js-main-target-form") { should have_css(".js-note-text", visible: true) } + end end - describe "editing the note" do - before do - find('.note').hover - find(".js-note-edit").click + describe "when editing a note", js: true do + it "should contain the hidden edit form" do + within("#note_#{note.id}") { should have_css(".note-edit-form", visible: false) } end - it "should show the note edit form and hide the note body" do - within("#note_#{note.id}") do - find(".note-edit-form", visible: true).should be_visible - find(".note-text", visible: false).should_not be_visible + describe "editing the note" do + before do + find('.note').hover + find(".js-note-edit").click end - end - - it "should reset the edit note form textarea with the original content of the note if cancelled" do - find('.note').hover - find(".js-note-edit").click - within(".note-edit-form") do - fill_in "note[note]", with: "Some new content" - find(".btn-cancel").click - find(".js-note-text", visible: false).text.should == note.note + it "should show the note edit form and hide the note body" do + within("#note_#{note.id}") do + find(".note-edit-form", visible: true).should be_visible + find(".note-text", visible: false).should_not be_visible + end end - end - it "appends the edited at time to the note" do - find('.note').hover - find(".js-note-edit").click + it "should reset the edit note form textarea with the original content of the note if cancelled" do + find('.note').hover + find(".js-note-edit").click - within(".note-edit-form") do - fill_in "note[note]", with: "Some new content" - find(".btn-save").click + within(".note-edit-form") do + fill_in "note[note]", with: "Some new content" + find(".btn-cancel").click + find(".js-note-text", visible: false).text.should == note.note + end end - within("#note_#{note.id}") do - should have_css(".note-last-update small") - find(".note-last-update small").text.should match(/Edited less than a minute ago/) + it "appends the edited at time to the note" do + find('.note').hover + find(".js-note-edit").click + + within(".note-edit-form") do + fill_in "note[note]", with: "Some new content" + find(".btn-save").click + end + + within("#note_#{note.id}") do + should have_css(".note-last-update small") + find(".note-last-update small").text.should match(/Edited less than a minute ago/) + end end end - end - describe "deleting an attachment" do - before do - find('.note').hover - find(".js-note-edit").click - end + describe "deleting an attachment" do + before do + find('.note').hover + find(".js-note-edit").click + end - it "shows the delete link" do - within(".note-attachment") do - should have_css(".js-note-attachment-delete") + it "shows the delete link" do + within(".note-attachment") do + should have_css(".js-note-attachment-delete") + end end - end - it "removes the attachment div and resets the edit form" do - find(".js-note-attachment-delete").click - should_not have_css(".note-attachment") - find(".note-edit-form", visible: false).should_not be_visible + it "removes the attachment div and resets the edit form" do + find(".js-note-attachment-delete").click + should_not have_css(".note-attachment") + find(".note-edit-form", visible: false).should_not be_visible + end end end end -end - -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 } - - before do - login_as :admin - visit diffs_project_merge_request_path(project, merge_request) - end - subject { page } + describe "On a merge request diff", js: true, feature: true do + let(:merge_request) { create(:merge_request) } + let(:project) { merge_request.source_project } - describe "when adding a note" do before do - find('a[data-line-code="8ec9a00bfd09b3190ac6b22251dbb1aa95a0579d_7_7"]').click - end - - describe "the notes holder" do - it { should have_css(".js-temp-notes-holder") } - - it { within(".js-temp-notes-holder") { should have_css(".new_note") } } + login_as :admin + visit diffs_project_merge_request_path(project, merge_request) end - describe "the note form" do - it "shouldn't add a second form for same row" do - find('a[data-line-code="8ec9a00bfd09b3190ac6b22251dbb1aa95a0579d_7_7"]').click + subject { page } - should have_css("tr[id='8ec9a00bfd09b3190ac6b22251dbb1aa95a0579d_7_7'] + .js-temp-notes-holder form", count: 1) + describe "when adding a note" do + before do + find("a[data-line-code=\"#{line_code}\"]").click end - it "should be removed when canceled" do - within(".diff-file form[rel$='8ec9a00bfd09b3190ac6b22251dbb1aa95a0579d_7_7']") do - find(".js-close-discussion-note-form").trigger("click") - end + describe "the notes holder" do + it { should have_css(".js-temp-notes-holder") } - should have_no_css(".js-temp-notes-holder") + it { within(".js-temp-notes-holder") { should have_css(".new_note") } } end - end - end - describe "with muliple note forms" do - before do - find('a[data-line-code="8ec9a00bfd09b3190ac6b22251dbb1aa95a0579d_7_7"]').click - find('a[data-line-code="8ec9a00bfd09b3190ac6b22251dbb1aa95a0579d_10_10"]').click - end + describe "the note form" do + it "shouldn't add a second form for same row" do + find("a[data-line-code=\"#{line_code}\"]").click - it { should have_css(".js-temp-notes-holder", count: 2) } - - describe "previewing them separately" do - before do - # add two separate texts and trigger previews on both - within("tr[id='8ec9a00bfd09b3190ac6b22251dbb1aa95a0579d_7_7'] + .js-temp-notes-holder") do - fill_in "note[note]", with: "One comment on line 7" - find(".js-note-preview-button").trigger("click") + should have_css("tr[id='#{line_code}'] + .js-temp-notes-holder form", count: 1) end - within("tr[id='8ec9a00bfd09b3190ac6b22251dbb1aa95a0579d_10_10'] + .js-temp-notes-holder") do - fill_in "note[note]", with: "Another comment on line 10" - find(".js-note-preview-button").trigger("click") + + it "should be removed when canceled" do + within(".diff-file form[rel$='#{line_code}']") do + find(".js-close-discussion-note-form").trigger("click") + end + + should have_no_css(".js-temp-notes-holder") end end end - describe "posting a note" do + describe "with muliple note forms" do before do - within("tr[id='8ec9a00bfd09b3190ac6b22251dbb1aa95a0579d_10_10'] + .js-temp-notes-holder") do - fill_in "note[note]", with: "Another comment on line 10" - click_button("Add Comment") + find("a[data-line-code=\"#{line_code}\"]").click + find("a[data-line-code=\"#{line_code_2}\"]").click + end + + it { should have_css(".js-temp-notes-holder", count: 2) } + + describe "previewing them separately" do + before do + # add two separate texts and trigger previews on both + within("tr[id='#{line_code}'] + .js-temp-notes-holder") do + fill_in "note[note]", with: "One comment on line 7" + find(".js-note-preview-button").trigger("click") + end + within("tr[id='#{line_code_2}'] + .js-temp-notes-holder") do + fill_in "note[note]", with: "Another comment on line 10" + find(".js-note-preview-button").trigger("click") + end end end - it 'should be added as discussion' do - should have_content("Another comment on line 10") - should have_css(".notes_holder") - should have_css(".notes_holder .note", count: 1) - should have_link("Reply") + describe "posting a note" do + before do + within("tr[id='#{line_code_2}'] + .js-temp-notes-holder") do + fill_in "note[note]", with: "Another comment on line 10" + click_button("Add Comment") + end + end + + it 'should be added as discussion' do + should have_content("Another comment on line 10") + should have_css(".notes_holder") + should have_css(".notes_holder .note", count: 1) + should have_link("Reply") + end end end end + + def line_code + sample_compare.changes.first[:line_code] + end + + def line_code_2 + sample_compare.changes.last[:line_code] + end end diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb index 053a1fe22f5..510b76fa9df 100644 --- a/spec/helpers/application_helper_spec.rb +++ b/spec/helpers/application_helper_spec.rb @@ -132,12 +132,12 @@ describe ApplicationHelper do it "includes a list of branch names" do options[0][0].should == 'Branches' - options[0][1].should include('master', 'stable') + options[0][1].should include('master', 'feature') end it "includes a list of tag names" do options[1][0].should == 'Tags' - options[1][1].should include('v0.9.4','v1.2.0') + options[1][1].should include('v1.0.0','v1.1.0') end it "includes a specific commit ref if defined" do diff --git a/spec/helpers/gitlab_markdown_helper_spec.rb b/spec/helpers/gitlab_markdown_helper_spec.rb index f176a393415..ba6af6f8b45 100644 --- a/spec/helpers/gitlab_markdown_helper_spec.rb +++ b/spec/helpers/gitlab_markdown_helper_spec.rb @@ -17,6 +17,7 @@ describe GitlabMarkdownHelper do before do # Helper expects a @project instance variable @project = project + @ref = 'markdown' @repository = project.repository end @@ -472,13 +473,13 @@ describe GitlabMarkdownHelper do it "should handle relative urls for a file in master" do actual = "[GitLab API doc](doc/api/README.md)\n" - expected = "<p><a href=\"/#{project.path_with_namespace}/blob/master/doc/api/README.md\">GitLab API doc</a></p>\n" + expected = "<p><a href=\"/#{project.path_with_namespace}/blob/#{@ref}/doc/api/README.md\">GitLab API doc</a></p>\n" markdown(actual).should match(expected) end it "should handle relative urls for a directory in master" do actual = "[GitLab API doc](doc/api)\n" - expected = "<p><a href=\"/#{project.path_with_namespace}/tree/master/doc/api\">GitLab API doc</a></p>\n" + expected = "<p><a href=\"/#{project.path_with_namespace}/tree/#{@ref}/doc/api\">GitLab API doc</a></p>\n" markdown(actual).should match(expected) end @@ -490,13 +491,13 @@ describe GitlabMarkdownHelper do it "should handle relative urls in reference links for a file in master" do actual = "[GitLab API doc][GitLab readme]\n [GitLab readme]: doc/api/README.md\n" - expected = "<p><a href=\"/#{project.path_with_namespace}/blob/master/doc/api/README.md\">GitLab API doc</a></p>\n" + expected = "<p><a href=\"/#{project.path_with_namespace}/blob/#{@ref}/doc/api/README.md\">GitLab API doc</a></p>\n" markdown(actual).should match(expected) end it "should handle relative urls in reference links for a directory in master" do actual = "[GitLab API doc directory][GitLab readmes]\n [GitLab readmes]: doc/api/\n" - expected = "<p><a href=\"/#{project.path_with_namespace}/tree/master/doc/api\">GitLab API doc directory</a></p>\n" + expected = "<p><a href=\"/#{project.path_with_namespace}/tree/#{@ref}/doc/api\">GitLab API doc directory</a></p>\n" markdown(actual).should match(expected) end diff --git a/spec/helpers/labels_helper_spec.rb b/spec/helpers/labels_helper_spec.rb index f66a5cc9f5c..1e64a201942 100644 --- a/spec/helpers/labels_helper_spec.rb +++ b/spec/helpers/labels_helper_spec.rb @@ -1,13 +1,6 @@ require 'spec_helper' describe LabelsHelper do - describe '#label_css_class' do - it 'returns label-danger when given Bug as param' do - expect(label_css_class('bug')).to eq('label-danger') - end - - it 'returns label-danger when given Bug as param' do - expect(label_css_class('Bug')).to eq('label-danger') - end - end + it { expect(text_color_for_bg('#EEEEEE')).to eq('#333') } + it { expect(text_color_for_bg('#222E2E')).to eq('#FFF') } end diff --git a/spec/helpers/tree_helper_spec.rb b/spec/helpers/tree_helper_spec.rb index d450b687caf..872dc2ebf31 100644 --- a/spec/helpers/tree_helper_spec.rb +++ b/spec/helpers/tree_helper_spec.rb @@ -2,7 +2,8 @@ require 'spec_helper' describe TreeHelper do describe '#markup?' do - %w(textile rdoc org creole mediawiki rst asciidoc pod).each do |type| + %w(textile rdoc org creole wiki mediawiki + rst adoc asciidoc asc).each do |type| it "returns true for #{type} files" do markup?("README.#{type}").should be_true end diff --git a/spec/lib/gitlab/satellite/merge_action_spec.rb b/spec/lib/gitlab/satellite/merge_action_spec.rb index 41d3321b173..479a73a1081 100644 --- a/spec/lib/gitlab/satellite/merge_action_spec.rb +++ b/spec/lib/gitlab/satellite/merge_action_spec.rb @@ -1,22 +1,16 @@ require 'spec_helper' describe 'Gitlab::Satellite::MergeAction' do - before(:each) do - @master = ['master', '69b34b7e9ad9f496f0ad10250be37d6265a03bba'] - @one_after_stable = ['stable', '6ea87c47f0f8a24ae031c3fff17bc913889ecd00'] #this commit sha is one after stable - @wiki_branch = ['wiki', '635d3e09b72232b6e92a38de6cc184147e5bcb41'] #this is the commit sha where the wiki branch goes off from master - @conflicting_metior = ['metior', '313d96e42b313a0af5ab50fa233bf43e27118b3f'] #this branch conflicts with the wiki branch - - # these commits are quite close together, itended to make string diffs/format patches small - @close_commit1 = ['2_3_notes_fix', '8470d70da67355c9c009e4401746b1d5410af2e3'] - @close_commit2 = ['scss_refactoring', 'f0f14c8eaba69ebddd766498a9d0b0e79becd633'] - end + include RepoHelpers let(:project) { create(:project, namespace: create(:group)) } let(:fork_project) { create(:project, namespace: create(:group), forked_from_project: project) } let(:merge_request) { create(:merge_request, source_project: project, target_project: project) } let(:merge_request_fork) { create(:merge_request, source_project: fork_project, target_project: project) } + let(:merge_request_with_conflict) { create(:merge_request, :conflict, source_project: project, target_project: project) } + let(:merge_request_fork_with_conflict) { create(:merge_request, :conflict, source_project: project, target_project: project) } + describe '#commits_between' do def verify_commits(commits, first_commit_sha, last_commit_sha) commits.each { |commit| commit.class.should == Gitlab::Git::Commit } @@ -26,51 +20,27 @@ describe 'Gitlab::Satellite::MergeAction' do context 'on fork' do it 'should get proper commits between' do - merge_request_fork.target_branch = @one_after_stable[0] - merge_request_fork.source_branch = @master[0] - commits = Gitlab::Satellite::MergeAction.new(merge_request_fork.author, merge_request_fork).commits_between - verify_commits(commits, @one_after_stable[1], @master[1]) - - merge_request_fork.target_branch = @wiki_branch[0] - merge_request_fork.source_branch = @master[0] commits = Gitlab::Satellite::MergeAction.new(merge_request_fork.author, merge_request_fork).commits_between - verify_commits(commits, @wiki_branch[1], @master[1]) + verify_commits(commits, sample_compare.commits.first, sample_compare.commits.last) end end context 'between branches' do it 'should raise exception -- not expected to be used by non forks' do - merge_request.target_branch = @one_after_stable[0] - merge_request.source_branch = @master[0] - expect {Gitlab::Satellite::MergeAction.new(merge_request.author, merge_request).commits_between}.to raise_error - - merge_request.target_branch = @wiki_branch[0] - merge_request.source_branch = @master[0] - expect {Gitlab::Satellite::MergeAction.new(merge_request.author, merge_request).commits_between}.to raise_error + expect { Gitlab::Satellite::MergeAction.new(merge_request.author, merge_request).commits_between }.to raise_error end end end describe '#format_patch' do - let(:target_commit) {['artiom-config-examples','9edbac5ac88ffa1ec9dad0097226b51e29ebc9ac']} - let(:source_commit) {['metior', '313d96e42b313a0af5ab50fa233bf43e27118b3f']} - def verify_content(patch) - (patch.include? source_commit[1]).should be_true - (patch.include? '635d3e09b72232b6e92a38de6cc184147e5bcb41').should be_true - (patch.include? '2bb2dee057327c81978ed0aa99904bd7ff5e6105').should be_true - (patch.include? '2e83de1924ad3429b812d17498b009a8b924795d').should be_true - (patch.include? 'ee45a49c57a362305431cbf004e4590b713c910e').should be_true - (patch.include? 'a6870dd08f8f274d9a6b899f638c0c26fefaa690').should be_true - - (patch.include? 'e74fae147abc7d2ffbf93d363dbbe45b87751f6f').should be_false - (patch.include? '86f76b11c670425bbab465087f25172378d76147').should be_false + sample_compare.commits.each do |commit| + patch.include?(commit).should be_true + end end context 'on fork' do it 'should build a format patch' do - merge_request_fork.target_branch = target_commit[0] - merge_request_fork.source_branch = source_commit[0] patch = Gitlab::Satellite::MergeAction.new(merge_request_fork.author, merge_request_fork).format_patch verify_content(patch) end @@ -78,8 +48,6 @@ describe 'Gitlab::Satellite::MergeAction' do context 'between branches' do it 'should build a format patch' do - merge_request.target_branch = target_commit[0] - merge_request.source_branch = source_commit[0] patch = Gitlab::Satellite::MergeAction.new(merge_request_fork.author, merge_request).format_patch verify_content(patch) end @@ -87,7 +55,6 @@ describe 'Gitlab::Satellite::MergeAction' do end describe '#diffs_between_satellite tested against diff_in_satellite' do - def is_a_matching_diff(diff, diffs) diff_count = diff.scan('diff --git').size diff_count.should >= 1 @@ -100,50 +67,38 @@ describe 'Gitlab::Satellite::MergeAction' do context 'on fork' do it 'should get proper diffs' do - merge_request_fork.target_branch = @close_commit1[0] - merge_request_fork.source_branch = @master[0] diffs = Gitlab::Satellite::MergeAction.new(merge_request_fork.author, merge_request_fork).diffs_between_satellite - - merge_request_fork.target_branch = @close_commit1[0] - merge_request_fork.source_branch = @master[0] diff = Gitlab::Satellite::MergeAction.new(merge_request.author, merge_request_fork).diff_in_satellite - is_a_matching_diff(diff, diffs) end end context 'between branches' do it 'should get proper diffs' do - merge_request.target_branch = @close_commit1[0] - merge_request.source_branch = @master[0] - expect{Gitlab::Satellite::MergeAction.new(merge_request.author, merge_request).diffs_between_satellite}.to raise_error + expect{ Gitlab::Satellite::MergeAction.new(merge_request.author, merge_request).diffs_between_satellite }.to raise_error end end end describe '#can_be_merged?' do context 'on fork' do - it 'return true or false depending on if something is mergable' do - merge_request_fork.target_branch = @one_after_stable[0] - merge_request_fork.source_branch = @master[0] - Gitlab::Satellite::MergeAction.new(merge_request_fork.author, merge_request_fork).can_be_merged?.should be_true - - merge_request_fork.target_branch = @conflicting_metior[0] - merge_request_fork.source_branch = @wiki_branch[0] - Gitlab::Satellite::MergeAction.new(merge_request_fork.author, merge_request_fork).can_be_merged?.should be_false - end + it { Gitlab::Satellite::MergeAction.new( + merge_request_fork.author, + merge_request_fork).can_be_merged?.should be_true } + + it { Gitlab::Satellite::MergeAction.new( + merge_request_fork_with_conflict.author, + merge_request_fork_with_conflict).can_be_merged?.should be_false } end context 'between branches' do - it 'return true or false depending on if something is mergable' do - merge_request.target_branch = @one_after_stable[0] - merge_request.source_branch = @master[0] - Gitlab::Satellite::MergeAction.new(merge_request.author, merge_request).can_be_merged?.should be_true - - merge_request.target_branch = @conflicting_metior[0] - merge_request.source_branch = @wiki_branch[0] - Gitlab::Satellite::MergeAction.new(merge_request.author, merge_request).can_be_merged?.should be_false - end + it { Gitlab::Satellite::MergeAction.new( + merge_request.author, + merge_request).can_be_merged?.should be_true } + + it { Gitlab::Satellite::MergeAction.new( + merge_request_with_conflict.author, + merge_request_with_conflict).can_be_merged?.should be_false } end end end diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb index 314b2691c40..a337408630b 100644 --- a/spec/mailers/notify_spec.rb +++ b/spec/mailers/notify_spec.rb @@ -3,6 +3,7 @@ require 'spec_helper' describe Notify do include EmailSpec::Helpers include EmailSpec::Matchers + include RepoHelpers let(:gitlab_sender) { Gitlab.config.gitlab.email_from } let(:recipient) { create(:user, email: 'recipient@example.com') } @@ -524,7 +525,7 @@ describe Notify do describe 'email on push with multiple commits' do let(:example_site_path) { root_path } let(:user) { create(:user) } - let(:compare) { Gitlab::Git::Compare.new(project.repository.raw_repository, 'cd5c4bac', 'b1e6a9db') } + let(:compare) { Gitlab::Git::Compare.new(project.repository.raw_repository, sample_image_commit.id, sample_commit.id) } let(:commits) { Commit.decorate(compare.commits) } let(:diff_path) { project_compare_path(project, from: commits.first, to: commits.last) } @@ -545,11 +546,11 @@ describe Notify do end it 'includes commits list' do - should have_body_text /tree css fixes/ + should have_body_text /Change some files/ end it 'includes diffs' do - should have_body_text /Checkout wiki pages for installation information/ + should have_body_text /def archive_formats_regex/ end it 'contains a link to the diff' do @@ -560,7 +561,7 @@ describe Notify do describe 'email on push with a single commit' do let(:example_site_path) { root_path } let(:user) { create(:user) } - let(:compare) { Gitlab::Git::Compare.new(project.repository.raw_repository, '8716fc78', 'b1e6a9db') } + let(:compare) { Gitlab::Git::Compare.new(project.repository.raw_repository, sample_commit.parent_id, sample_commit.id) } let(:commits) { Commit.decorate(compare.commits) } let(:diff_path) { project_commit_path(project, commits.first) } @@ -581,11 +582,11 @@ describe Notify do end it 'includes commits list' do - should have_body_text /tree css fixes/ + should have_body_text /Change some files/ end it 'includes diffs' do - should have_body_text /Checkout wiki pages for installation information/ + should have_body_text /def archive_formats_regex/ end it 'contains a link to the diff' do diff --git a/spec/models/commit_spec.rb b/spec/models/commit_spec.rb index d8ab171d3ee..1673184cbe4 100644 --- a/spec/models/commit_spec.rb +++ b/spec/models/commit_spec.rb @@ -11,7 +11,7 @@ describe Commit do end it "truncates a message without a newline at 80 characters" do - message = commit.safe_message * 10 + message = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec sodales id felis id blandit. Vivamus egestas lacinia lacus, sed rutrum mauris.' commit.stub(:safe_message).and_return(message) commit.title.should == "#{message[0..79]}…" @@ -24,11 +24,14 @@ describe Commit do commit.title.should == message end - it "truncates a message with a newline after 80 characters at 70 characters" do - message = (commit.safe_message * 10) + "\n" + it "does not truncates a message with a newline after 80 but less 100 characters" do + message =<<eos +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec sodales id felis id blandit. +Vivamus egestas lacinia lacus, sed rutrum mauris. +eos commit.stub(:safe_message).and_return(message) - commit.title.should == "#{message[0..79]}…" + commit.title.should == message.split("\n").first end end diff --git a/spec/models/label_link_spec.rb b/spec/models/label_link_spec.rb new file mode 100644 index 00000000000..078e61a7d62 --- /dev/null +++ b/spec/models/label_link_spec.rb @@ -0,0 +1,9 @@ +require 'spec_helper' + +describe LabelLink do + let(:label) { create(:label_link) } + it { label.should be_valid } + + it { should belong_to(:label) } + it { should belong_to(:target) } +end diff --git a/spec/models/label_spec.rb b/spec/models/label_spec.rb new file mode 100644 index 00000000000..5098af84cc3 --- /dev/null +++ b/spec/models/label_spec.rb @@ -0,0 +1,8 @@ +require 'spec_helper' + +describe Label do + let(:label) { create(:label) } + it { label.should be_valid } + + it { should belong_to(:project) } +end diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index bc537b7312b..82ab97cdd7a 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -124,24 +124,21 @@ describe Project do describe :update_merge_requests do let(:project) { create(:project) } - - before do - @merge_request = create(:merge_request, source_project: project, target_project: project) - @key = create(:key, user_id: project.owner.id) - end + let(:merge_request) { create(:merge_request, source_project: project, target_project: project) } + let(:key) { create(:key, user_id: project.owner.id) } + let(:prev_commit_id) { merge_request.commits.last.id } + let(:commit_id) { merge_request.commits.first.id } it "should close merge request if last commit from source branch was pushed to target branch" do - @merge_request.reload_code - @merge_request.last_commit.id.should == "69b34b7e9ad9f496f0ad10250be37d6265a03bba" - project.update_merge_requests("8716fc78f3c65bbf7bcf7b574febd583bc5d2812", "69b34b7e9ad9f496f0ad10250be37d6265a03bba", "refs/heads/stable", @key.user) - @merge_request.reload - @merge_request.merged?.should be_true + project.update_merge_requests(prev_commit_id, commit_id, "refs/heads/#{merge_request.target_branch}", key.user) + merge_request.reload + merge_request.merged?.should be_true end it "should update merge request commits with new one if pushed to source branch" do - project.update_merge_requests("8716fc78f3c65bbf7bcf7b574febd583bc5d2812", "69b34b7e9ad9f496f0ad10250be37d6265a03bba", "refs/heads/master", @key.user) - @merge_request.reload - @merge_request.last_commit.id.should == "69b34b7e9ad9f496f0ad10250be37d6265a03bba" + project.update_merge_requests(prev_commit_id, commit_id, "refs/heads/#{merge_request.source_branch}", key.user) + merge_request.reload + merge_request.last_commit.id.should == commit_id end end @@ -237,7 +234,7 @@ describe Project do project.protected_branches.create(name: 'master') end - it { project.open_branches.map(&:name).should include('bootstrap') } + it { project.open_branches.map(&:name).should include('feature') } it { project.open_branches.map(&:name).should_not include('master') } end diff --git a/spec/models/project_wiki_spec.rb b/spec/models/project_wiki_spec.rb index f06a5cd4ecc..e4ee2fc5b13 100644 --- a/spec/models/project_wiki_spec.rb +++ b/spec/models/project_wiki_spec.rb @@ -1,33 +1,14 @@ require "spec_helper" describe ProjectWiki do - - def remove_temp_repo(path) - FileUtils.rm_rf path - end - - def commit_details - commit = {name: user.name, email: user.email, message: "test commit"} - end - - def create_page(name, content) - subject.wiki.write_page(name, :markdown, content, commit_details) - end - - def destroy_page(page) - subject.wiki.delete_page(page, commit_details) - end - - let(:project) { create(:project) } + let(:project) { create(:empty_project) } let(:repository) { project.repository } let(:user) { project.owner } let(:gitlab_shell) { Gitlab::Shell.new } + let(:project_wiki) { ProjectWiki.new(project, user) } - subject { ProjectWiki.new(project, user) } - - before do - create_temp_repo(subject.send(:path_to_repo)) - end + subject { project_wiki } + before { project_wiki.wiki } describe "#path_with_namespace" do it "returns the project path with namespace with the .wiki extension" do @@ -60,23 +41,13 @@ describe ProjectWiki do subject.wiki.should be_a Gollum::Wiki end - before do - Gitlab::Shell.any_instance.stub(:add_repository) do - create_temp_repo("#{Rails.root}/tmp/test-git-base-path/non-existant.wiki.git") - end - project.stub(:path_with_namespace).and_return("non-existant") - end - it "creates a new wiki repo if one does not yet exist" do - wiki = ProjectWiki.new(project, user) - wiki.create_page("index", "test content").should_not == false - - FileUtils.rm_rf wiki.send(:path_to_repo) + project_wiki.create_page("index", "test content").should be_true end it "raises CouldNotCreateWikiError if it can't create the wiki repository" do - ProjectWiki.any_instance.stub(:init_repo).and_return(false) - expect { ProjectWiki.new(project, user).wiki }.to raise_exception(ProjectWiki::CouldNotCreateWikiError) + project_wiki.stub(:init_repo).and_return(false) + expect { project_wiki.send(:create_repo!) }.to raise_exception(ProjectWiki::CouldNotCreateWikiError) end end @@ -242,4 +213,26 @@ describe ProjectWiki do end end + private + + def create_temp_repo(path) + FileUtils.mkdir_p path + system(*%W(git init --quiet --bare -- #{path})) + end + + def remove_temp_repo(path) + FileUtils.rm_rf path + end + + def commit_details + commit = {name: user.name, email: user.email, message: "test commit"} + end + + def create_page(name, content) + subject.wiki.write_page(name, :markdown, content, commit_details) + end + + def destroy_page(page) + subject.wiki.delete_page(page, commit_details) + end end diff --git a/spec/models/wiki_page_spec.rb b/spec/models/wiki_page_spec.rb index 005c513af3c..cb42822b9bb 100644 --- a/spec/models/wiki_page_spec.rb +++ b/spec/models/wiki_page_spec.rb @@ -1,35 +1,12 @@ require "spec_helper" describe WikiPage do - - def remove_temp_repo(path) - FileUtils.rm_rf path - end - - def commit_details - commit = {name: user.name, email: user.email, message: "test commit"} - end - - def create_page(name, content) - wiki.wiki.write_page(name, :markdown, content, commit_details) - end - - def destroy_page(title) - page = wiki.wiki.paged(title) - wiki.wiki.delete_page(page, commit_details) - end - - let(:project) { create(:project) } - let(:repository) { project.repository } + let(:project) { create(:empty_project) } let(:user) { project.owner } let(:wiki) { ProjectWiki.new(project, user) } subject { WikiPage.new(wiki) } - before do - create_temp_repo(wiki.send(:path_to_repo)) - end - describe "#initialize" do context "when initialized with an existing gollum page" do before do @@ -171,4 +148,22 @@ describe WikiPage do end end + private + + def remove_temp_repo(path) + FileUtils.rm_rf path + end + + def commit_details + commit = {name: user.name, email: user.email, message: "test commit"} + end + + def create_page(name, content) + wiki.wiki.write_page(name, :markdown, content, commit_details) + end + + def destroy_page(title) + page = wiki.wiki.paged(title) + wiki.wiki.delete_page(page, commit_details) + end end diff --git a/spec/requests/api/branches_spec.rb b/spec/requests/api/branches_spec.rb index b145e620122..f3d7ca2ed21 100644 --- a/spec/requests/api/branches_spec.rb +++ b/spec/requests/api/branches_spec.rb @@ -9,6 +9,8 @@ describe API::API, api: true do let!(:project) { create(:project, creator_id: user.id) } let!(:master) { create(:users_project, user: user, project: project, project_access: UsersProject::MASTER) } let!(:guest) { create(:users_project, user: user2, project: project, project_access: UsersProject::GUEST) } + let!(:branch_name) { 'feature' } + let!(:branch_sha) { '0b4bc9a49b562e85de7cc9e834518ea6828729b9' } describe "GET /projects/:id/repository/branches" do it "should return an array of project branches" do @@ -21,11 +23,11 @@ describe API::API, api: true do describe "GET /projects/:id/repository/branches/:branch" do it "should return the branch information for a single branch" do - get api("/projects/#{project.id}/repository/branches/new_design", user) + get api("/projects/#{project.id}/repository/branches/#{branch_name}", user) response.status.should == 200 - json_response['name'].should == 'new_design' - json_response['commit']['id'].should == '621491c677087aa243f165eab467bfdfbee00be1' + json_response['name'].should == branch_name + json_response['commit']['id'].should == branch_sha json_response['protected'].should == false end @@ -42,11 +44,11 @@ describe API::API, api: true do describe "PUT /projects/:id/repository/branches/:branch/protect" do it "should protect a single branch" do - put api("/projects/#{project.id}/repository/branches/new_design/protect", user) + put api("/projects/#{project.id}/repository/branches/#{branch_name}/protect", user) response.status.should == 200 - json_response['name'].should == 'new_design' - json_response['commit']['id'].should == '621491c677087aa243f165eab467bfdfbee00be1' + json_response['name'].should == branch_name + json_response['commit']['id'].should == branch_sha json_response['protected'].should == true end @@ -56,24 +58,24 @@ describe API::API, api: true do end it "should return a 403 error if guest" do - put api("/projects/#{project.id}/repository/branches/new_design/protect", user2) + put api("/projects/#{project.id}/repository/branches/#{branch_name}/protect", user2) response.status.should == 403 end it "should return success when protect branch again" do - put api("/projects/#{project.id}/repository/branches/new_design/protect", user) - put api("/projects/#{project.id}/repository/branches/new_design/protect", user) + put api("/projects/#{project.id}/repository/branches/#{branch_name}/protect", user) + put api("/projects/#{project.id}/repository/branches/#{branch_name}/protect", user) response.status.should == 200 end end describe "PUT /projects/:id/repository/branches/:branch/unprotect" do it "should unprotect a single branch" do - put api("/projects/#{project.id}/repository/branches/new_design/unprotect", user) + put api("/projects/#{project.id}/repository/branches/#{branch_name}/unprotect", user) response.status.should == 200 - json_response['name'].should == 'new_design' - json_response['commit']['id'].should == '621491c677087aa243f165eab467bfdfbee00be1' + json_response['name'].should == branch_name + json_response['commit']['id'].should == branch_sha json_response['protected'].should == false end @@ -83,8 +85,8 @@ describe API::API, api: true do end it "should return success when unprotect branch again" do - put api("/projects/#{project.id}/repository/branches/new_design/unprotect", user) - put api("/projects/#{project.id}/repository/branches/new_design/unprotect", user) + put api("/projects/#{project.id}/repository/branches/#{branch_name}/unprotect", user) + put api("/projects/#{project.id}/repository/branches/#{branch_name}/unprotect", user) response.status.should == 200 end end @@ -92,19 +94,19 @@ describe API::API, api: true do describe "POST /projects/:id/repository/branches" do it "should create a new branch" do post api("/projects/#{project.id}/repository/branches", user), - branch_name: 'new_design', - ref: '621491c677087aa243f165eab467bfdfbee00be1' + branch_name: branch_name, + ref: branch_sha response.status.should == 201 - json_response['name'].should == 'new_design' - json_response['commit']['id'].should == '621491c677087aa243f165eab467bfdfbee00be1' + json_response['name'].should == branch_name + json_response['commit']['id'].should == branch_sha end it "should deny for user without push access" do post api("/projects/#{project.id}/repository/branches", user2), - branch_name: 'new_design', - ref: '621491c677087aa243f165eab467bfdfbee00be1' + branch_name: branch_name, + ref: branch_sha response.status.should == 403 end @@ -114,13 +116,13 @@ describe API::API, api: true do before { Repository.any_instance.stub(rm_branch: true) } it "should remove branch" do - delete api("/projects/#{project.id}/repository/branches/new_design", user) + delete api("/projects/#{project.id}/repository/branches/#{branch_name}", 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) + project.protected_branches.create(name: branch_name) + delete api("/projects/#{project.id}/repository/branches/#{branch_name}", user) response.status.should == 405 json_response['message'].should == 'Protected branch cant be removed' end diff --git a/spec/requests/api/files_spec.rb b/spec/requests/api/files_spec.rb index e84122f2fbc..b43a202aec0 100644 --- a/spec/requests/api/files_spec.rb +++ b/spec/requests/api/files_spec.rb @@ -4,20 +4,22 @@ describe API::API, api: true do include ApiHelpers let(:user) { create(:user) } let!(:project) { create(:project, namespace: user.namespace ) } + let(:file_path) { 'files/ruby/popen.rb' } + before { project.team << [user, :developer] } describe "GET /projects/:id/repository/files" do it "should return file info" do params = { - file_path: 'app/models/key.rb', + file_path: file_path, ref: 'master', } get api("/projects/#{project.id}/repository/files", user), params response.status.should == 200 - json_response['file_path'].should == 'app/models/key.rb' - json_response['file_name'].should == 'key.rb' - Base64.decode64(json_response['content']).lines.first.should == "class Key < ActiveRecord::Base\n" + json_response['file_path'].should == file_path + json_response['file_name'].should == 'popen.rb' + Base64.decode64(json_response['content']).lines.first.should == "require 'fileutils'\n" end it "should return a 400 bad request if no params given" do @@ -74,7 +76,7 @@ describe API::API, api: true do describe "PUT /projects/:id/repository/files" do let(:valid_params) { { - file_path: 'spec/spec_helper.rb', + file_path: file_path, branch_name: 'master', content: 'puts 8', commit_message: 'Changed file' @@ -88,7 +90,7 @@ describe API::API, api: true do put api("/projects/#{project.id}/repository/files", user), valid_params response.status.should == 200 - json_response['file_path'].should == 'spec/spec_helper.rb' + json_response['file_path'].should == file_path end it "should return a 400 bad request if no params given" do @@ -109,7 +111,7 @@ describe API::API, api: true do describe "DELETE /projects/:id/repository/files" do let(:valid_params) { { - file_path: 'spec/spec_helper.rb', + file_path: file_path, branch_name: 'master', commit_message: 'Changed file' } @@ -122,7 +124,7 @@ describe API::API, api: true do delete api("/projects/#{project.id}/repository/files", user), valid_params response.status.should == 200 - json_response['file_path'].should == 'spec/spec_helper.rb' + json_response['file_path'].should == file_path end it "should return a 400 bad request if no params given" do diff --git a/spec/requests/api/labels_spec.rb b/spec/requests/api/labels_spec.rb new file mode 100644 index 00000000000..d40c2c21cec --- /dev/null +++ b/spec/requests/api/labels_spec.rb @@ -0,0 +1,24 @@ +require 'spec_helper' + +describe API::API, api: true do + include ApiHelpers + + let(:user) { create(:user) } + let(:project) { create(:project, creator_id: user.id, namespace: user.namespace) } + let!(:label1) { create(:label, title: 'label1', project: project) } + + before do + project.team << [user, :master] + end + + + describe 'GET /projects/:id/labels' do + it 'should return project labels' do + get api("/projects/#{project.id}/labels", user) + response.status.should == 200 + json_response.should be_an Array + json_response.size.should == 1 + json_response.first['name'].should == label1.name + end + end +end diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index 41841e855fd..12a3a07ff76 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -10,13 +10,6 @@ describe API::API, api: true do let(:snippet) { create(:project_snippet, author: user, project: project, title: 'example') } let(:users_project) { create(:users_project, user: user, project: project, project_access: UsersProject::MASTER) } let(:users_project2) { create(:users_project, user: user3, project: project, project_access: UsersProject::DEVELOPER) } - let(:issue_with_labels) { create(:issue, author: user, assignee: user, project: project, :label_list => "label1, label2") } - let(:merge_request_with_labels) do - create(:merge_request, :simple, author: user, assignee: user, - source_project: project, target_project: project, title: 'Test', - label_list: 'label3, label4') - end - describe "GET /projects" do before { project } @@ -634,46 +627,4 @@ describe API::API, api: true do end end end - - describe 'GET /projects/:id/labels' do - context 'with an issue' do - before { issue_with_labels } - - it 'should return project labels' do - get api("/projects/#{project.id}/labels", user) - response.status.should == 200 - json_response.should be_an Array - json_response.first['name'].should == issue_with_labels.labels.first.name - json_response.last['name'].should == issue_with_labels.labels.last.name - end - end - - context 'with a merge request' do - before { merge_request_with_labels } - - it 'should return project labels' do - get api("/projects/#{project.id}/labels", user) - response.status.should == 200 - json_response.should be_an Array - json_response.first['name'].should == merge_request_with_labels.labels.first.name - json_response.last['name'].should == merge_request_with_labels.labels.last.name - end - end - - context 'with an issue and a merge request' do - before do - issue_with_labels - merge_request_with_labels - end - - it 'should return project labels from both' do - get api("/projects/#{project.id}/labels", user) - response.status.should == 200 - json_response.should be_an Array - all_labels = issue_with_labels.labels.map(&:name).to_a - .concat(merge_request_with_labels.labels.map(&:name).to_a) - json_response.map { |e| e['name'] }.should =~ all_labels - end - end - end end diff --git a/spec/requests/api/repositories_spec.rb b/spec/requests/api/repositories_spec.rb index a02231a5bba..f8603e11a04 100644 --- a/spec/requests/api/repositories_spec.rb +++ b/spec/requests/api/repositories_spec.rb @@ -3,6 +3,8 @@ require 'mime/types' describe API::API, api: true do include ApiHelpers + include RepoHelpers + let(:user) { create(:user) } let(:user2) { create(:user) } let!(:project) { create(:project, creator_id: user.id) } @@ -29,6 +31,7 @@ describe API::API, api: true do response.status.should == 201 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), tag_name: 'v1.0.0', @@ -47,7 +50,7 @@ describe API::API, api: true do response.status.should == 200 json_response.should be_an Array - json_response.first['name'].should == 'app' + json_response.first['name'].should == 'encoding' json_response.first['type'].should == 'tree' json_response.first['mode'].should == '040000' end @@ -92,7 +95,7 @@ describe API::API, api: true do describe "GET /projects/:id/repository/raw_blobs/:sha" do it "should get the raw file contents" do - get api("/projects/#{project.id}/repository/raw_blobs/d1aff2896d99d7acc4d9780fbb716b113c45ecf7", user) + get api("/projects/#{project.id}/repository/raw_blobs/#{sample_blob.oid}", user) response.status.should == 200 end end @@ -130,21 +133,21 @@ describe API::API, api: true do describe 'GET /projects/:id/repository/compare' do it "should compare branches" do - get api("/projects/#{project.id}/repository/compare", user), from: 'master', to: 'simple_merge_request' + get api("/projects/#{project.id}/repository/compare", user), from: 'master', to: 'feature' response.status.should == 200 json_response['commits'].should be_present json_response['diffs'].should be_present end it "should compare tags" do - get api("/projects/#{project.id}/repository/compare", user), from: 'v1.0.1', to: 'v1.0.2' + get api("/projects/#{project.id}/repository/compare", user), from: 'v1.0.0', to: 'v1.1.0' 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' + get api("/projects/#{project.id}/repository/compare", user), from: sample_commit.id, to: sample_commit.parent_id response.status.should == 200 json_response['commits'].should be_empty json_response['diffs'].should be_empty @@ -152,7 +155,7 @@ describe API::API, api: true do end it "should compare commits in reverse order" do - get api("/projects/#{project.id}/repository/compare", user), from: '1e689bfba395', to: 'b1e6a9dbf1c85' + get api("/projects/#{project.id}/repository/compare", user), from: sample_commit.parent_id, to: sample_commit.id response.status.should == 200 json_response['commits'].should be_present json_response['diffs'].should be_present @@ -175,9 +178,9 @@ describe API::API, api: true do contributor = json_response.first contributor['email'].should == 'dmitriy.zaporozhets@gmail.com' contributor['name'].should == 'Dmitriy Zaporozhets' - contributor['commits'].should == 185 - contributor['additions'].should == 66072 - contributor['deletions'].should == 63013 + contributor['commits'].should == 13 + contributor['additions'].should == 4081 + contributor['deletions'].should == 29 end end end diff --git a/spec/seed_project.tar.gz b/spec/seed_project.tar.gz Binary files differdeleted file mode 100644 index 8d32a927da8..00000000000 --- a/spec/seed_project.tar.gz +++ /dev/null diff --git a/spec/services/git_push_service_spec.rb b/spec/services/git_push_service_spec.rb index 6b89f213bec..fa99acabc78 100644 --- a/spec/services/git_push_service_spec.rb +++ b/spec/services/git_push_service_spec.rb @@ -1,14 +1,16 @@ require 'spec_helper' describe GitPushService do + include RepoHelpers + let (:user) { create :user } let (:project) { create :project } let (:service) { GitPushService.new } before do @blankrev = '0000000000000000000000000000000000000000' - @oldrev = 'b98a310def241a6fd9c9a9a3e7934c48e498fe81' - @newrev = 'b19a04f53caeebf4fe5ec2327cb83e9253dc91bb' + @oldrev = sample_commit.parent_id + @newrev = sample_commit.id @ref = 'refs/heads/master' end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 2181238ae9f..6934cabadfa 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -38,14 +38,7 @@ RSpec.configure do |config| config.include TestEnv - # 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.before(:suite) do - TestEnv.init(init_repos: true, repos: false) - end - config.before(:each) do - TestEnv.setup_stubs + TestEnv.init end end diff --git a/spec/support/big_commits.rb b/spec/support/big_commits.rb deleted file mode 100644 index 69daa709dd9..00000000000 --- a/spec/support/big_commits.rb +++ /dev/null @@ -1,8 +0,0 @@ -module BigCommits - HUGE_COMMIT_ID = "7f92534f767fa20357a11c63f973ae3b79cc5b85" - HUGE_COMMIT_MESSAGE = "pybments.rb version up. gitignore improved" - - BIG_COMMIT_ID = "d62200cad430565bd9f80befaf329297120330b5" - BIG_COMMIT_MESSAGE = "clean-up code" -end - diff --git a/spec/support/repo_helpers.rb b/spec/support/repo_helpers.rb new file mode 100644 index 00000000000..4c4775da692 --- /dev/null +++ b/spec/support/repo_helpers.rb @@ -0,0 +1,99 @@ +module RepoHelpers + extend self + + # Text file in repo + # + # Ex. + # + # # Get object + # blob = RepoHelpers.text_blob + # + # blob.path # => 'files/js/commit.js.coffee' + # blob.data # => 'class Commit...' + # + def sample_blob + OpenStruct.new( + oid: '5f53439ca4b009096571d3c8bc3d09d30e7431b3', + path: "files/js/commit.js.coffee", + data: <<eos +class Commit + constructor: -> + $('.files .diff-file').each -> + new CommitFile(this) + +@Commit = Commit +eos + ) + end + + def sample_commit + OpenStruct.new( + id: "570e7b2abdd848b95f2f578043fc23bd6f6fd24d", + parent_id: '6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9', + author_full_name: "Dmitriy Zaporozhets", + author_email: "dmitriy.zaporozhets@gmail.com", + files_changed_count: 2, + line_code: '2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_14', + line_code_path: 'files/ruby/popen.rb', + del_line_code: '2f6fcd96b88b36ce98c38da085c795a27d92a3dd_13_13', + message: <<eos +Change some files +Signed-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com> +eos + ) + end + + def sample_big_commit + OpenStruct.new( + id: "913c66a37b4a45b9769037c55c2d238bd0942d2e", + author_full_name: "Dmitriy Zaporozhets", + author_email: "dmitriy.zaporozhets@gmail.com", + message: <<eos +Files, encoding and much more +Signed-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com> +eos + ) + end + + def sample_image_commit + OpenStruct.new( + id: "2f63565e7aac07bcdadb654e253078b727143ec4", + author_full_name: "Dmitriy Zaporozhets", + author_email: "dmitriy.zaporozhets@gmail.com", + old_blob_id: '33f3729a45c02fc67d00adb1b8bca394b0e761d9', + new_blob_id: '2f63565e7aac07bcdadb654e253078b727143ec4', + message: <<eos +Modified image +Signed-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com> +eos + ) + end + + def sample_compare + changes = [ + { + line_code: 'a5cc2925ca8258af241be7e5b0381edf30266302_20_20', + file_path: '.gitignore', + }, + { + line_code: '7445606fbf8f3683cd42bdc54b05d7a0bc2dfc44_4_6', + file_path: '.gitmodules', + } + ] + + commits = [ + '5937ac0a7beb003549fc5fd26fc247adbce4a52e', + '570e7b2abdd848b95f2f578043fc23bd6f6fd24d', + '6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9', + 'd14d6c0abdd253381df51a723d58691b2ee1ab08', + 'c1acaa58bbcbc3eafe538cb8274ba387047b69f8', + ].reverse # last commit is recent one + + OpenStruct.new( + source_branch: 'master', + target_branch: 'feature', + changes: changes, + commits: commits + ) + end +end diff --git a/spec/support/test_env.rb b/spec/support/test_env.rb index 85059dfa9e9..e67c29a6783 100644 --- a/spec/support/test_env.rb +++ b/spec/support/test_env.rb @@ -5,167 +5,63 @@ module TestEnv # Test environment # - # all repositories and namespaces stored at - # RAILS_APP/tmp/test-git-base-path - # - # Next shell methods are stubbed and return true - # - mv_repository - # - remove_repository - # - add_key - # - remove_key + # See gitlab.yml.example test section for paths # def init(opts = {}) RSpec::Mocks::setup(self) # Disable mailer for spinach tests disable_mailer if opts[:mailer] == false - setup_stubs - - clear_test_repo_dir if opts[:init_repos] == true - setup_test_repos(opts) if opts[:repos] == true - end - - def disable_mailer - NotificationService.any_instance.stub(mailer: double.as_null_object) - end - def enable_mailer - NotificationService.any_instance.unstub(:mailer) - end + # Clean /tmp/tests + tmp_test_path = Rails.root.join('tmp', 'tests') - def setup_stubs() - # Use tmp dir for FS manipulations - repos_path = testing_path() - ProjectWiki.any_instance.stub(:init_repo) do |path| - create_temp_repo(File.join(repos_path, "#{path}.git")) + if File.directory?(tmp_test_path) + FileUtils.rm_r(tmp_test_path) end - Gitlab.config.gitlab_shell.stub(repos_path: repos_path) + FileUtils.mkdir_p(tmp_test_path) - Gitlab.config.satellites.stub(path: satellite_path) + # Setup GitLab shell for test instance + setup_gitlab_shell - Gitlab::Git::Repository.stub(repos_path: repos_path) - - Gitlab::Shell.any_instance.stub( - add_repository: true, - mv_repository: true, - remove_repository: true, - update_repository_head: true, - add_key: true, - remove_key: true, - version: '6.3.0' - ) - - Gitlab::Satellite::MergeAction.any_instance.stub( - merge!: true, - ) - - Gitlab::Satellite::Satellite.any_instance.stub( - exists?: true, - destroy: true, - create: true, - lock_files_dir: repos_path - ) - - MergeRequest.any_instance.stub( - check_if_can_be_merged: true - ) - Repository.any_instance.stub( - size: 12.45 - ) - end - - def clear_repo_dir(namespace, name) - setup_stubs - # Clean any .wiki.git that may have been created - FileUtils.rm_rf File.join(testing_path(), "#{name}.wiki.git") + # Create repository for FactoryGirl.create(:project) + setup_factory_repo end - def reset_satellite_dir - setup_stubs - [ - %W(git reset --hard --quiet), - %W(git clean -fx --quiet), - %W(git checkout --quiet origin/master) - ].each do |git_cmd| - system(*git_cmd, chdir: seed_satellite_path) - end - end - - # Create a repo and it's satellite - def create_repo(namespace, name) - setup_stubs - repo = repo(namespace, name) - - # Symlink tmp/repositories/gitlabhq to tmp/test-git-base-path/gitlabhq - FileUtils.ln_sf(seed_repo_path, repo) - create_satellite(repo, namespace, name) - end - - private - - def testing_path - Rails.root.join('tmp', 'test-git-base-path') - end - - def seed_repo_path - Rails.root.join('tmp', 'repositories', 'gitlabhq') - end - - def seed_satellite_path - Rails.root.join('tmp', 'satellite', 'gitlabhq') - end - - def satellite_path - "#{testing_path()}/satellite" + def disable_mailer + NotificationService.any_instance.stub(mailer: double.as_null_object) end - def repo(namespace, name) - unless (namespace.nil? || namespace.path.nil? || namespace.path.strip.empty?) - repo = File.join(testing_path(), "#{namespace.path}/#{name}.git") - else - repo = File.join(testing_path(), "#{name}.git") - end + def enable_mailer + NotificationService.any_instance.unstub(:mailer) end - def satellite(namespace, name) - unless (namespace.nil? || namespace.path.nil? || namespace.path.strip.empty?) - satellite_repo = File.join(satellite_path, namespace.path, name) - else - satellite_repo = File.join(satellite_path, name) + def setup_gitlab_shell + unless File.directory?(Gitlab.config.gitlab_shell.path) + %x[rake gitlab:shell:install] end end - def setup_test_repos(opts ={}) - create_repo(nil, 'gitlabhq') #unless opts[:repo].nil? || !opts[:repo].include?('') - create_repo(nil, 'source_gitlabhq') #unless opts[:repo].nil? || !opts[:repo].include?('source_') - create_repo(nil, 'target_gitlabhq') #unless opts[:repo].nil? || !opts[:repo].include?('target_') - end + def setup_factory_repo + repo_path = repos_path + "/root/testme.git" + clone_url = 'https://gitlab.com/gitlab-org/gitlab-test.git' - def clear_test_repo_dir - setup_stubs - - # Remove tmp/test-git-base-path - FileUtils.rm_rf Gitlab.config.gitlab_shell.repos_path - - # Recreate tmp/test-git-base-path - FileUtils.mkdir_p Gitlab.config.gitlab_shell.repos_path - - # Since much more is happening in satellites - FileUtils.mkdir_p Gitlab.config.satellites.path + unless File.directory?(repo_path) + git_cmd = %W(git clone --bare #{clone_url} #{repo_path}) + system(*git_cmd) + end end - # Create a testing satellite, and clone the source repo into it - def create_satellite(source_repo, namespace, satellite_name) - satellite_repo = satellite(namespace, satellite_name) - # Symlink tmp/satellite/gitlabhq to tmp/test-git-base-path/satellite/gitlabhq, create the directory if it doesn't exist already - satellite_dir = File.dirname(satellite_repo) - FileUtils.mkdir_p(satellite_dir) unless File.exists?(satellite_dir) - FileUtils.ln_sf(seed_satellite_path, satellite_repo) + def copy_repo(project) + base_repo_path = File.expand_path(repos_path + "/root/testme.git") + target_repo_path = File.expand_path(repos_path + "/#{project.namespace.path}/#{project.path}.git") + FileUtils.mkdir_p(target_repo_path) + FileUtils.cp_r("#{base_repo_path}/.", target_repo_path) + FileUtils.chmod_R 0755, target_repo_path end - def create_temp_repo(path) - FileUtils.mkdir_p path - system(*%W(git init --quiet --bare -- #{path})) + def repos_path + Gitlab.config.gitlab_shell.repos_path end end diff --git a/spec/support/valid_commit.rb b/spec/support/valid_commit.rb deleted file mode 100644 index 98bc59b573f..00000000000 --- a/spec/support/valid_commit.rb +++ /dev/null @@ -1,16 +0,0 @@ -module ValidCommit - ID = "8470d70da67355c9c009e4401746b1d5410af2e3" - MESSAGE = "notes controller refactored" - AUTHOR_FULL_NAME = "Dmitriy Zaporozhets" - AUTHOR_EMAIL = "dmitriy.zaporozhets@gmail.com" - - FILES = [".foreman", ".gitignore", ".rails_footnotes", ".rspec", ".travis.yml", "CHANGELOG", "Gemfile", "Gemfile.lock", "LICENSE", "Procfile", "Procfile.production", "README.md", "Rakefile", "VERSION", "app", "config.ru", "config", "db", "doc", "lib", "log", "public", "resque.sh", "script", "spec", "vendor"] - FILES_COUNT = 26 - - C_FILE_PATH = "app/models" - C_FILES = [".gitkeep", "ability.rb", "commit.rb", "issue.rb", "key.rb", "mailer_observer.rb", "merge_request.rb", "note.rb", "project.rb", "protected_branch.rb", "repository.rb", "snippet.rb", "tree.rb", "user.rb", "users_project.rb", "web_hook.rb", "wiki.rb"] - - BLOB_FILE = %{%h3= @key.title\n%hr\n%pre= @key.key\n.actions\n = link_to 'Remove', @key, :confirm => 'Are you sure?', :method => :delete, :class => \"btn danger delete-key\"\n\n\n} - BLOB_FILE_PATH = "app/views/keys/show.html.haml" -end - diff --git a/spec/support/valid_commit_with_alt_email.rb b/spec/support/valid_commit_with_alt_email.rb deleted file mode 100644 index 75854c63a59..00000000000 --- a/spec/support/valid_commit_with_alt_email.rb +++ /dev/null @@ -1,6 +0,0 @@ -module ValidCommitWithAltEmail - ID = "1e689bfba39525ead225eaf611948cfbe8ac34cf" - MESSAGE = "fixed notes logic" - AUTHOR_FULL_NAME = "Dmitriy Zaporozhets" - AUTHOR_EMAIL = "dzaporozhets@sphereconsultinginc.com" -end |
