Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
23288f62da
commit
6b9d3a4e83
143 changed files with 665 additions and 719 deletions
|
@ -235,12 +235,6 @@ RSpec/FactoriesInMigrationSpecs:
|
|||
- 'spec/lib/ee/gitlab/background_migration/**/*.rb'
|
||||
- 'ee/spec/lib/ee/gitlab/background_migration/**/*.rb'
|
||||
|
||||
Cop/IncludeActionViewContext:
|
||||
Enabled: true
|
||||
Exclude:
|
||||
- 'spec/**/*'
|
||||
- 'ee/spec/**/*'
|
||||
|
||||
Cop/IncludeSidekiqWorker:
|
||||
Enabled: true
|
||||
Exclude:
|
||||
|
|
5
Gemfile
5
Gemfile
|
@ -1,6 +1,6 @@
|
|||
source 'https://rubygems.org'
|
||||
|
||||
gem 'rails', '5.2.3'
|
||||
gem 'rails', '6.0.2'
|
||||
|
||||
gem 'bootsnap', '~> 1.4'
|
||||
|
||||
|
@ -305,7 +305,7 @@ gem 'gitlab-labkit', '0.9.1'
|
|||
|
||||
# I18n
|
||||
gem 'ruby_parser', '~> 3.8', require: false
|
||||
gem 'rails-i18n', '~> 5.1'
|
||||
gem 'rails-i18n', '~> 6.0'
|
||||
gem 'gettext_i18n_rails', '~> 1.8.0'
|
||||
gem 'gettext_i18n_rails_js', '~> 1.3'
|
||||
gem 'gettext', '~> 3.2.2', require: false, group: :development
|
||||
|
@ -332,6 +332,7 @@ group :metrics do
|
|||
end
|
||||
|
||||
group :development do
|
||||
gem 'listen', '~> 3.0'
|
||||
gem 'brakeman', '~> 4.2', require: false
|
||||
gem 'danger', '~> 6.0', require: false
|
||||
|
||||
|
|
129
Gemfile.lock
129
Gemfile.lock
|
@ -6,50 +6,64 @@ GEM
|
|||
ace-rails-ap (4.1.2)
|
||||
acme-client (2.0.5)
|
||||
faraday (~> 0.9, >= 0.9.1)
|
||||
actioncable (5.2.3)
|
||||
actionpack (= 5.2.3)
|
||||
actioncable (6.0.2)
|
||||
actionpack (= 6.0.2)
|
||||
nio4r (~> 2.0)
|
||||
websocket-driver (>= 0.6.1)
|
||||
actionmailer (5.2.3)
|
||||
actionpack (= 5.2.3)
|
||||
actionview (= 5.2.3)
|
||||
activejob (= 5.2.3)
|
||||
actionmailbox (6.0.2)
|
||||
actionpack (= 6.0.2)
|
||||
activejob (= 6.0.2)
|
||||
activerecord (= 6.0.2)
|
||||
activestorage (= 6.0.2)
|
||||
activesupport (= 6.0.2)
|
||||
mail (>= 2.7.1)
|
||||
actionmailer (6.0.2)
|
||||
actionpack (= 6.0.2)
|
||||
actionview (= 6.0.2)
|
||||
activejob (= 6.0.2)
|
||||
mail (~> 2.5, >= 2.5.4)
|
||||
rails-dom-testing (~> 2.0)
|
||||
actionpack (5.2.3)
|
||||
actionview (= 5.2.3)
|
||||
activesupport (= 5.2.3)
|
||||
actionpack (6.0.2)
|
||||
actionview (= 6.0.2)
|
||||
activesupport (= 6.0.2)
|
||||
rack (~> 2.0)
|
||||
rack-test (>= 0.6.3)
|
||||
rails-dom-testing (~> 2.0)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
||||
actionview (5.2.3)
|
||||
activesupport (= 5.2.3)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
||||
actiontext (6.0.2)
|
||||
actionpack (= 6.0.2)
|
||||
activerecord (= 6.0.2)
|
||||
activestorage (= 6.0.2)
|
||||
activesupport (= 6.0.2)
|
||||
nokogiri (>= 1.8.5)
|
||||
actionview (6.0.2)
|
||||
activesupport (= 6.0.2)
|
||||
builder (~> 3.1)
|
||||
erubi (~> 1.4)
|
||||
rails-dom-testing (~> 2.0)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.0.3)
|
||||
activejob (5.2.3)
|
||||
activesupport (= 5.2.3)
|
||||
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
||||
activejob (6.0.2)
|
||||
activesupport (= 6.0.2)
|
||||
globalid (>= 0.3.6)
|
||||
activemodel (5.2.3)
|
||||
activesupport (= 5.2.3)
|
||||
activerecord (5.2.3)
|
||||
activemodel (= 5.2.3)
|
||||
activesupport (= 5.2.3)
|
||||
arel (>= 9.0)
|
||||
activemodel (6.0.2)
|
||||
activesupport (= 6.0.2)
|
||||
activerecord (6.0.2)
|
||||
activemodel (= 6.0.2)
|
||||
activesupport (= 6.0.2)
|
||||
activerecord-explain-analyze (0.1.0)
|
||||
activerecord (>= 4)
|
||||
pg
|
||||
activestorage (5.2.3)
|
||||
actionpack (= 5.2.3)
|
||||
activerecord (= 5.2.3)
|
||||
activestorage (6.0.2)
|
||||
actionpack (= 6.0.2)
|
||||
activejob (= 6.0.2)
|
||||
activerecord (= 6.0.2)
|
||||
marcel (~> 0.3.1)
|
||||
activesupport (5.2.3)
|
||||
activesupport (6.0.2)
|
||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||
i18n (>= 0.7, < 2)
|
||||
minitest (~> 5.1)
|
||||
tzinfo (~> 1.1)
|
||||
zeitwerk (~> 2.2)
|
||||
acts-as-taggable-on (6.5.0)
|
||||
activerecord (>= 5.0, < 6.1)
|
||||
adamantium (0.2.0)
|
||||
|
@ -62,7 +76,6 @@ GEM
|
|||
apollo_upload_server (2.0.0.beta.3)
|
||||
graphql (>= 1.8)
|
||||
rails (>= 4.2)
|
||||
arel (9.0.0)
|
||||
asana (0.9.3)
|
||||
faraday (~> 0.9)
|
||||
faraday_middleware (~> 0.9)
|
||||
|
@ -198,13 +211,14 @@ GEM
|
|||
declarative-option (0.1.0)
|
||||
default_value_for (3.3.0)
|
||||
activerecord (>= 3.2.0, < 6.1)
|
||||
derailed_benchmarks (1.3.5)
|
||||
derailed_benchmarks (1.4.2)
|
||||
benchmark-ips (~> 2)
|
||||
get_process_mem (~> 0)
|
||||
heapy (~> 0)
|
||||
memory_profiler (~> 0)
|
||||
rack (>= 1)
|
||||
rake (> 10, < 13)
|
||||
rake (> 10, < 14)
|
||||
ruby-statistics (>= 2.1)
|
||||
thor (~> 0.19)
|
||||
descendants_tracker (0.0.4)
|
||||
thread_safe (~> 0.3, >= 0.3.1)
|
||||
|
@ -348,7 +362,8 @@ GEM
|
|||
gemoji (3.0.1)
|
||||
gemojione (3.3.0)
|
||||
json
|
||||
get_process_mem (0.2.3)
|
||||
get_process_mem (0.2.5)
|
||||
ffi (~> 1.0)
|
||||
gettext (3.2.9)
|
||||
locale (>= 2.0.5)
|
||||
text (>= 1.3.0)
|
||||
|
@ -434,8 +449,9 @@ GEM
|
|||
activesupport
|
||||
grape (~> 1.0)
|
||||
rake (~> 12)
|
||||
grape_logging (1.7.0)
|
||||
grape_logging (1.8.3)
|
||||
grape
|
||||
rack
|
||||
graphiql-rails (1.4.10)
|
||||
railties
|
||||
sprockets-rails
|
||||
|
@ -510,7 +526,7 @@ GEM
|
|||
mime-types (~> 3.0)
|
||||
multi_xml (>= 0.5.2)
|
||||
httpclient (2.8.3)
|
||||
i18n (1.7.1)
|
||||
i18n (1.7.0)
|
||||
concurrent-ruby (~> 1.0)
|
||||
i18n_data (0.8.0)
|
||||
icalendar (2.4.1)
|
||||
|
@ -609,12 +625,12 @@ GEM
|
|||
memoist (0.16.0)
|
||||
memoizable (0.4.2)
|
||||
thread_safe (~> 0.3, >= 0.3.1)
|
||||
memory_profiler (0.9.13)
|
||||
memory_profiler (0.9.14)
|
||||
method_source (0.9.2)
|
||||
mime-types (3.2.2)
|
||||
mime-types-data (~> 3.2015)
|
||||
mime-types-data (3.2019.0331)
|
||||
mimemagic (0.3.2)
|
||||
mimemagic (0.3.3)
|
||||
mini_magick (4.9.5)
|
||||
mini_mime (1.0.2)
|
||||
mini_portile2 (2.4.0)
|
||||
|
@ -787,18 +803,20 @@ GEM
|
|||
rack-test (1.1.0)
|
||||
rack (>= 1.0, < 3)
|
||||
rack-timeout (0.5.1)
|
||||
rails (5.2.3)
|
||||
actioncable (= 5.2.3)
|
||||
actionmailer (= 5.2.3)
|
||||
actionpack (= 5.2.3)
|
||||
actionview (= 5.2.3)
|
||||
activejob (= 5.2.3)
|
||||
activemodel (= 5.2.3)
|
||||
activerecord (= 5.2.3)
|
||||
activestorage (= 5.2.3)
|
||||
activesupport (= 5.2.3)
|
||||
rails (6.0.2)
|
||||
actioncable (= 6.0.2)
|
||||
actionmailbox (= 6.0.2)
|
||||
actionmailer (= 6.0.2)
|
||||
actionpack (= 6.0.2)
|
||||
actiontext (= 6.0.2)
|
||||
actionview (= 6.0.2)
|
||||
activejob (= 6.0.2)
|
||||
activemodel (= 6.0.2)
|
||||
activerecord (= 6.0.2)
|
||||
activestorage (= 6.0.2)
|
||||
activesupport (= 6.0.2)
|
||||
bundler (>= 1.3.0)
|
||||
railties (= 5.2.3)
|
||||
railties (= 6.0.2)
|
||||
sprockets-rails (>= 2.0.0)
|
||||
rails-controller-testing (1.0.4)
|
||||
actionpack (>= 5.0.1.x)
|
||||
|
@ -809,15 +827,15 @@ GEM
|
|||
nokogiri (>= 1.6)
|
||||
rails-html-sanitizer (1.3.0)
|
||||
loofah (~> 2.3)
|
||||
rails-i18n (5.1.1)
|
||||
rails-i18n (6.0.0)
|
||||
i18n (>= 0.7, < 2)
|
||||
railties (>= 5.0, < 6)
|
||||
railties (5.2.3)
|
||||
actionpack (= 5.2.3)
|
||||
activesupport (= 5.2.3)
|
||||
railties (>= 6.0.0, < 7)
|
||||
railties (6.0.2)
|
||||
actionpack (= 6.0.2)
|
||||
activesupport (= 6.0.2)
|
||||
method_source
|
||||
rake (>= 0.8.7)
|
||||
thor (>= 0.19.0, < 2.0)
|
||||
thor (>= 0.20.3, < 2.0)
|
||||
rainbow (3.0.0)
|
||||
raindrops (0.19.0)
|
||||
rake (12.3.3)
|
||||
|
@ -937,6 +955,7 @@ GEM
|
|||
ruby-progressbar (1.10.1)
|
||||
ruby-saml (1.7.2)
|
||||
nokogiri (>= 1.5.10)
|
||||
ruby-statistics (2.1.1)
|
||||
ruby_dep (1.5.0)
|
||||
ruby_parser (3.13.1)
|
||||
sexp_processor (~> 4.9)
|
||||
|
@ -1111,9 +1130,9 @@ GEM
|
|||
hashdiff
|
||||
webpack-rails (0.9.11)
|
||||
railties (>= 3.2.0)
|
||||
websocket-driver (0.7.0)
|
||||
websocket-driver (0.7.1)
|
||||
websocket-extensions (>= 0.1.0)
|
||||
websocket-extensions (0.1.3)
|
||||
websocket-extensions (0.1.4)
|
||||
wikicloth (0.8.1)
|
||||
builder
|
||||
expression_parser
|
||||
|
@ -1122,6 +1141,7 @@ GEM
|
|||
xml-simple (1.1.5)
|
||||
xpath (3.2.0)
|
||||
nokogiri (~> 1.8)
|
||||
zeitwerk (2.2.2)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
@ -1259,6 +1279,7 @@ DEPENDENCIES
|
|||
license_finder (~> 5.4)
|
||||
licensee (~> 8.9)
|
||||
liquid (~> 4.0)
|
||||
listen (~> 3.0)
|
||||
lograge (~> 0.5)
|
||||
loofah (~> 2.2)
|
||||
lru_redux
|
||||
|
@ -1309,9 +1330,9 @@ DEPENDENCIES
|
|||
rack-oauth2 (~> 1.9.3)
|
||||
rack-proxy (~> 0.6.0)
|
||||
rack-timeout
|
||||
rails (= 5.2.3)
|
||||
rails (= 6.0.2)
|
||||
rails-controller-testing
|
||||
rails-i18n (~> 5.1)
|
||||
rails-i18n (~> 6.0)
|
||||
rainbow (~> 3.0)
|
||||
raindrops (~> 0.18)
|
||||
rblineprof (~> 0.3.6)
|
||||
|
|
68
app/assets/javascripts/editor/editor_lite.js
Normal file
68
app/assets/javascripts/editor/editor_lite.js
Normal file
|
@ -0,0 +1,68 @@
|
|||
import { editor as monacoEditor, languages as monacoLanguages, Uri } from 'monaco-editor';
|
||||
import gitlabTheme from '~/ide/lib/themes/gl_theme';
|
||||
import { defaultEditorOptions } from '~/ide/lib/editor_options';
|
||||
import { clearDomElement } from './utils';
|
||||
|
||||
export default class Editor {
|
||||
constructor(options = {}) {
|
||||
this.editorEl = null;
|
||||
this.blobContent = '';
|
||||
this.blobPath = '';
|
||||
this.instance = null;
|
||||
this.model = null;
|
||||
this.options = {
|
||||
...defaultEditorOptions,
|
||||
...options,
|
||||
};
|
||||
|
||||
Editor.setupMonacoTheme();
|
||||
}
|
||||
|
||||
static setupMonacoTheme() {
|
||||
monacoEditor.defineTheme(gitlabTheme.themeName, gitlabTheme.monacoTheme);
|
||||
monacoEditor.setTheme('gitlab');
|
||||
}
|
||||
|
||||
createInstance({ el = undefined, blobPath = '', blobContent = '' } = {}) {
|
||||
if (!el) return;
|
||||
this.editorEl = el;
|
||||
this.blobContent = blobContent;
|
||||
this.blobPath = blobPath;
|
||||
|
||||
clearDomElement(this.editorEl);
|
||||
|
||||
this.model = monacoEditor.createModel(
|
||||
this.blobContent,
|
||||
undefined,
|
||||
new Uri('gitlab', false, this.blobPath),
|
||||
);
|
||||
|
||||
monacoEditor.onDidCreateEditor(this.renderEditor.bind(this));
|
||||
|
||||
this.instance = monacoEditor.create(this.editorEl, this.options);
|
||||
this.instance.setModel(this.model);
|
||||
}
|
||||
|
||||
dispose() {
|
||||
return this.instance && this.instance.dispose();
|
||||
}
|
||||
|
||||
renderEditor() {
|
||||
delete this.editorEl.dataset.editorLoading;
|
||||
}
|
||||
|
||||
updateModelLanguage(path) {
|
||||
if (path === this.blobPath) return;
|
||||
this.blobPath = path;
|
||||
const ext = `.${path.split('.').pop()}`;
|
||||
const language = monacoLanguages
|
||||
.getLanguages()
|
||||
.find(lang => lang.extensions.indexOf(ext) !== -1);
|
||||
const id = language ? language.id : 'plaintext';
|
||||
monacoEditor.setModelLanguage(this.model, id);
|
||||
}
|
||||
|
||||
getValue() {
|
||||
return this.model.getValue();
|
||||
}
|
||||
}
|
11
app/assets/javascripts/editor/utils.js
Normal file
11
app/assets/javascripts/editor/utils.js
Normal file
|
@ -0,0 +1,11 @@
|
|||
export const clearDomElement = el => {
|
||||
if (!el || !el.firstChild) return;
|
||||
|
||||
while (el.firstChild) {
|
||||
el.removeChild(el.firstChild);
|
||||
}
|
||||
};
|
||||
|
||||
export default () => ({
|
||||
clearDomElement,
|
||||
});
|
|
@ -8,20 +8,13 @@ import ModelManager from './common/model_manager';
|
|||
import editorOptions, { defaultEditorOptions } from './editor_options';
|
||||
import gitlabTheme from './themes/gl_theme';
|
||||
import keymap from './keymap.json';
|
||||
import { clearDomElement } from '~/editor/utils';
|
||||
|
||||
function setupMonacoTheme() {
|
||||
monacoEditor.defineTheme(gitlabTheme.themeName, gitlabTheme.monacoTheme);
|
||||
monacoEditor.setTheme('gitlab');
|
||||
}
|
||||
|
||||
export const clearDomElement = el => {
|
||||
if (!el || !el.firstChild) return;
|
||||
|
||||
while (el.firstChild) {
|
||||
el.removeChild(el.firstChild);
|
||||
}
|
||||
};
|
||||
|
||||
export default class Editor {
|
||||
static create(options = {}) {
|
||||
if (!this.editorInstance) {
|
||||
|
|
|
@ -41,7 +41,7 @@ export default {
|
|||
changedIcon() {
|
||||
// False positive i18n lint: https://gitlab.com/gitlab-org/frontend/eslint-plugin-i18n/issues/26
|
||||
// eslint-disable-next-line @gitlab/i18n/no-non-i18n-strings
|
||||
const suffix = !this.file.changed && this.file.staged && this.showStagedIcon ? '-solid' : '';
|
||||
const suffix = this.file.staged && this.showStagedIcon ? '-solid' : '';
|
||||
|
||||
return `${getCommitIconMap(this.file).icon}${suffix}`;
|
||||
},
|
||||
|
@ -49,25 +49,19 @@ export default {
|
|||
return `${this.changedIcon} float-left d-block`;
|
||||
},
|
||||
tooltipTitle() {
|
||||
if (!this.showTooltip) return undefined;
|
||||
if (!this.showTooltip || !this.file.changed) return undefined;
|
||||
|
||||
const type = this.file.tempFile ? 'addition' : 'modification';
|
||||
|
||||
if (this.file.changed && !this.file.staged) {
|
||||
return sprintf(__('Unstaged %{type}'), {
|
||||
type,
|
||||
});
|
||||
} else if (!this.file.changed && this.file.staged) {
|
||||
if (this.file.staged) {
|
||||
return sprintf(__('Staged %{type}'), {
|
||||
type,
|
||||
});
|
||||
} else if (this.file.changed && this.file.staged) {
|
||||
return sprintf(__('Unstaged and staged %{type}'), {
|
||||
type,
|
||||
});
|
||||
}
|
||||
|
||||
return undefined;
|
||||
return sprintf(__('Unstaged %{type}'), {
|
||||
type,
|
||||
});
|
||||
},
|
||||
showIcon() {
|
||||
return (
|
||||
|
|
|
@ -21,10 +21,6 @@
|
|||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.btn-group {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.control {
|
||||
float: left;
|
||||
margin-left: 10px;
|
||||
|
|
|
@ -120,7 +120,7 @@ class ApplicationController < ActionController::Base
|
|||
def render(*args)
|
||||
super.tap do
|
||||
# Set a header for custom error pages to prevent them from being intercepted by gitlab-workhorse
|
||||
if (400..599).cover?(response.status) && workhorse_excluded_content_types.include?(response.content_type)
|
||||
if (400..599).cover?(response.status) && workhorse_excluded_content_types.include?(response.media_type)
|
||||
response.headers['X-GitLab-Custom-Error'] = '1'
|
||||
end
|
||||
end
|
||||
|
|
|
@ -21,9 +21,9 @@ module MembershipActions
|
|||
member = Members::UpdateService
|
||||
.new(current_user, update_params)
|
||||
.execute(member)
|
||||
.present(current_user: current_user)
|
||||
|
||||
present_members([member])
|
||||
member = present_members([member]).first
|
||||
|
||||
respond_to do |format|
|
||||
format.js { render 'shared/members/update', locals: { member: member } }
|
||||
end
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
module SendFileUpload
|
||||
def send_upload(file_upload, send_params: {}, redirect_params: {}, attachment: nil, proxy: false, disposition: 'attachment')
|
||||
if attachment
|
||||
response_disposition = ::Gitlab::ContentDisposition.format(disposition: disposition, filename: attachment)
|
||||
response_disposition = ActionDispatch::Http::ContentDisposition.format(disposition: disposition, filename: attachment)
|
||||
|
||||
# Response-Content-Type will not override an existing Content-Type in
|
||||
# Google Cloud Storage, so the metadata needs to be cleared on GCS for
|
||||
|
@ -15,7 +15,7 @@ module SendFileUpload
|
|||
# cross-origin JavaScript protection.
|
||||
send_params[:content_type] = 'text/plain' if File.extname(attachment) == '.js'
|
||||
|
||||
send_params.merge!(filename: attachment, disposition: utf8_encoded_disposition(disposition, attachment))
|
||||
send_params.merge!(filename: attachment, disposition: disposition)
|
||||
end
|
||||
|
||||
if file_upload.file_storage?
|
||||
|
@ -28,18 +28,6 @@ module SendFileUpload
|
|||
end
|
||||
end
|
||||
|
||||
# Since Rails 5 doesn't properly support support non-ASCII filenames,
|
||||
# we have to add our own to ensure RFC 5987 compliance. However, Rails
|
||||
# 5 automatically appends `filename#{filename}` here:
|
||||
# https://github.com/rails/rails/blob/v5.0.7/actionpack/lib/action_controller/metal/data_streaming.rb#L137
|
||||
# Rails 6 will have https://github.com/rails/rails/pull/33829, so we
|
||||
# can get rid of this special case handling when we upgrade.
|
||||
def utf8_encoded_disposition(disposition, filename)
|
||||
content = ::Gitlab::ContentDisposition.new(disposition: disposition, filename: filename)
|
||||
|
||||
"#{disposition}; #{content.utf8_filename}"
|
||||
end
|
||||
|
||||
def guess_content_type(filename)
|
||||
types = MIME::Types.type_for(filename)
|
||||
|
||||
|
|
|
@ -3,11 +3,12 @@
|
|||
class Projects::ReleasesController < Projects::ApplicationController
|
||||
# Authorize
|
||||
before_action :require_non_empty_project, except: [:index]
|
||||
before_action :release, only: %i[edit update]
|
||||
before_action :release, only: %i[edit show update]
|
||||
before_action :authorize_read_release!
|
||||
before_action do
|
||||
push_frontend_feature_flag(:release_issue_summary, project)
|
||||
push_frontend_feature_flag(:release_evidence_collection, project, default_enabled: true)
|
||||
push_frontend_feature_flag(:release_show_page, project)
|
||||
end
|
||||
before_action :authorize_update_release!, only: %i[edit update]
|
||||
before_action :authorize_read_release_evidence!, only: [:evidence]
|
||||
|
@ -29,6 +30,16 @@ class Projects::ReleasesController < Projects::ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
def show
|
||||
return render_404 unless Feature.enabled?(:release_show_page, project)
|
||||
|
||||
respond_to do |format|
|
||||
format.html do
|
||||
render :show
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def releases
|
||||
|
@ -37,7 +48,9 @@ class Projects::ReleasesController < Projects::ApplicationController
|
|||
|
||||
def edit
|
||||
respond_to do |format|
|
||||
format.html { render 'edit' }
|
||||
format.html do
|
||||
render :edit
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ require 'nokogiri'
|
|||
|
||||
module MarkupHelper
|
||||
include ActionView::Helpers::TextHelper
|
||||
include ::Gitlab::ActionViewOutput::Context
|
||||
include ActionView::Context
|
||||
|
||||
def plain?(filename)
|
||||
Gitlab::MarkupHelper.plain?(filename)
|
||||
|
|
|
@ -200,6 +200,10 @@ class CommitStatus < ApplicationRecord
|
|||
update_all('processed=TRUE, lock_version=COALESCE(lock_version,0)+1')
|
||||
end
|
||||
|
||||
def self.locking_enabled?
|
||||
false
|
||||
end
|
||||
|
||||
def locking_enabled?
|
||||
will_save_change_to_status?
|
||||
end
|
||||
|
|
|
@ -130,6 +130,10 @@ module Issuable
|
|||
|
||||
strip_attributes :title
|
||||
|
||||
def self.locking_enabled?
|
||||
false
|
||||
end
|
||||
|
||||
# We want to use optimistic lock for cases when only title or description are involved
|
||||
# http://api.rubyonrails.org/classes/ActiveRecord/Locking/Optimistic.html
|
||||
def locking_enabled?
|
||||
|
|
|
@ -37,6 +37,8 @@ module MirrorAuthentication
|
|||
end
|
||||
|
||||
define_method("#{name}=") do |value|
|
||||
credentials_will_change!
|
||||
|
||||
self.credentials ||= {}
|
||||
|
||||
# Removal of the password, username, etc, generally causes an update of
|
||||
|
|
|
@ -712,7 +712,7 @@ class MergeRequest < ApplicationRecord
|
|||
end
|
||||
|
||||
def validate_branch_name(attr)
|
||||
return unless changes_include?(attr)
|
||||
return unless will_save_change_to_attribute?(attr)
|
||||
|
||||
branch = read_attribute(attr)
|
||||
|
||||
|
|
|
@ -21,7 +21,10 @@ class NotificationSetting < ApplicationRecord
|
|||
# pending delete).
|
||||
#
|
||||
scope :for_projects, -> do
|
||||
includes(:project).references(:projects).where(source_type: 'Project').where.not(projects: { id: nil, pending_delete: true })
|
||||
includes(:project).references(:projects)
|
||||
.where(source_type: 'Project')
|
||||
.where.not(projects: { id: nil })
|
||||
.where.not(projects: { pending_delete: true })
|
||||
end
|
||||
|
||||
EMAIL_EVENTS = [
|
||||
|
|
|
@ -208,7 +208,7 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
|
|||
AnchorData.new(false,
|
||||
statistic_icon + _('New file'),
|
||||
project_new_blob_path(project, default_branch || 'master'),
|
||||
'success')
|
||||
'missing')
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
module UserStatusTooltip
|
||||
extend ActiveSupport::Concern
|
||||
include ActionView::Helpers::TagHelper
|
||||
include ::Gitlab::ActionViewOutput::Context
|
||||
include ActionView::Context
|
||||
include EmojiHelper
|
||||
include UsersHelper
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ module SpamCheckMethods
|
|||
# attribute values.
|
||||
# rubocop:disable Gitlab/ModuleWithInstanceVariables
|
||||
def spam_check(spammable, user)
|
||||
SpamCheckService.new(
|
||||
Spam::SpamCheckService.new(
|
||||
spammable: spammable,
|
||||
request: @request
|
||||
).execute(
|
||||
|
|
|
@ -8,8 +8,18 @@ module Metrics
|
|||
ALLOWED_FILE_TYPE = '.yml'
|
||||
USER_DASHBOARDS_DIR = ::Metrics::Dashboard::ProjectDashboardService::DASHBOARD_ROOT
|
||||
|
||||
def self.allowed_dashboard_templates
|
||||
@allowed_dashboard_templates ||= Set[::Metrics::Dashboard::SystemDashboardService::DASHBOARD_PATH].freeze
|
||||
class << self
|
||||
def allowed_dashboard_templates
|
||||
@allowed_dashboard_templates ||= Set[::Metrics::Dashboard::SystemDashboardService::DASHBOARD_PATH].freeze
|
||||
end
|
||||
|
||||
def sequences
|
||||
@sequences ||= {
|
||||
::Metrics::Dashboard::SystemDashboardService::DASHBOARD_PATH => [::Gitlab::Metrics::Dashboard::Stages::CommonMetricsInserter,
|
||||
::Gitlab::Metrics::Dashboard::Stages::ProjectMetricsInserter,
|
||||
::Gitlab::Metrics::Dashboard::Stages::Sorter].freeze
|
||||
}.freeze
|
||||
end
|
||||
end
|
||||
|
||||
def execute
|
||||
|
@ -92,7 +102,9 @@ module Metrics
|
|||
end
|
||||
|
||||
def new_dashboard_content
|
||||
File.read(Rails.root.join(dashboard_template))
|
||||
::Gitlab::Metrics::Dashboard::Processor
|
||||
.new(project, raw_dashboard, sequence, {})
|
||||
.process.deep_stringify_keys.to_yaml
|
||||
end
|
||||
|
||||
def repository
|
||||
|
@ -106,6 +118,14 @@ module Metrics
|
|||
result
|
||||
end
|
||||
end
|
||||
|
||||
def raw_dashboard
|
||||
YAML.safe_load(File.read(Rails.root.join(dashboard_template)))
|
||||
end
|
||||
|
||||
def sequence
|
||||
self.class.sequences[dashboard_template]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -12,7 +12,7 @@ module Projects
|
|||
matching_programming_languages = ensure_programming_languages(detection)
|
||||
|
||||
RepositoryLanguage.transaction do
|
||||
project.repository_languages.where(programming_language_id: detection.deletions).delete_all
|
||||
RepositoryLanguage.where(project_id: project.id, programming_language_id: detection.deletions).delete_all
|
||||
|
||||
detection.updates.each do |update|
|
||||
RepositoryLanguage
|
||||
|
|
|
@ -20,6 +20,8 @@ module Projects
|
|||
::Projects::MoveProjectAuthorizationsService.new(@project, @current_user)
|
||||
.execute(source_project, remove_remaining_elements: remove_remaining_elements)
|
||||
|
||||
@project.save(touch: false)
|
||||
|
||||
success
|
||||
end
|
||||
end
|
||||
|
|
|
@ -13,8 +13,6 @@ module Projects
|
|||
include Gitlab::ShellAdapter
|
||||
TransferError = Class.new(StandardError)
|
||||
|
||||
attr_reader :new_namespace
|
||||
|
||||
def execute(new_namespace)
|
||||
@new_namespace = new_namespace
|
||||
|
||||
|
@ -39,6 +37,8 @@ module Projects
|
|||
|
||||
private
|
||||
|
||||
attr_reader :old_path, :new_path, :new_namespace
|
||||
|
||||
# rubocop: disable CodeReuse/ActiveRecord
|
||||
def transfer(project)
|
||||
@old_path = project.full_path
|
||||
|
@ -132,6 +132,8 @@ module Projects
|
|||
end
|
||||
|
||||
def rollback_folder_move
|
||||
return if project.hashed_storage?(:repository)
|
||||
|
||||
move_repo_folder(@new_path, @old_path)
|
||||
move_repo_folder("#{@new_path}.wiki", "#{@old_path}.wiki")
|
||||
end
|
||||
|
|
68
app/services/spam/spam_check_service.rb
Normal file
68
app/services/spam/spam_check_service.rb
Normal file
|
@ -0,0 +1,68 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Spam
|
||||
class SpamCheckService
|
||||
include AkismetMethods
|
||||
|
||||
attr_accessor :spammable, :request, :options
|
||||
attr_reader :spam_log
|
||||
|
||||
def initialize(spammable:, request:)
|
||||
@spammable = spammable
|
||||
@request = request
|
||||
@options = {}
|
||||
|
||||
if @request
|
||||
@options[:ip_address] = @request.env['action_dispatch.remote_ip'].to_s
|
||||
@options[:user_agent] = @request.env['HTTP_USER_AGENT']
|
||||
@options[:referrer] = @request.env['HTTP_REFERRER']
|
||||
else
|
||||
@options[:ip_address] = @spammable.ip_address
|
||||
@options[:user_agent] = @spammable.user_agent
|
||||
end
|
||||
end
|
||||
|
||||
def execute(api: false, recaptcha_verified:, spam_log_id:, user_id:)
|
||||
if recaptcha_verified
|
||||
# If it's a request which is already verified through recaptcha,
|
||||
# update the spam log accordingly.
|
||||
SpamLog.verify_recaptcha!(user_id: user_id, id: spam_log_id)
|
||||
else
|
||||
# Otherwise, it goes to Akismet for spam check.
|
||||
# If so, it assigns spammable object as "spam" and creates a SpamLog record.
|
||||
possible_spam = check(api)
|
||||
spammable.spam = possible_spam unless spammable.allow_possible_spam?
|
||||
spammable.spam_log = spam_log
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def check(api)
|
||||
return unless request
|
||||
return unless check_for_spam?
|
||||
return unless akismet.spam?
|
||||
|
||||
create_spam_log(api)
|
||||
true
|
||||
end
|
||||
|
||||
def check_for_spam?
|
||||
spammable.check_for_spam?
|
||||
end
|
||||
|
||||
def create_spam_log(api)
|
||||
@spam_log = SpamLog.create!(
|
||||
{
|
||||
user_id: spammable.author_id,
|
||||
title: spammable.spam_title,
|
||||
description: spammable.spam_description,
|
||||
source_ip: options[:ip_address],
|
||||
user_agent: options[:user_agent],
|
||||
noteable_type: spammable.class.to_s,
|
||||
via_api: api
|
||||
}
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,66 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class SpamCheckService
|
||||
include AkismetMethods
|
||||
|
||||
attr_accessor :spammable, :request, :options
|
||||
attr_reader :spam_log
|
||||
|
||||
def initialize(spammable:, request:)
|
||||
@spammable = spammable
|
||||
@request = request
|
||||
@options = {}
|
||||
|
||||
if @request
|
||||
@options[:ip_address] = @request.env['action_dispatch.remote_ip'].to_s
|
||||
@options[:user_agent] = @request.env['HTTP_USER_AGENT']
|
||||
@options[:referrer] = @request.env['HTTP_REFERRER']
|
||||
else
|
||||
@options[:ip_address] = @spammable.ip_address
|
||||
@options[:user_agent] = @spammable.user_agent
|
||||
end
|
||||
end
|
||||
|
||||
def execute(api: false, recaptcha_verified:, spam_log_id:, user_id:)
|
||||
if recaptcha_verified
|
||||
# If it's a request which is already verified through recaptcha,
|
||||
# update the spam log accordingly.
|
||||
SpamLog.verify_recaptcha!(user_id: user_id, id: spam_log_id)
|
||||
else
|
||||
# Otherwise, it goes to Akismet for spam check.
|
||||
# If so, it assigns spammable object as "spam" and creates a SpamLog record.
|
||||
possible_spam = check(api)
|
||||
spammable.spam = possible_spam unless spammable.allow_possible_spam?
|
||||
spammable.spam_log = spam_log
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def check(api)
|
||||
return unless request
|
||||
return unless check_for_spam?
|
||||
return unless akismet.spam?
|
||||
|
||||
create_spam_log(api)
|
||||
true
|
||||
end
|
||||
|
||||
def check_for_spam?
|
||||
spammable.check_for_spam?
|
||||
end
|
||||
|
||||
def create_spam_log(api)
|
||||
@spam_log = SpamLog.create!(
|
||||
{
|
||||
user_id: spammable.author_id,
|
||||
title: spammable.spam_title,
|
||||
description: spammable.spam_description,
|
||||
source_ip: options[:ip_address],
|
||||
user_agent: options[:user_agent],
|
||||
noteable_type: spammable.class.to_s,
|
||||
via_api: api
|
||||
}
|
||||
)
|
||||
end
|
||||
end
|
|
@ -125,7 +125,7 @@ module ObjectStorage
|
|||
|
||||
included do
|
||||
include AfterCommitQueue
|
||||
after_save on: [:create, :update] do
|
||||
after_save do
|
||||
background_upload(changed_mounts)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -49,13 +49,6 @@
|
|||
= render 'projects/buttons/star'
|
||||
= render 'projects/buttons/fork'
|
||||
|
||||
- if can?(current_user, :download_code, @project)
|
||||
.project-clone-holder.d-inline-flex.d-md-none.btn-block
|
||||
= render "shared/mobile_clone_panel"
|
||||
|
||||
.project-clone-holder.d-none.d-md-inline-flex
|
||||
= render "projects/buttons/clone"
|
||||
|
||||
- if can?(current_user, :download_code, @project)
|
||||
%nav.project-stats
|
||||
.nav-links.quick-links
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
- project = project || @project
|
||||
- dropdown_class = local_assigns.fetch(:dropdown_class, '')
|
||||
|
||||
.git-clone-holder.js-git-clone-holder.input-group
|
||||
%a#clone-dropdown.input-group-text.btn.btn-primary.btn-xs.clone-dropdown-btn.qa-clone-dropdown{ href: '#', data: { toggle: 'dropdown' } }
|
||||
.git-clone-holder.js-git-clone-holder
|
||||
%a#clone-dropdown.btn.btn-primary.clone-dropdown-btn.qa-clone-dropdown{ href: '#', data: { toggle: 'dropdown' } }
|
||||
%span.append-right-4.js-clone-dropdown-label
|
||||
= _('Clone')
|
||||
= sprite_icon("arrow-down", css_class: "icon")
|
||||
%ul.p-3.dropdown-menu.dropdown-menu-right.dropdown-menu-large.dropdown-menu-selectable.clone-options-dropdown.qa-clone-options
|
||||
%ul.p-3.dropdown-menu.dropdown-menu-large.dropdown-menu-selectable.clone-options-dropdown.qa-clone-options{ class: dropdown_class }
|
||||
- if ssh_enabled?
|
||||
%li
|
||||
%label.label-bold
|
||||
|
|
|
@ -11,9 +11,14 @@
|
|||
|
||||
- if @project.can_current_user_push_code?
|
||||
%p.append-bottom-0
|
||||
= _('You can create files directly in GitLab using one of the following options.')
|
||||
= _('You can get started by cloning the repository or start adding files to it with one of the following options.')
|
||||
|
||||
.project-buttons.qa-quick-actions
|
||||
.project-clone-holder.d-block.d-md-none.mt-2.mr-2
|
||||
= render "shared/mobile_clone_panel"
|
||||
|
||||
.project-clone-holder.d-none.d-md-inline-block.mt-2.mr-2.float-left
|
||||
= render "projects/buttons/clone"
|
||||
= render 'stat_anchor_list', anchors: @project.empty_repo_statistics_buttons
|
||||
|
||||
- if can?(current_user, :push_code, @project)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<% self.formats = ["html"] %>
|
||||
<% self.formats = [:html] %>
|
||||
|
||||
<%= raw(
|
||||
{
|
||||
|
|
4
app/views/projects/releases/show.html.haml
Normal file
4
app/views/projects/releases/show.html.haml
Normal file
|
@ -0,0 +1,4 @@
|
|||
- add_to_breadcrumbs _("Releases"), project_releases_path(@project)
|
||||
- page_title @release.name
|
||||
|
||||
#js-show-release-page{ data: { project_id: @project.id, tag_name: @release.tag } }
|
|
@ -101,3 +101,9 @@
|
|||
= render "projects/buttons/xcode_link"
|
||||
|
||||
= render 'projects/buttons/download', project: @project, ref: @ref
|
||||
|
||||
.project-clone-holder.d-block.d-md-none.mt-sm-2.mt-md-0>
|
||||
= render "shared/mobile_clone_panel"
|
||||
|
||||
.project-clone-holder.d-none.d-md-inline-block>
|
||||
= render "projects/buttons/clone", dropdown_class: 'dropdown-menu-right'
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
.btn-group.mobile-git-clone.js-mobile-git-clone.btn-block
|
||||
= clipboard_button(button_text: default_clone_label, text: default_url_to_repo(project), hide_button_icon: true, class: "btn-primary flex-fill bold justify-content-center input-group-text clone-dropdown-btn js-clone-dropdown-label")
|
||||
%button.btn.btn-primary.dropdown-toggle.js-dropdown-toggle.flex-grow-0.d-flex-center{ type: "button", data: { toggle: "dropdown" } }
|
||||
%button.btn.btn-primary.dropdown-toggle.js-dropdown-toggle.flex-grow-0.d-flex-center.w-auto.ml-0{ type: "button", data: { toggle: "dropdown" } }
|
||||
= sprite_icon("arrow-down", css_class: "dropdown-btn-icon icon")
|
||||
%ul.dropdown-menu.dropdown-menu-selectable.dropdown-menu-right.clone-options-dropdown{ data: { dropdown: true } }
|
||||
- if ssh_enabled?
|
||||
|
|
|
@ -26,49 +26,26 @@ module MailScheduler
|
|||
end
|
||||
|
||||
def self.perform_async(*args)
|
||||
super(*Arguments.serialize(args))
|
||||
super(*ActiveJob::Arguments.serialize(args))
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# If an argument is in the ActiveJob::Arguments::TYPE_WHITELIST list,
|
||||
# This is copied over from https://github.com/rails/rails/blob/v6.0.1/activejob/lib/active_job/arguments.rb#L50
|
||||
# because it is declared as a private constant
|
||||
PERMITTED_TYPES = [NilClass, String, Integer, Float, BigDecimal, TrueClass, FalseClass].freeze
|
||||
|
||||
private_constant :PERMITTED_TYPES
|
||||
|
||||
# If an argument is in the PERMITTED_TYPES list,
|
||||
# it means the argument cannot be deserialized.
|
||||
# Which means there's something wrong with our code.
|
||||
def check_arguments!(args)
|
||||
args.each do |arg|
|
||||
if arg.class.in?(ActiveJob::Arguments::TYPE_WHITELIST)
|
||||
if arg.class.in?(PERMITTED_TYPES)
|
||||
raise(ArgumentError, "Argument `#{arg}` cannot be deserialized because of its type")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Permit ActionController::Parameters for serializable Hash
|
||||
#
|
||||
# Port of
|
||||
# https://github.com/rails/rails/commit/945fdd76925c9f615bf016717c4c8db2b2955357#diff-fc90ec41ef75be8b2259526fe1a8b663
|
||||
module Arguments
|
||||
include ActiveJob::Arguments
|
||||
extend self
|
||||
|
||||
private
|
||||
|
||||
def serialize_argument(argument)
|
||||
case argument
|
||||
when -> (arg) { arg.respond_to?(:permitted?) }
|
||||
serialize_hash(argument.to_h).tap do |result|
|
||||
result[WITH_INDIFFERENT_ACCESS_KEY] = serialize_argument(true)
|
||||
end
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Make sure we remove this patch starting with Rails 6.0.
|
||||
if Rails.version.start_with?('6.0')
|
||||
raise <<~MSG
|
||||
Please remove the patch `Arguments` module and use `ActiveJob::Arguments` again.
|
||||
MSG
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
12
bin/setup
12
bin/setup
|
@ -1,6 +1,5 @@
|
|||
#!/usr/bin/env ruby
|
||||
require 'fileutils'
|
||||
include FileUtils
|
||||
|
||||
# path to your application root.
|
||||
APP_ROOT = File.expand_path('..', __dir__)
|
||||
|
@ -9,24 +8,25 @@ def system!(*args)
|
|||
system(*args) || abort("\n== Command #{args} failed ==")
|
||||
end
|
||||
|
||||
chdir APP_ROOT do
|
||||
# This script is a starting point to setup your application.
|
||||
FileUtils.chdir APP_ROOT do
|
||||
# This script is a way to setup or update your development environment automatically.
|
||||
# This script is idempotent, so that you can run it at anytime and get an expectable outcome.
|
||||
# Add necessary setup steps to this file.
|
||||
|
||||
puts '== Installing dependencies =='
|
||||
system! 'gem install bundler --conservative'
|
||||
system('bundle check') || system!('bundle install')
|
||||
|
||||
# Install JavaScript dependencies if using Yarn
|
||||
# Install JavaScript dependencies
|
||||
# system('bin/yarn')
|
||||
|
||||
# puts "\n== Copying sample files =="
|
||||
# unless File.exist?('config/database.yml')
|
||||
# cp 'config/database.yml.sample', 'config/database.yml'
|
||||
# FileUtils.cp 'config/database.yml.sample', 'config/database.yml'
|
||||
# end
|
||||
|
||||
puts "\n== Preparing database =="
|
||||
system! 'bin/rails db:setup'
|
||||
system! 'bin/rails db:prepare'
|
||||
|
||||
puts "\n== Removing old logs and tempfiles =="
|
||||
system! 'bin/rails log:clear tmp:clear'
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Remove unstaged and staged modification tooltip
|
||||
merge_request: 23847
|
||||
author:
|
||||
type: fixed
|
5
changelogs/unreleased/31034-upgrade-to-rails-6.yml
Normal file
5
changelogs/unreleased/31034-upgrade-to-rails-6.yml
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Upgrade to Rails 6
|
||||
merge_request: 19891
|
||||
author:
|
||||
type: other
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
title: Extends 'Duplicate dashboard' feature, by including custom metrics added to
|
||||
GitLab-defined dashboards.
|
||||
merge_request: 21923
|
||||
author:
|
||||
type: added
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Move the clone button to the tree controls area
|
||||
merge_request: 17752
|
||||
author: Ablay Keldibek
|
||||
type: changed
|
|
@ -1,7 +1,9 @@
|
|||
require_relative 'boot'
|
||||
|
||||
# Based on https://github.com/rails/rails/blob/v5.2.3/railties/lib/rails/all.rb
|
||||
# Based on https://github.com/rails/rails/blob/v6.0.1/railties/lib/rails/all.rb
|
||||
# Only load the railties we need instead of loading everything
|
||||
require 'rails'
|
||||
|
||||
require 'active_record/railtie'
|
||||
require 'action_controller/railtie'
|
||||
require 'action_view/railtie'
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
# Load the rails application
|
||||
|
||||
# Load the Rails application.
|
||||
require_relative 'application'
|
||||
|
||||
# Initialize the rails application
|
||||
# Initialize the Rails application.
|
||||
Rails.application.initialize!
|
||||
|
|
|
@ -50,4 +50,8 @@ Rails.application.configure do
|
|||
|
||||
# BetterErrors live shell (REPL) on every stack frame
|
||||
BetterErrors::Middleware.allow_ip!("127.0.0.1/0")
|
||||
|
||||
# Use an evented file watcher to asynchronously detect changes in source code,
|
||||
# routes, locales, etc. This feature depends on the listen gem.
|
||||
config.file_watcher = ActiveSupport::EventedFileUpdateChecker
|
||||
end
|
||||
|
|
|
@ -24,10 +24,11 @@ module RegisterDateTimeWithTimeZone
|
|||
def initialize_type_map(mapping = type_map)
|
||||
super mapping
|
||||
|
||||
mapping.register_type 'timestamptz' do |_, _, sql_type|
|
||||
precision = extract_precision(sql_type)
|
||||
ActiveRecord::ConnectionAdapters::PostgreSQLAdapter::OID::DateTimeWithTimeZone.new(precision: precision)
|
||||
end
|
||||
register_class_with_precision(
|
||||
mapping,
|
||||
'timestamptz',
|
||||
ActiveRecord::ConnectionAdapters::PostgreSQLAdapter::OID::DateTimeWithTimeZone
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -46,3 +47,5 @@ end
|
|||
if (ActiveRecord::Base.connection.active? rescue false)
|
||||
ActiveRecord::Base.connection.send :reload_type_map
|
||||
end
|
||||
|
||||
ActiveRecord::Base.time_zone_aware_types += [:datetime_with_timezone]
|
||||
|
|
|
@ -6,7 +6,7 @@ module ActiveRecord
|
|||
self
|
||||
end
|
||||
|
||||
def self.run(preloader)
|
||||
def self.run
|
||||
end
|
||||
|
||||
def self.preloaded_records
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
ActiveRecord::ConnectionAdapters::ConnectionPool.prepend Gitlab::Patch::ActiveRecordQueryCache
|
|
@ -26,7 +26,7 @@ module ActiveRecord
|
|||
locking_column => possible_previous_lock_value,
|
||||
self.class.primary_key => id_in_database
|
||||
).update_all(
|
||||
attributes_with_values_for_update(attribute_names)
|
||||
attributes_with_values(attribute_names)
|
||||
)
|
||||
|
||||
if affected_rows != 1
|
||||
|
|
|
@ -12,4 +12,5 @@ if csp_settings['enabled']
|
|||
|
||||
Rails.application.config.content_security_policy_report_only = csp_settings['report_only']
|
||||
Rails.application.config.content_security_policy_nonce_generator = ->(request) { SecureRandom.base64(16) }
|
||||
Rails.application.config.content_security_policy_nonce_directives = %w(script-src)
|
||||
end
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
# Be sure to restart your server when you modify this file.
|
||||
|
||||
Rails.application.config.action_dispatch.use_cookies_with_metadata = false
|
||||
Rails.application.config.action_dispatch.cookies_serializer = :hybrid
|
||||
|
|
|
@ -166,7 +166,7 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
|
|||
end
|
||||
end
|
||||
|
||||
resources :releases, only: [:index, :edit], param: :tag, constraints: { tag: %r{[^/]+} } do
|
||||
resources :releases, only: [:index, :show, :edit], param: :tag, constraints: { tag: %r{[^/]+} } do
|
||||
member do
|
||||
get :evidence
|
||||
end
|
||||
|
|
10
db/schema.rb
10
db/schema.rb
|
@ -2,11 +2,11 @@
|
|||
# of editing this file, please use the migrations feature of Active Record to
|
||||
# incrementally modify your database, and then regenerate this schema definition.
|
||||
#
|
||||
# Note that this schema.rb definition is the authoritative source for your
|
||||
# database schema. If you need to create the application database on another
|
||||
# system, you should be using db:schema:load, not running all the migrations
|
||||
# from scratch. The latter is a flawed and unsustainable approach (the more migrations
|
||||
# you'll amass, the slower it'll run and the greater likelihood for issues).
|
||||
# This file is the source Rails uses to define your schema when running `rails
|
||||
# db:schema:load`. When creating a new database, `rails db:schema:load` tends to
|
||||
# be faster and is potentially less error prone than running all of your
|
||||
# migrations from scratch. Old migrations may fail to apply correctly if those
|
||||
# migrations use external dependencies or application code.
|
||||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ See already supported package types in [Packages documentation](../administratio
|
|||
Since GitLab packages' UI is pretty generic, it is possible to add basic new
|
||||
package system support with solely backend changes. This guide is superficial and does
|
||||
not cover the way the code should be written. However, you can find a good example
|
||||
by looking at existing merge requests with Maven and NPM support:
|
||||
by looking at merge requests with Maven and NPM support:
|
||||
|
||||
- [NPM registry support](https://gitlab.com/gitlab-org/gitlab/merge_requests/8673).
|
||||
- [Conan repository](https://gitlab.com/gitlab-org/gitlab/issues/8248).
|
||||
|
|
|
@ -434,7 +434,7 @@ module API
|
|||
|
||||
def present_disk_file!(path, filename, content_type = 'application/octet-stream')
|
||||
filename ||= File.basename(path)
|
||||
header['Content-Disposition'] = ::Gitlab::ContentDisposition.format(disposition: 'attachment', filename: filename)
|
||||
header['Content-Disposition'] = ActionDispatch::Http::ContentDisposition.format(disposition: 'attachment', filename: filename)
|
||||
header['Content-Transfer-Encoding'] = 'binary'
|
||||
content_type content_type
|
||||
|
||||
|
@ -542,7 +542,7 @@ module API
|
|||
def send_git_blob(repository, blob)
|
||||
env['api.format'] = :txt
|
||||
content_type 'text/plain'
|
||||
header['Content-Disposition'] = ::Gitlab::ContentDisposition.format(disposition: 'inline', filename: blob.name)
|
||||
header['Content-Disposition'] = ActionDispatch::Http::ContentDisposition.format(disposition: 'inline', filename: blob.name)
|
||||
|
||||
# Let Workhorse examine the content and determine the better content disposition
|
||||
header[Gitlab::Workhorse::DETECT_HEADER] = "true"
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# This file was simplified from https://raw.githubusercontent.com/rails/rails/195f39804a7a4a0034f25e8704220e03d95a752a/actionview/lib/action_view/context.rb.
|
||||
#
|
||||
# It is only needed by modules that need to call ActionView helper
|
||||
# methods (e.g. those in
|
||||
# https://github.com/rails/rails/tree/c4d3e202e10ae627b3b9c34498afb45450652421/actionview/lib/action_view/helpers)
|
||||
# to generate tags outside of a Rails controller (e.g. API, Sidekiq,
|
||||
# etc.).
|
||||
#
|
||||
# In Rails 5, ActionView::Context automatically includes CompiledTemplates.
|
||||
# This means that any module that includes ActionView::Context is now a descendant
|
||||
# of CompiledTemplates.
|
||||
#
|
||||
# When a partial is rendered for the first time, it runs
|
||||
# Module#module_eval, which will evaluate a string source that defines a
|
||||
# new method. For example:
|
||||
#
|
||||
# def _app_views_profiles_show_html_haml___1285955918103175884_70307801785400(local_assigns, output_buffer)
|
||||
# "hello world"
|
||||
# end
|
||||
#
|
||||
# When a new method is defined, the Ruby interpreter clears the method
|
||||
# cache for all descendants, and all methods for those modules will have
|
||||
# to be redefined. This can lead to a significant performance penalty.
|
||||
#
|
||||
# Rails 6 fixes this behavior by moving out the `include
|
||||
# CompiledTemplates` into ActionView::Base so that including `ActionView::Context`
|
||||
# doesn't quietly affect other modules in this way.
|
||||
|
||||
if Rails::VERSION::STRING.start_with?('6')
|
||||
raise 'This module is no longer needed in Rails 6. Use ActionView::Context instead.'
|
||||
end
|
||||
|
||||
module Gitlab
|
||||
module ActionViewOutput
|
||||
module Context
|
||||
attr_accessor :output_buffer, :view_flow
|
||||
end
|
||||
end
|
||||
end
|
|
@ -33,7 +33,7 @@ module Gitlab
|
|||
def template_name
|
||||
return unless template_name_valid?
|
||||
|
||||
location.first(-SUFFIX.length)
|
||||
location.delete_suffix(SUFFIX)
|
||||
end
|
||||
|
||||
def template_name_valid?
|
||||
|
|
|
@ -1,54 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
# This ports ActionDispatch::Http::ContentDisposition (https://github.com/rails/rails/pull/33829,
|
||||
# which will be available in Rails 6.
|
||||
module Gitlab
|
||||
class ContentDisposition # :nodoc:
|
||||
# Make sure we remove this patch starting with Rails 6.0.
|
||||
if Rails.version.start_with?('6.0')
|
||||
raise <<~MSG
|
||||
Please remove this file and use `ActionDispatch::Http::ContentDisposition` instead.
|
||||
MSG
|
||||
end
|
||||
|
||||
def self.format(disposition:, filename:)
|
||||
new(disposition: disposition, filename: filename).to_s
|
||||
end
|
||||
|
||||
attr_reader :disposition, :filename
|
||||
|
||||
def initialize(disposition:, filename:)
|
||||
@disposition = disposition
|
||||
@filename = filename
|
||||
end
|
||||
|
||||
# rubocop:disable Style/VariableInterpolation
|
||||
TRADITIONAL_ESCAPED_CHAR = /[^ A-Za-z0-9!#$+.^_`|~-]/.freeze
|
||||
|
||||
def ascii_filename
|
||||
'filename="' + percent_escape(::I18n.transliterate(filename), TRADITIONAL_ESCAPED_CHAR) + '"'
|
||||
end
|
||||
|
||||
RFC_5987_ESCAPED_CHAR = /[^A-Za-z0-9!#$&+.^_`|~-]/.freeze
|
||||
# rubocop:enable Style/VariableInterpolation
|
||||
|
||||
def utf8_filename
|
||||
"filename*=UTF-8''" + percent_escape(filename, RFC_5987_ESCAPED_CHAR)
|
||||
end
|
||||
|
||||
def to_s
|
||||
if filename
|
||||
"#{disposition}; #{ascii_filename}; #{utf8_filename}"
|
||||
else
|
||||
"#{disposition}"
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def percent_escape(string, pattern)
|
||||
string.gsub(pattern) do |char|
|
||||
char.bytes.map { |byte| "%%%02X" % byte }.join
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -204,15 +204,16 @@ module Gitlab
|
|||
# pool_size - The size of the DB pool.
|
||||
# host - An optional host name to use instead of the default one.
|
||||
def self.create_connection_pool(pool_size, host = nil, port = nil)
|
||||
# See activerecord-4.2.7.1/lib/active_record/connection_adapters/connection_specification.rb
|
||||
env = Rails.env
|
||||
original_config = ActiveRecord::Base.configurations
|
||||
original_config = ActiveRecord::Base.configurations.to_h
|
||||
|
||||
env_config = original_config[env].merge('pool' => pool_size)
|
||||
env_config['host'] = host if host
|
||||
env_config['port'] = port if port
|
||||
|
||||
config = original_config.merge(env => env_config)
|
||||
config = ActiveRecord::DatabaseConfigurations.new(
|
||||
original_config.merge(env => env_config)
|
||||
)
|
||||
|
||||
spec =
|
||||
ActiveRecord::
|
||||
|
|
|
@ -382,7 +382,7 @@ module Gitlab
|
|||
count_arel = table.project(Arel.star.count.as('count'))
|
||||
count_arel = yield table, count_arel if block_given?
|
||||
|
||||
total = exec_query(count_arel.to_sql).to_hash.first['count'].to_i
|
||||
total = exec_query(count_arel.to_sql).to_a.first['count'].to_i
|
||||
|
||||
return if total == 0
|
||||
|
||||
|
@ -399,7 +399,7 @@ module Gitlab
|
|||
|
||||
start_arel = table.project(table[:id]).order(table[:id].asc).take(1)
|
||||
start_arel = yield table, start_arel if block_given?
|
||||
start_id = exec_query(start_arel.to_sql).to_hash.first['id'].to_i
|
||||
start_id = exec_query(start_arel.to_sql).to_a.first['id'].to_i
|
||||
|
||||
loop do
|
||||
stop_arel = table.project(table[:id])
|
||||
|
@ -409,7 +409,7 @@ module Gitlab
|
|||
.skip(batch_size)
|
||||
|
||||
stop_arel = yield table, stop_arel if block_given?
|
||||
stop_row = exec_query(stop_arel.to_sql).to_hash.first
|
||||
stop_row = exec_query(stop_arel.to_sql).to_a.first
|
||||
|
||||
update_arel = Arel::UpdateManager.new
|
||||
.table(table)
|
||||
|
|
|
@ -1,39 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# Fixes a bug where the query cache isn't aware of the shared
|
||||
# ActiveRecord connection used in tests
|
||||
# https://github.com/rails/rails/issues/36587
|
||||
|
||||
# To be removed with https://gitlab.com/gitlab-org/gitlab-foss/issues/64413
|
||||
|
||||
module Gitlab
|
||||
module Patch
|
||||
module ActiveRecordQueryCache
|
||||
# rubocop:disable Gitlab/ModuleWithInstanceVariables
|
||||
def enable_query_cache!
|
||||
@query_cache_enabled[connection_cache_key(current_thread)] = true
|
||||
connection.enable_query_cache! if active_connection?
|
||||
end
|
||||
|
||||
def disable_query_cache!
|
||||
@query_cache_enabled.delete connection_cache_key(current_thread)
|
||||
connection.disable_query_cache! if active_connection?
|
||||
end
|
||||
|
||||
def query_cache_enabled
|
||||
@query_cache_enabled[connection_cache_key(current_thread)]
|
||||
end
|
||||
|
||||
def active_connection?
|
||||
@thread_cached_conns[connection_cache_key(current_thread)]
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def current_thread
|
||||
@lock_thread || Thread.current
|
||||
end
|
||||
# rubocop:enable Gitlab/ModuleWithInstanceVariables
|
||||
end
|
||||
end
|
||||
end
|
|
@ -37,10 +37,10 @@ module Gitlab
|
|||
controller = env[CONTROLLER_KEY]
|
||||
action = "#{controller.class.name}##{controller.action_name}"
|
||||
|
||||
if controller.content_type == 'text/html'
|
||||
if controller.media_type == 'text/html'
|
||||
action
|
||||
else
|
||||
"#{action} (#{controller.content_type})"
|
||||
"#{action} (#{controller.media_type})"
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -20432,9 +20432,6 @@ msgstr ""
|
|||
msgid "Unstaged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstaged and staged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstar"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -20020,9 +20020,6 @@ msgstr ""
|
|||
msgid "Unstaged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstaged and staged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstar"
|
||||
msgstr "Без звезда"
|
||||
|
||||
|
|
|
@ -20020,9 +20020,6 @@ msgstr ""
|
|||
msgid "Unstaged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstaged and staged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstar"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -20020,9 +20020,6 @@ msgstr ""
|
|||
msgid "Unstaged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstaged and staged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstar"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -20020,9 +20020,6 @@ msgstr ""
|
|||
msgid "Unstaged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstaged and staged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstar"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -20226,9 +20226,6 @@ msgstr ""
|
|||
msgid "Unstaged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstaged and staged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstar"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -20432,9 +20432,6 @@ msgstr ""
|
|||
msgid "Unstaged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstaged and staged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstar"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -20020,9 +20020,6 @@ msgstr ""
|
|||
msgid "Unstaged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstaged and staged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstar"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -20020,9 +20020,6 @@ msgstr "Nicht vorgemerkt"
|
|||
msgid "Unstaged %{type}"
|
||||
msgstr "Nicht vorgemerkt %{type}"
|
||||
|
||||
msgid "Unstaged and staged %{type}"
|
||||
msgstr "Nicht vorgemerkt und vorgemerkt %{type}"
|
||||
|
||||
msgid "Unstar"
|
||||
msgstr "Entfavorisieren"
|
||||
|
||||
|
|
|
@ -20020,9 +20020,6 @@ msgstr ""
|
|||
msgid "Unstaged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstaged and staged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstar"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -20020,9 +20020,6 @@ msgstr ""
|
|||
msgid "Unstaged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstaged and staged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstar"
|
||||
msgstr "Malsteligi"
|
||||
|
||||
|
|
|
@ -20020,9 +20020,6 @@ msgstr ""
|
|||
msgid "Unstaged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstaged and staged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstar"
|
||||
msgstr "No Destacar"
|
||||
|
||||
|
|
|
@ -20020,9 +20020,6 @@ msgstr ""
|
|||
msgid "Unstaged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstaged and staged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstar"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -20020,9 +20020,6 @@ msgstr ""
|
|||
msgid "Unstaged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstaged and staged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstar"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -20020,9 +20020,6 @@ msgstr ""
|
|||
msgid "Unstaged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstaged and staged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstar"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -20020,9 +20020,6 @@ msgstr "Désindexé"
|
|||
msgid "Unstaged %{type}"
|
||||
msgstr "Désindexation de %{type}"
|
||||
|
||||
msgid "Unstaged and staged %{type}"
|
||||
msgstr "%{type} non-indéxés et indexés"
|
||||
|
||||
msgid "Unstar"
|
||||
msgstr "Supprimer des favoris"
|
||||
|
||||
|
|
|
@ -20259,9 +20259,6 @@ msgstr ""
|
|||
msgid "Unstaged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstaged and staged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstar"
|
||||
msgstr ""
|
||||
|
||||
|
@ -21553,9 +21550,6 @@ msgstr ""
|
|||
msgid "You can create a new one or check them in your Personal Access Tokens settings %{pat_link}"
|
||||
msgstr ""
|
||||
|
||||
msgid "You can create files directly in GitLab using one of the following options."
|
||||
msgstr ""
|
||||
|
||||
msgid "You can create new ones at your %{pat_link_start}Personal Access Tokens%{pat_link_end} settings"
|
||||
msgstr ""
|
||||
|
||||
|
@ -21571,6 +21565,9 @@ msgstr ""
|
|||
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
|
||||
msgstr ""
|
||||
|
||||
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
|
||||
msgstr ""
|
||||
|
||||
msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -20020,9 +20020,6 @@ msgstr ""
|
|||
msgid "Unstaged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstaged and staged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstar"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -20226,9 +20226,6 @@ msgstr ""
|
|||
msgid "Unstaged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstaged and staged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstar"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -20020,9 +20020,6 @@ msgstr ""
|
|||
msgid "Unstaged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstaged and staged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstar"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -20123,9 +20123,6 @@ msgstr ""
|
|||
msgid "Unstaged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstaged and staged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstar"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -20020,9 +20020,6 @@ msgstr ""
|
|||
msgid "Unstaged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstaged and staged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstar"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -19917,9 +19917,6 @@ msgstr ""
|
|||
msgid "Unstaged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstaged and staged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstar"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -20020,9 +20020,6 @@ msgstr "Unstaged"
|
|||
msgid "Unstaged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstaged and staged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstar"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -19917,9 +19917,6 @@ msgstr "ステージを取り消し"
|
|||
msgid "Unstaged %{type}"
|
||||
msgstr "ステージを取り消し %{type}"
|
||||
|
||||
msgid "Unstaged and staged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstar"
|
||||
msgstr "スターを外す"
|
||||
|
||||
|
|
|
@ -20020,9 +20020,6 @@ msgstr ""
|
|||
msgid "Unstaged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstaged and staged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstar"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -19917,9 +19917,6 @@ msgstr "스테이징 안됨"
|
|||
msgid "Unstaged %{type}"
|
||||
msgstr "%{type} 스테이징 취소"
|
||||
|
||||
msgid "Unstaged and staged %{type}"
|
||||
msgstr "스테이징 취소, 그리고 %{type} 스테이징"
|
||||
|
||||
msgid "Unstar"
|
||||
msgstr "별표 제거"
|
||||
|
||||
|
|
|
@ -20020,9 +20020,6 @@ msgstr ""
|
|||
msgid "Unstaged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstaged and staged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstar"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -20020,9 +20020,6 @@ msgstr ""
|
|||
msgid "Unstaged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstaged and staged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstar"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -20020,9 +20020,6 @@ msgstr ""
|
|||
msgid "Unstaged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstaged and staged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstar"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -20020,9 +20020,6 @@ msgstr ""
|
|||
msgid "Unstaged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstaged and staged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstar"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -20020,9 +20020,6 @@ msgstr ""
|
|||
msgid "Unstaged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstaged and staged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstar"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -20020,9 +20020,6 @@ msgstr ""
|
|||
msgid "Unstaged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstaged and staged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstar"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -20226,9 +20226,6 @@ msgstr ""
|
|||
msgid "Unstaged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstaged and staged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstar"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -20020,9 +20020,6 @@ msgstr "Fora da lista de commit"
|
|||
msgid "Unstaged %{type}"
|
||||
msgstr "%{type} fora da lista para commit"
|
||||
|
||||
msgid "Unstaged and staged %{type}"
|
||||
msgstr "%{type} dentro e fora da lista para commit"
|
||||
|
||||
msgid "Unstar"
|
||||
msgstr "Desmarcar como favorito"
|
||||
|
||||
|
|
|
@ -20020,9 +20020,6 @@ msgstr ""
|
|||
msgid "Unstaged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstaged and staged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstar"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -20123,9 +20123,6 @@ msgstr ""
|
|||
msgid "Unstaged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstaged and staged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstar"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -20226,9 +20226,6 @@ msgstr ""
|
|||
msgid "Unstaged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstaged and staged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstar"
|
||||
msgstr "Убрать из избранного"
|
||||
|
||||
|
|
|
@ -20226,9 +20226,6 @@ msgstr ""
|
|||
msgid "Unstaged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstaged and staged %{type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unstar"
|
||||
msgstr ""
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue