Commit 2731c9e1 authored by GitLab Bot's avatar GitLab Bot

Merge remote-tracking branch 'upstream/master' into ce-to-ee-2018-07-20

parents 50a8acda d15309ca
...@@ -133,7 +133,7 @@ Most issues will have labels for at least one of the following: ...@@ -133,7 +133,7 @@ Most issues will have labels for at least one of the following:
- Type: ~"feature proposal", ~bug, ~customer, etc. - Type: ~"feature proposal", ~bug, ~customer, etc.
- Subject: ~wiki, ~"container registry", ~ldap, ~api, ~frontend, etc. - Subject: ~wiki, ~"container registry", ~ldap, ~api, ~frontend, etc.
- Team: ~"CI/CD", ~Discussion, ~Quality, ~Platform, etc. - Team: ~"CI/CD", ~Plan, ~Quality, ~Platform, etc.
- Release Scoping: ~Deliverable, ~Stretch, ~"Next Patch Release" - Release Scoping: ~Deliverable, ~Stretch, ~"Next Patch Release"
- Priority: ~P1, ~P2, ~P3, ~P4 - Priority: ~P1, ~P2, ~P3, ~P4
- Severity: ~S1, ~S2, ~S3, ~S4 - Severity: ~S1, ~S2, ~S3, ~S4
...@@ -187,12 +187,13 @@ The current team labels are: ...@@ -187,12 +187,13 @@ The current team labels are:
- ~Configuration - ~Configuration
- ~"CI/CD" - ~"CI/CD"
- ~Discussion - ~Create
- ~Distribution - ~Distribution
- ~Documentation - ~Documentation
- ~Geo - ~Geo
- ~Gitaly - ~Gitaly
- ~Monitoring - ~Monitoring
- ~Plan
- ~Platform - ~Platform
- ~Quality - ~Quality
- ~Release - ~Release
......
...@@ -335,6 +335,7 @@ group :development do ...@@ -335,6 +335,7 @@ group :development do
end end
group :development, :test do group :development, :test do
gem 'bootsnap', '~> 1.3'
gem 'bullet', '~> 5.5.0', require: !!ENV['ENABLE_BULLET'] gem 'bullet', '~> 5.5.0', require: !!ENV['ENABLE_BULLET']
gem 'pry-byebug', '~> 3.4.1', platform: :mri gem 'pry-byebug', '~> 3.4.1', platform: :mri
gem 'pry-rails', '~> 0.3.4' gem 'pry-rails', '~> 0.3.4'
......
...@@ -95,6 +95,8 @@ GEM ...@@ -95,6 +95,8 @@ GEM
binding_of_caller (0.7.2) binding_of_caller (0.7.2)
debug_inspector (>= 0.0.1) debug_inspector (>= 0.0.1)
blankslate (2.1.2.4) blankslate (2.1.2.4)
bootsnap (1.3.1)
msgpack (~> 1.0)
bootstrap_form (2.7.0) bootstrap_form (2.7.0)
brakeman (4.2.1) brakeman (4.2.1)
browser (2.2.0) browser (2.2.0)
...@@ -528,6 +530,7 @@ GEM ...@@ -528,6 +530,7 @@ GEM
mini_portile2 (2.3.0) mini_portile2 (2.3.0)
minitest (5.7.0) minitest (5.7.0)
mousetrap-rails (1.4.6) mousetrap-rails (1.4.6)
msgpack (1.2.4)
multi_json (1.13.1) multi_json (1.13.1)
multi_xml (0.6.0) multi_xml (0.6.0)
multipart-post (2.0.0) multipart-post (2.0.0)
...@@ -1016,6 +1019,7 @@ DEPENDENCIES ...@@ -1016,6 +1019,7 @@ DEPENDENCIES
benchmark-ips (~> 2.3.0) benchmark-ips (~> 2.3.0)
better_errors (~> 2.1.0) better_errors (~> 2.1.0)
binding_of_caller (~> 0.7.2) binding_of_caller (~> 0.7.2)
bootsnap (~> 1.3)
bootstrap_form (~> 2.7.0) bootstrap_form (~> 2.7.0)
brakeman (~> 4.2) brakeman (~> 4.2)
browser (~> 2.2) browser (~> 2.2)
......
...@@ -98,6 +98,8 @@ GEM ...@@ -98,6 +98,8 @@ GEM
binding_of_caller (0.7.2) binding_of_caller (0.7.2)
debug_inspector (>= 0.0.1) debug_inspector (>= 0.0.1)
blankslate (2.1.2.4) blankslate (2.1.2.4)
bootsnap (1.3.1)
msgpack (~> 1.0)
bootstrap_form (2.7.0) bootstrap_form (2.7.0)
brakeman (4.2.1) brakeman (4.2.1)
browser (2.2.0) browser (2.2.0)
...@@ -531,6 +533,7 @@ GEM ...@@ -531,6 +533,7 @@ GEM
mini_portile2 (2.3.0) mini_portile2 (2.3.0)
minitest (5.7.0) minitest (5.7.0)
mousetrap-rails (1.4.6) mousetrap-rails (1.4.6)
msgpack (1.2.4)
multi_json (1.13.1) multi_json (1.13.1)
multi_xml (0.6.0) multi_xml (0.6.0)
multipart-post (2.0.0) multipart-post (2.0.0)
...@@ -1026,6 +1029,7 @@ DEPENDENCIES ...@@ -1026,6 +1029,7 @@ DEPENDENCIES
benchmark-ips (~> 2.3.0) benchmark-ips (~> 2.3.0)
better_errors (~> 2.1.0) better_errors (~> 2.1.0)
binding_of_caller (~> 0.7.2) binding_of_caller (~> 0.7.2)
bootsnap (~> 1.3)
bootstrap_form (~> 2.7.0) bootstrap_form (~> 2.7.0)
brakeman (~> 4.2) brakeman (~> 4.2)
browser (~> 2.2) browser (~> 2.2)
......
11.1.0-pre 11.2.0-pre
...@@ -14,6 +14,7 @@ import 'core-js/es6/weak-map'; ...@@ -14,6 +14,7 @@ import 'core-js/es6/weak-map';
// Browser polyfills // Browser polyfills
import 'classlist-polyfill'; import 'classlist-polyfill';
import 'formdata-polyfill';
import './polyfills/custom_event'; import './polyfills/custom_event';
import './polyfills/element'; import './polyfills/element';
import './polyfills/event'; import './polyfills/event';
......
...@@ -49,13 +49,15 @@ export default class Profile { ...@@ -49,13 +49,15 @@ export default class Profile {
saveForm() { saveForm() {
const self = this; const self = this;
const formData = new FormData(this.form[0]); const formData = new FormData(this.form.get(0));
const avatarBlob = this.avatarGlCrop.getBlob(); const avatarBlob = this.avatarGlCrop.getBlob();
if (avatarBlob != null) { if (avatarBlob != null) {
formData.append('user[avatar]', avatarBlob, 'avatar.png'); formData.append('user[avatar]', avatarBlob, 'avatar.png');
} }
formData.delete('user[avatar]-trigger');
axios({ axios({
method: this.form.attr('method'), method: this.form.attr('method'),
url: this.form.attr('action'), url: this.form.attr('action'),
......
...@@ -10,7 +10,6 @@ class Projects::RawController < Projects::ApplicationController ...@@ -10,7 +10,6 @@ class Projects::RawController < Projects::ApplicationController
def show def show
@blob = @repository.blob_at(@commit.id, @path) @blob = @repository.blob_at(@commit.id, @path)
if @blob if @blob
headers['X-Content-Type-Options'] = 'nosniff' headers['X-Content-Type-Options'] = 'nosniff'
...@@ -19,7 +18,7 @@ class Projects::RawController < Projects::ApplicationController ...@@ -19,7 +18,7 @@ class Projects::RawController < Projects::ApplicationController
if @blob.stored_externally? if @blob.stored_externally?
send_lfs_object send_lfs_object
else else
send_git_blob @repository, @blob send_git_blob @repository, @blob, inline: (params[:inline] != 'false')
end end
else else
render_404 render_404
......
...@@ -114,22 +114,22 @@ module BlobHelper ...@@ -114,22 +114,22 @@ module BlobHelper
icon("#{file_type_icon_class('file', mode, name)} fw") icon("#{file_type_icon_class('file', mode, name)} fw")
end end
def blob_raw_url(only_path: false) def blob_raw_url(**kwargs)
if @build && @entry if @build && @entry
raw_project_job_artifacts_url(@project, @build, path: @entry.path, only_path: only_path) raw_project_job_artifacts_url(@project, @build, path: @entry.path, **kwargs)
elsif @snippet elsif @snippet
if @snippet.project_id if @snippet.project_id
raw_project_snippet_url(@project, @snippet, only_path: only_path) raw_project_snippet_url(@project, @snippet, **kwargs)
else else
raw_snippet_url(@snippet, only_path: only_path) raw_snippet_url(@snippet, **kwargs)
end end
elsif @blob elsif @blob
project_raw_url(@project, @id, only_path: only_path) project_raw_url(@project, @id, **kwargs)
end end
end end
def blob_raw_path def blob_raw_path(**kwargs)
blob_raw_url(only_path: true) blob_raw_url(**kwargs, only_path: true)
end end
# SVGs can contain malicious JavaScript; only include whitelisted # SVGs can contain malicious JavaScript; only include whitelisted
...@@ -226,16 +226,17 @@ module BlobHelper ...@@ -226,16 +226,17 @@ module BlobHelper
def open_raw_blob_button(blob) def open_raw_blob_button(blob)
return if blob.empty? return if blob.empty?
return if blob.raw_binary? || blob.stored_externally?
if blob.raw_binary? || blob.stored_externally? title = 'Open raw'
icon = sprite_icon('download') link_to icon('file-code-o'), blob_raw_path, class: 'btn btn-sm has-tooltip', target: '_blank', rel: 'noopener noreferrer', title: title, data: { container: 'body' }
title = 'Download' end
else
icon = icon('file-code-o') def download_blob_button(blob)
title = 'Open raw' return if blob.empty?
end
link_to icon, blob_raw_path, class: 'btn btn-sm has-tooltip', target: '_blank', rel: 'noopener noreferrer', title: title, data: { container: 'body' } title = 'Download'
link_to sprite_icon('download'), blob_raw_path(inline: false), download: @path, class: 'btn btn-sm has-tooltip', target: '_blank', rel: 'noopener noreferrer', title: title, data: { container: 'body' }
end end
def blob_render_error_reason(viewer) def blob_render_error_reason(viewer)
......
...@@ -2,9 +2,9 @@ ...@@ -2,9 +2,9 @@
# Workhorse will also serve files when using `send_file`. # Workhorse will also serve files when using `send_file`.
module WorkhorseHelper module WorkhorseHelper
# Send a Git blob through Workhorse # Send a Git blob through Workhorse
def send_git_blob(repository, blob) def send_git_blob(repository, blob, inline: true)
headers.store(*Gitlab::Workhorse.send_git_blob(repository, blob)) headers.store(*Gitlab::Workhorse.send_git_blob(repository, blob))
headers['Content-Disposition'] = 'inline' headers['Content-Disposition'] = inline ? 'inline' : 'attachment'
headers['Content-Type'] = safe_content_type(blob) headers['Content-Type'] = safe_content_type(blob)
render plain: "" render plain: ""
end end
......
...@@ -27,6 +27,6 @@ ...@@ -27,6 +27,6 @@
.btn-group{ role: "group" }< .btn-group{ role: "group" }<
= copy_blob_source_button(blob) = copy_blob_source_button(blob)
= open_raw_blob_button(blob) = download_blob_button(blob)
= render 'projects/blob/content', blob: blob = render 'projects/blob/content', blob: blob
...@@ -8,8 +8,8 @@ ...@@ -8,8 +8,8 @@
.btn-group{ role: "group" }< .btn-group{ role: "group" }<
= copy_blob_source_button(blob) unless blame = copy_blob_source_button(blob) unless blame
= open_raw_blob_button(blob) = open_raw_blob_button(blob)
= download_blob_button(blob)
= view_on_environment_button(@commit.sha, @path, @environment) if @environment = view_on_environment_button(@commit.sha, @path, @environment) if @environment
.btn-group{ role: "group" }< .btn-group{ role: "group" }<
= render_if_exists 'projects/blob/header_file_locks_link' = render_if_exists 'projects/blob/header_file_locks_link'
= edit_blob_button = edit_blob_button
......
---
title: Add download button for single file (including raw files) in repository
merge_request: 20480
author: Kia Mei Somabes
type: added
---
title: Resolve "Unable to save user profile update with Safari"
merge_request: 20676
author:
type: fixed
---
title: Fix accessing imported pipeline builds
merge_request: 20713
author:
type: fixed
---
title: Fixed bug with invalid repository reference using the wiki search
merge_request: 20722
author:
type: fixed
...@@ -9,3 +9,8 @@ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../#{gemfile}", __dir__) ...@@ -9,3 +9,8 @@ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../#{gemfile}", __dir__)
# Set up gems listed in the Gemfile. # Set up gems listed in the Gemfile.
require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE']) require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
begin
require 'bootsnap/setup'
rescue LoadError
# bootsnap is optional dependency, so if we don't have it it's fine
end
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class MigrateProcessCommitWorkerJobs < ActiveRecord::Migration class MigrateProcessCommitWorkerJobs < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers include Gitlab::Database::MigrationHelpers
class Repository
attr_reader :storage
def initialize(storage, relative_path)
@storage = storage
@relative_path = relative_path
end
def gitaly_repository
Gitaly::Repository.new(storage_name: @storage, relative_path: @relative_path)
end
end
class Project < ActiveRecord::Base class Project < ActiveRecord::Base
def self.find_including_path(id) def self.find_including_path(id)
select("projects.*, CONCAT(namespaces.path, '/', projects.path) AS path_with_namespace") select("projects.*, CONCAT(namespaces.path, '/', projects.path) AS path_with_namespace")
...@@ -11,19 +21,12 @@ class MigrateProcessCommitWorkerJobs < ActiveRecord::Migration ...@@ -11,19 +21,12 @@ class MigrateProcessCommitWorkerJobs < ActiveRecord::Migration
.find_by(id: id) .find_by(id: id)
end end
def repository_storage_path def commit(rev)
Gitlab::GitalyClient::StorageSettings.allow_disk_access do Gitlab::GitalyClient::CommitService.new(repository).find_commit(rev)
Gitlab.config.repositories.storages[repository_storage].legacy_disk_path
end
end
def repository_path
# TODO: review if the change from Legacy storage needs to reflect here as well.
File.join(repository_storage_path, read_attribute(:path_with_namespace) + '.git')
end end
def repository def repository
@repository ||= Rugged::Repository.new(repository_path) @repository ||= Repository.new(repository_storage, read_attribute(:path_with_namespace) + '.git')
end end
end end
...@@ -42,22 +45,19 @@ class MigrateProcessCommitWorkerJobs < ActiveRecord::Migration ...@@ -42,22 +45,19 @@ class MigrateProcessCommitWorkerJobs < ActiveRecord::Migration
next unless project next unless project
begin commit = project.commit(payload['args'][2])
commit = project.repository.lookup(payload['args'][2]) next unless commit
rescue Rugged::OdbError
next
end
hash = { hash = {
id: commit.oid, id: commit.id,
message: encode(commit.message), message: encode(commit.body),
parent_ids: commit.parent_ids, parent_ids: commit.parent_ids.to_a,
authored_date: commit.author[:time], authored_date: Time.at(commit.author.date.seconds).utc,
author_name: encode(commit.author[:name]), author_name: encode(commit.author.name),
author_email: encode(commit.author[:email]), author_email: encode(commit.author.email),
committed_date: commit.committer[:time], committed_date: Time.at(commit.committer.date.seconds).utc,
committer_email: encode(commit.committer[:email]), committer_email: encode(commit.committer.email),
committer_name: encode(commit.committer[:name]) committer_name: encode(commit.committer.name)
} }
payload['args'][2] = hash payload['args'][2] = hash
......
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class RemoveDotGitFromUsernames < ActiveRecord::Migration class RemoveDotGitFromUsernames < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers include Gitlab::Database::MigrationHelpers
include Gitlab::ShellAdapter include Gitlab::ShellAdapter
# Set this constant to true if this migration requires downtime.
DOWNTIME = false DOWNTIME = false
def up def up
...@@ -64,16 +60,14 @@ class RemoveDotGitFromUsernames < ActiveRecord::Migration ...@@ -64,16 +60,14 @@ class RemoveDotGitFromUsernames < ActiveRecord::Migration
# we rename suffix instead of removing it # we rename suffix instead of removing it
path = path.sub(/\.git\z/, '_git') path = path.sub(/\.git\z/, '_git')
Gitlab::GitalyClient::StorageSettings.allow_disk_access do check_routes(path.dup, 0, path)
check_routes(path.dup, 0, path)
end
end end
def check_routes(base, counter, path) def check_routes(base, counter, path)
route_exists = route_exists?(path) route_exists = route_exists?(path)
Gitlab.config.repositories.storages.each do |shard, storage| Gitlab.config.repositories.storages.each do |shard, _storage|
if route_exists || path_exists?(shard, storage.legacy_disk_path) if route_exists || path_exists?(shard, path)
counter += 1 counter += 1
path = "#{base}#{counter}" path = "#{base}#{counter}"
......
...@@ -41,6 +41,7 @@ description: 'Learn how to contribute to GitLab.' ...@@ -41,6 +41,7 @@ description: 'Learn how to contribute to GitLab.'
- [View sent emails or preview mailers](emails.md) - [View sent emails or preview mailers](emails.md)
- [Shell commands](shell_commands.md) in the GitLab codebase - [Shell commands](shell_commands.md) in the GitLab codebase
- [`Gemfile` guidelines](gemfile.md) - [`Gemfile` guidelines](gemfile.md)
- [Pry debugging](pry_debugging.md)
- [Sidekiq debugging](sidekiq_debugging.md) - [Sidekiq debugging](sidekiq_debugging.md)
- [Gotchas](gotchas.md) to avoid - [Gotchas](gotchas.md) to avoid
- [Avoid modules with instance variables](module_with_instance_variables.md) if possible - [Avoid modules with instance variables](module_with_instance_variables.md) if possible
......
# Pry debugging
## Invoking pry debugging
To invoke the debugger, place `binding.pry` somewhere in your
code. When the Ruby interpreter hits that code, execution will stop,
and you can type in commands to debug the state of the program
## `byebug` vs `binding.pry`
`byebug` has a very similar interface as `gdb`, but `byebug` does not
use the powerful Pry REPL.
`binding.pry` uses Pry, but lacks some of the `byebug`
features. GitLab uses the [`pry-byebug`](https://github.com/deivid-rodriguez/pry-byebug)
gem. This gem brings some capabilities `byebug` to `binding.pry`, so
using that, will give you the most debugging powers.
## `byebug`
Check out [the docs](https://github.com/deivid-rodriguez/byebug) for the full list of commands.
You can start the Pry REPL with the `pry` command.
## `pry`
There are **a lot** of features present in `pry`, too much to cover in
this document, so for the full documentation head over to the [Pry wiki](https://github.com/pry/pry/wiki).
Below are a few features definitely worth checking out, also run
`help` in a pry session to see what else you can do.
### State navigation
With the [state navigation](https://github.com/pry/pry/wiki/State-navigation)
you can move around in the code to discover methods and such:
```ruby
# Change context
[1] pry(main)> cd Pry
[2] pry(Pry):1>
# Print methods
[2] pry(Pry):1> ls -m
# Find a method
[3] pry(Pry):1> find-method to_yaml
```
### Source browsing
You [look at the source code](https://github.com/pry/pry/wiki/Source-browsing)
from your `pry` session:
```ruby
[1] pry(main)> $ Array#first
# The above is equivalent to
[2] pry(main)> cd Array
[3] pry(Array):1> show-source first
```
`$` is an alias for `show-source`.
### Documentation browsing
Similar to source browsing, is [Documentation browsing](https://github.com/pry/pry/wiki/Documentation-browsing).
```ruby
[1] pry(main)> show-doc Array#first
```
`?` is an alias for `show-doc`.
### Command history
With <kdb>Ctrl+R</kbd> you can search your [command history](https://github.com/pry/pry/wiki/History).
## Stepping
To step through the code, you can use the following commands:
- `break`: Manage breakpoints.
- `step`: Step execution into the next line or method. Takes an
optional numeric argument to step multiple times.
- `next`: Step over to the next line within the same frame. Also takes
an optional numeric argument to step multiple lines.
- `finish`: Execute until current stack frame returns.
- `continue`: Continue program execution and end the Pry session.
## Callstack navigation
You also can move around in the callstack with these commands:
- `backtrace`: Shows the current stack. You can use the numbers on the
left side with the frame command to navigate the stack.
- `up`: Moves the stack frame up. Takes an optional numeric argument
to move multiple frames.
- `down`: Moves the stack frame down. Takes an optional numeric
argument to move multiple frames.
- `frame <n>`: Moves to a specific frame. Called without arguments
will show the current frame.
## Short commands
When you use `binding.pry` instead of `byebug`, the short commands
like `s`, `n`, `f`, and `c` do not work. To reinstall them, add this
to `~/.pryrc`:
```ruby
if defined?(PryByebug)
Pry.commands.alias_command 's', 'step'
Pry.commands.alias_command 'n', 'next'
Pry.commands.alias_command 'f', 'finish'
Pry.commands.alias_command 'c', 'continue'
end
```
## Repeat last command
You can repeat the last command by just hitting the <kbd>Enter</kbd>
key (e.g., with `step` or`next`), if you place the following snippet
in your `~/.pryrc`:
```ruby
Pry::Commands.command /^$/, "repeat last command" do
_pry_.run_command Pry.history.to_a.last
end
```
`byebug` supports this out-of-the-box.
...@@ -101,7 +101,7 @@ CHROME_HEADLESS=0 bundle exec rspec some_spec.rb ...@@ -101,7 +101,7 @@ CHROME_HEADLESS=0 bundle exec rspec some_spec.rb
The test will go by quickly, but this will give you an idea of what's happening. The test will go by quickly, but this will give you an idea of what's happening.
You can also add `byebug` or `binding.pry` to pause execution and step through You can also add `byebug` or `binding.pry` to pause execution and [step through](../pry_debugging.md#stepping)
the test. the test.
#### Screenshots #### Screenshots
......
...@@ -194,12 +194,12 @@ sudo apt-get install pgloader ...@@ -194,12 +194,12 @@ sudo apt-get install pgloader
1. Switch database from MySQL to PostgreSQL 1. Switch database from MySQL to PostgreSQL
``` bash ``` bash
cd /home/git/gitlab cd /home/git/gitlab
sudo -u git mv config/database.yml config/database.yml.bak sudo -u git mv config/database.yml config/database.yml.bak
sudo -u git cp config/database.yml.postgresql config/database.yml sudo -u git cp config/database.yml.postgresql config/database.yml
sudo -u git -H chmod o-rwx config/database.yml sudo -u git -H chmod o-rwx config/database.yml
``` ```
1. Run the following commands to prepare the schema: 1. Run the following commands to prepare the schema:
......
...@@ -34,7 +34,7 @@ module Gitlab ...@@ -34,7 +34,7 @@ module Gitlab
def self.fabricate(resource) def self.fabricate(resource)
case resource case resource
when Hash when Hash
self.new(resource) self.new(resource.symbolize_keys)
when ::HasVariable when ::HasVariable
self.new(resource.to_runner_variable) self.new(resource.to_runner_variable)
when self when self
......
# Gitlab::Git::Repository is a wrapper around native Rugged::Repository object
require 'tempfile' require 'tempfile'
require 'forwardable' require 'forwardable'
require "rubygems/package" require "rubygems/package"
......
...@@ -5,7 +5,7 @@ module Gitlab ...@@ -5,7 +5,7 @@ module Gitlab
def initialize(current_user, project, query, repository_ref = nil, per_page: 20) def initialize(current_user, project, query, repository_ref = nil, per_page: 20)
@current_user = current_user @current_user = current_user
@project = project @project = project
@repository_ref = repository_ref.presence || project.default_branch @repository_ref = repository_ref.presence
@query = query @query = query
@per_page = per_page @per_page = per_page
end end
...@@ -95,7 +95,7 @@ module Gitlab ...@@ -95,7 +95,7 @@ module Gitlab
def blobs def blobs
return [] unless Ability.allowed?(@current_user, :download_code, @project) return [] unless Ability.allowed?(@current_user, :download_code, @project)
@blobs ||= Gitlab::FileFinder.new(project, repository_ref).find(query) @blobs ||= Gitlab::FileFinder.new(project, repository_project_ref).find(query)
end end
def wiki_blobs def wiki_blobs
...@@ -103,11 +103,8 @@ module Gitlab ...@@ -103,11 +103,8 @@ module Gitlab
@wiki_blobs ||= begin @wiki_blobs ||= begin
if project.wiki_enabled? && query.present? if project.wiki_enabled? && query.present?
project_wiki = ProjectWiki.new(project) unless project.wiki.empty?
Gitlab::WikiFileFinder.new(project, repository_wiki_ref).find(query)
unless project_wiki.empty?
ref = repository_ref || project.wiki.default_branch
Gitlab::WikiFileFinder.new(project, ref).find(query)
else else
[] []
end end
...@@ -150,5 +147,13 @@ module Gitlab ...@@ -150,5 +147,13 @@ module Gitlab
def project_ids_relation def project_ids_relation
project project
end end
def repository_project_ref
@repository_project_ref ||= repository_ref || project.default_branch
end
def repository_wiki_ref
@repository_wiki_ref ||= repository_ref || project.wiki.default_branch
end
end end
end end
...@@ -13,8 +13,9 @@ module Gitlab ...@@ -13,8 +13,9 @@ module Gitlab
object = YAML.safe_load(string, [Symbol]) object = YAML.safe_load(string, [Symbol])
object.map do |variable| object.map do |variable|
variable[:key] = variable[:key].to_s variable.symbolize_keys.tap do |variable|
variable variable[:key] = variable[:key].to_s
end
end end
end end
......
...@@ -134,28 +134,5 @@ namespace :gitlab do ...@@ -134,28 +134,5 @@ namespace :gitlab do
puts "To block these users run this command with BLOCK=true".color(:yellow) puts "To block these users run this command with BLOCK=true".color(:yellow)
end end
end end
# This is a rake task which removes faulty refs. These refs where only
# created in the 8.13.RC cycle, and fixed in the stable builds which were
# released. So likely this should only be run once on gitlab.com
# Faulty refs are moved so they are kept around, else some features break.
desc 'GitLab | Cleanup | Remove faulty deployment refs'
task move_faulty_deployment_refs: :gitlab_environment do
projects = Project.where(id: Deployment.select(:project_id).distinct)
projects.find_each do |project|
rugged = project.repository.rugged
max_iid = project.deployments.maximum(:iid)
rugged.references.each('refs/environments/**/*') do |ref|
id = ref.name.split('/').last.to_i
next unless id > max_iid
project.deployments.find(id).create_ref
project.repository.delete_refs(ref)
end
end
end
end end
end end
...@@ -75,6 +75,14 @@ describe Gitlab::Ci::Variables::Collection::Item do ...@@ -75,6 +75,14 @@ describe Gitlab::Ci::Variables::Collection::Item do
expect(resource).to eq variable expect(resource).to eq variable
end end
it 'supports using a hash with stringified values' do
variable = { 'key' => 'VARIABLE', 'value' => 'my value' }
resource = described_class.fabricate(variable)
expect(resource).to eq(key: 'VARIABLE', value: 'my value')
end
it 'supports using an active record resource' do it 'supports using an active record resource' do
variable = create(:ci_variable, key: 'CI_VAR', value: '123') variable = create(:ci_variable, key: 'CI_VAR', value: '123')
resource = described_class.fabricate(variable) resource = described_class.fabricate(variable)
......
...@@ -64,6 +64,49 @@ describe Gitlab::ProjectSearchResults do ...@@ -64,6 +64,49 @@ describe Gitlab::ProjectSearchResults do
end end
end end
shared_examples 'blob search repository ref' do |entity_type|
let(:query) { 'files' }
let(:file_finder) { double }
let(:project_branch) { 'project_branch' }
subject(:results) { described_class.new(user, project, query, repository_ref).objects(blob_type) }
before do
allow(entity).to receive(:default_branch).and_return(project_branch)
allow(file_finder).to receive(:find).and_return([])
end
context 'when repository_ref exists' do
let(:repository_ref) { 'ref_branch' }
it 'uses it' do
expect(Gitlab::FileFinder).to receive(:new).with(project, repository_ref).and_return(file_finder)
results
end
end
context 'when repository_ref is not present' do
let(:repository_ref) { nil }
it "uses #{entity_type} repository default reference" do
expect(Gitlab::FileFinder).to receive(:new).with(project, project_branch).and_return(file_finder)
results
end
end
context 'when repository_ref is blank' do
let(:repository_ref) { '' }
it "uses #{entity_type} repository default reference" do
expect(Gitlab::FileFinder).to receive(:new).with(project, project_branch).and_return(file_finder)
results
end
end
end
describe 'blob search' do describe 'blob search' do
let(:project) { create(:project, :public, :repository) } let(:project) { create(:project, :public, :repository) }
...@@ -75,6 +118,11 @@ describe Gitlab::ProjectSearchResults do ...@@ -75,6 +118,11 @@ describe Gitlab::ProjectSearchResults do
let(:expected_file_by_content) { 'CHANGELOG' } let(:expected_file_by_content) { 'CHANGELOG' }
end end
it_behaves_like 'blob search repository ref', 'project' do
let(:blob_type) { 'blobs' }
let(:entity) { project }
end
describe 'parsing results' do describe 'parsing results' do
let(:results) { project.repository.search_files_by_content('feature', 'master') } let(:results) { project.repository.search_files_by_content('feature', 'master') }
let(:search_result) { results.first } let(:search_result) { results.first }
...@@ -212,6 +260,11 @@ describe Gitlab::ProjectSearchResults do ...@@ -212,6 +260,11 @@ describe Gitlab::ProjectSearchResults do
let(:expected_file_by_name) { 'Files/Title.md' } let(:expected_file_by_name) { 'Files/Title.md' }
let(:expected_file_by_content) { 'CHANGELOG.md' } let(:expected_file_by_content) { 'CHANGELOG.md' }
end end
it_behaves_like 'blob search repository ref', 'wiki' do
let(:blob_type) { 'wiki_blobs' }
let(:entity) { project.wiki }
end
end end
it 'does not list issues on private projects' do it 'does not list issues on private projects' do
......
require 'spec_helper' require 'fast_spec_helper'
describe Gitlab::Serializer::Ci::Variables do describe Gitlab::Serializer::Ci::Variables do
subject do subject do
...@@ -6,11 +6,11 @@ describe Gitlab::Serializer::Ci::Variables do ...@@ -6,11 +6,11 @@ describe Gitlab::Serializer::Ci::Variables do
end end
let(:object) do let(:object) do
[{ key: :key, value: 'value', public: true }, [{ 'key' => :key, 'value' => 'value', 'public' => true },
{ key: 'wee', value: 1, public: false }] { key: 'wee', value: 1, public: false }]
end end
it 'converts keys into strings' do it 'converts keys into strings and symbolizes hash' do
is_expected.to eq([ is_expected.to eq([
{ key: 'key', value: 'value', public: true }, { key: 'key', value: 'value', public: true },
{ key: 'wee', value: 1, public: false } { key: 'wee', value: 1, public: false }
......
...@@ -4,14 +4,11 @@ require 'spec_helper' ...@@ -4,14 +4,11 @@ require 'spec_helper'
require Rails.root.join('db', 'migrate', '20161124141322_migrate_process_commit_worker_jobs.rb') require Rails.root.join('db', 'migrate', '20161124141322_migrate_process_commit_worker_jobs.rb')
describe MigrateProcessCommitWorkerJobs do describe MigrateProcessCommitWorkerJobs do
let(:project) { create(:project, :legacy_storage, :repository) } # rubocop:disable RSpec/FactoriesInMigrationSpecs set(:project) { create(:project, :legacy_storage, :repository) } # rubocop:disable RSpec/FactoriesInMigrationSpecs
let(:user) { create(:user) } # rubocop:disable RSpec/FactoriesInMigrationSpecs set(:user) { create(:user) } # rubocop:disable RSpec/FactoriesInMigrationSpecs
let(:rugged) do let(:commit) do
Gitlab::GitalyClient::StorageSettings.allow_disk_access do Gitlab::Git::Commit.last(project.repository.raw)
project.repository.rugged
end
end end
let(:commit) { rugged.rev_parse(project.commit.id) }
describe 'Project' do describe 'Project' do
describe 'find_including_path' do describe 'find_including_path' do
...@@ -29,32 +26,13 @@ describe MigrateProcessCommitWorkerJobs do ...@@ -29,32 +26,13 @@ describe MigrateProcessCommitWorkerJobs do
end end
end end
describe '#repository_storage_path' do
it 'returns the storage path for the repository' do
migration_project = described_class::Project
.find_including_path(project.id)
expect(File.directory?(migration_project.repository_storage_path))
.to eq(true)
end
end
describe '#repository_path' do
it 'returns the path to the repository' do
migration_project = described_class::Project
.find_including_path(project.id)
expect(File.directory?(migration_project.repository_path)).to eq(true)
end
end
describe '#repository' do describe '#repository' do
it 'returns a Rugged::Repository' do it 'returns a mock implemention of ::Repository' do
migration_project = described_class::Project migration_project = described_class::Project
.find_including_path(project.id) .find_including_path(project.id)
expect(migration_project.repository) expect(migration_project.repository).to respond_to(:storage)
.to be_an_instance_of(Rugged::Repository) expect(migration_project.repository).to respond_to(:gitaly_repository)
end end
end end
end end
...@@ -72,7 +50,7 @@ describe MigrateProcessCommitWorkerJobs do ...@@ -72,7 +50,7 @@ describe MigrateProcessCommitWorkerJobs do
before do before do
Sidekiq.redis do |redis| Sidekiq.redis do |redis|
job = JSON.dump(args: [project.id, user.id, commit.oid]) job = JSON.dump(args: [project.id, user.id, commit.id])
redis.lpush('queue:process_commit', job) redis.lpush('queue:process_commit', job)
end end
end end
...@@ -88,9 +66,10 @@ describe MigrateProcessCommitWorkerJobs do ...@@ -88,9 +66,10 @@ describe MigrateProcessCommitWorkerJobs do
end end
it 'skips jobs using commits that no longer exist' do it 'skips jobs using commits that no longer exist' do
allow_any_instance_of(Rugged::Repository).to receive(:lookup) allow_any_instance_of(Gitlab::GitalyClient::CommitService)
.with(commit.oid) .to receive(:find_commit)
.and_raise(Rugged::OdbError) .with(commit.id)
.and_return(nil)
migration.up migration.up
...@@ -104,11 +83,7 @@ describe MigrateProcessCommitWorkerJobs do ...@@ -104,11 +83,7 @@ describe MigrateProcessCommitWorkerJobs do
end end
it 'encodes data to UTF-8' do it 'encodes data to UTF-8' do
allow_any_instance_of(Rugged::Repository).to receive(:lookup) allow(commit).to receive(:body)
.with(commit.oid)
.and_return(commit)
allow(commit).to receive(:message)
.and_return('김치'.force_encoding('BINARY')) .and_return('김치'.force_encoding('BINARY'))
migration.up migration.up
...@@ -140,7 +115,7 @@ describe MigrateProcessCommitWorkerJobs do ...@@ -140,7 +115,7 @@ describe MigrateProcessCommitWorkerJobs do
end end
it 'includes the commit ID' do it 'includes the commit ID' do
expect(commit_hash['id']).to eq(commit.oid) expect(commit_hash['id']).to eq(commit.id)
end end
it 'includes the commit message' do it 'includes the commit message' do
...@@ -152,27 +127,27 @@ describe MigrateProcessCommitWorkerJobs do ...@@ -152,27 +127,27 @@ describe MigrateProcessCommitWorkerJobs do
end end
it 'includes the author date' do it 'includes the author date' do
expect(commit_hash['authored_date']).to eq(commit.author[:time].to_s) expect(commit_hash['authored_date']).to eq(commit.authored_date.to_s)
end end
it 'includes the author name' do it 'includes the author name' do
expect(commit_hash['author_name']).to eq(commit.author[:name]) expect(commit_hash['author_name']).to eq(commit.author_name)
end end
it 'includes the author Email' do it 'includes the author Email' do
expect(commit_hash['author_email']).to eq(commit.author[:email]) expect(commit_hash['author_email']).to eq(commit.author_email)
end end
it 'includes the commit date' do it 'includes the commit date' do
expect(commit_hash['committed_date']).to eq(commit.committer[:time].to_s) expect(commit_hash['committed_date']).to eq(commit.committed_date.to_s)
end end
it 'includes the committer name' do it 'includes the committer name' do
expect(commit_hash['committer_name']).to eq(commit.committer[:name]) expect(commit_hash['committer_name']).to eq(commit.committer_name)
end end
it 'includes the committer Email' do it 'includes the committer Email' do
expect(commit_hash['committer_email']).to eq(commit.committer[:email]) expect(commit_hash['committer_email']).to eq(commit.committer_email)
end end
end end
end end
...@@ -186,7 +161,7 @@ describe MigrateProcessCommitWorkerJobs do ...@@ -186,7 +161,7 @@ describe MigrateProcessCommitWorkerJobs do
before do before do
Sidekiq.redis do |redis| Sidekiq.redis do |redis|
job = JSON.dump(args: [project.id, user.id, commit.oid]) job = JSON.dump(args: [project.id, user.id, commit.id])
redis.lpush('queue:process_commit', job) redis.lpush('queue:process_commit', job)
migration.up migration.up
...@@ -215,7 +190,7 @@ describe MigrateProcessCommitWorkerJobs do ...@@ -215,7 +190,7 @@ describe MigrateProcessCommitWorkerJobs do
end end
it 'includes the commit SHA' do it 'includes the commit SHA' do
expect(job['args'][2]).to eq(commit.oid) expect(job['args'][2]).to eq(commit.id)
end end
end end
end end
......
...@@ -2271,6 +2271,34 @@ describe Ci::Build do ...@@ -2271,6 +2271,34 @@ describe Ci::Build do
end end
end end
describe '#yaml_variables' do
before do
build.update_attribute(:yaml_variables, variables)
end
context 'when serialized valu is a symbolized hash' do
let(:variables) do
[{ key: :VARIABLE, value: 'my value 1' }]
end
it 'keeps symbolizes keys and stringifies variables names' do
expect(build.yaml_variables)
.to eq [{ key: 'VARIABLE', value: 'my value 1' }]
end
end
context 'when serialized value is a hash with string keys' do
let(:variables) do
[{ 'key' => :VARIABLE, 'value' => 'my value 2' }]
end
it 'symblizes variables hash' do
expect(build.yaml_variables)
.to eq [{ key: 'VARIABLE', value: 'my value 2' }]
end
end
end
describe 'state transition: any => [:pending]' do describe 'state transition: any => [:pending]' do
let(:build) { create(:ci_build, :created) } let(:build) { create(:ci_build, :created) }
......
...@@ -3319,6 +3319,10 @@ form-data@~2.3.0, form-data@~2.3.1: ...@@ -3319,6 +3319,10 @@ form-data@~2.3.0, form-data@~2.3.1:
combined-stream "1.0.6" combined-stream "1.0.6"
mime-types "^2.1.12" mime-types "^2.1.12"
formdata-polyfill@^3.0.11:
version "3.0.11"
resolved "https://registry.yarnpkg.com/formdata-polyfill/-/formdata-polyfill-3.0.11.tgz#c82b4b4bea3356c0a6752219e54ce1edb2a7fb5b"
forwarded@~0.1.2: forwarded@~0.1.2:
version "0.1.2" version "0.1.2"
resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84"
......
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