Commit f933199a authored by Ruben Davila's avatar Ruben Davila

Merge remote-tracking branch 'ce/master' into ce-to-ee

parents b9c7011a f4282412
......@@ -3,11 +3,14 @@ Please view this file on the master branch, on stable branches it's out of date.
v 8.11.0 (unreleased)
- Fix the title of the toggle dropdown button. !5515 (herminiotorres)
- Improve diff performance by eliminating redundant checks for text blobs
- Convert switch icon into icon font (ClemMakesApps)
- Remove magic comments (`# encoding: UTF-8`) from Ruby files. !5456 (winniehell)
- Add support for relative links starting with ./ or / to RelativeLinkFilter (winniehell)
- Fix CI status icon link underline (ClemMakesApps)
- The Repository class is now instrumented
- Cache the commit author in RequestStore to avoid extra lookups in PostReceive
- Expand commit message width in repo view (ClemMakesApps)
- Cache highlighted diff lines for merge requests
- Fix of 'Commits being passed to custom hooks are already reachable when using the UI'
- Add support for using RequestStore within Sidekiq tasks via SIDEKIQ_REQUEST_STORE env variable
- Optimize maximum user access level lookup in loading of notes
......@@ -17,11 +20,14 @@ v 8.11.0 (unreleased)
- Clean up unused routes (Josef Strzibny)
- Add green outline to New Branch button. !5447 (winniehell)
- Update to gitlab_git 10.4.1 and take advantage of preserved Ref objects
- Remove delay when hitting "Reply..." button on page with a lot of discussions
- Retrieve rendered HTML from cache in one request
- Fix renaming repository when name contains invalid chararacters under project settings
- Optimize checking if a user has read access to a list of issues !5370
- Nokogiri's various parsing methods are now instrumented
- Add simple identifier to public SSH keys (muteor)
- Add a way to send an email and create an issue based on private personal token. Find the email address from issues page. !3363
- Fix filter input alignment (ClemMakesApps)
- Include old revision in merge request update hooks (Ben Boeckel)
- Add build event color in HipChat messages (David Eisner)
- Make fork counter always clickable. !5463 (winniehell)
......@@ -32,15 +38,19 @@ v 8.11.0 (unreleased)
- Bump gitlab_git to speedup DiffCollection iterations
- Make branches sortable without push permission !5462 (winniehell)
- Check for Ci::Build artifacts at database level on pipeline partial
- Convert image diff background image to CSS (ClemMakesApps)
- Make "New issue" button in Issue page less obtrusive !5457 (winniehell)
- Gitlab::Metrics.current_transaction needs to be public for RailsQueueDuration
- Fix search for notes which belongs to deleted objects
- Add GitLab Workhorse version to admin dashboard (Katarzyna Kobierska Ula Budziszewska)
- Allow branch names ending with .json for graph and network page !5579 (winniehell)
- Add the `sprockets-es6` gem
- Multiple trigger variables show in separate lines (Katarzyna Kobierska Ula Budziszewska)
- Profile requests when a header is passed
- Avoid calculation of line_code and position for _line partial when showing diff notes on discussion tab.
- Speedup DiffNote#active? on discussions, preloading noteables and avoid touching git repository to return diff_refs when possible
- Add commit stats in commit api. !5517 (dixpac)
- Add CI configuration button on project page
- Make error pages responsive (Takuya Noguchi)
- Change requests_profiles resource constraint to catch virtually any file
- Reduce number of queries made for merge_requests/:id/diffs
......
......@@ -41,6 +41,8 @@ abbreviation.
If you have read this guide and want to know how the GitLab [core team]
operates please see [the GitLab contributing process](PROCESS.md).
- [GitLab Inc engineers should refer to the engineering workflow document](https://about.gitlab.com/handbook/engineering/workflow/)
## Contributor license agreement
By submitting code as an individual you agree to the
......
......@@ -8,6 +8,8 @@ treatment, etc.). And so that maintainers know what to expect from contributors
(use the latest version, ensure that the issue is addressed, friendly treatment,
etc.).
- [GitLab Inc engineers should refer to the engineering workflow document](https://about.gitlab.com/handbook/engineering/workflow/)
## Common actions
### Issue team
......
......@@ -128,7 +128,7 @@
$date = $('.js-artifacts-remove');
if ($date.length) {
date = $date.text();
return $date.text($.timefor(new Date(date), ' '));
return $date.text($.timefor(new Date(date.replace(/-/g, '/')), ' '));
}
};
......
......@@ -47,8 +47,8 @@
}
}
},
setup: function(wrap) {
this.input = $('.js-gfm-input');
setup: function(input) {
this.input = input || $('.js-gfm-input');
this.destroyAtWho();
this.setupAtWho();
if (this.dataSource) {
......
......@@ -21,7 +21,7 @@
this.form.find('.div-dropzone').remove();
this.form.addClass('gfm-form');
disableButtonIfEmptyField(this.form.find('.js-note-text'), this.form.find('.js-comment-button'));
GitLab.GfmAutoComplete.setup();
GitLab.GfmAutoComplete.setup(this.form.find('.js-gfm-input'));
new DropzoneInput(this.form);
autosize(this.textarea);
this.addEventListeners();
......
......@@ -182,7 +182,6 @@
> form {
display: inline-block;
margin-top: -1px;
}
.icon-label {
......@@ -193,7 +192,6 @@
height: 35px;
display: inline-block;
position: relative;
top: 2px;
margin-right: $gl-padding-top;
/* Medium devices (desktops, 992px and up) */
......
.commits-compare-switch {
@include btn-default;
@include btn-white;
background: image-url("switch_icon.png") no-repeat center center;
text-indent: -9999px;
float: left;
margin-right: 9px;
}
......
......@@ -164,7 +164,10 @@
line-height: 0;
img {
border: 1px solid #fff;
background: image-url('trans_bg.gif');
background-image: linear-gradient(45deg, #e5e5e5 25%, transparent 25%, transparent 75%, #e5e5e5 75%, #e5e5e5 100%),
linear-gradient(45deg, #e5e5e5 25%, transparent 25%, transparent 75%, #e5e5e5 75%, #e5e5e5 100%);
background-size: 10px 10px;
background-position: 0 0, 5px 5px;
max-width: 100%;
}
&.deleted {
......
......@@ -58,6 +58,10 @@
.tree_commit {
max-width: 320px;
.str-truncated {
max-width: 100%;
}
}
.tree_time_ago {
......
module DiffForPath
extend ActiveSupport::Concern
def render_diff_for_path(diffs, diff_refs, project)
diff_file = safe_diff_files(diffs, diff_refs: diff_refs, repository: project.repository).find do |diff|
def render_diff_for_path(diffs)
diff_file = diffs.diff_files.find do |diff|
diff.old_path == params[:old_path] && diff.new_path == params[:new_path]
end
......@@ -14,7 +14,7 @@ module DiffForPath
locals = {
diff_file: diff_file,
diff_commit: diff_commit,
diff_refs: diff_refs,
diff_refs: diffs.diff_refs,
blob: blob,
project: project
}
......
......@@ -28,7 +28,7 @@ class Projects::CommitController < Projects::ApplicationController
end
def diff_for_path
render_diff_for_path(@diffs, @commit.diff_refs, @project)
render_diff_for_path(@commit.diffs(diff_options))
end
def builds
......
......@@ -21,7 +21,7 @@ class Projects::CompareController < Projects::ApplicationController
def diff_for_path
return render_404 unless @compare
render_diff_for_path(@diffs, @diff_refs, @project)
render_diff_for_path(@compare.diffs(diff_options))
end
def create
......@@ -40,18 +40,12 @@ class Projects::CompareController < Projects::ApplicationController
@compare = CompareService.new.execute(@project, @head_ref, @project, @start_ref)
if @compare
@commits = Commit.decorate(@compare.commits, @project)
@start_commit = @project.commit(@start_ref)
@commit = @project.commit(@head_ref)
@base_commit = @project.merge_base_commit(@start_ref, @head_ref)
@commits = @compare.commits
@start_commit = @compare.start_commit
@commit = @compare.commit
@base_commit = @compare.base_commit
@diffs = @compare.diffs(diff_options)
@diff_refs = Gitlab::Diff::DiffRefs.new(
base_sha: @base_commit.try(:sha),
start_sha: @start_commit.try(:sha),
head_sha: @commit.try(:sha)
)
@diff_notes_disabled = true
@grouped_diff_discussions = {}
......
......@@ -5,6 +5,7 @@ class Projects::IssuesController < Projects::ApplicationController
include ToggleAwardEmoji
include IssuableCollections
before_action :redirect_to_external_issue_tracker, only: [:index, :new]
before_action :module_enabled
before_action :issue, only: [:edit, :update, :show, :referenced_merge_requests,
:related_branches, :can_create_branch]
......@@ -207,6 +208,18 @@ class Projects::IssuesController < Projects::ApplicationController
return render_404 unless @project.issues_enabled && @project.default_issues_tracker?
end
def redirect_to_external_issue_tracker
external = @project.external_issue_tracker
return unless external
if action_name == 'new'
redirect_to external.new_issue_path
else
redirect_to external.issues_url
end
end
# Since iids are implemented only in 6.1
# user may navigate to issue page using old global ids.
#
......
......@@ -86,7 +86,11 @@ class Projects::MergeRequestsController < Projects::ApplicationController
respond_to do |format|
format.html { define_discussion_vars }
format.json { render json: { html: view_to_html_string("projects/merge_requests/show/_diffs") } }
format.json do
@diffs = @merge_request.diffs(diff_options)
render json: { html: view_to_html_string("projects/merge_requests/show/_diffs") }
end
end
end
......@@ -104,9 +108,8 @@ class Projects::MergeRequestsController < Projects::ApplicationController
end
define_commit_vars
diffs = @merge_request.diffs(diff_options)
render_diff_for_path(diffs, @merge_request.diff_refs, @merge_request.project)
render_diff_for_path(@merge_request.diffs(diff_options))
end
def commits
......@@ -154,7 +157,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
@commits = @merge_request.compare_commits.reverse
@commit = @merge_request.diff_head_commit
@base_commit = @merge_request.diff_base_commit
@diffs = @merge_request.compare.diffs(diff_options) if @merge_request.compare
@diffs = @merge_request.diffs(diff_options) if @merge_request.compare
@diff_notes_disabled = true
@pipeline = @merge_request.pipeline
......@@ -418,6 +421,8 @@ class Projects::MergeRequestsController < Projects::ApplicationController
fresh.
discussions
preload_noteable_for_regular_notes(@discussions.flat_map(&:notes))
# This is not executed lazily
@notes = Banzai::NoteRenderer.render(
@discussions.flat_map(&:notes),
......
......@@ -206,10 +206,10 @@ module CommitsHelper
end
end
def view_file_btn(commit_sha, diff, project)
def view_file_btn(commit_sha, diff_new_path, project)
link_to(
namespace_project_blob_path(project.namespace, project,
tree_join(commit_sha, diff.new_path)),
tree_join(commit_sha, diff_new_path)),
class: 'btn view-file js-view-file btn-file-option'
) do
raw('View file @') + content_tag(:span, commit_sha[0..6],
......
......@@ -30,11 +30,7 @@ module DiffHelper
options[:paths] = params.values_at(:old_path, :new_path)
end
Commit.max_diff_options.merge(options)
end
def safe_diff_files(diffs, diff_refs: nil, repository: nil)
diffs.decorate! { |diff| Gitlab::Diff::File.new(diff, diff_refs: diff_refs, repository: repository) }
options
end
def unfold_bottom_class(bottom)
......
......@@ -13,38 +13,6 @@ module IssuesHelper
OpenStruct.new(id: 0, title: 'None (backlog)', name: 'Unassigned')
end
def url_for_project_issues(project = @project, options = {})
return '' if project.nil?
url =
if options[:only_path]
project.issues_tracker.project_path
else
project.issues_tracker.project_url
end
# Ensure we return a valid URL to prevent possible XSS.
URI.parse(url).to_s
rescue URI::InvalidURIError
''
end
def url_for_new_issue(project = @project, options = {})
return '' if project.nil?
url =
if options[:only_path]
project.issues_tracker.new_issue_path
else
project.issues_tracker.new_issue_url
end
# Ensure we return a valid URL to prevent possible XSS.
URI.parse(url).to_s
rescue URI::InvalidURIError
''
end
def url_for_issue(issue_iid, project = @project, options = {})
return '' if project.nil?
......
......@@ -92,6 +92,10 @@ module NotesHelper
project.team.max_member_access_for_user_ids(user_ids)
end
def preload_noteable_for_regular_notes(notes)
ActiveRecord::Associations::Preloader.new.preload(notes.select { |note| !note.for_commit? }, :noteable)
end
def note_max_access_for_user(note)
note.project.team.human_max_access(note.author_id)
end
......
......@@ -272,6 +272,10 @@ module ProjectsHelper
filename_path(project, :version)
end
def ci_configuration_path(project)
filename_path(project, :gitlab_ci_yml)
end
def project_wiki_path_with_version(proj, page, version, is_newest)
url_params = is_newest ? {} : { version_id: version }
namespace_project_wiki_path(proj.namespace, proj, page, url_params)
......
......@@ -104,7 +104,7 @@ class Commit
end
def diff_line_count
@diff_line_count ||= Commit::diff_line_count(self.diffs)
@diff_line_count ||= Commit::diff_line_count(raw_diffs)
@diff_line_count
end
......@@ -123,15 +123,17 @@ class Commit
# In case this first line is longer than 100 characters, it is cut off
# after 80 characters and ellipses (`&hellp;`) are appended.
def title
title = safe_message
full_title.length > 100 ? full_title[0..79] << "…" : full_title
end
return no_commit_message if title.blank?
# Returns the full commits title
def full_title
return @full_title if @full_title
title_end = title.index("\n")
if (!title_end && title.length > 100) || (title_end && title_end > 100)
title[0..79] << "…"
if safe_message.blank?
@full_title = no_commit_message
else
title.split("\n", 2).first
@full_title = safe_message.split("\n", 2).first
end
end
......@@ -315,6 +317,14 @@ class Commit
nil
end
def raw_diffs(*args)
raw.diffs(*args)
end
def diffs(diff_options = nil)
Gitlab::Diff::FileCollection::Commit.new(self, diff_options: diff_options)
end
private
def find_author_by_any_email
......@@ -324,7 +334,7 @@ class Commit
def repo_changes
changes = { added: [], modified: [], removed: [] }
diffs.each do |diff|
raw_diffs.each do |diff|
if diff.deleted_file
changes[:removed] << diff.old_path
elsif diff.renamed_file || diff.new_file
......
class Compare
delegate :same, :head, :base, to: :@compare
attr_reader :project
def self.decorate(compare, project)
if compare.is_a?(Compare)
compare
else
self.new(compare, project)
end
end
def initialize(compare, project)
@compare = compare
@project = project
end
def commits
@commits ||= Commit.decorate(@compare.commits, project)
end
def start_commit
return @start_commit if defined?(@start_commit)
commit = @compare.base
@start_commit = commit ? ::Commit.new(commit, project) : nil
end
def head_commit
return @head_commit if defined?(@head_commit)
commit = @compare.head
@head_commit = commit ? ::Commit.new(commit, project) : nil
end
alias_method :commit, :head_commit
def base_commit
return @base_commit if defined?(@base_commit)
@base_commit = if start_commit && head_commit
project.merge_base_commit(start_commit.id, head_commit.id)
else
nil
end
end
def raw_diffs(*args)
@compare.diffs(*args)
end
def diffs(diff_options = nil)
Gitlab::Diff::FileCollection::Compare.new(self,
project: project,
diff_options: diff_options,
diff_refs: diff_refs)
end
def diff_refs
Gitlab::Diff::DiffRefs.new(
base_sha: base_commit.try(:sha),
start_sha: start_commit.try(:sha),
head_sha: commit.try(:sha)
)
end
end
......@@ -67,7 +67,7 @@ class DiffNote < Note
return false unless supported?
return true if for_commit?
diff_refs ||= self.noteable.diff_refs
diff_refs ||= noteable_diff_refs
self.position.diff_refs == diff_refs
end
......@@ -78,6 +78,14 @@ class DiffNote < Note
!self.for_merge_request? || self.noteable.support_new_diff_notes?
end
def noteable_diff_refs
if noteable.respond_to?(:diff_sha_refs)
noteable.diff_sha_refs
else
noteable.diff_refs
end
end
def set_original_position
self.original_position = self.position.dup
end
......@@ -96,7 +104,7 @@ class DiffNote < Note
self.project,
nil,
old_diff_refs: self.position.diff_refs,
new_diff_refs: self.noteable.diff_refs,
new_diff_refs: noteable_diff_refs,
paths: self.position.paths
).execute(self)
end
......
......@@ -49,6 +49,12 @@ class Discussion
self.noteable == target && !diff_discussion?
end
def active?
return @active if defined?(@active)
@active = first_note.active?
end
def expanded?
!diff_discussion? || active?
end
......
......@@ -28,8 +28,9 @@ class Key < ActiveRecord::Base
end
def publishable_key
# Removes anything beyond the keytype and key itself
self.key.split[0..1].join(' ')
# Strip out the keys comment so we don't leak email addresses
# Replace with simple ident of user_name (hostname)
self.key.split[0..1].push("#{self.user_name} (#{Gitlab.config.gitlab.host})").join(' ')
end
# projects that has this key
......
......@@ -85,7 +85,7 @@ class LegacyDiffNote < Note
return nil unless noteable
return @diff if defined?(@diff)
@diff = noteable.diffs(Commit.max_diff_options).find do |d|
@diff = noteable.raw_diffs(Commit.max_diff_options).find do |d|
d.new_path && Digest::SHA1.hexdigest(d.new_path) == diff_file_hash
end
end
......@@ -116,7 +116,7 @@ class LegacyDiffNote < Note
# Find the diff on noteable that matches our own
def find_noteable_diff
diffs = noteable.diffs(Commit.max_diff_options)
diffs = noteable.raw_diffs(Commit.max_diff_options)
diffs.find { |d| d.new_path == self.diff.new_path }
end
end
......@@ -169,8 +169,16 @@ class MergeRequest < ActiveRecord::Base
merge_request_diff ? merge_request_diff.first_commit : compare_commits.first
end
def diffs(*args)
merge_request_diff ? merge_request_diff.diffs(*args) : compare.diffs(*args)
def raw_diffs(*args)
merge_request_diff ? merge_request_diff.diffs(*args) : compare.raw_diffs(*args)
end
def diffs(diff_options = nil)
if self.compare
self.compare.diffs(diff_options)
else
Gitlab::Diff::FileCollection::MergeRequest.new(self, diff_options: diff_options)
end
end
def diff_size
......@@ -260,6 +268,19 @@ class MergeRequest < ActiveRecord::Base
)
end
# Return diff_refs instance trying to not touch the git repository
def diff_sha_refs
if merge_request_diff && merge_request_diff.diff_refs_by_sha?
return Gitlab::Diff::DiffRefs.new(
base_sha: merge_request_diff.base_commit_sha,
start_sha: merge_request_diff.start_commit_sha,
head_sha: merge_request_diff.head_commit_sha
)
else
diff_refs
end
end
def validate_branches
if target_project == source_project && target_branch == source_branch
errors.add :branch_conflict, "You can not use same project/branch for source and target"
......@@ -321,6 +342,8 @@ class MergeRequest < ActiveRecord::Base
merge_request_diff.reload_content
MergeRequests::MergeRequestDiffCacheService.new.execute(self)
new_diff_refs = self.diff_refs
update_diff_notes_positions(
......@@ -786,7 +809,7 @@ class MergeRequest < ActiveRecord::Base
end
def support_new_diff_notes?
diff_refs && diff_refs.complete?
diff_sha_refs && diff_sha_refs.complete?
end
def update_diff_notes_positions(old_diff_refs:, new_diff_refs:)
......
......@@ -82,6 +82,10 @@ class MergeRequestDiff < ActiveRecord::Base
project.commit(self.head_commit_sha)
end
def diff_refs_by_sha?
base_commit_sha? && head_commit_sha? && start_commit_sha?
end
def compare
@compare ||=
begin
......
......@@ -437,7 +437,7 @@ class Repository
# We don't want to flush the cache if the commit didn't actually make any
# changes to any of the possible avatar files.
if revision && commit = self.commit(revision)
return unless commit.diffs.
return unless commit.raw_diffs.
any? { |diff| AVATAR_FILES.include?(diff.new_path) }
end
......
......@@ -20,10 +20,12 @@ class CompareService
)
end
Gitlab::Git::Compare.new(
raw_compare = Gitlab::Git::Compare.new(
target_project.repository.raw_repository,
target_branch,
source_sha,
source_sha
)
Compare.new(raw_compare, target_project)
end
end
......@@ -34,7 +34,7 @@ module MergeRequests
# 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.source_project)
merge_request.compare_commits = commits
merge_request.can_be_created = true
merge_request.compare = compare
else
......
module MergeRequests
class MergeRequestDiffCacheService
def execute(merge_request)
# Executing the iteration we cache all the highlighted diff information
merge_request.diffs.diff_files.to_a
end
end
end
......@@ -66,7 +66,7 @@
- if project_nav_tab? :issues
= nav_link(controller: [:issues, :labels, :milestones]) do
= link_to url_for_project_issues(@project, only_path: true), title: 'Issues', class: 'shortcuts-issues' do
= link_to namespace_project_issues_path(@project.namespace, @project), title: 'Issues', class: 'shortcuts-issues' do
%span
Issues
- if @project.default_issues_tracker?
......
......@@ -9,7 +9,7 @@
- if can_create_issue
%li
= link_to url_for_new_issue(@project, only_path: true) do
= link_to new_namespace_project_issue_path(@project.namespace, @project) do
= icon('exclamation-circle fw')
New issue
......
......@@ -2,7 +2,7 @@
= nav_link(path: 'commit#show') do
= link_to namespace_project_commit_path(@project.namespace, @project, @commit.id) do
Changes
%span.badge= @diffs.count
%span.badge= @diffs.size
= nav_link(path: 'commit#builds') do
= link_to builds_namespace_project_commit_path(@project.namespace, @project, @commit.id) do
Builds
......
......@@ -7,7 +7,7 @@
= render "ci_menu"
- else
%div.block-connector
= render "projects/diffs/diffs", diffs: @diffs, project: @project, diff_refs: @commit.diff_refs
= render "projects/diffs/diffs", diffs: @diffs
= render "projects/notes/notes_with_form"
- if can_collaborate_with_project?
- %w(revert cherry-pick).each do |type|
......
= form_tag namespace_project_compare_index_path(@project.namespace, @project), method: :post, class: 'form-inline js-requires-input' do
.clearfix
- if params[:to] && params[:from]
= link_to 'switch', {from: params[:to], to: params[:from]}, {class: 'commits-compare-switch has-tooltip', title: 'Switch base of comparison'}
= link_to icon('exchange'), {from: params[:to], to: params[:from]}, {class: 'commits-compare-switch has-tooltip', title: 'Switch base of comparison'}
.form-group.dropdown.compare-form-group.js-compare-from-dropdown
.input-group.inline-input-group
%span.input-group-addon from
......
......@@ -8,7 +8,7 @@
- if @commits.present?
= render "projects/commits/commit_list"
= render "projects/diffs/diffs", diffs: @diffs, project: @project, diff_refs: @diff_refs
= render "projects/diffs/diffs", diffs: @diffs
- else
.light-well
.center
......
- show_whitespace_toggle = local_assigns.fetch(:show_whitespace_toggle, true)
- diff_files = diffs.diff_files
- if diff_view == 'parallel'
- fluid_layout true
- diff_files = safe_diff_files(diffs, diff_refs: diff_refs, repository: project.repository)
.content-block.oneline-block.files-changed
.inline-parallel-buttons
- if !expand_all_diffs? && diff_files.any? { |diff_file| diff_file.collapsed? }
= link_to 'Expand all', url_for(params.merge(expand_all_diffs: 1, format: nil)), class: 'btn btn-default'
- if show_whitespace_toggle
- if current_controller?(:commit)
= commit_diff_whitespace_link(@project, @commit, class: 'hidden-xs')
= commit_diff_whitespace_link(diffs.project, @commit, class: 'hidden-xs')
- elsif current_controller?(:merge_requests)
= diff_merge_request_whitespace_link(@project, @merge_request, class: 'hidden-xs')
= diff_merge_request_whitespace_link(diffs.project, @merge_request, class: 'hidden-xs')
- elsif current_controller?(:compare)
= diff_compare_whitespace_link(@project, params[:from], params[:to], class: 'hidden-xs')
= diff_compare_whitespace_link(diffs.project, params[:from], params[:to], class: 'hidden-xs')
.btn-group
= inline_diff_btn
= parallel_diff_btn
......@@ -23,12 +22,12 @@
- if diff_files.overflow?
= render 'projects/diffs/warning', diff_files: diff_files
.files{data: {can_create_note: (!@diff_notes_disabled && can?(current_user, :create_note, @project))}}
.files{data: {can_create_note: (!@diff_notes_disabled && can?(current_user, :create_note, diffs.project))}}
- diff_files.each_with_index do |diff_file, index|
- diff_commit = commit_for_diff(diff_file)
- blob = diff_file.blob(diff_commit)
- next unless blob
- blob.load_all_data!(project.repository) unless blob.only_display_raw?
- blob.load_all_data!(diffs.project.repository) unless blob.only_display_raw?
= render 'projects/diffs/file', i: index, project: project,
diff_file: diff_file, diff_commit: diff_commit, blob: blob, diff_refs: diff_refs
= render 'projects/diffs/file', i: index, project: diffs.project,
diff_file: diff_file, diff_commit: diff_commit, blob: blob
......@@ -15,6 +15,6 @@
from_merge_request_id: @merge_request.id,
skip_visible_check: true)
= view_file_btn(diff_commit.id, diff_file, project)
= view_file_btn(diff_commit.id, diff_file.new_path, project)
= render 'projects/diffs/content', diff_file: diff_file, diff_commit: diff_commit, diff_refs: diff_refs, blob: blob, project: project
= render 'projects/diffs/content', diff_file: diff_file, diff_commit: diff_commit, blob: blob, project: project
......@@ -32,7 +32,7 @@
:javascript
$.ajax({
type: "GET",
url: location.href,
url: "#{namespace_project_graph_path(@project.namespace, @project, current_ref, format: :json)}",
dataType: "json",
success: function (data) {
var graph = new ContributorsStatGraph();
......
......@@ -2,7 +2,7 @@
%ul{ class: (container_class) }
- if project_nav_tab?(:issues) && !current_controller?(:merge_requests)
= nav_link(controller: :issues) do
= link_to url_for_project_issues(@project, only_path: true), title: 'Issues' do
= link_to namespace_project_issues_path(@project.namespace, @project), title: 'Issues' do
%span
Issues
......
......@@ -42,7 +42,7 @@
%h4 This comparison includes more than #{MergeRequestDiff::COMMITS_SAFE_SIZE} commits.
%p To preserve performance the line changes are not shown.
- else
= render "projects/diffs/diffs", diffs: @diffs, project: @project, diff_refs: @merge_request.diff_refs, show_whitespace_toggle: false
= render "projects/diffs/diffs", diffs: @diffs, show_whitespace_toggle: false
- if @pipeline
#builds.builds.tab-pane
= render "projects/merge_requests/show/builds"
......
- if @merge_request_diff.collected?
= render "projects/diffs/diffs", diffs: @merge_request.diffs(diff_options),
project: @merge_request.project, diff_refs: @merge_request.diff_refs
= render "projects/diffs/diffs", diffs: @diffs
- elsif @merge_request_diff.empty?
.nothing-here-block Nothing to merge from #{@merge_request.source_branch} into #{@merge_request.target_branch}
- else
......
......@@ -43,6 +43,10 @@
%li
= link_to 'Contribution guide', contribution_guide_path(@project)
- if @repository.gitlab_ci_yml
%li
= link_to 'CI configuration', ci_configuration_path(@project)
- if current_user && can_push_branch?(@project, @project.default_branch)
- unless @repository.changelog
%li.missing
......
%span.str-truncated
= link_to_gfm commit.title, namespace_project_commit_path(@project.namespace, @project, commit.id), class: "tree-commit-link"
= link_to_gfm commit.full_title, namespace_project_commit_path(@project.namespace, @project, commit.id), class: "tree-commit-link"
......@@ -33,25 +33,14 @@ class EmailsOnPushWorker
reverse_compare = false
if action == :push
merge_base_sha = project.merge_base_commit(before_sha, after_sha).try(:sha)
compare = Gitlab::Git::Compare.new(project.repository.raw_repository, before_sha, after_sha)
diff_refs = Gitlab::Diff::DiffRefs.new(
base_sha: merge_base_sha,
start_sha: before_sha,
head_sha: after_sha
)
compare = CompareService.new.execute(project, before_sha, project, after_sha)
diff_refs = compare.diff_refs
return false if compare.same
if compare.commits.empty?
compare = Gitlab::Git::Compare.new(project.repository.raw_repository, after_sha, before_sha)
diff_refs = Gitlab::Diff::DiffRefs.new(
base_sha: merge_base_sha,
start_sha: after_sha,
head_sha: before_sha
)
compare = CompareService.new.execute(project, after_sha, project, before_sha)
diff_refs = compare.diff_refs
reverse_compare = true
......
......@@ -141,8 +141,10 @@ class IrkerWorker
end
def files_count(commit)
files = "#{commit.diffs.real_size} file"
files += 's' if commit.diffs.count > 1
diffs = commit.raw_diffs
files = "#{diffs.real_size} file"
files += 's' if diffs.size > 1
files
end
......
......@@ -674,13 +674,17 @@ Rails.application.routes.draw do
get '/compare/:from...:to', to: 'compare#show', as: 'compare', constraints: { from: /.+/, to: /.+/ }
resources :network, only: [:show], constraints: { id: /(?:[^.]|\.(?!json$))+/, format: /json/ }
resources :graphs, only: [:show], constraints: { id: /(?:[^.]|\.(?!json$))+/, format: /json/ } do
member do
get :commits
get :ci
get :languages
# Don't use format parameter as file extension (old 3.0.x behavior)
# See http://guides.rubyonrails.org/routing.html#route-globbing-and-wildcard-segments
scope format: false do
resources :network, only: [:show], constraints: { id: Gitlab::Regex.git_reference_regex }
resources :graphs, only: [:show], constraints: { id: Gitlab::Regex.git_reference_regex } do
member do
get :commits
get :ci
get :languages
end
end
end
......
......@@ -90,6 +90,10 @@ your `.gitlab-ci.yml`, you have to follow the
[Using a private Docker Registry][private-docker]
documentation. This workflow will be simplified in the future.
## Troubleshooting
See [the GitLab Docker registry troubleshooting guide](troubleshooting.md).
[ce-4040]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/4040
[docker-docs]: https://docs.docker.com/engine/userguide/intro/
[private-docker]: https://gitlab.com/gitlab-org/gitlab-ci-multi-runner/blob/master/docs/configuration/advanced-configuration.md#using-a-private-docker-registry
# Troubleshooting the GitLab Container Registry
## Basic Troubleshooting
1. Check to make sure that the system clock on your Docker client and GitLab server have
been synchronized (e.g. via NTP).
2. If you are using an S3-backed Registry, double check that the IAM
permissions and the S3 credentials (including region) are correct. See [the
sample IAM policy](https://docs.docker.com/registry/storage-drivers/s3/)
for more details.
3. Check the Registry logs (e.g. `/var/log/gitlab/registry/current`) and the GitLab production logs
for errors (e.g. `/var/log/gitlab/gitlab-rails/production.log`). You may be able to find clues
there.
## Advanced Troubleshooting
>**NOTE:** The following section is only recommended for experts.
Sometimes it's not obvious what is wrong, and you may need to dive deeper into
the communication between the Docker client and the Registry to find out
what's wrong. We will use a concrete example in the past to illustrate how to
diagnose a problem with the S3 setup.
### Unexpected 403 error during push
A user attempted to enable an S3-backed Registry. The `docker login` step went
fine. However, when pushing an image, the output showed:
```
The push refers to a repository [s3-testing.myregistry.com:4567/root/docker-test]
dc5e59c14160: Pushing [==================================================>] 14.85 kB
03c20c1a019a: Pushing [==================================================>] 2.048 kB
a08f14ef632e: Pushing [==================================================>] 2.048 kB
228950524c88: Pushing 2.048 kB
6a8ecde4cc03: Pushing [==> ] 9.901 MB/205.7 MB
5f70bf18a086: Pushing 1.024 kB
737f40e80b7f: Waiting
82b57dbc5385: Waiting
19429b698a22: Waiting
9436069b92a3: Waiting
error parsing HTTP 403 response body: unexpected end of JSON input: ""
```
This error is ambiguous, as it's not clear whether the 403 is coming from the
GitLab Rails application, the Docker Registry, or something else. In this
case, since we know that since the login succeeded, we probably need to look
at the communication between the client and the Registry.
The REST API between the Docker client and Registry is [described
here](https://docs.docker.com/registry/spec/api/). Normally, one would just
use Wireshark or tcpdump to capture the traffic and see where things went
wrong. However, since all communication between Docker clients and servers
are done over HTTPS, it's a bit difficult to decrypt the traffic quickly even
if you know the private key. What can we do instead?
One way would be to disable HTTPS by setting up an [insecure
Registry](https://docs.docker.com/registry/insecure/). This could introduce a
security hole and is only recommended for local testing. If you have a
production system and can't or don't want to do this, there is another way:
use mitmproxy, which stands for Man-in-the-Middle Proxy.
### mitmproxy
[mitmproxy](https://mitmproxy.org/) allows you to place a proxy between your
client and server to inspect all traffic. One wrinkle is that your system
needs to trust the mitmproxy SSL certificates for this to work.
The following installation instructions assume you are running Ubuntu:
1. Install mitmproxy (see http://docs.mitmproxy.org/en/stable/install.html)
1. Run `mitmproxy --port 9000` to generate its certificates.
Enter <kbd>CTRL</kbd>-<kbd>C</kbd> to quit.
1. Install the certificate from `~/.mitmproxy` to your system:
```sh
sudo cp ~/.mitmproxy/mitmproxy-ca-cert.pem /usr/local/share/ca-certificates/mitmproxy-ca-cert.crt
sudo update-ca-certificates
```
If successful, the output should indicate that a certificate was added:
```sh
Updating certificates in /etc/ssl/certs... 1 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d....done.
```
To verify that the certificates are properly installed, run:
```sh
mitmproxy --port 9000
```
This will run mitmproxy on port `9000`. In another window, run:
```sh
curl --proxy http://localhost:9000 https://httpbin.org/status/200
```
If everything is setup correctly, you will see information on the mitmproxy window and
no errors from the curl commands.
### Running the Docker daemon with a proxy
For Docker to connect through a proxy, you must start the Docker daemon with the
proper environment variables. The easiest way is to shutdown Docker (e.g. `sudo initctl stop docker`)
and then run Docker by hand. As root, run:
```sh
export HTTP_PROXY="http://localhost:9000"
export HTTPS_PROXY="https://localhost:9000"
docker daemon --debug
```
This will launch the Docker daemon and proxy all connections through mitmproxy.
### Running the Docker client
Now that we have mitmproxy and Docker running, we can attempt to login and push
a container image. You may need to run as root to do this. For example:
```sh
docker login s3-testing.myregistry.com:4567
docker push s3-testing.myregistry.com:4567/root/docker-test
```
In the example above, we see the following trace on the mitmproxy window:
![mitmproxy output from Docker](img/mitmproxy-docker.png)
The above image shows:
* The initial PUT requests went through fine with a 201 status code.
* The 201 redirected the client to the S3 bucket.
* The HEAD request to the AWS bucket reported a 403 Unauthorized.
What does this mean? This strongly suggests that the S3 user does not have the right
[permissions to perform a HEAD request](http://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectHEAD.html).
The solution: check the [IAM permissions again](https://docs.docker.com/registry/storage-drivers/s3/).
Once the right permissions were set, the error will go away.
......@@ -62,23 +62,7 @@ sudo -u git -H git checkout v0.7.8
sudo -u git -H make
```
### 6. Update MySQL permissions
If you are using MySQL you need to grant the GitLab user the necessary
permissions on the database:
```bash
# Login to MySQL
mysql -u root -p
# Grant the GitLab user the REFERENCES permission on the database
GRANT REFERENCES ON `gitlabhq_production`.* TO 'git'@'localhost';
# Quit the database session
mysql> \q
```
### 7. Install libs, migrations, etc.
### 6. Install libs, migrations, etc.
```bash
cd /home/git/gitlab
......@@ -100,7 +84,7 @@ sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS
```
### 8. Update configuration files
### 7. Update configuration files
#### New configuration options for `gitlab.yml`
......@@ -110,14 +94,6 @@ There are new configuration options available for [`gitlab.yml`](config/gitlab.y
git diff origin/8-10-stable:config/gitlab.yml.example origin/8-11-stable:config/gitlab.yml.example
```
#### Git configuration
Disable `git gc --auto` because GitLab runs `git gc` for us already.
```sh
sudo -u git -H git config --global gc.auto 0
```
#### Nginx configuration
Ensure you're still up-to-date with the latest NGINX configuration changes:
......@@ -157,12 +133,12 @@ Ensure you're still up-to-date with the latest init script changes:
sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
### 9. Start application
### 8. Start application
sudo service gitlab start
sudo service nginx restart
### 10. Check application status
### 9. Check application status
Check if GitLab and its environment are configured correctly:
......
......@@ -54,7 +54,7 @@ module API
sha = params[:sha]
commit = user_project.commit(sha)
not_found! "Commit" unless commit
commit.diffs.to_a
commit.raw_diffs.to_a
end
# Get a commit's comments
......@@ -96,7 +96,7 @@ module API
}
if params[:path] && params[:line] && params[:line_type]
commit.diffs(all_diffs: true).each do |diff|
commit.raw_diffs(all_diffs: true).each do |diff|
next unless diff.new_path == params[:path]
lines = Gitlab::Diff::Parser.new.parse(diff.diff.each_line)
......
......@@ -240,7 +240,7 @@ module API
class MergeRequestChanges < MergeRequest
expose :diffs, as: :changes, using: Entities::RepoDiff do |compare, _|
compare.diffs(all_diffs: true).to_a
compare.raw_diffs(all_diffs: true).to_a
end
end
......
......@@ -63,15 +63,18 @@ module Gitlab
diff_refs.try(:head_sha)
end
attr_writer :highlighted_diff_lines
# Array of Gitlab::Diff::Line objects
def diff_lines
@lines ||= Gitlab::Diff::Parser.new.parse(raw_diff.each_line).to_a
@diff_lines ||= Gitlab::Diff::Parser.new.parse(raw_diff.each_line).to_a
end
def highlighted_diff_lines
@highlighted_diff_lines ||= Gitlab::Diff::Highlight.new(self, repository: self.repository).highlight
end
# Array[<Hash>] with right/left keys that contains Gitlab::Diff::Line objects which text is hightlighted
def parallel_diff_lines
@parallel_diff_lines ||= Gitlab::Diff::ParallelDiff.new(self).parallelize
end
......
module Gitlab
module Diff
module FileCollection
class Base
attr_reader :project, :diff_options, :diff_view, :diff_refs
delegate :count, :size, :real_size, to: :diff_files
def self.default_options
::Commit.max_diff_options.merge(ignore_whitespace_change: false, no_collapse: false)
end
def initialize(diffable, project:, diff_options: nil, diff_refs: nil)
diff_options = self.class.default_options.merge(diff_options || {})
@diffable = diffable
@diffs = diffable.raw_diffs(diff_options)
@project = project
@diff_options = diff_options
@diff_refs = diff_refs
end
def diff_files
@diff_files ||= @diffs.decorate! { |diff| decorate_diff!(diff) }
end
private
def decorate_diff!(diff)
Gitlab::Diff::File.new(diff, repository: project.repository, diff_refs: diff_refs)
end
end
end
end
end
module Gitlab
module Diff
module FileCollection
class Commit < Base
def initialize(commit, diff_options:)
super(commit,
project: commit.project,
diff_options: diff_options,
diff_refs: commit.diff_refs)
end
end
end
end
end
module Gitlab
module Diff
module FileCollection
class Compare < Base
def initialize(compare, project:, diff_options:, diff_refs: nil)
super(compare,
project: project,
diff_options: diff_options,
diff_refs: diff_refs)
end
end
end
end
end
module Gitlab
module Diff
module FileCollection
class MergeRequest < Base
def initialize(merge_request, diff_options:)
@merge_request = merge_request
super(merge_request,
project: merge_request.project,
diff_options: diff_options,
diff_refs: merge_request.diff_refs)
end
def diff_files
super.tap { |_| store_highlight_cache }
end
private
# Extracted method to highlight in the same iteration to the diff_collection.
def decorate_diff!(diff)
diff_file = super
cache_highlight!(diff_file) if cacheable?
diff_file
end
def highlight_diff_file_from_cache!(diff_file, cache_diff_lines)
diff_file.highlighted_diff_lines = cache_diff_lines.map do |line|
Gitlab::Diff::Line.init_from_hash(line)
end
end
#
# If we find the highlighted diff files lines on the cache we replace existing diff_files lines (no highlighted)
# for the highlighted ones, so we just skip their execution.
# If the highlighted diff files lines are not cached we calculate and cache them.
#
# The content of the cache is a Hash where the key correspond to the file_path and the values are Arrays of
# hashes that represent serialized diff lines.
#
def cache_highlight!(diff_file)
file_path = diff_file.file_path
if highlight_cache[file_path]
highlight_diff_file_from_cache!(diff_file, highlight_cache[file_path])
else
highlight_cache[file_path] = diff_file.highlighted_diff_lines.map(&:to_hash)
end
end
def highlight_cache
return @highlight_cache if defined?(@highlight_cache)
@highlight_cache = Rails.cache.read(cache_key) || {}
@highlight_cache_was_empty = @highlight_cache.empty?
@highlight_cache
end
def store_highlight_cache
Rails.cache.write(cache_key, highlight_cache) if @highlight_cache_was_empty
end
def cacheable?
@merge_request.merge_request_diff.present?
end
def cache_key
[@merge_request.merge_request_diff, 'highlighted-diff-files', diff_options]
end
end
end
end
end
......@@ -40,8 +40,6 @@ module Gitlab
def highlight_line(diff_line)
return unless diff_file && diff_file.diff_refs
line_prefix = diff_line.text.match(/\A(.)/) ? $1 : ' '
rich_line =
if diff_line.unchanged? || diff_line.added?
new_lines[diff_line.new_pos - 1]
......@@ -51,7 +49,10 @@ module Gitlab
# Only update text if line is found. This will prevent
# issues with submodules given the line only exists in diff content.
"#{line_prefix}#{rich_line}".html_safe if rich_line
if rich_line
line_prefix = diff_line.text.match(/\A(.)/) ? $1 : ' '
"#{line_prefix}#{rich_line}".html_safe
end
end
def inline_diffs
......
......@@ -9,6 +9,20 @@ module Gitlab
@old_pos, @new_pos = old_pos, new_pos
end
def self.init_from_hash(hash)
new(hash[:text], hash[:type], hash[:index], hash[:old_pos], hash[:new_pos])
end
def serialize_keys
@serialize_keys ||= %i(text type index old_pos new_pos)
end
def to_hash
hash = {}
serialize_keys.each { |key| hash[key] = send(key) }
hash
end
def old_line
old_pos unless added? || meta?
end
......
......@@ -35,21 +35,22 @@ module Gitlab
def commits
return unless compare
@commits ||= Commit.decorate(compare.commits, project)
@commits ||= compare.commits
end
def diffs
return unless compare
@diffs ||= safe_diff_files(compare.diffs(max_files: 30), diff_refs: diff_refs, repository: project.repository)
# This diff is more moderated in number of files and lines
@diffs ||= compare.diffs(max_files: 30, max_lines: 5000, no_collapse: true).diff_files
end
def diffs_count
diffs.count if diffs
diffs.size if diffs
end
def compare
@opts[:compare]
@opts[:compare] if @opts[:compare]
end
def diff_refs
......@@ -97,16 +98,18 @@ module Gitlab
if commits.length > 1
namespace_project_compare_url(project_namespace,
project,
from: Commit.new(compare.base, project),
to: Commit.new(compare.head, project))
from: compare.start_commit,
to: compare.head_commit)
else
namespace_project_commit_url(project_namespace,
project, commits.first)
project,
commits.first)
end
else
unless @action == :delete
namespace_project_tree_url(project_namespace,
project, ref_name)
project,
ref_name)
end
end
end
......
......@@ -83,7 +83,7 @@ describe Projects::CommitController do
let(:format) { :diff }
it "should really only be a git diff" do
go(id: commit.id, format: format)
go(id: '66eceea0db202bb39c4e445e8ca28689645366c5', format: format)
expect(response.body).to start_with("diff --git")
end
......@@ -92,8 +92,9 @@ describe Projects::CommitController do
go(id: '66eceea0db202bb39c4e445e8ca28689645366c5', format: format, w: 1)
expect(response.body).to start_with("diff --git")
# without whitespace option, there are more than 2 diff_splits
diff_splits = assigns(:diffs).first.diff.split("\n")
# without whitespace option, there are more than 2 diff_splits for other formats
diff_splits = assigns(:diffs).diff_files.first.diff.diff.split("\n")
expect(diff_splits.length).to be <= 2
end
end
......@@ -266,9 +267,9 @@ describe Projects::CommitController do
end
it 'only renders the diffs for the path given' do
expect(controller).to receive(:render_diff_for_path).and_wrap_original do |meth, diffs, diff_refs, project|
expect(diffs.map(&:new_path)).to contain_exactly(existing_path)
meth.call(diffs, diff_refs, project)
expect(controller).to receive(:render_diff_for_path).and_wrap_original do |meth, diffs|
expect(diffs.diff_files.map(&:new_path)).to contain_exactly(existing_path)
meth.call(diffs)
end
diff_for_path(id: commit.id, old_path: existing_path, new_path: existing_path)
......
......@@ -19,7 +19,7 @@ describe Projects::CompareController do
to: ref_to)
expect(response).to be_success
expect(assigns(:diffs).first).not_to be_nil
expect(assigns(:diffs).diff_files.first).not_to be_nil
expect(assigns(:commits).length).to be >= 1
end
......@@ -32,10 +32,11 @@ describe Projects::CompareController do
w: 1)
expect(response).to be_success
expect(assigns(:diffs).first).not_to be_nil
diff_file = assigns(:diffs).diff_files.first
expect(diff_file).not_to be_nil
expect(assigns(:commits).length).to be >= 1
# without whitespace option, there are more than 2 diff_splits
diff_splits = assigns(:diffs).first.diff.split("\n")
diff_splits = diff_file.diff.diff.split("\n")
expect(diff_splits.length).to be <= 2
end
......@@ -48,7 +49,7 @@ describe Projects::CompareController do
to: ref_to)
expect(response).to be_success
expect(assigns(:diffs).to_a).to eq([])
expect(assigns(:diffs).diff_files.to_a).to eq([])
expect(assigns(:commits)).to eq([])
end
......@@ -87,9 +88,9 @@ describe Projects::CompareController do
end
it 'only renders the diffs for the path given' do
expect(controller).to receive(:render_diff_for_path).and_wrap_original do |meth, diffs, diff_refs, project|
expect(diffs.map(&:new_path)).to contain_exactly(existing_path)
meth.call(diffs, diff_refs, project)
expect(controller).to receive(:render_diff_for_path).and_wrap_original do |meth, diffs|
expect(diffs.diff_files.map(&:new_path)).to contain_exactly(existing_path)
meth.call(diffs)
end
diff_for_path(from: ref_from, to: ref_to, old_path: existing_path, new_path: existing_path)
......
......@@ -6,37 +6,65 @@ describe Projects::IssuesController do
let(:issue) { create(:issue, project: project) }
describe "GET #index" do
before do
sign_in(user)
project.team << [user, :developer]
end
context 'external issue tracker' do
it 'redirects to the external issue tracker' do
external = double(issues_url: 'https://example.com/issues')
allow(project).to receive(:external_issue_tracker).and_return(external)
controller.instance_variable_set(:@project, project)
it "returns index" do
get :index, namespace_id: project.namespace.path, project_id: project.path
get :index, namespace_id: project.namespace.path, project_id: project
expect(response).to have_http_status(200)
expect(response).to redirect_to('https://example.com/issues')
end
end
it "return 301 if request path doesn't match project path" do
get :index, namespace_id: project.namespace.path, project_id: project.path.upcase
context 'internal issue tracker' do
before do
sign_in(user)
project.team << [user, :developer]
end
expect(response).to redirect_to(namespace_project_issues_path(project.namespace, project))
end
it "returns index" do
get :index, namespace_id: project.namespace.path, project_id: project.path
expect(response).to have_http_status(200)
end
it "returns 404 when issues are disabled" do
project.issues_enabled = false
project.save
it "return 301 if request path doesn't match project path" do
get :index, namespace_id: project.namespace.path, project_id: project.path.upcase
get :index, namespace_id: project.namespace.path, project_id: project.path
expect(response).to have_http_status(404)
expect(response).to redirect_to(namespace_project_issues_path(project.namespace, project))
end
it "returns 404 when issues are disabled" do
project.issues_enabled = false
project.save
get :index, namespace_id: project.namespace.path, project_id: project.path
expect(response).to have_http_status(404)
end
it "returns 404 when external issue tracker is enabled" do
controller.instance_variable_set(:@project, project)
allow(project).to receive(:default_issues_tracker?).and_return(false)
get :index, namespace_id: project.namespace.path, project_id: project.path
expect(response).to have_http_status(404)
end
end
end
describe 'GET #new' do
context 'external issue tracker' do
it 'redirects to the external issue tracker' do
external = double(new_issue_path: 'https://example.com/issues/new')
allow(project).to receive(:external_issue_tracker).and_return(external)
controller.instance_variable_set(:@project, project)
it "returns 404 when external issue tracker is enabled" do
controller.instance_variable_set(:@project, project)
allow(project).to receive(:default_issues_tracker?).and_return(false)
get :new, namespace_id: project.namespace.path, project_id: project
get :index, namespace_id: project.namespace.path, project_id: project.path
expect(response).to have_http_status(404)
expect(response).to redirect_to('https://example.com/issues/new')
end
end
end
......
......@@ -523,9 +523,9 @@ describe Projects::MergeRequestsController do
end
it 'only renders the diffs for the path given' do
expect(controller).to receive(:render_diff_for_path).and_wrap_original do |meth, diffs, diff_refs, project|
expect(diffs.map(&:new_path)).to contain_exactly(existing_path)
meth.call(diffs, diff_refs, project)
expect(controller).to receive(:render_diff_for_path).and_wrap_original do |meth, diffs|
expect(diffs.diff_files.map(&:new_path)).to contain_exactly(existing_path)
meth.call(diffs)
end
diff_for_path(id: merge_request.iid, old_path: existing_path, new_path: existing_path)
......@@ -586,9 +586,9 @@ describe Projects::MergeRequestsController do
end
it 'only renders the diffs for the path given' do
expect(controller).to receive(:render_diff_for_path).and_wrap_original do |meth, diffs, diff_refs, project|
expect(diffs.map(&:new_path)).to contain_exactly(existing_path)
meth.call(diffs, diff_refs, project)
expect(controller).to receive(:render_diff_for_path).and_wrap_original do |meth, diffs|
expect(diffs.diff_files.map(&:new_path)).to contain_exactly(existing_path)
meth.call(diffs)
end
diff_for_path(old_path: existing_path, new_path: existing_path, merge_request: { source_branch: 'feature', target_branch: 'master' })
......@@ -608,9 +608,9 @@ describe Projects::MergeRequestsController do
end
it 'only renders the diffs for the path given' do
expect(controller).to receive(:render_diff_for_path).and_wrap_original do |meth, diffs, diff_refs, project|
expect(diffs.map(&:new_path)).to contain_exactly(existing_path)
meth.call(diffs, diff_refs, project)
expect(controller).to receive(:render_diff_for_path).and_wrap_original do |meth, diffs|
expect(diffs.diff_files.map(&:new_path)).to contain_exactly(existing_path)
meth.call(diffs)
end
diff_for_path(old_path: existing_path, new_path: existing_path, merge_request: { source_project: other_project, source_branch: 'feature', target_branch: 'master' })
......
......@@ -20,7 +20,11 @@ describe BranchesFinder do
result = branches_finder.execute
expect(result.first.name).to eq('crlf-diff')
recently_updated_branch = repository.branches.max do |a, b|
repository.commit(a.target).committed_date <=> repository.commit(b.target).committed_date
end
expect(result.first.name).to eq(recently_updated_branch.name)
end
it 'sorts by last_updated' do
......
......@@ -6,7 +6,7 @@ describe DiffHelper do
let(:project) { create(:project) }
let(:repository) { project.repository }
let(:commit) { project.commit(sample_commit.id) }
let(:diffs) { commit.diffs }
let(:diffs) { commit.raw_diffs }
let(:diff) { diffs.first }
let(:diff_refs) { [commit.parent, commit] }
let(:diff_file) { Gitlab::Diff::File.new(diff, diff_refs: diff_refs, repository: repository) }
......@@ -32,16 +32,6 @@ describe DiffHelper do
end
describe 'diff_options' do
it 'should return hard limit for a diff if force diff is true' do
allow(controller).to receive(:params) { { force_show_diff: true } }
expect(diff_options).to include(Commit.max_diff_options)
end
it 'should return hard limit for a diff if expand_all_diffs is true' do
allow(controller).to receive(:params) { { expand_all_diffs: true } }
expect(diff_options).to include(Commit.max_diff_options)
end
it 'should return no collapse false' do
expect(diff_options).to include(no_collapse: false)
end
......@@ -55,6 +45,18 @@ describe DiffHelper do
allow(controller).to receive(:action_name) { 'diff_for_path' }
expect(diff_options).to include(no_collapse: true)
end
it 'should return paths if action name diff_for_path and param old path' do
allow(controller).to receive(:params) { { old_path: 'lib/wadus.rb' } }
allow(controller).to receive(:action_name) { 'diff_for_path' }
expect(diff_options[:paths]).to include('lib/wadus.rb')
end
it 'should return paths if action name diff_for_path and param new path' do
allow(controller).to receive(:params) { { new_path: 'lib/wadus.rb' } }
allow(controller).to receive(:action_name) { 'diff_for_path' }
expect(diff_options[:paths]).to include('lib/wadus.rb')
end
end
describe 'unfold_bottom_class' do
......
......@@ -5,52 +5,6 @@ describe IssuesHelper do
let(:issue) { create :issue, project: project }
let(:ext_project) { create :redmine_project }
describe "url_for_project_issues" do
let(:project_url) { ext_project.external_issue_tracker.project_url }
let(:ext_expected) { project_url.gsub(':project_id', ext_project.id.to_s) }
let(:int_expected) { polymorphic_path([@project.namespace, project]) }
it "should return internal path if used internal tracker" do
@project = project
expect(url_for_project_issues).to match(int_expected)
end
it "should return path to external tracker" do
@project = ext_project
expect(url_for_project_issues).to match(ext_expected)
end
it "should return empty string if project nil" do
@project = nil
expect(url_for_project_issues).to eq ""
end
it 'returns an empty string if project_url is invalid' do
expect(project).to receive_message_chain('issues_tracker.project_url') { 'javascript:alert("foo");' }
expect(url_for_project_issues(project)).to eq ''
end
it 'returns an empty string if project_path is invalid' do
expect(project).to receive_message_chain('issues_tracker.project_path') { 'javascript:alert("foo");' }
expect(url_for_project_issues(project, only_path: true)).to eq ''
end
describe "when external tracker was enabled and then config removed" do
before do
@project = ext_project
allow(Gitlab.config).to receive(:issues_tracker).and_return(nil)
end
it "should return path to external tracker" do
expect(url_for_project_issues).to match(ext_expected)
end
end
end
describe "url_for_issue" do
let(:issues_url) { ext_project.external_issue_tracker.issues_url}
let(:ext_expected) { issues_url.gsub(':id', issue.iid.to_s).gsub(':project_id', ext_project.id.to_s) }
......@@ -97,52 +51,6 @@ describe IssuesHelper do
end
end
describe 'url_for_new_issue' do
let(:issues_url) { ext_project.external_issue_tracker.new_issue_url }
let(:ext_expected) { issues_url.gsub(':project_id', ext_project.id.to_s) }
let(:int_expected) { new_namespace_project_issue_path(project.namespace, project) }
it "should return internal path if used internal tracker" do
@project = project
expect(url_for_new_issue).to match(int_expected)
end
it "should return path to external tracker" do
@project = ext_project
expect(url_for_new_issue).to match(ext_expected)
end
it "should return empty string if project nil" do
@project = nil
expect(url_for_new_issue).to eq ""
end
it 'returns an empty string if issue_url is invalid' do
expect(project).to receive_message_chain('issues_tracker.new_issue_url') { 'javascript:alert("foo");' }
expect(url_for_new_issue(project)).to eq ''
end
it 'returns an empty string if issue_path is invalid' do
expect(project).to receive_message_chain('issues_tracker.new_issue_path') { 'javascript:alert("foo");' }
expect(url_for_new_issue(project, only_path: true)).to eq ''
end
describe "when external tracker was enabled and then config removed" do
before do
@project = ext_project
allow(Gitlab.config).to receive(:issues_tracker).and_return(nil)
end
it "should return internal path" do
expect(url_for_new_issue).to match(ext_expected)
end
end
end
describe "merge_requests_sentence" do
subject { merge_requests_sentence(merge_requests)}
let(:merge_requests) do
......
......@@ -5,7 +5,7 @@ describe Gitlab::Diff::File, lib: true do
let(:project) { create(:project) }
let(:commit) { project.commit(sample_commit.id) }
let(:diff) { commit.diffs.first }
let(:diff) { commit.raw_diffs.first }
let(:diff_file) { Gitlab::Diff::File.new(diff, diff_refs: commit.diff_refs, repository: project.repository) }
describe '#diff_lines' do
......
......@@ -5,7 +5,7 @@ describe Gitlab::Diff::Highlight, lib: true do
let(:project) { create(:project) }
let(:commit) { project.commit(sample_commit.id) }
let(:diff) { commit.diffs.first }
let(:diff) { commit.raw_diffs.first }
let(:diff_file) { Gitlab::Diff::File.new(diff, diff_refs: commit.diff_refs, repository: project.repository) }
describe '#highlight' do
......
......@@ -6,7 +6,7 @@ describe Gitlab::Diff::LineMapper, lib: true do
let(:project) { create(:project) }
let(:repository) { project.repository }
let(:commit) { project.commit(sample_commit.id) }
let(:diffs) { commit.diffs }
let(:diffs) { commit.raw_diffs }
let(:diff) { diffs.first }
let(:diff_file) { Gitlab::Diff::File.new(diff, diff_refs: commit.diff_refs, repository: repository) }
subject { described_class.new(diff_file) }
......
......@@ -6,7 +6,7 @@ describe Gitlab::Diff::ParallelDiff, lib: true do
let(:project) { create(:project) }
let(:repository) { project.repository }
let(:commit) { project.commit(sample_commit.id) }
let(:diffs) { commit.diffs }
let(:diffs) { commit.raw_diffs }
let(:diff) { diffs.first }
let(:diff_file) { Gitlab::Diff::File.new(diff, diff_refs: commit.diff_refs, repository: repository) }
subject { described_class.new(diff_file) }
......
......@@ -5,7 +5,7 @@ describe Gitlab::Diff::Parser, lib: true do
let(:project) { create(:project) }
let(:commit) { project.commit(sample_commit.id) }
let(:diff) { commit.diffs.first }
let(:diff) { commit.raw_diffs.first }
let(:parser) { Gitlab::Diff::Parser.new }
describe '#parse' do
......
......@@ -16,9 +16,12 @@ describe Gitlab::Email::Message::RepositoryPush do
{ author_id: author.id, ref: 'master', action: :push, compare: compare,
send_from_committer_email: true }
end
let(:compare) do
let(:raw_compare) do
Gitlab::Git::Compare.new(project.repository.raw_repository,
sample_image_commit.id, sample_commit.id)
sample_image_commit.id, sample_commit.id)
end
let(:compare) do
Compare.decorate(raw_compare, project)
end
describe '#project' do
......@@ -62,17 +65,17 @@ describe Gitlab::Email::Message::RepositoryPush do
describe '#diffs_count' do
subject { message.diffs_count }
it { is_expected.to eq compare.diffs.count }
it { is_expected.to eq raw_compare.diffs.size }
end
describe '#compare' do
subject { message.compare }
it { is_expected.to be_an_instance_of Gitlab::Git::Compare }
it { is_expected.to be_an_instance_of Compare }
end
describe '#compare_timeout' do
subject { message.compare_timeout }
it { is_expected.to eq compare.diffs.overflow? }
it { is_expected.to eq raw_compare.diffs.overflow? }
end
describe '#reverse_compare?' do
......
......@@ -1003,8 +1003,9 @@ 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, sample_image_commit.id, sample_commit.id) }
let(:commits) { Commit.decorate(compare.commits, nil) }
let(:raw_compare) { Gitlab::Git::Compare.new(project.repository.raw_repository, sample_image_commit.id, sample_commit.id) }
let(:compare) { Compare.decorate(raw_compare, project) }
let(:commits) { compare.commits }
let(:diff_path) { namespace_project_compare_path(project.namespace, project, from: Commit.new(compare.base, project), to: Commit.new(compare.head, project)) }
let(:send_from_committer_email) { false }
let(:diff_refs) { Gitlab::Diff::DiffRefs.new(base_sha: project.merge_base_commit(sample_image_commit.id, sample_commit.id).id, head_sha: sample_commit.id) }
......@@ -1105,8 +1106,9 @@ 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, sample_commit.parent_id, sample_commit.id) }
let(:commits) { Commit.decorate(compare.commits, nil) }
let(:raw_compare) { Gitlab::Git::Compare.new(project.repository.raw_repository, sample_commit.parent_id, sample_commit.id) }
let(:compare) { Compare.decorate(raw_compare, project) }
let(:commits) { compare.commits }
let(:diff_path) { namespace_project_commit_path(project.namespace, project, commits.first) }
let(:diff_refs) { Gitlab::Diff::DiffRefs.new(base_sha: project.merge_base_commit(sample_image_commit.id, sample_commit.id).id, head_sha: sample_commit.id) }
......
......@@ -86,6 +86,27 @@ eos
end
end
describe '#full_title' do
it "returns no_commit_message when safe_message is blank" do
allow(commit).to receive(:safe_message).and_return('')
expect(commit.full_title).to eq("--no commit message")
end
it "returns entire message if there is no newline" do
message = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec sodales id felis id blandit. Vivamus egestas lacinia lacus, sed rutrum mauris.'
allow(commit).to receive(:safe_message).and_return(message)
expect(commit.full_title).to eq(message)
end
it "returns first line of message if there is a newLine" do
message = commit.safe_message.split(" ").first
allow(commit).to receive(:safe_message).and_return(message + "\n" + message)
expect(commit.full_title).to eq(message)
end
end
describe "delegation" do
subject { commit }
......
require 'spec_helper'
describe Compare, models: true do
include RepoHelpers
let(:project) { create(:project, :public) }
let(:commit) { project.commit }
let(:start_commit) { sample_image_commit }
let(:head_commit) { sample_commit }
let(:raw_compare) { Gitlab::Git::Compare.new(project.repository.raw_repository, start_commit.id, head_commit.id) }
subject { described_class.new(raw_compare, project) }
describe '#start_commit' do
it 'returns raw compare base commit' do
expect(subject.start_commit.id).to eq(start_commit.id)
end
it 'returns nil if compare base commit is nil' do
expect(raw_compare).to receive(:base).and_return(nil)
expect(subject.start_commit).to eq(nil)
end
end
describe '#commit' do
it 'returns raw compare head commit' do
expect(subject.commit.id).to eq(head_commit.id)
end
it 'returns nil if compare head commit is nil' do
expect(raw_compare).to receive(:head).and_return(nil)
expect(subject.commit).to eq(nil)
end
end
describe '#base_commit' do
let(:base_commit) { Commit.new(another_sample_commit, project) }
it 'returns project merge base commit' do
expect(project).to receive(:merge_base_commit).with(start_commit.id, head_commit.id).and_return(base_commit)
expect(subject.base_commit).to eq(base_commit)
end
it 'returns nil if there is no start_commit' do
expect(subject).to receive(:start_commit).and_return(nil)
expect(subject.base_commit).to eq(nil)
end
it 'returns nil if there is no head commit' do
expect(subject).to receive(:head_commit).and_return(nil)
expect(subject.base_commit).to eq(nil)
end
end
describe '#diff_refs' do
it 'uses base_commit sha as base_sha' do
expect(subject).to receive(:base_commit).at_least(:once).and_call_original
expect(subject.diff_refs.base_sha).to eq(subject.base_commit.id)
end
it 'uses start_commit sha as start_sha' do
expect(subject.diff_refs.start_sha).to eq(start_commit.id)
end
it 'uses commit sha as head sha' do
expect(subject.diff_refs.head_sha).to eq(head_commit.id)
end
end
end
......@@ -119,7 +119,7 @@ describe DiffNote, models: true do
context "when the merge request's diff refs don't match that of the diff note" do
before do
allow(subject.noteable).to receive(:diff_refs).and_return(commit.diff_refs)
allow(subject.noteable).to receive(:diff_sha_refs).and_return(commit.diff_refs)
end
it "returns false" do
......@@ -168,7 +168,7 @@ describe DiffNote, models: true do
context "when the note is outdated" do
before do
allow(merge_request).to receive(:diff_refs).and_return(commit.diff_refs)
allow(merge_request).to receive(:diff_sha_refs).and_return(commit.diff_refs)
end
it "uses the DiffPositionUpdateService" do
......
......@@ -16,12 +16,13 @@ describe Key, models: true do
end
describe "Methods" do
let(:user) { create(:user) }
it { is_expected.to respond_to :projects }
it { is_expected.to respond_to :publishable_key }
describe "#publishable_keys" do
it 'strips all personal information' do
expect(build(:key).publishable_key).not_to match(/dummy@gitlab/)
it 'replaces SSH key comment with simple identifier of username + hostname' do
expect(build(:key, user: user).publishable_key).to include("#{user.name} (localhost)")
end
end
end
......
......@@ -58,7 +58,7 @@ describe LegacyDiffNote, models: true do
# Generate a real line_code value so we know it will match. We use a
# random line from a random diff just for funsies.
diff = merge.diffs.to_a.sample
diff = merge.raw_diffs.to_a.sample
line = Gitlab::Diff::Parser.new.parse(diff.diff.each_line).to_a.sample
code = Gitlab::Diff::LineCode.generate(diff.new_path, line.new_pos, line.old_pos)
......
......@@ -128,7 +128,7 @@ describe MergeRequest, models: true do
end
end
describe '#diffs' do
describe '#raw_diffs' do
let(:merge_request) { build(:merge_request) }
let(:options) { { paths: ['a/b', 'b/a', 'c/*'] } }
......@@ -138,6 +138,31 @@ describe MergeRequest, models: true do
expect(merge_request.merge_request_diff).to receive(:diffs).with(options)
merge_request.raw_diffs(options)
end
end
context 'when there are no MR diffs' do
it 'delegates to the compare object' do
merge_request.compare = double(:compare)
expect(merge_request.compare).to receive(:raw_diffs).with(options)
merge_request.raw_diffs(options)
end
end
end
describe '#diffs' do
let(:merge_request) { build(:merge_request) }
let(:options) { { paths: ['a/b', 'b/a', 'c/*'] } }
context 'when there are MR diffs' do
it 'delegates to the MR diffs' do
merge_request.merge_request_diff = MergeRequestDiff.new
expect(merge_request.merge_request_diff).to receive(:diffs).with(hash_including(options))
merge_request.diffs(options)
end
end
......@@ -743,6 +768,12 @@ describe MergeRequest, models: true do
subject.reload_diff
end
it "executs diff cache service" do
expect_any_instance_of(MergeRequests::MergeRequestDiffCacheService).to receive(:execute).with(subject)
subject.reload_diff
end
it "updates diff note positions" do
old_diff_refs = subject.diff_refs
......@@ -959,4 +990,28 @@ describe MergeRequest, models: true do
end
end
end
describe "#diff_sha_refs" do
context "with diffs" do
subject { create(:merge_request, :with_diffs) }
it "does not touch the repository" do
subject # Instantiate the object
expect_any_instance_of(Repository).not_to receive(:commit)
subject.diff_sha_refs
end
it "returns expected diff_refs" do
expected_diff_refs = Gitlab::Diff::DiffRefs.new(
base_sha: subject.merge_request_diff.base_commit_sha,
start_sha: subject.merge_request_diff.start_commit_sha,
head_sha: subject.merge_request_diff.head_commit_sha
)
expect(subject.diff_sha_refs).to eq(expected_diff_refs)
end
end
end
end
......@@ -1202,7 +1202,7 @@ describe Repository, models: true do
it 'does not flush the cache if the commit does not change any logos' do
diff = double(:diff, new_path: 'test.txt')
expect(commit).to receive(:diffs).and_return([diff])
expect(commit).to receive(:raw_diffs).and_return([diff])
expect(cache).not_to receive(:expire)
repository.expire_avatar_cache(repository.root_ref, '123')
......@@ -1211,7 +1211,7 @@ describe Repository, models: true do
it 'flushes the cache if the commit changes any of the logos' do
diff = double(:diff, new_path: Repository::AVATAR_FILES[0])
expect(commit).to receive(:diffs).and_return([diff])
expect(commit).to receive(:raw_diffs).and_return([diff])
expect(cache).to receive(:expire).with(:avatar)
repository.expire_avatar_cache(repository.root_ref, '123')
......
......@@ -657,7 +657,7 @@ describe User, models: true do
user = create :user
key = create :key, key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQD33bWLBxu48Sev9Fert1yzEO4WGcWglWF7K/AwblIUFselOt/QdOL9DSjpQGxLagO1s9wl53STIO8qGS4Ms0EJZyIXOEFMjFJ5xmjSy+S37By4sG7SsltQEHMxtbtFOaW5LV2wCrX+rUsRNqLMamZjgjcPO0/EgGCXIGMAYW4O7cwGZdXWYIhQ1Vwy+CsVMDdPkPgBXqK7nR/ey8KMs8ho5fMNgB5hBw/AL9fNGhRw3QTD6Q12Nkhl4VZES2EsZqlpNnJttnPdp847DUsT6yuLRlfiQfz5Cn9ysHFdXObMN5VYIiPFwHeYCZp1X2S4fDZooRE8uOLTfxWHPXwrhqSH", user_id: user.id
expect(user.all_ssh_keys).to include(key.key)
expect(user.all_ssh_keys).to include(a_string_starting_with(key.key))
end
end
......
......@@ -173,10 +173,10 @@ describe API::API, api: true do
end
it 'should return the inline comment' do
post api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}/comments", user), note: 'My comment', path: project.repository.commit.diffs.first.new_path, line: 7, line_type: 'new'
post api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}/comments", user), note: 'My comment', path: project.repository.commit.raw_diffs.first.new_path, line: 7, line_type: 'new'
expect(response).to have_http_status(201)
expect(json_response['note']).to eq('My comment')
expect(json_response['path']).to eq(project.repository.commit.diffs.first.new_path)
expect(json_response['path']).to eq(project.repository.commit.raw_diffs.first.new_path)
expect(json_response['line']).to eq(7)
expect(json_response['line_type']).to eq('new')
end
......
......@@ -479,13 +479,16 @@ end
describe Projects::NetworkController, 'routing' do
it 'to #show' do
expect(get('/gitlab/gitlabhq/network/master')).to route_to('projects/network#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master')
expect(get('/gitlab/gitlabhq/network/master.json')).to route_to('projects/network#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master', format: 'json')
expect(get('/gitlab/gitlabhq/network/ends-with.json')).to route_to('projects/network#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'ends-with.json')
expect(get('/gitlab/gitlabhq/network/master?format=json')).to route_to('projects/network#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master', format: 'json')
end
end
describe Projects::GraphsController, 'routing' do
it 'to #show' do
expect(get('/gitlab/gitlabhq/graphs/master')).to route_to('projects/graphs#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master')
expect(get('/gitlab/gitlabhq/graphs/ends-with.json')).to route_to('projects/graphs#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'ends-with.json')
expect(get('/gitlab/gitlabhq/graphs/master?format=json')).to route_to('projects/graphs#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master', format: 'json')
end
end
......
......@@ -61,7 +61,7 @@ describe MergeRequests::BuildService, services: true do
end
context 'one commit in the diff' do
let(:commits) { [commit_1] }
let(:commits) { Commit.decorate([commit_1], project) }
it 'allows the merge request to be created' do
expect(merge_request.can_be_created).to eq(true)
......@@ -84,7 +84,7 @@ describe MergeRequests::BuildService, services: true do
end
context 'commit has no description' do
let(:commits) { [commit_2] }
let(:commits) { Commit.decorate([commit_2], project) }
it 'uses the title of the commit as the title of the merge request' do
expect(merge_request.title).to eq(commit_2.safe_message)
......@@ -111,7 +111,7 @@ describe MergeRequests::BuildService, services: true do
end
context 'commit has no description' do
let(:commits) { [commit_2] }
let(:commits) { Commit.decorate([commit_2], project) }
it 'sets the description to "Closes #$issue-iid"' do
expect(merge_request.description).to eq("Closes ##{issue.iid}")
......@@ -121,7 +121,7 @@ describe MergeRequests::BuildService, services: true do
end
context 'more than one commit in the diff' do
let(:commits) { [commit_1, commit_2] }
let(:commits) { Commit.decorate([commit_1, commit_2], project) }
it 'allows the merge request to be created' do
expect(merge_request.can_be_created).to eq(true)
......
require 'spec_helper'
describe MergeRequests::MergeRequestDiffCacheService do
let(:subject) { MergeRequests::MergeRequestDiffCacheService.new }
describe '#execute' do
it 'retrieves the diff files to cache the highlighted result' do
merge_request = create(:merge_request)
cache_key = [merge_request.merge_request_diff, 'highlighted-diff-files', Gitlab::Diff::FileCollection::MergeRequest.default_options]
expect(Rails.cache).to receive(:read).with(cache_key).and_return({})
expect(Rails.cache).to receive(:write).with(cache_key, anything)
subject.execute(merge_request)
end
end
end
......@@ -6,6 +6,7 @@ module TestEnv
# When developing the seed repository, comment out the branch you will modify.
BRANCH_SHA = {
'empty-branch' => '7efb185',
'ends-with.json' => '98b0d8b3',
'flatten-dir' => 'e56497b',
'feature' => '0b4bc9a',
'feature_conflict' => 'bb5206f',
......
......@@ -38,7 +38,7 @@ Teaspoon.configure do |config|
# Specify a file matcher as a regular expression and all matching files will be loaded when the suite is run. These
# files need to be within an asset path. You can add asset paths using the `config.asset_paths`.
suite.matcher = "{spec/javascripts,app/assets}/**/*_spec.{js,js.coffee,coffee}"
suite.matcher = "{spec/javascripts,app/assets}/**/*_spec.{js,js.es6,es6}"
# Load additional JS files, but requiring them in your spec helper is the preferred way to do this.
# suite.javascripts = []
......
require 'spec_helper'
describe 'projects/tree/show' do
include Devise::TestHelpers
let(:project) { create(:project) }
let(:repository) { project.repository }
before do
assign(:project, project)
assign(:repository, repository)
allow(view).to receive(:can?).and_return(true)
allow(view).to receive(:can_collaborate_with_project?).and_return(true)
end
context 'for branch names ending on .json' do
let(:ref) { 'ends-with.json' }
let(:commit) { repository.commit(ref) }
let(:path) { '' }
let(:tree) { repository.tree(commit.id, path) }
before do
assign(:ref, ref)
assign(:commit, commit)
assign(:id, commit.id)
assign(:tree, tree)
assign(:path, path)
end
it 'displays correctly' do
render
expect(rendered).to have_css('.js-project-refs-dropdown .dropdown-toggle-text', text: ref)
expect(rendered).to have_css('.readme-holder .file-content', text: ref)
end
end
end
# elm-package generated files
elm-stuff/
elm-stuff
# elm-repl generated files
repl-temp-*
......@@ -22,3 +22,6 @@ _testmain.go
*.exe
*.test
*.prof
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
pom.xml
pom.xml.asc
*jar
*.jar
*.class
/lib/
/classes/
/target/
......
......@@ -52,7 +52,7 @@ Carthage/Build
fastlane/report.xml
fastlane/screenshots
#Code Injection
# Code Injection
#
# After new code Injection tools there's a generated folder /iOSInjectionProject
# https://github.com/johnno1962/injectionforxcode
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment