summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitlab-ci.yml66
-rw-r--r--CHANGELOG.md11
-rw-r--r--GITALY_SERVER_VERSION2
-rw-r--r--app/assets/javascripts/blob/viewer/index.js4
-rw-r--r--app/assets/javascripts/dispatcher.js6
-rw-r--r--app/assets/javascripts/line_highlighter.js6
-rw-r--r--app/controllers/concerns/renders_blob.rb4
-rw-r--r--app/controllers/projects/blob_controller.rb2
-rw-r--r--app/controllers/projects/snippets_controller.rb23
-rw-r--r--app/controllers/snippets_controller.rb13
-rw-r--r--app/helpers/blob_helper.rb24
-rw-r--r--app/models/repository.rb16
-rw-r--r--app/models/snippet.rb26
-rw-r--r--app/models/snippet_blob.rb59
-rw-r--r--app/views/projects/blob/_header.html.haml4
-rw-r--r--app/views/projects/blob/viewers/_markup.html.haml3
-rw-r--r--app/views/projects/snippets/show.html.haml2
-rw-r--r--app/views/search/results/_snippet_blob.html.haml2
-rw-r--r--app/views/shared/snippets/_blob.html.haml29
-rw-r--r--app/views/snippets/show.html.haml2
-rw-r--r--changelogs/unreleased/2246-uuid-is-nil-for-new-installation.yml4
-rw-r--r--changelogs/unreleased/28968-prevent-people-from-creating-branches-if-they-don-have-permission-to-push.yml4
-rw-r--r--changelogs/unreleased/30645-show-pipeline-events-description.yml4
-rw-r--r--changelogs/unreleased/30973-fix-network-graph-ordering.yml4
-rw-r--r--changelogs/unreleased/31292-milestone-sidebar-display-incorect-number-of-mr-when-minimized.yml4
-rw-r--r--changelogs/unreleased/add_index_on_ci_runners_contacted_at.yml4
-rw-r--r--changelogs/unreleased/dm-blob-download-button.yml4
-rw-r--r--changelogs/unreleased/dm-fix-ghost-user-validation.yml4
-rw-r--r--changelogs/unreleased/dm-snippet-blob-viewers.yml4
-rw-r--r--changelogs/unreleased/dont-blow-up-when-email-has-no-references-header.yml5
-rw-r--r--changelogs/unreleased/pages-0-4-1.yml4
-rw-r--r--changelogs/unreleased/zj-accept-default-branch-param.yml4
-rw-r--r--db/migrate/20160419122101_add_only_allow_merge_if_build_succeeds_to_projects.rb1
-rw-r--r--db/migrate/20160608195742_add_repository_storage_to_projects.rb1
-rw-r--r--db/migrate/20160715154212_add_request_access_enabled_to_projects.rb1
-rw-r--r--db/migrate/20160715204316_add_request_access_enabled_to_groups.rb1
-rw-r--r--db/migrate/20160831223750_remove_features_enabled_from_projects.rb1
-rw-r--r--db/migrate/20160913162434_remove_projects_pushes_since_gc.rb1
-rw-r--r--db/migrate/20170124193147_add_two_factor_columns_to_namespaces.rb1
-rw-r--r--db/migrate/20170124193205_add_two_factor_columns_to_users.rb1
-rw-r--r--db/migrate/20170301125302_add_printing_merge_request_link_enabled_to_project.rb1
-rw-r--r--db/migrate/20170305180853_add_auto_cancel_pending_pipelines_to_project.rb1
-rw-r--r--db/migrate/20170315174634_revert_add_notified_of_own_activity_to_users.rb1
-rw-r--r--doc/user/profile/account/delete_account.md2
-rw-r--r--features/project/snippets.feature1
-rw-r--r--features/snippets/snippets.feature1
-rw-r--r--features/steps/project/snippets.rb5
-rw-r--r--features/steps/project/source/browse_files.rb2
-rw-r--r--features/steps/snippets/snippets.rb4
-rw-r--r--lib/gitlab/email/receiver.rb2
-rw-r--r--lib/gitlab/git/repository.rb6
-rw-r--r--lib/gitlab/gitaly_client/commit.rb29
-rw-r--r--lib/gitlab/user_access.rb4
-rw-r--r--rubocop/cop/migration/add_column_with_default_to_large_table.rb51
-rw-r--r--rubocop/cop/migration/reversible_add_column_with_default.rb (renamed from rubocop/cop/migration/add_column_with_default.rb)21
-rw-r--r--rubocop/rubocop.rb3
-rwxr-xr-xscripts/lint-doc.sh1
-rwxr-xr-xscripts/static-analysis40
-rw-r--r--spec/features/merge_requests/create_new_mr_spec.rb1
-rw-r--r--spec/features/projects/blobs/blob_show_spec.rb37
-rw-r--r--spec/features/projects/snippets/show_spec.rb132
-rw-r--r--spec/features/snippets/create_snippet_spec.rb8
-rw-r--r--spec/features/snippets/public_snippets_spec.rb3
-rw-r--r--spec/features/snippets/show_spec.rb126
-rw-r--r--spec/helpers/blob_helper_spec.rb1
-rw-r--r--spec/javascripts/fixtures/line_highlighter.html.haml2
-rw-r--r--spec/lib/gitlab/email/receiver_spec.rb10
-rw-r--r--spec/lib/gitlab/user_access_spec.rb4
-rw-r--r--spec/models/repository_spec.rb24
-rw-r--r--spec/models/snippet_blob_spec.rb47
-rw-r--r--spec/models/snippet_spec.rb13
-rw-r--r--spec/rubocop/cop/migration/add_column_with_default_to_large_table_spec.rb44
-rw-r--r--spec/rubocop/cop/migration/reversible_add_column_with_default_spec.rb (renamed from spec/rubocop/cop/migration/add_column_with_default_spec.rb)4
-rw-r--r--spec/views/projects/blob/_viewer.html.haml_spec.rb1
74 files changed, 781 insertions, 212 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index ddc2c5f2542..dab1b220bfb 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -253,38 +253,32 @@ spinach mysql 9 10: *spinach-knapsack-mysql
SETUP_DB: "false"
USE_BUNDLE_INSTALL: "true"
-.exec: &exec
+.rake-exec: &rake-exec
<<: *ruby-static-analysis
<<: *dedicated-runner
<<: *except-docs
stage: test
script:
- - bundle exec $CI_JOB_NAME
+ - bundle exec rake $CI_JOB_NAME
-rubocop:
+static-analysis:
<<: *ruby-static-analysis
<<: *dedicated-runner
<<: *except-docs
stage: test
script:
- - bundle exec "rubocop --require rubocop-rspec"
-
-rake haml_lint: *exec
-rake scss_lint: *exec
-rake config_lint: *exec
-rake brakeman: *exec
-rake flay: *exec
-license_finder: *exec
-rake downtime_check:
- <<: *exec
+ - scripts/static-analysis
+
+downtime_check:
+ <<: *rake-exec
except:
- master
- tags
- /^[\d-]+-stable(-ee)?$/
- /^docs\/*/
-rake ee_compat_check:
- <<: *exec
+ee_compat_check:
+ <<: *rake-exec
only:
- branches@gitlab-org/gitlab-ce
except:
@@ -309,12 +303,12 @@ rake ee_compat_check:
script:
- bundle exec rake db:migrate:reset
-rake pg db:migrate:reset:
+db:migrate:reset pg:
<<: *db-migrate-reset
<<: *use-pg
<<: *except-docs
-rake mysql db:migrate:reset:
+db:migrate:reset mysql:
<<: *db-migrate-reset
<<: *use-mysql
<<: *except-docs
@@ -326,12 +320,12 @@ rake mysql db:migrate:reset:
- bundle exec rake db:rollback STEP=120
- bundle exec rake db:migrate
-rake pg db:rollback:
+db:rollback pg:
<<: *db-rollback
<<: *use-pg
<<: *except-docs
-rake mysql db:rollback:
+db:rollback mysql:
<<: *db-rollback
<<: *use-mysql
<<: *except-docs
@@ -353,17 +347,17 @@ rake mysql db:rollback:
paths:
- log/development.log
-rake pg db:seed_fu:
+db:seed_fu pg:
<<: *db-seed_fu
<<: *use-pg
<<: *except-docs
-rake mysql db:seed_fu:
+db:seed_fu mysql:
<<: *db-seed_fu
<<: *use-mysql
<<: *except-docs
-rake gitlab:assets:compile:
+gitlab:assets:compile:
stage: test
<<: *dedicated-runner
<<: *except-docs
@@ -383,7 +377,7 @@ rake gitlab:assets:compile:
paths:
- webpack-report/
-rake karma:
+karma:
cache:
paths:
- vendor/ruby
@@ -402,16 +396,6 @@ rake karma:
paths:
- coverage-javascript/
-docs:check:apilint:
- image: "phusion/baseimage"
- stage: test
- <<: *dedicated-runner
- cache: {}
- dependencies: []
- before_script: []
- script:
- - scripts/lint-doc.sh
-
docs:check:links:
image: "registry.gitlab.com/gitlab-org/gitlab-build-images:nanoc-bootstrap-ruby-2.4-alpine"
stage: test
@@ -459,11 +443,11 @@ bundler:audit:
- . scripts/prepare_build.sh
- bundle exec rake db:migrate
-migration pg paths:
+migration path pg:
<<: *migration-paths
<<: *use-pg
-migration mysql paths:
+migration path mysql:
<<: *migration-paths
<<: *use-mysql
@@ -485,14 +469,6 @@ coverage:
- coverage/index.html
- coverage/assets/
-lint:javascript:
- <<: *dedicated-runner
- <<: *except-docs
- stage: test
- before_script: []
- script:
- - yarn run eslint
-
lint:javascript:report:
<<: *dedicated-runner
<<: *except-docs
@@ -548,8 +524,8 @@ pages:
<<: *dedicated-runner
dependencies:
- coverage
- - rake karma
- - rake gitlab:assets:compile
+ - karma
+ - gitlab:assets:compile
- lint:javascript:report
script:
- mv public/ .public/
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a47c43dd5d6..2686d778b09 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,17 @@
documentation](doc/development/changelog.md) for instructions on adding your own
entry.
+## 9.1.2 (2017-05-01)
+
+- Add index on ci_runners.contacted_at. !10876 (blackst0ne)
+- Fix pipeline events description for Slack and Mattermost integration. !10908
+- Fixed milestone sidebar showing incorrect number of MRs when collapsed. !10933
+- Fix ordering of commits in the network graph. !10936
+- Ensure the chat notifications service properly saves the "Notify only default branch" setting. !10959
+- Lazily sets UUID in ApplicationSetting for new installations.
+- Skip validation when creating internal (ghost, service desk) users.
+- Use GitLab Pages v0.4.1.
+
## 9.1.1 (2017-04-26)
- Add a transaction around move_issues_to_ghost_user. !10465
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION
index a918a2aa18d..a3df0a6959e 100644
--- a/GITALY_SERVER_VERSION
+++ b/GITALY_SERVER_VERSION
@@ -1 +1 @@
-0.6.0
+0.8.0
diff --git a/app/assets/javascripts/blob/viewer/index.js b/app/assets/javascripts/blob/viewer/index.js
index 7efa8537298..07d67d49aa5 100644
--- a/app/assets/javascripts/blob/viewer/index.js
+++ b/app/assets/javascripts/blob/viewer/index.js
@@ -6,7 +6,7 @@ export default class BlobViewer {
this.copySourceBtn = document.querySelector('.js-copy-blob-source-btn');
this.simpleViewer = document.querySelector('.blob-viewer[data-type="simple"]');
this.richViewer = document.querySelector('.blob-viewer[data-type="rich"]');
- this.$blobContentHolder = $('#blob-content-holder');
+ this.$fileHolder = $('.file-holder');
let initialViewerName = document.querySelector('.blob-viewer:not(.hidden)').getAttribute('data-type');
@@ -82,7 +82,7 @@ export default class BlobViewer {
viewer.setAttribute('data-loaded', 'true');
- this.$blobContentHolder.trigger('highlight:line');
+ this.$fileHolder.trigger('highlight:line');
this.toggleCopyButtonState();
});
diff --git a/app/assets/javascripts/dispatcher.js b/app/assets/javascripts/dispatcher.js
index d3d75c4bf4a..15fe87f21ea 100644
--- a/app/assets/javascripts/dispatcher.js
+++ b/app/assets/javascripts/dispatcher.js
@@ -356,6 +356,10 @@ const ShortcutsBlob = require('./shortcuts_blob');
case 'users:show':
new UserCallout();
break;
+ case 'snippets:show':
+ new LineHighlighter();
+ new BlobViewer();
+ break;
}
switch (path.first()) {
case 'sessions':
@@ -434,6 +438,8 @@ const ShortcutsBlob = require('./shortcuts_blob');
shortcut_handler = new ShortcutsNavigation();
if (path[2] === 'show') {
new ZenMode();
+ new LineHighlighter();
+ new BlobViewer();
}
break;
case 'labels':
diff --git a/app/assets/javascripts/line_highlighter.js b/app/assets/javascripts/line_highlighter.js
index a6f7bea99f5..3ac6dedf131 100644
--- a/app/assets/javascripts/line_highlighter.js
+++ b/app/assets/javascripts/line_highlighter.js
@@ -57,9 +57,9 @@ require('vendor/jquery.scrollTo');
}
LineHighlighter.prototype.bindEvents = function() {
- const $blobContentHolder = $('#blob-content-holder');
- $blobContentHolder.on('click', 'a[data-line-number]', this.clickHandler);
- $blobContentHolder.on('highlight:line', this.highlightHash);
+ const $fileHolder = $('.file-holder');
+ $fileHolder.on('click', 'a[data-line-number]', this.clickHandler);
+ $fileHolder.on('highlight:line', this.highlightHash);
};
LineHighlighter.prototype.highlightHash = function() {
diff --git a/app/controllers/concerns/renders_blob.rb b/app/controllers/concerns/renders_blob.rb
index d478c3bb6ca..9faf68e6d97 100644
--- a/app/controllers/concerns/renders_blob.rb
+++ b/app/controllers/concerns/renders_blob.rb
@@ -14,4 +14,8 @@ module RendersBlob
html: view_to_html_string("projects/blob/_viewer", viewer: viewer, load_asynchronously: false)
}
end
+
+ def override_max_blob_size(blob)
+ blob.override_max_size! if params[:override_max_size] == 'true'
+ end
end
diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb
index be5822b2cd4..9489bbddfc4 100644
--- a/app/controllers/projects/blob_controller.rb
+++ b/app/controllers/projects/blob_controller.rb
@@ -35,7 +35,7 @@ class Projects::BlobController < Projects::ApplicationController
end
def show
- @blob.override_max_size! if params[:override_max_size] == 'true'
+ override_max_blob_size(@blob)
respond_to do |format|
format.html do
diff --git a/app/controllers/projects/snippets_controller.rb b/app/controllers/projects/snippets_controller.rb
index 5c9e0d4d1a1..66f913f8f9d 100644
--- a/app/controllers/projects/snippets_controller.rb
+++ b/app/controllers/projects/snippets_controller.rb
@@ -3,6 +3,7 @@ class Projects::SnippetsController < Projects::ApplicationController
include ToggleAwardEmoji
include SpammableActions
include SnippetsActions
+ include RendersBlob
before_action :module_enabled
before_action :snippet, only: [:show, :edit, :destroy, :update, :raw, :toggle_award_emoji, :mark_as_spam]
@@ -55,11 +56,23 @@ class Projects::SnippetsController < Projects::ApplicationController
end
def show
- @note = @project.notes.new(noteable: @snippet)
- @noteable = @snippet
-
- @discussions = @snippet.discussions
- @notes = prepare_notes_for_rendering(@discussions.flat_map(&:notes))
+ blob = @snippet.blob
+ override_max_blob_size(blob)
+
+ respond_to do |format|
+ format.html do
+ @note = @project.notes.new(noteable: @snippet)
+ @noteable = @snippet
+
+ @discussions = @snippet.discussions
+ @notes = prepare_notes_for_rendering(@discussions.flat_map(&:notes))
+ render 'show'
+ end
+
+ format.json do
+ render_blob_json(blob)
+ end
+ end
end
def destroy
diff --git a/app/controllers/snippets_controller.rb b/app/controllers/snippets_controller.rb
index 056910fad67..906833505d1 100644
--- a/app/controllers/snippets_controller.rb
+++ b/app/controllers/snippets_controller.rb
@@ -3,6 +3,7 @@ class SnippetsController < ApplicationController
include SpammableActions
include SnippetsActions
include MarkdownPreview
+ include RendersBlob
before_action :snippet, only: [:show, :edit, :destroy, :update, :raw, :download]
@@ -60,6 +61,18 @@ class SnippetsController < ApplicationController
end
def show
+ blob = @snippet.blob
+ override_max_blob_size(blob)
+
+ respond_to do |format|
+ format.html do
+ render 'show'
+ end
+
+ format.json do
+ render_blob_json(blob)
+ end
+ end
end
def destroy
diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb
index cc47654dc06..377b080b3c6 100644
--- a/app/helpers/blob_helper.rb
+++ b/app/helpers/blob_helper.rb
@@ -119,7 +119,15 @@ module BlobHelper
end
def blob_raw_url
- namespace_project_raw_path(@project.namespace, @project, @id)
+ if @snippet
+ if @snippet.project_id
+ raw_namespace_project_snippet_path(@project.namespace, @project, @snippet)
+ else
+ raw_snippet_path(@snippet)
+ end
+ elsif @blob
+ namespace_project_raw_path(@project.namespace, @project, @id)
+ end
end
# SVGs can contain malicious JavaScript; only include whitelisted
@@ -209,11 +217,21 @@ module BlobHelper
end
def copy_blob_source_button(blob)
+ return unless blob.rendered_as_text?(ignore_errors: false)
+
clipboard_button(target: ".blob-content[data-blob-id='#{blob.id}']", class: "btn btn-sm js-copy-blob-source-btn", title: "Copy source to clipboard")
end
- def open_raw_file_button(path)
- link_to icon('file-code-o'), path, class: 'btn btn-sm has-tooltip', target: '_blank', rel: 'noopener noreferrer', title: 'Open raw', data: { container: 'body' }
+ def open_raw_blob_button(blob)
+ if blob.raw_binary?
+ icon = icon('download')
+ title = 'Download'
+ else
+ icon = icon('file-code-o')
+ title = 'Open raw'
+ end
+
+ link_to icon, blob_raw_url, class: 'btn btn-sm has-tooltip', target: '_blank', rel: 'noopener noreferrer', title: title, data: { container: 'body' }
end
def blob_render_error_reason(viewer)
diff --git a/app/models/repository.rb b/app/models/repository.rb
index d02aea49689..feabfa111fb 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -961,15 +961,13 @@ class Repository
end
def is_ancestor?(ancestor_id, descendant_id)
- # NOTE: This feature is intentionally disabled until
- # https://gitlab.com/gitlab-org/gitlab-ce/issues/30586 is resolved
- # Gitlab::GitalyClient.migrate(:is_ancestor) do |is_enabled|
- # if is_enabled
- # raw_repository.is_ancestor?(ancestor_id, descendant_id)
- # else
- merge_base_commit(ancestor_id, descendant_id) == ancestor_id
- # end
- # end
+ Gitlab::GitalyClient.migrate(:is_ancestor) do |is_enabled|
+ if is_enabled
+ raw_repository.is_ancestor?(ancestor_id, descendant_id)
+ else
+ merge_base_commit(ancestor_id, descendant_id) == ancestor_id
+ end
+ end
end
def empty_repo?
diff --git a/app/models/snippet.rb b/app/models/snippet.rb
index 380835707e8..d8860718cb5 100644
--- a/app/models/snippet.rb
+++ b/app/models/snippet.rb
@@ -1,6 +1,5 @@
class Snippet < ActiveRecord::Base
include Gitlab::VisibilityLevel
- include Linguist::BlobHelper
include CacheMarkdownField
include Noteable
include Participable
@@ -87,47 +86,26 @@ class Snippet < ActiveRecord::Base
]
end
- def data
- content
+ def blob
+ @blob ||= Blob.decorate(SnippetBlob.new(self), nil)
end
def hook_attrs
attributes
end
- def size
- 0
- end
-
def file_name
super.to_s
end
- # alias for compatibility with blobs and highlighting
- def path
- file_name
- end
-
- def name
- file_name
- end
-
def sanitized_file_name
file_name.gsub(/[^a-zA-Z0-9_\-\.]+/, '')
end
- def mode
- nil
- end
-
def visibility_level_field
:visibility_level
end
- def no_highlighting?
- content.lines.count > 1000
- end
-
def notes_with_associations
notes.includes(:author)
end
diff --git a/app/models/snippet_blob.rb b/app/models/snippet_blob.rb
new file mode 100644
index 00000000000..d6cab74eb1a
--- /dev/null
+++ b/app/models/snippet_blob.rb
@@ -0,0 +1,59 @@
+class SnippetBlob
+ include Linguist::BlobHelper
+
+ attr_reader :snippet
+
+ def initialize(snippet)
+ @snippet = snippet
+ end
+
+ delegate :id, to: :snippet
+
+ def name
+ snippet.file_name
+ end
+
+ alias_method :path, :name
+
+ def size
+ data.bytesize
+ end
+
+ def data
+ snippet.content
+ end
+
+ def rendered_markup
+ return unless Gitlab::MarkupHelper.gitlab_markdown?(name)
+
+ Banzai.render_field(snippet, :content)
+ end
+
+ def mode
+ nil
+ end
+
+ def binary?
+ false
+ end
+
+ def load_all_data!(repository)
+ # No-op
+ end
+
+ def lfs_pointer?
+ false
+ end
+
+ def lfs_oid
+ nil
+ end
+
+ def lfs_size
+ nil
+ end
+
+ def truncated?
+ false
+ end
+end
diff --git a/app/views/projects/blob/_header.html.haml b/app/views/projects/blob/_header.html.haml
index b89cd460455..219dc14645b 100644
--- a/app/views/projects/blob/_header.html.haml
+++ b/app/views/projects/blob/_header.html.haml
@@ -15,8 +15,8 @@
= render 'projects/blob/viewer_switcher', blob: blob unless blame
.btn-group{ role: "group" }<
- = copy_blob_source_button(blob) if !blame && blob.rendered_as_text?(ignore_errors: false)
- = open_raw_file_button(namespace_project_raw_path(@project.namespace, @project, @id))
+ = copy_blob_source_button(blob) unless blame
+ = open_raw_blob_button(blob)
= view_on_environment_button(@commit.sha, @path, @environment) if @environment
.btn-group{ role: "group" }<
diff --git a/app/views/projects/blob/viewers/_markup.html.haml b/app/views/projects/blob/viewers/_markup.html.haml
index b9a998d96ff..230305b488d 100644
--- a/app/views/projects/blob/viewers/_markup.html.haml
+++ b/app/views/projects/blob/viewers/_markup.html.haml
@@ -1,3 +1,4 @@
- blob = viewer.blob
+- rendered_markup = blob.rendered_markup if blob.respond_to?(:rendered_markup)
.file-content.wiki
- = markup(blob.name, blob.data)
+ = markup(blob.name, blob.data, rendered: rendered_markup)
diff --git a/app/views/projects/snippets/show.html.haml b/app/views/projects/snippets/show.html.haml
index 7c6be003d4c..7a175f63eeb 100644
--- a/app/views/projects/snippets/show.html.haml
+++ b/app/views/projects/snippets/show.html.haml
@@ -4,7 +4,7 @@
.project-snippets
%article.file-holder.snippet-file-content
- = render 'shared/snippets/blob', raw_path: raw_namespace_project_snippet_path(@project.namespace, @project, @snippet)
+ = render 'shared/snippets/blob'
.row-content-block.top-block.content-component-block
= render 'award_emoji/awards_block', awardable: @snippet, inline: true
diff --git a/app/views/search/results/_snippet_blob.html.haml b/app/views/search/results/_snippet_blob.html.haml
index f2fe5742c12..c4a5131c1a7 100644
--- a/app/views/search/results/_snippet_blob.html.haml
+++ b/app/views/search/results/_snippet_blob.html.haml
@@ -39,7 +39,7 @@
.blob-content
- snippet_chunks.each do |chunk|
- unless chunk[:data].empty?
- = highlight(snippet.file_name, chunk[:data], repository: nil, plain: snippet.no_highlighting?)
+ = highlight(snippet.file_name, chunk[:data], repository: nil, plain: snippet.blob.no_highlighting?)
- else
.file-content.code
.nothing-here-block Empty file
diff --git a/app/views/shared/snippets/_blob.html.haml b/app/views/shared/snippets/_blob.html.haml
index 37c66ff2595..67d186e2874 100644
--- a/app/views/shared/snippets/_blob.html.haml
+++ b/app/views/shared/snippets/_blob.html.haml
@@ -1,29 +1,24 @@
+- blob = @snippet.blob
.js-file-title.file-title-flex-parent
.file-header-content
- = blob_icon @snippet.mode, @snippet.path
+ = blob_icon blob.mode, blob.path
%strong.file-title-name
- = @snippet.path
+ = blob.path
- = copy_file_path_button(@snippet.path)
+ = copy_file_path_button(blob.path)
+
+ %small
+ = number_to_human_size(blob.raw_size)
.file-actions.hidden-xs
+ = render 'projects/blob/viewer_switcher', blob: blob
+
.btn-group{ role: "group" }<
- = copy_blob_source_button(@snippet)
- = open_raw_file_button(raw_path)
+ = copy_blob_source_button(blob)
+ = open_raw_blob_button(blob)
- if defined?(download_path) && download_path
= link_to icon('download'), download_path, class: "btn btn-sm has-tooltip", title: 'Download', data: { container: 'body' }
-- if @snippet.content.empty?
- .file-content.code
- .nothing-here-block Empty file
-- else
- - if markup?(@snippet.file_name)
- .file-content.wiki
- - if gitlab_markdown?(@snippet.file_name)
- = preserve(markdown_field(@snippet, :content))
- - else
- = markup(@snippet.file_name, @snippet.content)
- - else
- = render 'shared/file_highlight', blob: @snippet
+= render 'projects/blob/content', blob: blob
diff --git a/app/views/snippets/show.html.haml b/app/views/snippets/show.html.haml
index e5711ca79c7..8a80013bbfd 100644
--- a/app/views/snippets/show.html.haml
+++ b/app/views/snippets/show.html.haml
@@ -3,7 +3,7 @@
= render 'shared/snippets/header'
%article.file-holder.snippet-file-content
- = render 'shared/snippets/blob', raw_path: raw_snippet_path(@snippet), download_path: download_snippet_path(@snippet)
+ = render 'shared/snippets/blob', download_path: download_snippet_path(@snippet)
.row-content-block.top-block.content-component-block
= render 'award_emoji/awards_block', awardable: @snippet, inline: true
diff --git a/changelogs/unreleased/2246-uuid-is-nil-for-new-installation.yml b/changelogs/unreleased/2246-uuid-is-nil-for-new-installation.yml
deleted file mode 100644
index 70d35f06af4..00000000000
--- a/changelogs/unreleased/2246-uuid-is-nil-for-new-installation.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Lazily sets UUID in ApplicationSetting for new installations
-merge_request:
-author:
diff --git a/changelogs/unreleased/28968-prevent-people-from-creating-branches-if-they-don-have-permission-to-push.yml b/changelogs/unreleased/28968-prevent-people-from-creating-branches-if-they-don-have-permission-to-push.yml
new file mode 100644
index 00000000000..6612cfd8866
--- /dev/null
+++ b/changelogs/unreleased/28968-prevent-people-from-creating-branches-if-they-don-have-permission-to-push.yml
@@ -0,0 +1,4 @@
+---
+title: Prevent people from creating branches if they don't have persmission to push
+merge_request:
+author:
diff --git a/changelogs/unreleased/30645-show-pipeline-events-description.yml b/changelogs/unreleased/30645-show-pipeline-events-description.yml
deleted file mode 100644
index fb75dde1d86..00000000000
--- a/changelogs/unreleased/30645-show-pipeline-events-description.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix pipeline events description for Slack and Mattermost integration
-merge_request: 10908
-author:
diff --git a/changelogs/unreleased/30973-fix-network-graph-ordering.yml b/changelogs/unreleased/30973-fix-network-graph-ordering.yml
deleted file mode 100644
index 420ec107842..00000000000
--- a/changelogs/unreleased/30973-fix-network-graph-ordering.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix ordering of commits in the network graph
-merge_request: 10936
-author:
diff --git a/changelogs/unreleased/31292-milestone-sidebar-display-incorect-number-of-mr-when-minimized.yml b/changelogs/unreleased/31292-milestone-sidebar-display-incorect-number-of-mr-when-minimized.yml
deleted file mode 100644
index dee831c668b..00000000000
--- a/changelogs/unreleased/31292-milestone-sidebar-display-incorect-number-of-mr-when-minimized.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fixed milestone sidebar showing incorrect number of MRs when collapsed
-merge_request: 10933
-author:
diff --git a/changelogs/unreleased/add_index_on_ci_runners_contacted_at.yml b/changelogs/unreleased/add_index_on_ci_runners_contacted_at.yml
deleted file mode 100644
index 10c3206c2ff..00000000000
--- a/changelogs/unreleased/add_index_on_ci_runners_contacted_at.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add index on ci_runners.contacted_at
-merge_request: 10876
-author: blackst0ne
diff --git a/changelogs/unreleased/dm-blob-download-button.yml b/changelogs/unreleased/dm-blob-download-button.yml
new file mode 100644
index 00000000000..bd31137b670
--- /dev/null
+++ b/changelogs/unreleased/dm-blob-download-button.yml
@@ -0,0 +1,4 @@
+---
+title: Show Raw button as Download for binary files
+merge_request:
+author:
diff --git a/changelogs/unreleased/dm-fix-ghost-user-validation.yml b/changelogs/unreleased/dm-fix-ghost-user-validation.yml
deleted file mode 100644
index 4214786cb5a..00000000000
--- a/changelogs/unreleased/dm-fix-ghost-user-validation.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Skip validation when creating internal (ghost, service desk) users
-merge_request:
-author:
diff --git a/changelogs/unreleased/dm-snippet-blob-viewers.yml b/changelogs/unreleased/dm-snippet-blob-viewers.yml
new file mode 100644
index 00000000000..f218095f401
--- /dev/null
+++ b/changelogs/unreleased/dm-snippet-blob-viewers.yml
@@ -0,0 +1,4 @@
+---
+title: Use blob viewers for snippets
+merge_request:
+author:
diff --git a/changelogs/unreleased/dont-blow-up-when-email-has-no-references-header.yml b/changelogs/unreleased/dont-blow-up-when-email-has-no-references-header.yml
new file mode 100644
index 00000000000..a4345b70744
--- /dev/null
+++ b/changelogs/unreleased/dont-blow-up-when-email-has-no-references-header.yml
@@ -0,0 +1,5 @@
+---
+title: Gracefully handle failures for incoming emails which do not match on the To
+ header, and have no References header
+merge_request:
+author:
diff --git a/changelogs/unreleased/pages-0-4-1.yml b/changelogs/unreleased/pages-0-4-1.yml
deleted file mode 100644
index fbc78a36cae..00000000000
--- a/changelogs/unreleased/pages-0-4-1.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Use GitLab Pages v0.4.1
-merge_request:
-author:
diff --git a/changelogs/unreleased/zj-accept-default-branch-param.yml b/changelogs/unreleased/zj-accept-default-branch-param.yml
deleted file mode 100644
index 8f6fa8a6386..00000000000
--- a/changelogs/unreleased/zj-accept-default-branch-param.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Ensure the chat notifications service properly saves the "Notify only default branch" setting
-merge_request: 10959
-author:
diff --git a/db/migrate/20160419122101_add_only_allow_merge_if_build_succeeds_to_projects.rb b/db/migrate/20160419122101_add_only_allow_merge_if_build_succeeds_to_projects.rb
index 69d64ccd006..22bac46e25c 100644
--- a/db/migrate/20160419122101_add_only_allow_merge_if_build_succeeds_to_projects.rb
+++ b/db/migrate/20160419122101_add_only_allow_merge_if_build_succeeds_to_projects.rb
@@ -1,3 +1,4 @@
+# rubocop:disable Migration/AddColumnWithDefaultToLargeTable
class AddOnlyAllowMergeIfBuildSucceedsToProjects < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
diff --git a/db/migrate/20160608195742_add_repository_storage_to_projects.rb b/db/migrate/20160608195742_add_repository_storage_to_projects.rb
index c700d2b569d..0f3664c13ef 100644
--- a/db/migrate/20160608195742_add_repository_storage_to_projects.rb
+++ b/db/migrate/20160608195742_add_repository_storage_to_projects.rb
@@ -1,3 +1,4 @@
+# rubocop:disable Migration/AddColumnWithDefaultToLargeTable
class AddRepositoryStorageToProjects < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
diff --git a/db/migrate/20160715154212_add_request_access_enabled_to_projects.rb b/db/migrate/20160715154212_add_request_access_enabled_to_projects.rb
index bf0131c6d76..5dc26f8982a 100644
--- a/db/migrate/20160715154212_add_request_access_enabled_to_projects.rb
+++ b/db/migrate/20160715154212_add_request_access_enabled_to_projects.rb
@@ -1,3 +1,4 @@
+# rubocop:disable Migration/AddColumnWithDefaultToLargeTable
class AddRequestAccessEnabledToProjects < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
diff --git a/db/migrate/20160715204316_add_request_access_enabled_to_groups.rb b/db/migrate/20160715204316_add_request_access_enabled_to_groups.rb
index e7b14cd3ee2..4a317646788 100644
--- a/db/migrate/20160715204316_add_request_access_enabled_to_groups.rb
+++ b/db/migrate/20160715204316_add_request_access_enabled_to_groups.rb
@@ -1,3 +1,4 @@
+# rubocop:disable Migration/AddColumnWithDefaultToLargeTable
class AddRequestAccessEnabledToGroups < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
diff --git a/db/migrate/20160831223750_remove_features_enabled_from_projects.rb b/db/migrate/20160831223750_remove_features_enabled_from_projects.rb
index a2c207b49ea..7414a28ac97 100644
--- a/db/migrate/20160831223750_remove_features_enabled_from_projects.rb
+++ b/db/migrate/20160831223750_remove_features_enabled_from_projects.rb
@@ -1,6 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
+# rubocop:disable Migration/AddColumnWithDefaultToLargeTable
class RemoveFeaturesEnabledFromProjects < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
diff --git a/db/migrate/20160913162434_remove_projects_pushes_since_gc.rb b/db/migrate/20160913162434_remove_projects_pushes_since_gc.rb
index 18ea9d43a43..0100e30a733 100644
--- a/db/migrate/20160913162434_remove_projects_pushes_since_gc.rb
+++ b/db/migrate/20160913162434_remove_projects_pushes_since_gc.rb
@@ -1,6 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
+# rubocop:disable Migration/AddColumnWithDefaultToLargeTable
class RemoveProjectsPushesSinceGc < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
diff --git a/db/migrate/20170124193147_add_two_factor_columns_to_namespaces.rb b/db/migrate/20170124193147_add_two_factor_columns_to_namespaces.rb
index df5cddeb205..ae37da275fd 100644
--- a/db/migrate/20170124193147_add_two_factor_columns_to_namespaces.rb
+++ b/db/migrate/20170124193147_add_two_factor_columns_to_namespaces.rb
@@ -1,3 +1,4 @@
+# rubocop:disable Migration/AddColumnWithDefaultToLargeTable
class AddTwoFactorColumnsToNamespaces < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
diff --git a/db/migrate/20170124193205_add_two_factor_columns_to_users.rb b/db/migrate/20170124193205_add_two_factor_columns_to_users.rb
index 1d1021fcbb3..8d4aefa4365 100644
--- a/db/migrate/20170124193205_add_two_factor_columns_to_users.rb
+++ b/db/migrate/20170124193205_add_two_factor_columns_to_users.rb
@@ -1,3 +1,4 @@
+# rubocop:disable Migration/AddColumnWithDefaultToLargeTable
class AddTwoFactorColumnsToUsers < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
diff --git a/db/migrate/20170301125302_add_printing_merge_request_link_enabled_to_project.rb b/db/migrate/20170301125302_add_printing_merge_request_link_enabled_to_project.rb
index f54608ecceb..7ad01a04815 100644
--- a/db/migrate/20170301125302_add_printing_merge_request_link_enabled_to_project.rb
+++ b/db/migrate/20170301125302_add_printing_merge_request_link_enabled_to_project.rb
@@ -1,6 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
+# rubocop:disable Migration/AddColumnWithDefaultToLargeTable
class AddPrintingMergeRequestLinkEnabledToProject < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
diff --git a/db/migrate/20170305180853_add_auto_cancel_pending_pipelines_to_project.rb b/db/migrate/20170305180853_add_auto_cancel_pending_pipelines_to_project.rb
index aa64f2dddca..f335e77fb5e 100644
--- a/db/migrate/20170305180853_add_auto_cancel_pending_pipelines_to_project.rb
+++ b/db/migrate/20170305180853_add_auto_cancel_pending_pipelines_to_project.rb
@@ -1,3 +1,4 @@
+# rubocop:disable Migration/AddColumnWithDefaultToLargeTable
class AddAutoCancelPendingPipelinesToProject < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
diff --git a/db/migrate/20170315174634_revert_add_notified_of_own_activity_to_users.rb b/db/migrate/20170315174634_revert_add_notified_of_own_activity_to_users.rb
index b39c0a3be0f..6c9fe19ca34 100644
--- a/db/migrate/20170315174634_revert_add_notified_of_own_activity_to_users.rb
+++ b/db/migrate/20170315174634_revert_add_notified_of_own_activity_to_users.rb
@@ -1,3 +1,4 @@
+# rubocop:disable Migration/AddColumnWithDefaultToLargeTable
class RevertAddNotifiedOfOwnActivityToUsers < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
diff --git a/doc/user/profile/account/delete_account.md b/doc/user/profile/account/delete_account.md
index 505248536c8..b5d3b009044 100644
--- a/doc/user/profile/account/delete_account.md
+++ b/doc/user/profile/account/delete_account.md
@@ -1,7 +1,7 @@
# Deleting a User Account
- As a user, you can delete your own account by navigating to **Settings** > **Account** and selecting **Delete account**
-- As an admin, you can delete a user account by navigating to the **Admin Area**, selecting the **Users** tab, selecting a user, and clicking on **Remvoe user**
+- As an admin, you can delete a user account by navigating to the **Admin Area**, selecting the **Users** tab, selecting a user, and clicking on **Remove user**
## Associated Records
diff --git a/features/project/snippets.feature b/features/project/snippets.feature
index 3c51ea56585..50bc4c93df3 100644
--- a/features/project/snippets.feature
+++ b/features/project/snippets.feature
@@ -11,6 +11,7 @@ Feature: Project Snippets
Then I should see "Snippet one" in snippets
And I should not see "Snippet two" in snippets
+ @javascript
Scenario: I create new project snippet
Given I click link "New snippet"
And I submit new snippet "Snippet three"
diff --git a/features/snippets/snippets.feature b/features/snippets/snippets.feature
index e15d7c79342..1ad02780229 100644
--- a/features/snippets/snippets.feature
+++ b/features/snippets/snippets.feature
@@ -5,6 +5,7 @@ Feature: Snippets
And I have public "Personal snippet one" snippet
And I have private "Personal snippet private" snippet
+ @javascript
Scenario: I create new snippet
Given I visit new snippet page
And I submit new snippet "Personal snippet three"
diff --git a/features/steps/project/snippets.rb b/features/steps/project/snippets.rb
index a3bebfa4b71..60febd20104 100644
--- a/features/steps/project/snippets.rb
+++ b/features/steps/project/snippets.rb
@@ -3,6 +3,7 @@ class Spinach::Features::ProjectSnippets < Spinach::FeatureSteps
include SharedProject
include SharedNote
include SharedPaths
+ include WaitForAjax
step 'project "Shop" have "Snippet one" snippet' do
create(:project_snippet,
@@ -55,9 +56,10 @@ class Spinach::Features::ProjectSnippets < Spinach::FeatureSteps
fill_in "project_snippet_title", with: "Snippet three"
fill_in "project_snippet_file_name", with: "my_snippet.rb"
page.within('.file-editor') do
- find(:xpath, "//input[@id='project_snippet_content']").set 'Content of snippet three'
+ find('.ace_editor').native.send_keys 'Content of snippet three'
end
click_button "Create snippet"
+ wait_for_ajax
end
step 'I should see snippet "Snippet three"' do
@@ -79,6 +81,7 @@ class Spinach::Features::ProjectSnippets < Spinach::FeatureSteps
fill_in "note_note", with: "Good snippet!"
click_button "Comment"
end
+ wait_for_ajax
end
step 'I should see comment "Good snippet!"' do
diff --git a/features/steps/project/source/browse_files.rb b/features/steps/project/source/browse_files.rb
index 36fe21a047c..ef09bddddd8 100644
--- a/features/steps/project/source/browse_files.rb
+++ b/features/steps/project/source/browse_files.rb
@@ -367,7 +367,7 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps
step 'I should see buttons for allowed commands' do
page.within '.content' do
- expect(page).to have_link 'Open raw'
+ expect(page).to have_link 'Download'
expect(page).to have_content 'History'
expect(page).to have_content 'Permalink'
expect(page).not_to have_content 'Edit'
diff --git a/features/steps/snippets/snippets.rb b/features/steps/snippets/snippets.rb
index 19366b11071..0b3e942a4fd 100644
--- a/features/steps/snippets/snippets.rb
+++ b/features/steps/snippets/snippets.rb
@@ -3,6 +3,7 @@ class Spinach::Features::Snippets < Spinach::FeatureSteps
include SharedPaths
include SharedProject
include SharedSnippet
+ include WaitForAjax
step 'I click link "Personal snippet one"' do
click_link "Personal snippet one"
@@ -26,9 +27,10 @@ class Spinach::Features::Snippets < Spinach::FeatureSteps
fill_in "personal_snippet_title", with: "Personal snippet three"
fill_in "personal_snippet_file_name", with: "my_snippet.rb"
page.within('.file-editor') do
- find(:xpath, "//input[@id='personal_snippet_content']").set 'Content of snippet three'
+ find('.ace_editor').native.send_keys 'Content of snippet three'
end
click_button "Create snippet"
+ wait_for_ajax
end
step 'I submit new internal snippet' do
diff --git a/lib/gitlab/email/receiver.rb b/lib/gitlab/email/receiver.rb
index 419d56a51e0..c270c0ea9ff 100644
--- a/lib/gitlab/email/receiver.rb
+++ b/lib/gitlab/email/receiver.rb
@@ -70,6 +70,8 @@ module Gitlab
# Handle emails from clients which append with commas,
# example clients are Microsoft exchange and iOS app
Gitlab::IncomingEmail.scan_fallback_references(references)
+ when nil
+ []
end
end
diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb
index 452dba7971d..18eda0279f7 100644
--- a/lib/gitlab/git/repository.rb
+++ b/lib/gitlab/git/repository.rb
@@ -451,7 +451,7 @@ module Gitlab
# Returns true is +from+ is direct ancestor to +to+, otherwise false
def is_ancestor?(from, to)
- Gitlab::GitalyClient::Commit.is_ancestor(self, from, to)
+ gitaly_commit_client.is_ancestor(from, to)
end
# Return an array of Diff objects that represent the diff
@@ -1273,6 +1273,10 @@ module Gitlab
@gitaly_ref_client ||= Gitlab::GitalyClient::Ref.new(self)
end
+ def gitaly_commit_client
+ @gitaly_commit_client ||= Gitlab::GitalyClient::Commit.new(self)
+ end
+
# Returns the `Rugged` sorting type constant for a given
# sort type key. Valid keys are `:none`, `:topo`, and `:date`
def rugged_sort_type(key)
diff --git a/lib/gitlab/gitaly_client/commit.rb b/lib/gitlab/gitaly_client/commit.rb
index b7f39f3ef0b..27db1e19bc1 100644
--- a/lib/gitlab/gitaly_client/commit.rb
+++ b/lib/gitlab/gitaly_client/commit.rb
@@ -5,6 +5,23 @@ module Gitlab
# See http://stackoverflow.com/a/40884093/1856239 and https://github.com/git/git/blob/3ad8b5bf26362ac67c9020bf8c30eee54a84f56d/cache.h#L1011-L1012
EMPTY_TREE_ID = '4b825dc642cb6eb9a060e54bf8d69288fbee4904'.freeze
+ attr_accessor :stub
+
+ def initialize(repository)
+ @gitaly_repo = repository.gitaly_repository
+ @stub = Gitaly::Commit::Stub.new(nil, nil, channel_override: repository.gitaly_channel)
+ end
+
+ def is_ancestor(ancestor_id, child_id)
+ request = Gitaly::CommitIsAncestorRequest.new(
+ repository: @gitaly_repo,
+ ancestor_id: ancestor_id,
+ child_id: child_id
+ )
+
+ @stub.commit_is_ancestor(request).value
+ end
+
class << self
def diff_from_parent(commit, options = {})
repository = commit.project.repository
@@ -20,18 +37,6 @@ module Gitlab
Gitlab::Git::DiffCollection.new(stub.commit_diff(request), options)
end
-
- def is_ancestor(repository, ancestor_id, child_id)
- gitaly_repo = repository.gitaly_repository
- stub = Gitaly::Commit::Stub.new(nil, nil, channel_override: repository.gitaly_channel)
- request = Gitaly::CommitIsAncestorRequest.new(
- repository: gitaly_repo,
- ancestor_id: ancestor_id,
- child_id: child_id
- )
-
- stub.commit_is_ancestor(request).value
- end
end
end
end
diff --git a/lib/gitlab/user_access.rb b/lib/gitlab/user_access.rb
index 54728e5ff0e..e46ff313654 100644
--- a/lib/gitlab/user_access.rb
+++ b/lib/gitlab/user_access.rb
@@ -44,9 +44,7 @@ module Gitlab
if ProtectedBranch.protected?(project, ref)
return true if project.empty_repo? && project.user_can_push_to_empty_repo?(user)
- has_access = project.protected_branches.protected_ref_accessible_to?(ref, user, action: :push)
-
- has_access || !project.repository.branch_exists?(ref) && can_merge_to_branch?(ref)
+ project.protected_branches.protected_ref_accessible_to?(ref, user, action: :push)
else
user.can?(:push_code, project)
end
diff --git a/rubocop/cop/migration/add_column_with_default_to_large_table.rb b/rubocop/cop/migration/add_column_with_default_to_large_table.rb
new file mode 100644
index 00000000000..2372e6b60ea
--- /dev/null
+++ b/rubocop/cop/migration/add_column_with_default_to_large_table.rb
@@ -0,0 +1,51 @@
+require_relative '../../migration_helpers'
+
+module RuboCop
+ module Cop
+ module Migration
+ # This cop checks for `add_column_with_default` on a table that's been
+ # explicitly blacklisted because of its size.
+ #
+ # Even though this helper performs the update in batches to avoid
+ # downtime, using it with tables with millions of rows still causes a
+ # significant delay in the deploy process and is best avoided.
+ #
+ # See https://gitlab.com/gitlab-com/infrastructure/issues/1602 for more
+ # information.
+ class AddColumnWithDefaultToLargeTable < RuboCop::Cop::Cop
+ include MigrationHelpers
+
+ MSG = 'Using `add_column_with_default` on the `%s` table will take a ' \
+ 'long time to complete, and should be avoided unless absolutely ' \
+ 'necessary'.freeze
+
+ LARGE_TABLES = %i[
+ events
+ issues
+ merge_requests
+ namespaces
+ notes
+ projects
+ routes
+ users
+ ].freeze
+
+ def_node_matcher :add_column_with_default?, <<~PATTERN
+ (send nil :add_column_with_default $(sym ...) ...)
+ PATTERN
+
+ def on_send(node)
+ return unless in_migration?(node)
+
+ matched = add_column_with_default?(node)
+ return unless matched
+
+ table = matched.to_a.first
+ return unless LARGE_TABLES.include?(table)
+
+ add_offense(node, :expression, format(MSG, table))
+ end
+ end
+ end
+ end
+end
diff --git a/rubocop/cop/migration/add_column_with_default.rb b/rubocop/cop/migration/reversible_add_column_with_default.rb
index 54a920d4b49..f413f06f39b 100644
--- a/rubocop/cop/migration/add_column_with_default.rb
+++ b/rubocop/cop/migration/reversible_add_column_with_default.rb
@@ -5,29 +5,30 @@ module RuboCop
module Migration
# Cop that checks if `add_column_with_default` is used with `up`/`down` methods
# and not `change`.
- class AddColumnWithDefault < RuboCop::Cop::Cop
+ class ReversibleAddColumnWithDefault < RuboCop::Cop::Cop
include MigrationHelpers
+ def_node_matcher :add_column_with_default?, <<~PATTERN
+ (send nil :add_column_with_default $...)
+ PATTERN
+
+ def_node_matcher :defines_change?, <<~PATTERN
+ (def :change ...)
+ PATTERN
+
MSG = '`add_column_with_default` is not reversible so you must manually define ' \
'the `up` and `down` methods in your migration class, using `remove_column` in `down`'.freeze
def on_send(node)
return unless in_migration?(node)
-
- name = node.children[1]
-
- return unless name == :add_column_with_default
+ return unless add_column_with_default?(node)
node.each_ancestor(:def) do |def_node|
- next unless method_name(def_node) == :change
+ next unless defines_change?(def_node)
add_offense(def_node, :name)
end
end
-
- def method_name(node)
- node.children.first
- end
end
end
end
diff --git a/rubocop/rubocop.rb b/rubocop/rubocop.rb
index d580aa6857a..4ff204f939e 100644
--- a/rubocop/rubocop.rb
+++ b/rubocop/rubocop.rb
@@ -1,9 +1,10 @@
require_relative 'cop/custom_error_class'
require_relative 'cop/gem_fetcher'
require_relative 'cop/migration/add_column'
-require_relative 'cop/migration/add_column_with_default'
+require_relative 'cop/migration/add_column_with_default_to_large_table'
require_relative 'cop/migration/add_concurrent_foreign_key'
require_relative 'cop/migration/add_concurrent_index'
require_relative 'cop/migration/add_index'
require_relative 'cop/migration/remove_concurrent_index'
require_relative 'cop/migration/remove_index'
+require_relative 'cop/migration/reversible_add_column_with_default'
diff --git a/scripts/lint-doc.sh b/scripts/lint-doc.sh
index 62236ed539a..54c1ef3dfdd 100755
--- a/scripts/lint-doc.sh
+++ b/scripts/lint-doc.sh
@@ -21,4 +21,3 @@ fi
echo "✔ Linting passed"
exit 0
-
diff --git a/scripts/static-analysis b/scripts/static-analysis
new file mode 100755
index 00000000000..192d9d4c3ba
--- /dev/null
+++ b/scripts/static-analysis
@@ -0,0 +1,40 @@
+#!/usr/bin/env ruby
+
+require ::File.expand_path('../lib/gitlab/popen', __dir__)
+
+tasks = [
+ %w[bundle exec rake config_lint],
+ %w[bundle exec rake flay],
+ %w[bundle exec rake haml_lint],
+ %w[bundle exec rake scss_lint],
+ %w[bundle exec rake brakeman],
+ %w[bundle exec license_finder],
+ %w[scripts/lint-doc.sh],
+ %w[yarn run eslint],
+ %w[bundle exec rubocop --require rubocop-rspec]
+]
+
+failed_tasks = tasks.reduce({}) do |failures, task|
+ output, status = Gitlab::Popen.popen(task)
+
+ puts "Running: #{task.join(' ')}"
+ puts output
+
+ failures[task.join(' ')] = output unless status.zero?
+
+ failures
+end
+
+if failed_tasks.empty?
+ puts 'All static analyses passed successfully.'
+else
+ puts "\n===================================================\n\n"
+ puts "Some static analyses failed:"
+
+ failed_tasks.each do |failed_task, output|
+ puts "\n**** #{failed_task} failed with the following error:\n\n"
+ puts output
+ end
+
+ exit 1
+end
diff --git a/spec/features/merge_requests/create_new_mr_spec.rb b/spec/features/merge_requests/create_new_mr_spec.rb
index 16b09933bda..e1353ec71ed 100644
--- a/spec/features/merge_requests/create_new_mr_spec.rb
+++ b/spec/features/merge_requests/create_new_mr_spec.rb
@@ -20,6 +20,7 @@ feature 'Create New Merge Request', feature: true, js: true do
expect(page).to have_content('Target branch')
first('.js-source-branch').click
+ first('.dropdown-source-branch .dropdown-content')
find('.dropdown-source-branch .dropdown-content a', match: :first).click
expect(page).to have_content "b83d6e3"
diff --git a/spec/features/projects/blobs/blob_show_spec.rb b/spec/features/projects/blobs/blob_show_spec.rb
index cc11cb7a55f..6a6f8b4f4d5 100644
--- a/spec/features/projects/blobs/blob_show_spec.rb
+++ b/spec/features/projects/blobs/blob_show_spec.rb
@@ -1,13 +1,10 @@
require 'spec_helper'
feature 'File blob', :js, feature: true do
- include TreeHelper
- include WaitForAjax
-
let(:project) { create(:project, :public) }
def visit_blob(path, fragment = nil)
- visit namespace_project_blob_path(project.namespace, project, tree_join('master', path), anchor: fragment)
+ visit namespace_project_blob_path(project.namespace, project, File.join('master', path), anchor: fragment)
end
context 'Ruby file' do
@@ -27,6 +24,9 @@ feature 'File blob', :js, feature: true do
# shows an enabled copy button
expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)')
+
+ # shows a raw button
+ expect(page).to have_link('Open raw')
end
end
end
@@ -39,7 +39,7 @@ feature 'File blob', :js, feature: true do
wait_for_ajax
end
- it 'displays the blob' do
+ it 'displays the blob using the rich viewer' do
aggregate_failures do
# hides the simple viewer
expect(page).to have_selector('.blob-viewer[data-type="simple"]', visible: false)
@@ -53,6 +53,9 @@ feature 'File blob', :js, feature: true do
# shows a disabled copy button
expect(page).to have_selector('.js-copy-blob-source-btn.disabled')
+
+ # shows a raw button
+ expect(page).to have_link('Open raw')
end
end
@@ -63,7 +66,7 @@ feature 'File blob', :js, feature: true do
wait_for_ajax
end
- it 'displays the blob' do
+ it 'displays the blob using the simple viewer' do
aggregate_failures do
# hides the rich viewer
expect(page).to have_selector('.blob-viewer[data-type="simple"]')
@@ -84,7 +87,7 @@ feature 'File blob', :js, feature: true do
wait_for_ajax
end
- it 'displays the blob' do
+ it 'displays the blob using the rich viewer' do
aggregate_failures do
# hides the simple viewer
expect(page).to have_selector('.blob-viewer[data-type="simple"]', visible: false)
@@ -105,7 +108,7 @@ feature 'File blob', :js, feature: true do
wait_for_ajax
end
- it 'displays the blob' do
+ it 'displays the blob using the simple viewer' do
aggregate_failures do
# hides the rich viewer
expect(page).to have_selector('.blob-viewer[data-type="simple"]')
@@ -163,6 +166,9 @@ feature 'File blob', :js, feature: true do
# does not show a copy button
expect(page).not_to have_selector('.js-copy-blob-source-btn')
+
+ # shows a raw button
+ expect(page).to have_link('Open raw')
end
end
@@ -206,6 +212,9 @@ feature 'File blob', :js, feature: true do
# shows an enabled copy button
expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)')
+
+ # shows a raw button
+ expect(page).to have_link('Open raw')
end
end
end
@@ -240,6 +249,9 @@ feature 'File blob', :js, feature: true do
# does not show a copy button
expect(page).not_to have_selector('.js-copy-blob-source-btn')
+
+ # shows a download button
+ expect(page).to have_link('Download')
end
end
end
@@ -265,6 +277,9 @@ feature 'File blob', :js, feature: true do
# does not show a copy button
expect(page).not_to have_selector('.js-copy-blob-source-btn')
+
+ # shows a download button
+ expect(page).to have_link('Download')
end
end
end
@@ -286,6 +301,9 @@ feature 'File blob', :js, feature: true do
# shows an enabled copy button
expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)')
+
+ # shows a raw button
+ expect(page).to have_link('Open raw')
end
end
end
@@ -308,6 +326,9 @@ feature 'File blob', :js, feature: true do
# does not show a copy button
expect(page).not_to have_selector('.js-copy-blob-source-btn')
+
+ # shows a download button
+ expect(page).to have_link('Download')
end
end
end
diff --git a/spec/features/projects/snippets/show_spec.rb b/spec/features/projects/snippets/show_spec.rb
new file mode 100644
index 00000000000..7eb1210e307
--- /dev/null
+++ b/spec/features/projects/snippets/show_spec.rb
@@ -0,0 +1,132 @@
+require 'spec_helper'
+
+feature 'Project snippet', :js, feature: true do
+ let(:user) { create(:user) }
+ let(:project) { create(:project, :repository) }
+ let(:snippet) { create(:project_snippet, project: project, file_name: file_name, content: content) }
+
+ before do
+ project.team << [user, :master]
+ login_as(user)
+ end
+
+ context 'Ruby file' do
+ let(:file_name) { 'popen.rb' }
+ let(:content) { project.repository.blob_at('master', 'files/ruby/popen.rb').data }
+
+ before do
+ visit namespace_project_snippet_path(project.namespace, project, snippet)
+
+ wait_for_ajax
+ end
+
+ it 'displays the blob' do
+ aggregate_failures do
+ # shows highlighted Ruby code
+ expect(page).to have_content("require 'fileutils'")
+
+ # does not show a viewer switcher
+ expect(page).not_to have_selector('.js-blob-viewer-switcher')
+
+ # shows an enabled copy button
+ expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)')
+ end
+ end
+ end
+
+ context 'Markdown file' do
+ let(:file_name) { 'ruby-style-guide.md' }
+ let(:content) { project.repository.blob_at('master', 'files/markdown/ruby-style-guide.md').data }
+
+ context 'visiting directly' do
+ before do
+ visit namespace_project_snippet_path(project.namespace, project, snippet)
+
+ wait_for_ajax
+ end
+
+ it 'displays the blob using the rich viewer' do
+ aggregate_failures do
+ # hides the simple viewer
+ expect(page).to have_selector('.blob-viewer[data-type="simple"]', visible: false)
+ expect(page).to have_selector('.blob-viewer[data-type="rich"]')
+
+ # shows rendered Markdown
+ expect(page).to have_link("PEP-8")
+
+ # shows a viewer switcher
+ expect(page).to have_selector('.js-blob-viewer-switcher')
+
+ # shows a disabled copy button
+ expect(page).to have_selector('.js-copy-blob-source-btn.disabled')
+ end
+ end
+
+ context 'switching to the simple viewer' do
+ before do
+ find('.js-blob-viewer-switch-btn[data-viewer=simple]').click
+
+ wait_for_ajax
+ end
+
+ it 'displays the blob using the simple viewer' do
+ aggregate_failures do
+ # hides the rich viewer
+ expect(page).to have_selector('.blob-viewer[data-type="simple"]')
+ expect(page).to have_selector('.blob-viewer[data-type="rich"]', visible: false)
+
+ # shows highlighted Markdown code
+ expect(page).to have_content("[PEP-8](http://www.python.org/dev/peps/pep-0008/)")
+
+ # shows an enabled copy button
+ expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)')
+ end
+ end
+
+ context 'switching to the rich viewer again' do
+ before do
+ find('.js-blob-viewer-switch-btn[data-viewer=rich]').click
+
+ wait_for_ajax
+ end
+
+ it 'displays the blob using the rich viewer' do
+ aggregate_failures do
+ # hides the simple viewer
+ expect(page).to have_selector('.blob-viewer[data-type="simple"]', visible: false)
+ expect(page).to have_selector('.blob-viewer[data-type="rich"]')
+
+ # shows an enabled copy button
+ expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)')
+ end
+ end
+ end
+ end
+ end
+
+ context 'visiting with a line number anchor' do
+ before do
+ visit namespace_project_snippet_path(project.namespace, project, snippet, anchor: 'L1')
+
+ wait_for_ajax
+ end
+
+ it 'displays the blob using the simple viewer' do
+ aggregate_failures do
+ # hides the rich viewer
+ expect(page).to have_selector('.blob-viewer[data-type="simple"]')
+ expect(page).to have_selector('.blob-viewer[data-type="rich"]', visible: false)
+
+ # highlights the line in question
+ expect(page).to have_selector('#LC1.hll')
+
+ # shows highlighted Markdown code
+ expect(page).to have_content("[PEP-8](http://www.python.org/dev/peps/pep-0008/)")
+
+ # shows an enabled copy button
+ expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)')
+ end
+ end
+ end
+ end
+end
diff --git a/spec/features/snippets/create_snippet_spec.rb b/spec/features/snippets/create_snippet_spec.rb
index 5470276bf06..9409c323288 100644
--- a/spec/features/snippets/create_snippet_spec.rb
+++ b/spec/features/snippets/create_snippet_spec.rb
@@ -1,6 +1,6 @@
require 'rails_helper'
-feature 'Create Snippet', feature: true do
+feature 'Create Snippet', :js, feature: true do
before do
login_as :user
visit new_snippet_path
@@ -9,10 +9,11 @@ feature 'Create Snippet', feature: true do
scenario 'Authenticated user creates a snippet' do
fill_in 'personal_snippet_title', with: 'My Snippet Title'
page.within('.file-editor') do
- find(:xpath, "//input[@id='personal_snippet_content']").set 'Hello World!'
+ find('.ace_editor').native.send_keys 'Hello World!'
end
click_button 'Create snippet'
+ wait_for_ajax
expect(page).to have_content('My Snippet Title')
expect(page).to have_content('Hello World!')
@@ -22,10 +23,11 @@ feature 'Create Snippet', feature: true do
fill_in 'personal_snippet_title', with: 'My Snippet Title'
page.within('.file-editor') do
find(:xpath, "//input[@id='personal_snippet_file_name']").set 'snippet+file+name'
- find(:xpath, "//input[@id='personal_snippet_content']").set 'Hello World!'
+ find('.ace_editor').native.send_keys 'Hello World!'
end
click_button 'Create snippet'
+ wait_for_ajax
expect(page).to have_content('My Snippet Title')
expect(page).to have_content('snippet+file+name')
diff --git a/spec/features/snippets/public_snippets_spec.rb b/spec/features/snippets/public_snippets_spec.rb
index 34300ccb940..2df483818c3 100644
--- a/spec/features/snippets/public_snippets_spec.rb
+++ b/spec/features/snippets/public_snippets_spec.rb
@@ -1,10 +1,11 @@
require 'rails_helper'
-feature 'Public Snippets', feature: true do
+feature 'Public Snippets', :js, feature: true do
scenario 'Unauthenticated user should see public snippets' do
public_snippet = create(:personal_snippet, :public)
visit snippet_path(public_snippet)
+ wait_for_ajax
expect(page).to have_content(public_snippet.content)
end
diff --git a/spec/features/snippets/show_spec.rb b/spec/features/snippets/show_spec.rb
new file mode 100644
index 00000000000..cebcba6a230
--- /dev/null
+++ b/spec/features/snippets/show_spec.rb
@@ -0,0 +1,126 @@
+require 'spec_helper'
+
+feature 'Snippet', :js, feature: true do
+ let(:project) { create(:project, :repository) }
+ let(:snippet) { create(:personal_snippet, :public, file_name: file_name, content: content) }
+
+ context 'Ruby file' do
+ let(:file_name) { 'popen.rb' }
+ let(:content) { project.repository.blob_at('master', 'files/ruby/popen.rb').data }
+
+ before do
+ visit snippet_path(snippet)
+
+ wait_for_ajax
+ end
+
+ it 'displays the blob' do
+ aggregate_failures do
+ # shows highlighted Ruby code
+ expect(page).to have_content("require 'fileutils'")
+
+ # does not show a viewer switcher
+ expect(page).not_to have_selector('.js-blob-viewer-switcher')
+
+ # shows an enabled copy button
+ expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)')
+ end
+ end
+ end
+
+ context 'Markdown file' do
+ let(:file_name) { 'ruby-style-guide.md' }
+ let(:content) { project.repository.blob_at('master', 'files/markdown/ruby-style-guide.md').data }
+
+ context 'visiting directly' do
+ before do
+ visit snippet_path(snippet)
+
+ wait_for_ajax
+ end
+
+ it 'displays the blob using the rich viewer' do
+ aggregate_failures do
+ # hides the simple viewer
+ expect(page).to have_selector('.blob-viewer[data-type="simple"]', visible: false)
+ expect(page).to have_selector('.blob-viewer[data-type="rich"]')
+
+ # shows rendered Markdown
+ expect(page).to have_link("PEP-8")
+
+ # shows a viewer switcher
+ expect(page).to have_selector('.js-blob-viewer-switcher')
+
+ # shows a disabled copy button
+ expect(page).to have_selector('.js-copy-blob-source-btn.disabled')
+ end
+ end
+
+ context 'switching to the simple viewer' do
+ before do
+ find('.js-blob-viewer-switch-btn[data-viewer=simple]').click
+
+ wait_for_ajax
+ end
+
+ it 'displays the blob using the simple viewer' do
+ aggregate_failures do
+ # hides the rich viewer
+ expect(page).to have_selector('.blob-viewer[data-type="simple"]')
+ expect(page).to have_selector('.blob-viewer[data-type="rich"]', visible: false)
+
+ # shows highlighted Markdown code
+ expect(page).to have_content("[PEP-8](http://www.python.org/dev/peps/pep-0008/)")
+
+ # shows an enabled copy button
+ expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)')
+ end
+ end
+
+ context 'switching to the rich viewer again' do
+ before do
+ find('.js-blob-viewer-switch-btn[data-viewer=rich]').click
+
+ wait_for_ajax
+ end
+
+ it 'displays the blob using the rich viewer' do
+ aggregate_failures do
+ # hides the simple viewer
+ expect(page).to have_selector('.blob-viewer[data-type="simple"]', visible: false)
+ expect(page).to have_selector('.blob-viewer[data-type="rich"]')
+
+ # shows an enabled copy button
+ expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)')
+ end
+ end
+ end
+ end
+ end
+
+ context 'visiting with a line number anchor' do
+ before do
+ visit snippet_path(snippet, anchor: 'L1')
+
+ wait_for_ajax
+ end
+
+ it 'displays the blob using the simple viewer' do
+ aggregate_failures do
+ # hides the rich viewer
+ expect(page).to have_selector('.blob-viewer[data-type="simple"]')
+ expect(page).to have_selector('.blob-viewer[data-type="rich"]', visible: false)
+
+ # highlights the line in question
+ expect(page).to have_selector('#LC1.hll')
+
+ # shows highlighted Markdown code
+ expect(page).to have_content("[PEP-8](http://www.python.org/dev/peps/pep-0008/)")
+
+ # shows an enabled copy button
+ expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)')
+ end
+ end
+ end
+ end
+end
diff --git a/spec/helpers/blob_helper_spec.rb b/spec/helpers/blob_helper_spec.rb
index 379f62f73e1..075f1887d91 100644
--- a/spec/helpers/blob_helper_spec.rb
+++ b/spec/helpers/blob_helper_spec.rb
@@ -157,6 +157,7 @@ describe BlobHelper do
describe '#blob_render_error_options' do
before do
assign(:project, project)
+ assign(:blob, blob)
assign(:id, File.join('master', blob.path))
controller.params[:controller] = 'projects/blob'
diff --git a/spec/javascripts/fixtures/line_highlighter.html.haml b/spec/javascripts/fixtures/line_highlighter.html.haml
index 514877340e4..2782c50e298 100644
--- a/spec/javascripts/fixtures/line_highlighter.html.haml
+++ b/spec/javascripts/fixtures/line_highlighter.html.haml
@@ -1,4 +1,4 @@
-#blob-content-holder
+.file-holder
.file-content
.line-numbers
- 1.upto(25) do |i|
diff --git a/spec/lib/gitlab/email/receiver_spec.rb b/spec/lib/gitlab/email/receiver_spec.rb
index 2a86b427806..f127e45ae6a 100644
--- a/spec/lib/gitlab/email/receiver_spec.rb
+++ b/spec/lib/gitlab/email/receiver_spec.rb
@@ -7,9 +7,17 @@ describe Gitlab::Email::Receiver, lib: true do
context "when we cannot find a capable handler" do
let(:email_raw) { fixture_file('emails/valid_reply.eml').gsub(mail_key, "!!!") }
- it "raises a UnknownIncomingEmail" do
+ it "raises an UnknownIncomingEmail error" do
expect { receiver.execute }.to raise_error(Gitlab::Email::UnknownIncomingEmail)
end
+
+ context "and the email contains no references header" do
+ let(:email_raw) { fixture_file("emails/auto_reply.eml").gsub(mail_key, "!!!") }
+
+ it "raises an UnknownIncomingEmail error" do
+ expect { receiver.execute }.to raise_error(Gitlab::Email::UnknownIncomingEmail)
+ end
+ end
end
context "when the email is blank" do
diff --git a/spec/lib/gitlab/user_access_spec.rb b/spec/lib/gitlab/user_access_spec.rb
index 611cdbbc865..2b27ff66c09 100644
--- a/spec/lib/gitlab/user_access_spec.rb
+++ b/spec/lib/gitlab/user_access_spec.rb
@@ -87,10 +87,10 @@ describe Gitlab::UserAccess, lib: true do
expect(access.can_push_to_branch?(branch.name)).to be_falsey
end
- it 'returns true if branch does not exist and user has permission to merge' do
+ it 'returns false if branch does not exist' do
project.team << [user, :developer]
- expect(access.can_push_to_branch?(not_existing_branch.name)).to be_truthy
+ expect(access.can_push_to_branch?(not_existing_branch.name)).to be_falsey
end
end
diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb
index 98d0641443e..f6846cc1b2f 100644
--- a/spec/models/repository_spec.rb
+++ b/spec/models/repository_spec.rb
@@ -1849,17 +1849,15 @@ describe Repository, models: true do
end
end
- # TODO: Uncomment when feature is reenabled
- # describe '#is_ancestor?' do
- # context 'Gitaly is_ancestor feature enabled' do
- # it 'asks Gitaly server if it\'s an ancestor' do
- # commit = repository.commit
- # allow(Gitlab::GitalyClient).to receive(:feature_enabled?).with(:is_ancestor).and_return(true)
- # expect(Gitlab::GitalyClient::Commit).to receive(:is_ancestor).
- # with(repository.raw_repository, commit.id, commit.id).and_return(true)
- #
- # expect(repository.is_ancestor?(commit.id, commit.id)).to be true
- # end
- # end
- # end
+ describe '#is_ancestor?' do
+ context 'Gitaly is_ancestor feature enabled' do
+ it "asks Gitaly server if it's an ancestor" do
+ commit = repository.commit
+ expect(repository.raw_repository).to receive(:is_ancestor?).and_call_original
+ allow(Gitlab::GitalyClient).to receive(:feature_enabled?).with(:is_ancestor).and_return(true)
+
+ expect(repository.is_ancestor?(commit.id, commit.id)).to be true
+ end
+ end
+ end
end
diff --git a/spec/models/snippet_blob_spec.rb b/spec/models/snippet_blob_spec.rb
new file mode 100644
index 00000000000..120b390586b
--- /dev/null
+++ b/spec/models/snippet_blob_spec.rb
@@ -0,0 +1,47 @@
+require 'spec_helper'
+
+describe SnippetBlob, models: true do
+ let(:snippet) { create(:snippet) }
+
+ subject { described_class.new(snippet) }
+
+ describe '#id' do
+ it 'returns the snippet ID' do
+ expect(subject.id).to eq(snippet.id)
+ end
+ end
+
+ describe '#name' do
+ it 'returns the snippet file name' do
+ expect(subject.name).to eq(snippet.file_name)
+ end
+ end
+
+ describe '#size' do
+ it 'returns the data size' do
+ expect(subject.size).to eq(subject.data.bytesize)
+ end
+ end
+
+ describe '#data' do
+ it 'returns the snippet content' do
+ expect(subject.data).to eq(snippet.content)
+ end
+ end
+
+ describe '#rendered_markup' do
+ context 'when the content is GFM' do
+ let(:snippet) { create(:snippet, file_name: 'file.md') }
+
+ it 'returns the rendered GFM' do
+ expect(subject.rendered_markup).to eq(snippet.content_html)
+ end
+ end
+
+ context 'when the content is not GFM' do
+ it 'returns nil' do
+ expect(subject.rendered_markup).to be_nil
+ end
+ end
+ end
+end
diff --git a/spec/models/snippet_spec.rb b/spec/models/snippet_spec.rb
index 8095d01b69e..75b1fc7e216 100644
--- a/spec/models/snippet_spec.rb
+++ b/spec/models/snippet_spec.rb
@@ -5,7 +5,6 @@ describe Snippet, models: true do
subject { described_class }
it { is_expected.to include_module(Gitlab::VisibilityLevel) }
- it { is_expected.to include_module(Linguist::BlobHelper) }
it { is_expected.to include_module(Participable) }
it { is_expected.to include_module(Referable) }
it { is_expected.to include_module(Sortable) }
@@ -241,4 +240,16 @@ describe Snippet, models: true do
end
end
end
+
+ describe '#blob' do
+ let(:snippet) { create(:snippet) }
+
+ it 'returns a blob representing the snippet data' do
+ blob = snippet.blob
+
+ expect(blob).to be_a(Blob)
+ expect(blob.path).to eq(snippet.file_name)
+ expect(blob.data).to eq(snippet.content)
+ end
+ end
end
diff --git a/spec/rubocop/cop/migration/add_column_with_default_to_large_table_spec.rb b/spec/rubocop/cop/migration/add_column_with_default_to_large_table_spec.rb
new file mode 100644
index 00000000000..07cb3fc4a2e
--- /dev/null
+++ b/spec/rubocop/cop/migration/add_column_with_default_to_large_table_spec.rb
@@ -0,0 +1,44 @@
+require 'spec_helper'
+
+require 'rubocop'
+require 'rubocop/rspec/support'
+
+require_relative '../../../../rubocop/cop/migration/add_column_with_default_to_large_table'
+
+describe RuboCop::Cop::Migration::AddColumnWithDefaultToLargeTable do
+ include CopHelper
+
+ subject(:cop) { described_class.new }
+
+ context 'in migration' do
+ before do
+ allow(cop).to receive(:in_migration?).and_return(true)
+ end
+
+ described_class::LARGE_TABLES.each do |table|
+ it "registers an offense for the #{table} table" do
+ inspect_source(cop, "add_column_with_default :#{table}, :column, default: true")
+
+ aggregate_failures do
+ expect(cop.offenses.size).to eq(1)
+ expect(cop.offenses.map(&:line)).to eq([1])
+ end
+ end
+ end
+
+ it 'registers no offense for non-blacklisted tables' do
+ inspect_source(cop, "add_column_with_default :table, :column, default: true")
+
+ expect(cop.offenses).to be_empty
+ end
+ end
+
+ context 'outside of migration' do
+ it 'registers no offense' do
+ table = described_class::LARGE_TABLES.sample
+ inspect_source(cop, "add_column_with_default :#{table}, :column, default: true")
+
+ expect(cop.offenses).to be_empty
+ end
+ end
+end
diff --git a/spec/rubocop/cop/migration/add_column_with_default_spec.rb b/spec/rubocop/cop/migration/reversible_add_column_with_default_spec.rb
index 6b9b6b19650..3723d635083 100644
--- a/spec/rubocop/cop/migration/add_column_with_default_spec.rb
+++ b/spec/rubocop/cop/migration/reversible_add_column_with_default_spec.rb
@@ -3,9 +3,9 @@ require 'spec_helper'
require 'rubocop'
require 'rubocop/rspec/support'
-require_relative '../../../../rubocop/cop/migration/add_column_with_default'
+require_relative '../../../../rubocop/cop/migration/reversible_add_column_with_default'
-describe RuboCop::Cop::Migration::AddColumnWithDefault do
+describe RuboCop::Cop::Migration::ReversibleAddColumnWithDefault do
include CopHelper
subject(:cop) { described_class.new }
diff --git a/spec/views/projects/blob/_viewer.html.haml_spec.rb b/spec/views/projects/blob/_viewer.html.haml_spec.rb
index a4915264abe..501f90c5f9a 100644
--- a/spec/views/projects/blob/_viewer.html.haml_spec.rb
+++ b/spec/views/projects/blob/_viewer.html.haml_spec.rb
@@ -21,6 +21,7 @@ describe 'projects/blob/_viewer.html.haml', :view do
before do
assign(:project, project)
+ assign(:blob, blob)
assign(:id, File.join('master', blob.path))
controller.params[:controller] = 'projects/blob'