Commit cf9a0f28 authored by Filipa Lacerda's avatar Filipa Lacerda

[ci skip] Merge branch 'master' into 45318-FE-junit-tests

* master: (49 commits)
  Add changelog entry
  Fix `transform` typo
  Fix archived parameter for projects API
  Enable frozen string in apps/uploaders/*.rb
  Fix invalid link to GitLab.com architecture.md
  i18n: externalize strings from 'app/views/import'
  Remove Repository#lookup and unreachable rugged code
  refactor code based on feedback
  Trigger rails5 tests either by variable or ref name
  Fix link in help doc which was linking to old mono-repo, now in its own repo
  SubmoduleHelper - Project is not always available as an instance variable
  Allow Danger step to fail
  update webpack to v4.16
  Backport logger changes from EE
  Add the CI Job trigger as the build trigger
  Remove flaky and redundant expectations
  use fileuploader dynamic path method in uploads manager and add spec
  fix typo in uploads manager
  add small comment to download method in uploads manager
  refactor uploads manager
  ...
parents cd1b20ae 7f0431dd
image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.4.4-golang-1.9-git-2.17-chrome-67.0-node-8.x-yarn-1.2-postgresql-9.6-graphicsmagick-1.3.29" image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.4.4-golang-1.9-git-2.18-chrome-67.0-node-8.x-yarn-1.2-postgresql-9.6-graphicsmagick-1.3.29"
.dedicated-runner: &dedicated-runner .dedicated-runner: &dedicated-runner
retry: 1 retry: 1
...@@ -86,7 +86,9 @@ stages: ...@@ -86,7 +86,9 @@ stages:
.rails5: &rails5 .rails5: &rails5
allow_failure: true allow_failure: true
only: only:
- /rails5/ variables:
- $CI_COMMIT_REF_NAME =~ /rails5/
- $RAILS5_ENABLED
variables: variables:
BUNDLE_GEMFILE: "Gemfile.rails5" BUNDLE_GEMFILE: "Gemfile.rails5"
RAILS5: "true" RAILS5: "true"
...@@ -327,7 +329,7 @@ cloud-native-image: ...@@ -327,7 +329,7 @@ cloud-native-image:
cache: {} cache: {}
script: script:
- gem install gitlab --no-ri --no-rdoc - gem install gitlab --no-ri --no-rdoc
- ./scripts/trigger-build cng - BUILD_TRIGGER_TOKEN=$CI_JOB_TOKEN scripts/trigger-build cng
only: only:
- tags@gitlab-org/gitlab-ce - tags@gitlab-org/gitlab-ce
- tags@gitlab-org/gitlab-ee - tags@gitlab-org/gitlab-ee
...@@ -351,6 +353,7 @@ retrieve-tests-metadata: ...@@ -351,6 +353,7 @@ retrieve-tests-metadata:
danger-review: danger-review:
image: registry.gitlab.com/gitlab-org/gitaly/dangercontainer:latest image: registry.gitlab.com/gitlab-org/gitaly/dangercontainer:latest
stage: prepare stage: prepare
allow_failure: true
before_script: before_script:
- source scripts/utils.sh - source scripts/utils.sh
- retry gem install danger --no-ri --no-rdoc - retry gem install danger --no-ri --no-rdoc
......
...@@ -101,6 +101,7 @@ router.beforeEach((to, from, next) => { ...@@ -101,6 +101,7 @@ router.beforeEach((to, from, next) => {
store store
.dispatch('getMergeRequestData', { .dispatch('getMergeRequestData', {
projectId: fullProjectId, projectId: fullProjectId,
targetProjectId: to.query.target_project,
mergeRequestId: to.params.mrid, mergeRequestId: to.params.mrid,
}) })
.then(mr => { .then(mr => {
...@@ -119,12 +120,14 @@ router.beforeEach((to, from, next) => { ...@@ -119,12 +120,14 @@ router.beforeEach((to, from, next) => {
.then(() => .then(() =>
store.dispatch('getMergeRequestVersions', { store.dispatch('getMergeRequestVersions', {
projectId: fullProjectId, projectId: fullProjectId,
targetProjectId: to.query.target_project,
mergeRequestId: to.params.mrid, mergeRequestId: to.params.mrid,
}), }),
) )
.then(() => .then(() =>
store.dispatch('getMergeRequestChanges', { store.dispatch('getMergeRequestChanges', {
projectId: fullProjectId, projectId: fullProjectId,
targetProjectId: to.query.target_project,
mergeRequestId: to.params.mrid, mergeRequestId: to.params.mrid,
}), }),
) )
......
...@@ -4,12 +4,14 @@ import * as types from '../mutation_types'; ...@@ -4,12 +4,14 @@ import * as types from '../mutation_types';
export const getMergeRequestData = ( export const getMergeRequestData = (
{ commit, dispatch, state }, { commit, dispatch, state },
{ projectId, mergeRequestId, force = false } = {}, { projectId, mergeRequestId, targetProjectId = null, force = false } = {},
) => ) =>
new Promise((resolve, reject) => { new Promise((resolve, reject) => {
if (!state.projects[projectId].mergeRequests[mergeRequestId] || force) { if (!state.projects[projectId].mergeRequests[mergeRequestId] || force) {
service service
.getProjectMergeRequestData(projectId, mergeRequestId, { render_html: true }) .getProjectMergeRequestData(targetProjectId || projectId, mergeRequestId, {
render_html: true,
})
.then(({ data }) => { .then(({ data }) => {
commit(types.SET_MERGE_REQUEST, { commit(types.SET_MERGE_REQUEST, {
projectPath: projectId, projectPath: projectId,
...@@ -38,12 +40,12 @@ export const getMergeRequestData = ( ...@@ -38,12 +40,12 @@ export const getMergeRequestData = (
export const getMergeRequestChanges = ( export const getMergeRequestChanges = (
{ commit, dispatch, state }, { commit, dispatch, state },
{ projectId, mergeRequestId, force = false } = {}, { projectId, mergeRequestId, targetProjectId = null, force = false } = {},
) => ) =>
new Promise((resolve, reject) => { new Promise((resolve, reject) => {
if (!state.projects[projectId].mergeRequests[mergeRequestId].changes.length || force) { if (!state.projects[projectId].mergeRequests[mergeRequestId].changes.length || force) {
service service
.getProjectMergeRequestChanges(projectId, mergeRequestId) .getProjectMergeRequestChanges(targetProjectId || projectId, mergeRequestId)
.then(({ data }) => { .then(({ data }) => {
commit(types.SET_MERGE_REQUEST_CHANGES, { commit(types.SET_MERGE_REQUEST_CHANGES, {
projectPath: projectId, projectPath: projectId,
...@@ -71,12 +73,12 @@ export const getMergeRequestChanges = ( ...@@ -71,12 +73,12 @@ export const getMergeRequestChanges = (
export const getMergeRequestVersions = ( export const getMergeRequestVersions = (
{ commit, dispatch, state }, { commit, dispatch, state },
{ projectId, mergeRequestId, force = false } = {}, { projectId, mergeRequestId, targetProjectId = null, force = false } = {},
) => ) =>
new Promise((resolve, reject) => { new Promise((resolve, reject) => {
if (!state.projects[projectId].mergeRequests[mergeRequestId].versions.length || force) { if (!state.projects[projectId].mergeRequests[mergeRequestId].versions.length || force) {
service service
.getProjectMergeRequestVersions(projectId, mergeRequestId) .getProjectMergeRequestVersions(targetProjectId || projectId, mergeRequestId)
.then(res => res.data) .then(res => res.data)
.then(data => { .then(data => {
commit(types.SET_MERGE_REQUEST_VERSIONS, { commit(types.SET_MERGE_REQUEST_VERSIONS, {
......
<script> <script>
import $ from 'jquery'; import $ from 'jquery';
import PerformanceBarService from '../services/performance_bar_service';
import detailedMetric from './detailed_metric.vue'; import detailedMetric from './detailed_metric.vue';
import requestSelector from './request_selector.vue'; import requestSelector from './request_selector.vue';
import simpleMetric from './simple_metric.vue'; import simpleMetric from './simple_metric.vue';
import Flash from '../../flash';
export default { export default {
components: { components: {
detailedMetric, detailedMetric,
...@@ -69,37 +66,13 @@ export default { ...@@ -69,37 +66,13 @@ export default {
}, },
}, },
mounted() { mounted() {
this.interceptor = PerformanceBarService.registerInterceptor(
this.peekUrl,
this.loadRequestDetails,
);
this.loadRequestDetails(this.requestId, window.location.href);
this.currentRequest = this.requestId; this.currentRequest = this.requestId;
if (this.lineProfileModal.length) { if (this.lineProfileModal.length) {
this.lineProfileModal.modal('toggle'); this.lineProfileModal.modal('toggle');
} }
}, },
beforeDestroy() {
PerformanceBarService.removeInterceptor(this.interceptor);
},
methods: { methods: {
loadRequestDetails(requestId, requestUrl) {
if (!this.store.canTrackRequest(requestUrl)) {
return;
}
this.store.addRequest(requestId, requestUrl);
PerformanceBarService.fetchRequestDetails(this.peekUrl, requestId)
.then(res => {
this.store.addRequestDetails(requestId, res.data.data);
})
.catch(() =>
Flash(`Error getting performance bar results for ${requestId}`),
);
},
changeCurrentRequest(newRequestId) { changeCurrentRequest(newRequestId) {
this.currentRequest = newRequestId; this.currentRequest = newRequestId;
}, },
......
import Vue from 'vue'; import Vue from 'vue';
import performanceBarApp from './components/performance_bar_app.vue'; import Flash from '../flash';
import PerformanceBarService from './services/performance_bar_service';
import PerformanceBarStore from './stores/performance_bar_store'; import PerformanceBarStore from './stores/performance_bar_store';
export default ({ container }) => export default ({ container }) =>
new Vue({ new Vue({
el: container, el: container,
components: { components: {
performanceBarApp, performanceBarApp: () => import('./components/performance_bar_app.vue'),
}, },
data() { data() {
const performanceBarData = document.querySelector(this.$options.el) const performanceBarData = document.querySelector(this.$options.el)
...@@ -21,6 +22,34 @@ export default ({ container }) => ...@@ -21,6 +22,34 @@ export default ({ container }) =>
profileUrl: performanceBarData.profileUrl, profileUrl: performanceBarData.profileUrl,
}; };
}, },
mounted() {
this.interceptor = PerformanceBarService.registerInterceptor(
this.peekUrl,
this.loadRequestDetails,
);
this.loadRequestDetails(this.requestId, window.location.href);
},
beforeDestroy() {
PerformanceBarService.removeInterceptor(this.interceptor);
},
methods: {
loadRequestDetails(requestId, requestUrl) {
if (!this.store.canTrackRequest(requestUrl)) {
return;
}
this.store.addRequest(requestId, requestUrl);
PerformanceBarService.fetchRequestDetails(this.peekUrl, requestId)
.then(res => {
this.store.addRequestDetails(requestId, res.data.data);
})
.catch(() =>
Flash(`Error getting performance bar results for ${requestId}`),
);
},
},
render(createElement) { render(createElement) {
return createElement('performance-bar-app', { return createElement('performance-bar-app', {
props: { props: {
......
<script> <script>
import tooltip from '~/vue_shared/directives/tooltip'; import tooltip from '~/vue_shared/directives/tooltip';
import { n__ } from '~/locale'; import { n__ } from '~/locale';
import { webIDEUrl } from '~/lib/utils/url_utility'; import { mergeUrlParams, webIDEUrl } from '~/lib/utils/url_utility';
import Icon from '~/vue_shared/components/icon.vue'; import Icon from '~/vue_shared/components/icon.vue';
import clipboardButton from '~/vue_shared/components/clipboard_button.vue'; import clipboardButton from '~/vue_shared/components/clipboard_button.vue';
...@@ -43,7 +43,10 @@ export default { ...@@ -43,7 +43,10 @@ export default {
return this.isBranchTitleLong(this.mr.targetBranch); return this.isBranchTitleLong(this.mr.targetBranch);
}, },
webIdePath() { webIdePath() {
return webIDEUrl(this.mr.statusPath.replace('.json', '')); return mergeUrlParams({
target_project: this.mr.sourceProjectFullPath !== this.mr.targetProjectFullPath ?
this.mr.targetProjectFullPath : '',
}, webIDEUrl(`/${this.mr.sourceProjectFullPath}/merge_requests/${this.mr.iid}`));
}, },
}, },
methods: { methods: {
......
...@@ -16,10 +16,11 @@ export default class MergeRequestStore { ...@@ -16,10 +16,11 @@ export default class MergeRequestStore {
const pipelineStatus = data.pipeline ? data.pipeline.details.status : null; const pipelineStatus = data.pipeline ? data.pipeline.details.status : null;
this.squash = data.squash; this.squash = data.squash;
this.squashBeforeMergeHelpPath = this.squashBeforeMergeHelpPath || this.squashBeforeMergeHelpPath =
data.squash_before_merge_help_path; this.squashBeforeMergeHelpPath || data.squash_before_merge_help_path;
this.enableSquashBeforeMerge = this.enableSquashBeforeMerge || true; this.enableSquashBeforeMerge = this.enableSquashBeforeMerge || true;
this.iid = data.iid;
this.title = data.title; this.title = data.title;
this.targetBranch = data.target_branch; this.targetBranch = data.target_branch;
this.sourceBranch = data.source_branch; this.sourceBranch = data.source_branch;
...@@ -85,6 +86,8 @@ export default class MergeRequestStore { ...@@ -85,6 +86,8 @@ export default class MergeRequestStore {
this.isMergeAllowed = data.mergeable || false; this.isMergeAllowed = data.mergeable || false;
this.mergeOngoing = data.merge_ongoing; this.mergeOngoing = data.merge_ongoing;
this.allowCollaboration = data.allow_collaboration; this.allowCollaboration = data.allow_collaboration;
this.targetProjectFullPath = data.target_project_full_path;
this.sourceProjectFullPath = data.source_project_full_path;
// Cherry-pick and Revert actions related // Cherry-pick and Revert actions related
this.canCherryPickInCurrentMR = currentUser.can_cherry_pick_on_current_merge_request || false; this.canCherryPickInCurrentMR = currentUser.can_cherry_pick_on_current_merge_request || false;
...@@ -97,7 +100,8 @@ export default class MergeRequestStore { ...@@ -97,7 +100,8 @@ export default class MergeRequestStore {
this.hasCI = data.has_ci; this.hasCI = data.has_ci;
this.ciStatus = data.ci_status; this.ciStatus = data.ci_status;
this.isPipelineFailed = this.ciStatus === 'failed' || this.ciStatus === 'canceled'; this.isPipelineFailed = this.ciStatus === 'failed' || this.ciStatus === 'canceled';
this.isPipelinePassing = this.ciStatus === 'success' || this.ciStatus === 'success_with_warnings'; this.isPipelinePassing =
this.ciStatus === 'success' || this.ciStatus === 'success_with_warnings';
this.isPipelineSkipped = this.ciStatus === 'skipped'; this.isPipelineSkipped = this.ciStatus === 'skipped';
this.pipelineDetailedStatus = pipelineStatus; this.pipelineDetailedStatus = pipelineStatus;
this.isPipelineActive = data.pipeline ? data.pipeline.active : false; this.isPipelineActive = data.pipeline ? data.pipeline.active : false;
......
...@@ -126,7 +126,7 @@ export default { ...@@ -126,7 +126,7 @@ export default {
:cx="dotX" :cx="dotX"
:cy="dotY" :cy="dotY"
r="1.5" r="1.5"
tranform="translate(0 -1)" transform="translate(0 -1)"
/> />
</svg> </svg>
</div> </div>
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
# personal: boolean # personal: boolean
# search: string # search: string
# non_archived: boolean # non_archived: boolean
# archived: 'only' or boolean
# #
class ProjectsFinder < UnionFinder class ProjectsFinder < UnionFinder
include CustomAttributesFilter include CustomAttributesFilter
...@@ -130,7 +131,7 @@ class ProjectsFinder < UnionFinder ...@@ -130,7 +131,7 @@ class ProjectsFinder < UnionFinder
def by_archived(projects) def by_archived(projects)
if params[:non_archived] if params[:non_archived]
projects.non_archived projects.non_archived
elsif params.key?(:archived) # Back-compatibility with the places where `params[:archived]` can be set explicitly to `false` elsif params.key?(:archived)
if params[:archived] == 'only' if params[:archived] == 'only'
projects.archived projects.archived
elsif Gitlab::Utils.to_boolean(params[:archived]) elsif Gitlab::Utils.to_boolean(params[:archived])
......
...@@ -8,7 +8,7 @@ module SubmoduleHelper ...@@ -8,7 +8,7 @@ module SubmoduleHelper
url = repository.submodule_url_for(ref, submodule_item.path) url = repository.submodule_url_for(ref, submodule_item.path)
if url == '.' || url == './' if url == '.' || url == './'
url = File.join(Gitlab.config.gitlab.url, @project.full_path) url = File.join(Gitlab.config.gitlab.url, repository.project.full_path)
end end
if url =~ %r{([^/:]+)/([^/]+(?:\.git)?)\Z} if url =~ %r{([^/:]+)/([^/]+(?:\.git)?)\Z}
...@@ -31,7 +31,7 @@ module SubmoduleHelper ...@@ -31,7 +31,7 @@ module SubmoduleHelper
[namespace_project_path(namespace, project), [namespace_project_path(namespace, project),
namespace_project_tree_path(namespace, project, submodule_item.id)] namespace_project_tree_path(namespace, project, submodule_item.id)]
elsif relative_self_url?(url) elsif relative_self_url?(url)
relative_self_links(url, submodule_item.id) relative_self_links(url, submodule_item.id, repository.project)
elsif github_dot_com_url?(url) elsif github_dot_com_url?(url)
standard_links('github.com', namespace, project, submodule_item.id) standard_links('github.com', namespace, project, submodule_item.id)
elsif gitlab_dot_com_url?(url) elsif gitlab_dot_com_url?(url)
...@@ -73,7 +73,7 @@ module SubmoduleHelper ...@@ -73,7 +73,7 @@ module SubmoduleHelper
[base, [base, '/tree/', commit].join('')] [base, [base, '/tree/', commit].join('')]
end end
def relative_self_links(url, commit) def relative_self_links(url, commit, project)
url.rstrip! url.rstrip!
# Map relative links to a namespace and project # Map relative links to a namespace and project
# For example: # For example:
...@@ -85,7 +85,7 @@ module SubmoduleHelper ...@@ -85,7 +85,7 @@ module SubmoduleHelper
namespace = components.pop.gsub(/^\.\.$/, '') namespace = components.pop.gsub(/^\.\.$/, '')
if namespace.empty? if namespace.empty?
namespace = @project.namespace.full_path namespace = project.namespace.full_path
end end
begin begin
......
...@@ -92,10 +92,6 @@ class Deployment < ActiveRecord::Base ...@@ -92,10 +92,6 @@ class Deployment < ActiveRecord::Base
@stop_action ||= manual_actions.find_by(name: on_stop) @stop_action ||= manual_actions.find_by(name: on_stop)
end end
def stop_action?
stop_action.present?
end
def formatted_deployment_time def formatted_deployment_time
created_at.to_time.in_time_zone.to_s(:medium) created_at.to_time.in_time_zone.to_s(:medium)
end end
......
...@@ -117,7 +117,7 @@ class Environment < ActiveRecord::Base ...@@ -117,7 +117,7 @@ class Environment < ActiveRecord::Base
external_url.gsub(%r{\A.*?://}, '') external_url.gsub(%r{\A.*?://}, '')
end end
def stop_action? def stop_action_available?
available? && stop_action.present? available? && stop_action.present?
end end
......
...@@ -2,11 +2,12 @@ class EnvironmentPolicy < BasePolicy ...@@ -2,11 +2,12 @@ class EnvironmentPolicy < BasePolicy
delegate { @subject.project } delegate { @subject.project }
condition(:stop_with_deployment_allowed) do condition(:stop_with_deployment_allowed) do
@subject.stop_action? && can?(:create_deployment) && can?(:update_build, @subject.stop_action) @subject.stop_action_available? &&
can?(:create_deployment) && can?(:update_build, @subject.stop_action)
end end
condition(:stop_with_update_allowed) do condition(:stop_with_update_allowed) do
!@subject.stop_action? && can?(:update_environment, @subject) !@subject.stop_action_available? && can?(:update_environment, @subject)
end end
rule { stop_with_deployment_allowed | stop_with_update_allowed }.enable :stop_environment rule { stop_with_deployment_allowed | stop_with_update_allowed }.enable :stop_environment
......
...@@ -7,7 +7,7 @@ class EnvironmentEntity < Grape::Entity ...@@ -7,7 +7,7 @@ class EnvironmentEntity < Grape::Entity
expose :external_url expose :external_url
expose :environment_type expose :environment_type
expose :last_deployment, using: DeploymentEntity expose :last_deployment, using: DeploymentEntity
expose :stop_action?, as: :has_stop_action expose :stop_action_available?, as: :has_stop_action
expose :metrics_path, if: -> (environment, _) { environment.has_metrics? } do |environment| expose :metrics_path, if: -> (environment, _) { environment.has_metrics? } do |environment|
metrics_project_environment_path(environment.project, environment) metrics_project_environment_path(environment.project, environment)
......
...@@ -10,9 +10,15 @@ class MergeRequestWidgetEntity < IssuableEntity ...@@ -10,9 +10,15 @@ class MergeRequestWidgetEntity < IssuableEntity
expose :merge_when_pipeline_succeeds expose :merge_when_pipeline_succeeds
expose :source_branch expose :source_branch
expose :source_project_id expose :source_project_id
expose :source_project_full_path do |merge_request|
merge_request.source_project&.full_path
end
expose :squash expose :squash
expose :target_branch expose :target_branch
expose :target_project_id expose :target_project_id
expose :target_project_full_path do |merge_request|
merge_request.project&.full_path
end
expose :allow_collaboration expose :allow_collaboration
expose :should_be_rebased?, as: :should_be_rebased expose :should_be_rebased?, as: :should_be_rebased
......
# frozen_string_literal: true
class AccessTokenValidationService class AccessTokenValidationService
# Results: # Results:
VALID = :valid VALID = :valid
......
# frozen_string_literal: true
## ##
# Branch can be deleted either by DeleteBranchService # Branch can be deleted either by DeleteBranchService
# or by GitPushService. # or by GitPushService.
......
# frozen_string_literal: true
class AkismetService class AkismetService
attr_accessor :owner, :text, :options attr_accessor :owner, :text, :options
......
# frozen_string_literal: true
class AuditEventService class AuditEventService
def initialize(author, entity, details = {}) def initialize(author, entity, details = {})
@author, @entity, @details = author, entity, details @author, @entity, @details = author, entity, details
......
# frozen_string_literal: true
# Base class for services that count a single resource such as the number of # Base class for services that count a single resource such as the number of
# issues for a project. # issues for a project.
class BaseCountService class BaseCountService
......
# frozen_string_literal: true
class BaseRenderer class BaseRenderer
attr_reader :current_user attr_reader :current_user
......
# frozen_string_literal: true
class BaseService class BaseService
include Gitlab::Allowable include Gitlab::Allowable
......
...@@ -8,7 +8,7 @@ module Ci ...@@ -8,7 +8,7 @@ module Ci
return unless @ref.present? return unless @ref.present?
environments.each do |environment| environments.each do |environment|
next unless environment.stop_action? next unless environment.stop_action_available?
next unless can?(current_user, :stop_environment, environment) next unless can?(current_user, :stop_environment, environment)
environment.stop_with_action!(current_user) environment.stop_with_action!(current_user)
......
# frozen_string_literal: true
class CohortsService class CohortsService
MONTHS_INCLUDED = 12 MONTHS_INCLUDED = 12
......
# frozen_string_literal: true
require 'securerandom' require 'securerandom'
# Compare 2 refs for one repo or between repositories # Compare 2 refs for one repo or between repositories
......
# frozen_string_literal: true
class CreateBranchService < BaseService class CreateBranchService < BaseService
def execute(branch_name, ref) def execute(branch_name, ref)
create_master_branch if project.empty_repo? create_master_branch if project.empty_repo?
......
# frozen_string_literal: true
class CreateDeploymentService class CreateDeploymentService
attr_reader :job attr_reader :job
......
# frozen_string_literal: true
class CreateReleaseService < BaseService class CreateReleaseService < BaseService
def execute(tag_name, release_description) def execute(tag_name, release_description)
repository = project.repository repository = project.repository
......
# frozen_string_literal: true
class CreateSnippetService < BaseService class CreateSnippetService < BaseService
include SpamCheckService include SpamCheckService
......
# frozen_string_literal: true
class DeleteBranchService < BaseService class DeleteBranchService < BaseService
def execute(branch_name) def execute(branch_name)
repository = project.repository repository = project.repository
......
# frozen_string_literal: true
class DeleteMergedBranchesService < BaseService class DeleteMergedBranchesService < BaseService
def async_execute def async_execute
DeleteMergedBranchesWorker.perform_async(project.id, current_user.id) DeleteMergedBranchesWorker.perform_async(project.id, current_user.id)
......
# frozen_string_literal: true
# EventCreateService class # EventCreateService class
# #
# Used for creating events feed on dashboard after certain user action # Used for creating events feed on dashboard after certain user action
......
# frozen_string_literal: true
class GitPushService < BaseService class GitPushService < BaseService
attr_accessor :push_data, :push_commits attr_accessor :push_data, :push_commits
include Gitlab::Access include Gitlab::Access
......
# frozen_string_literal: true
class GitTagPushService < BaseService class GitTagPushService < BaseService
attr_accessor :push_data attr_accessor :push_data
......
# frozen_string_literal: true
class GravatarService class GravatarService
def execute(email, size = nil, scale = 2, username: nil) def execute(email, size = nil, scale = 2, username: nil)
return unless Gitlab::CurrentSettings.gravatar_enabled? return unless Gitlab::CurrentSettings.gravatar_enabled?
......
# frozen_string_literal: true
class HamService class HamService
attr_accessor :spam_log attr_accessor :spam_log
......
# frozen_string_literal: true
class ImportExportCleanUpService class ImportExportCleanUpService
LAST_MODIFIED_TIME_IN_MINUTES = 1440 LAST_MODIFIED_TIME_IN_MINUTES = 1440
......
# frozen_string_literal: true
class IssuableBaseService < BaseService class IssuableBaseService < BaseService
private private
......
# frozen_string_literal: true
class MergeRequestMetricsService class MergeRequestMetricsService
delegate :update!, to: :@merge_request_metrics delegate :update!, to: :@merge_request_metrics
......
# frozen_string_literal: true
require 'prometheus/client/formats/text' require 'prometheus/client/formats/text'
class MetricsService class MetricsService
......
# frozen_string_literal: true
class NoteSummary class NoteSummary
attr_reader :note attr_reader :note
attr_reader :metadata attr_reader :metadata
......
# frozen_string_literal: true
# #
# Used by NotificationService to determine who should receive notification # Used by NotificationService to determine who should receive notification
# #
......
# frozen_string_literal: true
# rubocop:disable GitlabSecurity/PublicSend # rubocop:disable GitlabSecurity/PublicSend
# NotificationService class # NotificationService class
......
# frozen_string_literal: true
class PreviewMarkdownService < BaseService class PreviewMarkdownService < BaseService
def execute def execute
text, commands = explain_quick_actions(params[:text]) text, commands = explain_quick_actions(params[:text])
......
# frozen_string_literal: true
# Service class for creating push event payloads as stored in the # Service class for creating push event payloads as stored in the
# "push_event_payloads" table. # "push_event_payloads" table.
# #
......
# frozen_string_literal: true
class RepairLdapBlockedUserService class RepairLdapBlockedUserService
attr_accessor :user attr_accessor :user
......
# frozen_string_literal: true
class RepositoryArchiveCleanUpService class RepositoryArchiveCleanUpService
LAST_MODIFIED_TIME_IN_MINUTES = 120 LAST_MODIFIED_TIME_IN_MINUTES = 120
......
# frozen_string_literal: true
class ResetProjectCacheService < BaseService class ResetProjectCacheService < BaseService
def execute def execute
@project.increment!(:jobs_cache_index) @project.increment!(:jobs_cache_index)
......
# frozen_string_literal: true
class SearchService class SearchService
include Gitlab::Allowable include Gitlab::Allowable
......
# frozen_string_literal: true
# SpamCheckService # SpamCheckService
# #
# Provide helper methods for checking if a given spammable object has # Provide helper methods for checking if a given spammable object has
......
# frozen_string_literal: true
class SpamService class SpamService
attr_accessor :spammable, :request, :options attr_accessor :spammable, :request, :options
attr_reader :spam_log attr_reader :spam_log
......
# frozen_string_literal: true
class SubmitUsagePingService class SubmitUsagePingService
URL = 'https://version.gitlab.com/usage_data'.freeze URL = 'https://version.gitlab.com/usage_data'.freeze
......
# frozen_string_literal: true
class SystemHooksService class SystemHooksService
def execute_hooks_for(model, event) def execute_hooks_for(model, event)
data = build_event_data(model, event) data = build_event_data(model, event)
......
# frozen_string_literal: true
# SystemNoteService # SystemNoteService
# #
# Used for creating system notes (e.g., when a user references a merge request # Used for creating system notes (e.g., when a user references a merge request
...@@ -21,9 +23,11 @@ module SystemNoteService ...@@ -21,9 +23,11 @@ module SystemNoteService
total_count = new_commits.length + existing_commits.length total_count = new_commits.length + existing_commits.length
commits_text = "#{total_count} commit".pluralize(total_count) commits_text = "#{total_count} commit".pluralize(total_count)
body = "added #{commits_text}\n\n" text_parts = ["added #{commits_text}"]
body << commits_list(noteable, new_commits, existing_commits, oldrev) text_parts << commits_list(noteable, new_commits, existing_commits, oldrev)
body << "\n\n[Compare with previous version](#{diff_comparison_url(noteable, project, oldrev)})" text_parts << "[Compare with previous version](#{diff_comparison_url(noteable, project, oldrev)})"
body = text_parts.join("\n\n")
create_note(NoteSummary.new(noteable, project, author, body, action: 'commit', commit_count: total_count)) create_note(NoteSummary.new(noteable, project, author, body, action: 'commit', commit_count: total_count))
end end
...@@ -103,18 +107,19 @@ module SystemNoteService ...@@ -103,18 +107,19 @@ module SystemNoteService
added_labels = added_labels.map(&references).join(' ') added_labels = added_labels.map(&references).join(' ')
removed_labels = removed_labels.map(&references).join(' ') removed_labels = removed_labels.map(&references).join(' ')
body = '' text_parts = []
if added_labels.present? if added_labels.present?
body << "added #{added_labels}" text_parts << "added #{added_labels}"
body << ' and ' if removed_labels.present? text_parts << 'and' if removed_labels.present?
end end
if removed_labels.present? if removed_labels.present?
body << "removed #{removed_labels}" text_parts << "removed #{removed_labels}"
end end
body << ' ' << 'label'.pluralize(labels_count) text_parts << 'label'.pluralize(labels_count)
body = text_parts.join(' ')
create_note(NoteSummary.new(noteable, project, author, body, action: 'label')) create_note(NoteSummary.new(noteable, project, author, body, action: 'label'))
end end
...@@ -188,8 +193,10 @@ module SystemNoteService ...@@ -188,8 +193,10 @@ module SystemNoteService
spent_at = noteable.spent_at spent_at = noteable.spent_at
parsed_time = Gitlab::TimeTrackingFormatter.output(time_spent.abs) parsed_time = Gitlab::TimeTrackingFormatter.output(time_spent.abs)
action = time_spent > 0 ? 'added' : 'subtracted' action = time_spent > 0 ? 'added' : 'subtracted'
body = "#{action} #{parsed_time} of time spent"
body << " at #{spent_at}" if spent_at text_parts = ["#{action} #{parsed_time} of time spent"]
text_parts << "at #{spent_at}" if spent_at
body = text_parts.join(' ')
end end
create_note(NoteSummary.new(noteable, project, author, body, action: 'time_tracking')) create_note(NoteSummary.new(noteable, project, author, body, action: 'time_tracking'))
...@@ -268,17 +275,19 @@ module SystemNoteService ...@@ -268,17 +275,19 @@ module SystemNoteService
diff_refs = change_position.diff_refs diff_refs = change_position.diff_refs
version_index = merge_request.merge_request_diffs.viewable.count version_index = merge_request.merge_request_diffs.viewable.count
body = "changed this line in" text_parts = ["changed this line in"]
if version_params = merge_request.version_params_for(diff_refs) if version_params = merge_request.version_params_for(diff_refs)
line_code = change_position.line_code(project.repository) line_code = change_position.line_code(project.repository)
url = url_helpers.diffs_project_merge_request_url(project, merge_request, version_params.merge(anchor: line_code)) url = url_helpers.diffs_project_merge_request_url(project, merge_request, version_params.merge(anchor: line_code))
body << " [version #{version_index} of the diff](#{url})" text_parts << "[version #{version_index} of the diff](#{url})"
else else
body << " version #{version_index} of the diff" text_parts << "version #{version_index} of the diff"
end end
body = text_parts.join(' ')
note_attributes = discussion.reply_attributes.merge(project: project, author: author, note: body) note_attributes = discussion.reply_attributes.merge(project: project, author: author, note: body)
note = Note.create(note_attributes.merge(system: true)) note = Note.create(note_attributes.merge(system: true))
note.system_note_metadata = SystemNoteMetadata.new(action: 'outdated') note.system_note_metadata = SystemNoteMetadata.new(action: 'outdated')
......
# frozen_string_literal: true
# TodoService class # TodoService class
# #
# Used for creating/updating todos after certain user actions # Used for creating/updating todos after certain user actions
......
# frozen_string_literal: true
class UpdateReleaseService < BaseService class UpdateReleaseService < BaseService
def execute(tag_name, release_description) def execute(tag_name, release_description)
repository = project.repository repository = project.repository
......
# frozen_string_literal: true
class UpdateSnippetService < BaseService class UpdateSnippetService < BaseService
include SpamCheckService include SpamCheckService
......
# frozen_string_literal: true
class UploadService class UploadService
def initialize(model, file, uploader_class = FileUploader) def initialize(model, file, uploader_class = FileUploader, **uploader_context)
@model, @file, @uploader_class = model, file, uploader_class @model, @file, @uploader_class, @uploader_context = model, file, uploader_class, uploader_context
end end
def execute def execute
return nil unless @file && @file.size <= max_attachment_size return nil unless @file && @file.size <= max_attachment_size
uploader = @uploader_class.new(@model) uploader = @uploader_class.new(@model, nil, @uploader_context)
uploader.store!(@file) uploader.store!(@file)
uploader.to_h uploader.to_h
......
# frozen_string_literal: true
class UserAgentDetailService class UserAgentDetailService
attr_accessor :spammable, :request attr_accessor :spammable, :request
......
# frozen_string_literal: true
class UserProjectAccessChangedService class UserProjectAccessChangedService
def initialize(user_ids) def initialize(user_ids)
@user_ids = Array.wrap(user_ids) @user_ids = Array.wrap(user_ids)
......
# frozen_string_literal: true
require_relative 'base_service' require_relative 'base_service'
class ValidateNewBranchService < BaseService class ValidateNewBranchService < BaseService
......
# frozen_string_literal: true
require 'resolv' require 'resolv'
class VerifyPagesDomainService < BaseService class VerifyPagesDomainService < BaseService
......
# frozen_string_literal: true
class WebHookService class WebHookService
class InternalErrorResponse class InternalErrorResponse
attr_reader :body, :headers, :code attr_reader :body, :headers, :code
......
...@@ -15,7 +15,7 @@ class FileUploader < GitlabUploader ...@@ -15,7 +15,7 @@ class FileUploader < GitlabUploader
prepend ObjectStorage::Extension::RecordsUploads prepend ObjectStorage::Extension::RecordsUploads
MARKDOWN_PATTERN = %r{\!?\[.*?\]\(/uploads/(?<secret>[0-9a-f]{32})/(?<file>.*?)\)} MARKDOWN_PATTERN = %r{\!?\[.*?\]\(/uploads/(?<secret>[0-9a-f]{32})/(?<file>.*?)\)}
DYNAMIC_PATH_PATTERN = %r{(?<secret>\h{32})/(?<identifier>.*)} DYNAMIC_PATH_PATTERN = %r{.*(?<secret>\h{32})/(?<identifier>.*)}
after :remove, :prune_store_dir after :remove, :prune_store_dir
...@@ -67,6 +67,10 @@ class FileUploader < GitlabUploader ...@@ -67,6 +67,10 @@ class FileUploader < GitlabUploader
SecureRandom.hex SecureRandom.hex
end end
def self.extract_dynamic_path(path)
DYNAMIC_PATH_PATTERN.match(path)
end
def upload_paths(identifier) def upload_paths(identifier)
[ [
File.join(secret, identifier), File.join(secret, identifier),
...@@ -143,7 +147,7 @@ class FileUploader < GitlabUploader ...@@ -143,7 +147,7 @@ class FileUploader < GitlabUploader
return if apply_context!(value.uploader_context) return if apply_context!(value.uploader_context)
# fallback to the regex based extraction # fallback to the regex based extraction
if matches = DYNAMIC_PATH_PATTERN.match(value.path) if matches = self.class.extract_dynamic_path(value.path)
@secret = matches[:secret] @secret = matches[:secret]
@identifier = matches[:identifier] @identifier = matches[:identifier]
end end
......
...@@ -2,9 +2,9 @@ ...@@ -2,9 +2,9 @@
= form_tag oauth_application_path(application) do = form_tag oauth_application_path(application) do
%input{ :name => "_method", :type => "hidden", :value => "delete" }/ %input{ :name => "_method", :type => "hidden", :value => "delete" }/
- if defined? small - if defined? small
= button_tag type: "submit", class: "btn btn-transparent", data: { confirm: "Are you sure?" } do = button_tag type: "submit", class: "btn btn-transparent", data: { confirm: _("Are you sure?") } do
%span.sr-only %span.sr-only
Destroy = _('Destroy')
= icon('trash') = icon('trash')
- else - else
= submit_tag 'Destroy', data: { confirm: "Are you sure?" }, class: submit_btn_css = submit_tag _('Destroy'), data: { confirm: _("Are you sure?") }, class: submit_btn_css
...@@ -10,16 +10,14 @@ ...@@ -10,16 +10,14 @@
= f.text_area :redirect_uri, class: 'form-control', required: true = f.text_area :redirect_uri, class: 'form-control', required: true
%span.form-text.text-muted %span.form-text.text-muted
Use one line per URI = _('Use one line per URI')
- if Doorkeeper.configuration.native_redirect_uri - if Doorkeeper.configuration.native_redirect_uri
%span.form-text.text-muted %span.form-text.text-muted
Use = _('Use <code>%{native_redirect_uri}</code> for local tests').html_safe % { native_redirect_uri: Doorkeeper.configuration.native_redirect_uri }
%code= Doorkeeper.configuration.native_redirect_uri
for local tests
.form-group .form-group
= f.label :scopes, class: 'label-light' = f.label :scopes, class: 'label-light'
= render 'shared/tokens/scopes_form', prefix: 'doorkeeper_application', token: application, scopes: @scopes = render 'shared/tokens/scopes_form', prefix: 'doorkeeper_application', token: application, scopes: @scopes
.prepend-top-default .prepend-top-default
= f.submit 'Save application', class: "btn btn-create" = f.submit _('Save application'), class: "btn btn-create"
- page_title "Edit", @application.name, "Applications" - page_title _("Edit"), @application.name, _("Applications")
- @content_class = "limit-container-width" unless fluid_layout - @content_class = "limit-container-width" unless fluid_layout
%h3.page-title Edit application %h3.page-title= _('Edit application')
= render 'form', application: @application = render 'form', application: @application
- page_title "Applications" - page_title _("Applications")
- @content_class = "limit-container-width" unless fluid_layout - @content_class = "limit-container-width" unless fluid_layout
.row.prepend-top-default .row.prepend-top-default
...@@ -7,28 +7,27 @@ ...@@ -7,28 +7,27 @@
= page_title = page_title
%p %p
- if user_oauth_applications? - if user_oauth_applications?
Manage applications that can use GitLab as an OAuth provider, = _("Manage applications that can use GitLab as an OAuth provider, and applications that you've authorized to use your account.")
and applications that you've authorized to use your account.
- else - else
Manage applications that you've authorized to use your account. = _("Manage applications that you've authorized to use your account.")
.col-lg-8 .col-lg-8
- if user_oauth_applications? - if user_oauth_applications?
%h5.prepend-top-0 %h5.prepend-top-0
Add new application = _('Add new application')
= render 'form', application: @application = render 'form', application: @application
%hr %hr
- if user_oauth_applications? - if user_oauth_applications?
.oauth-applications .oauth-applications
%h5 %h5
Your applications (#{@applications.size}) = _("Your applications (%{size})") % { size: @applications.size }
- if @applications.any? - if @applications.any?
.table-responsive .table-responsive
%table.table %table.table
%thead %thead
%tr %tr
%th Name %th= _('Name')
%th Callback URL %th= _('Callback URL')
%th Clients %th= _('Clients')
%th.last-heading %th.last-heading
%tbody %tbody
- @applications.each do |application| - @applications.each do |application|
...@@ -41,25 +40,25 @@ ...@@ -41,25 +40,25 @@
%td %td
= link_to edit_oauth_application_path(application), class: "btn btn-transparent append-right-5" do = link_to edit_oauth_application_path(application), class: "btn btn-transparent append-right-5" do
%span.sr-only %span.sr-only
Edit = _('Edit')
= icon('pencil') = icon('pencil')
= render 'delete_form', application: application, small: true = render 'delete_form', application: application, small: true
- else - else
.settings-message.text-center .settings-message.text-center
You don't have any applications = _("You don't have any applications")
.oauth-authorized-applications.prepend-top-20.append-bottom-default .oauth-authorized-applications.prepend-top-20.append-bottom-default
- if user_oauth_applications? - if user_oauth_applications?
%h5 %h5
Authorized applications (#{@authorized_tokens.size}) = _("Authorized applications (%{size})") % { size: @authorized_tokens.size }
- if @authorized_tokens.any? - if @authorized_tokens.any?
.table-responsive .table-responsive
%table.table.table-striped %table.table.table-striped
%thead %thead
%tr %tr
%th Name %th= _('Name')
%th Authorized At %th= _('Authorized At')
%th Scope %th= _('Scope')
%th %th
%tbody %tbody
- @authorized_apps.each do |app| - @authorized_apps.each do |app|
...@@ -72,12 +71,12 @@ ...@@ -72,12 +71,12 @@
- @authorized_anonymous_tokens.each do |token| - @authorized_anonymous_tokens.each do |token|
%tr %tr
%td %td
Anonymous = _('Anonymous')
.form-text.text-muted .form-text.text-muted
%em Authorization was granted by entering your username and password in the application. %em= _("Authorization was granted by entering your username and password in the application.")
%td= token.created_at %td= token.created_at
%td= token.scopes %td= token.scopes
%td= render 'doorkeeper/authorized_applications/delete_form', token: token %td= render 'doorkeeper/authorized_applications/delete_form', token: token
- else - else
.settings-message.text-center .settings-message.text-center
You don't have any authorized applications = _("You don't have any authorized applications")
- page_title "New Application" - page_title _("New Application")
%h3.page-title New Application %h3.page-title= _("New Application")
%hr %hr
......
- add_to_breadcrumbs "Applications", oauth_applications_path - add_to_breadcrumbs _("Applications"), oauth_applications_path
- breadcrumb_title @application.name - breadcrumb_title @application.name
- page_title @application.name, "Applications" - page_title @application.name, _("Applications")
- @content_class = "limit-container-width" unless fluid_layout - @content_class = "limit-container-width" unless fluid_layout
%h3.page-title %h3.page-title
Application: #{@application.name} = _("Application: %{name}") % { name: @application.name }
.table-holder.oauth-application-show .table-holder.oauth-application-show
%table.table %table.table
%tr %tr
%td %td
Application Id = _('Application Id')
%td %td
%code#application_id= @application.uid %code#application_id= @application.uid
%tr %tr
%td %td
Secret: = _('Secret:')
%td %td
%code#secret= @application.secret %code#secret= @application.secret
%tr %tr
%td %td
Callback url = _('Callback url')
%td %td
- @application.redirect_uri.split.each do |uri| - @application.redirect_uri.split.each do |uri|
%div %div
...@@ -30,5 +30,5 @@ ...@@ -30,5 +30,5 @@
= render "shared/tokens/scopes_list", token: @application = render "shared/tokens/scopes_list", token: @application
.form-actions .form-actions
= link_to 'Edit', edit_oauth_application_path(@application), class: 'btn btn-primary wide float-left' = link_to _('Edit'), edit_oauth_application_path(@application), class: 'btn btn-primary wide float-left'
= render 'delete_form', application: @application, submit_btn_css: 'btn btn-danger prepend-left-10' = render 'delete_form', application: @application, submit_btn_css: 'btn btn-danger prepend-left-10'
%h3.page-title An error has occurred %h3.page-title= _("An error has occurred")
%main{ :role => "main" } %main{ :role => "main" }
%pre= @pre_auth.error_response.body[:error_description] %pre= @pre_auth.error_response.body[:error_description]
...@@ -3,34 +3,28 @@ ...@@ -3,34 +3,28 @@
.modal-content .modal-content
.modal-header .modal-header
%h3.page-title %h3.page-title
Authorize - link_to_client = link_to(@pre_auth.client.name, @pre_auth.redirect_uri, target: '_blank', rel: 'noopener noreferrer')
= link_to @pre_auth.client.name, @pre_auth.redirect_uri, target: '_blank', rel: 'noopener noreferrer' = _("Authorize %{link_to_client} to use your account?")
to use your account?
.modal-body .modal-body
- if current_user.admin? - if current_user.admin?
.text-warning .text-warning
%p %p
= icon("exclamation-triangle fw") = icon("exclamation-triangle fw")
You are an admin, which means granting access to = _('You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution.').html_safe % { client_name: @pre_auth.client.name }
%strong= @pre_auth.client.name
will allow them to interact with GitLab as an admin as well. Proceed with caution.
%p %p
An application called - link_to_client = link_to(@pre_auth.client.name, @pre_auth.redirect_uri, target: '_blank', rel: 'noopener noreferrer')
= link_to @pre_auth.client.name, @pre_auth.redirect_uri, target: '_blank', rel: 'noopener noreferrer' = _("An application called %{link_to_client} is requesting access to your GitLab account.").html_safe % { link_to_client: link_to_client }
is requesting access to your GitLab account.
- auth_app_owner = @pre_auth.client.application.owner - auth_app_owner = @pre_auth.client.application.owner
- if auth_app_owner - if auth_app_owner
This application was created by - link_to_owner = link_to(auth_app_owner.name, user_path(auth_app_owner))
= succeed "." do = _("This application was created by %{link_to_owner}.").html_safe % { link_to_owner: link_to_owner }
= link_to auth_app_owner.name, user_path(auth_app_owner)
Please note that this application is not provided by GitLab and you should verify its authenticity before = _("Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access.")
allowing access.
- if @pre_auth.scopes - if @pre_auth.scopes
%p %p
This application will be able to: = _("This application will be able to:")
%ul %ul
- @pre_auth.scopes.each do |scope| - @pre_auth.scopes.each do |scope|
%li %li
...@@ -44,7 +38,7 @@ ...@@ -44,7 +38,7 @@
= hidden_field_tag :response_type, @pre_auth.response_type = hidden_field_tag :response_type, @pre_auth.response_type
= hidden_field_tag :scope, @pre_auth.scope = hidden_field_tag :scope, @pre_auth.scope
= hidden_field_tag :nonce, @pre_auth.nonce = hidden_field_tag :nonce, @pre_auth.nonce
= submit_tag "Deny", class: "btn btn-danger" = submit_tag _("Deny"), class: "btn btn-danger"
= form_tag oauth_authorization_path, method: :post, class: 'inline' do = form_tag oauth_authorization_path, method: :post, class: 'inline' do
= hidden_field_tag :client_id, @pre_auth.client.uid = hidden_field_tag :client_id, @pre_auth.client.uid
= hidden_field_tag :redirect_uri, @pre_auth.redirect_uri = hidden_field_tag :redirect_uri, @pre_auth.redirect_uri
...@@ -52,4 +46,4 @@ ...@@ -52,4 +46,4 @@
= hidden_field_tag :response_type, @pre_auth.response_type = hidden_field_tag :response_type, @pre_auth.response_type
= hidden_field_tag :scope, @pre_auth.scope = hidden_field_tag :scope, @pre_auth.scope
= hidden_field_tag :nonce, @pre_auth.nonce = hidden_field_tag :nonce, @pre_auth.nonce
= submit_tag "Authorize", class: "btn btn-success prepend-left-10" = submit_tag _("Authorize"), class: "btn btn-success prepend-left-10"
%h3.page-title Authorization code: %h3.page-title= _("Authorization code:")
%main{ :role => "main" } %main{ :role => "main" }
%code#authorization_code= params[:code] %code#authorization_code= params[:code]
...@@ -6,4 +6,4 @@ ...@@ -6,4 +6,4 @@
= form_tag path do = form_tag path do
%input{ :name => "_method", :type => "hidden", :value => "delete" }/ %input{ :name => "_method", :type => "hidden", :value => "delete" }/
= submit_tag 'Revoke', onclick: "return confirm('Are you sure?')", class: 'btn btn-remove btn-sm' = submit_tag _('Revoke'), onclick: "return confirm('#{_('Are you sure?')}')", class: 'btn btn-remove btn-sm'
%header %header
%h1 Your authorized applications %h1= _("Your authorized applications")
%main{ :role => "main" } %main{ :role => "main" }
.table-holder .table-holder
%table.table.table-striped %table.table.table-striped
%thead %thead
%tr %tr
%th Application %th= _('Application')
%th Created At %th= _('Created At')
%th %th
%th %th
%tbody %tbody
......
:plain :plain
job = $("tr#repo_#{@repo_id}") job = $("tr#repo_#{@repo_id}")
job.find(".import-actions").html("<p class='alert alert-danger'>Access denied! Please verify you can add deploy keys to this repository.</p>") job.find(".import-actions").html("<p class='alert alert-danger'>#{_('Access denied! Please verify you can add deploy keys to this repository.')}</p>")
- page_title 'Bitbucket import' - page_title _('Bitbucket import')
- header_title 'Projects', root_path - header_title _('Projects'), root_path
%h3.page-title %h3.page-title
%i.fa.fa-bitbucket %i.fa.fa-bitbucket
Import projects from Bitbucket = _('Import projects from Bitbucket')
- if @repos.any? - if @repos.any?
%p.light %p.light
Select projects you want to import. = _('Select projects you want to import.')
%hr %hr
%p %p
- if @incompatible_repos.any? - if @incompatible_repos.any?
= button_tag class: 'btn btn-import btn-success js-import-all' do = button_tag class: 'btn btn-import btn-success js-import-all' do
Import all compatible projects = _('Import all compatible projects')
= icon('spinner spin', class: 'loading-icon') = icon('spinner spin', class: 'loading-icon')
- else - else
= button_tag class: 'btn btn-import btn-success js-import-all' do = button_tag class: 'btn btn-import btn-success js-import-all' do
Import all projects = _('Import all projects')
= icon('spinner spin', class: 'loading-icon') = icon('spinner spin', class: 'loading-icon')
.table-responsive .table-responsive
...@@ -26,9 +26,9 @@ ...@@ -26,9 +26,9 @@
%colgroup.import-jobs-status-col %colgroup.import-jobs-status-col
%thead %thead
%tr %tr
%th From Bitbucket %th= _('From Bitbucket')
%th To GitLab %th= _('To GitLab')
%th Status %th= _('Status')
%tbody %tbody
- @already_added_projects.each do |project| - @already_added_projects.each do |project|
%tr{ id: "project_#{project.id}", class: "#{project_status_css_class(project.import_status)}" } %tr{ id: "project_#{project.id}", class: "#{project_status_css_class(project.import_status)}" }
...@@ -40,10 +40,10 @@ ...@@ -40,10 +40,10 @@
- if project.import_status == 'finished' - if project.import_status == 'finished'
%span %span
%i.fa.fa-check %i.fa.fa-check
done = _('done')
- elsif project.import_status == 'started' - elsif project.import_status == 'started'
%i.fa.fa-spinner.fa-spin %i.fa.fa-spinner.fa-spin
started = _('started')
- else - else
= project.human_import_status_name = project.human_import_status_name
...@@ -66,7 +66,7 @@ ...@@ -66,7 +66,7 @@
= text_field_tag :path, repo.name, class: "input-mini form-control", tabindex: 2, autofocus: true, required: true = text_field_tag :path, repo.name, class: "input-mini form-control", tabindex: 2, autofocus: true, required: true
%td.import-actions.job-status %td.import-actions.job-status
= button_tag class: 'btn btn-import js-add-to-import' do = button_tag class: 'btn btn-import js-add-to-import' do
Import = _('Import')
= icon('spinner spin', class: 'loading-icon') = icon('spinner spin', class: 'loading-icon')
- @incompatible_repos.each do |repo| - @incompatible_repos.each do |repo|
%tr{ id: "repo_#{repo.owner}___#{repo.slug}" } %tr{ id: "repo_#{repo.owner}___#{repo.slug}" }
...@@ -74,16 +74,13 @@ ...@@ -74,16 +74,13 @@
= link_to repo.full_name, "https://bitbucket.org/#{repo.full_name}", target: '_blank', rel: 'noopener noreferrer' = link_to repo.full_name, "https://bitbucket.org/#{repo.full_name}", target: '_blank', rel: 'noopener noreferrer'
%td.import-target %td.import-target
%td.import-actions-job-status %td.import-actions-job-status
= label_tag 'Incompatible Project', nil, class: 'label badge-danger' = label_tag _('Incompatible Project'), nil, class: 'label badge-danger'
- if @incompatible_repos.any? - if @incompatible_repos.any?
%p %p
One or more of your Bitbucket projects cannot be imported into GitLab = _("One or more of your Bitbucket projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git.")
directly because they use Subversion or Mercurial for version control, - link_to_git = link_to(_('Git'), 'https://www.atlassian.com/git/tutorials/migrating-overview')
rather than Git. Please convert - link_to_import_flow = link_to(_('import flow'), status_import_bitbucket_path)
= link_to 'them to Git,', 'https://www.atlassian.com/git/tutorials/migrating-overview' = _("Please convert them to %{link_to_git}, and go through the %{link_to_import_flow} again.").html_safe % { link_to_git: link_to_git, link_to_import_flow: link_to_import_flow }
and go through the
= link_to 'import flow', status_import_bitbucket_path
again.
.js-importer-status{ data: { jobs_import_path: "#{jobs_import_bitbucket_path}", import_path: "#{import_bitbucket_path}" } } .js-importer-status{ data: { jobs_import_path: "#{jobs_import_bitbucket_path}", import_path: "#{import_bitbucket_path}" } }
- page_title "FogBugz Import" - page_title _("FogBugz Import")
- header_title "Projects", root_path - header_title _("Projects"), root_path
%h3.page-title %h3.page-title
%i.fa.fa-bug %i.fa.fa-bug
Import projects from FogBugz = _('Import projects from FogBugz')
%hr %hr
= form_tag callback_import_fogbugz_path do = form_tag callback_import_fogbugz_path do
%p %p
To get started you enter your FogBugz URL and login information below. = _("To get started you enter your FogBugz URL and login information below. In the next steps, you'll be able to map users and select the projects you want to import.")
In the next steps, you'll be able to map users and select the projects
you want to import.
.form-group.row .form-group.row
= label_tag :uri, 'FogBugz URL', class: 'col-form-label col-md-2' = label_tag :uri, _('FogBugz URL'), class: 'col-form-label col-md-2'
.col-md-4 .col-md-4
= text_field_tag :uri, nil, placeholder: 'https://mycompany.fogbugz.com', class: 'form-control' = text_field_tag :uri, nil, placeholder: 'https://mycompany.fogbugz.com', class: 'form-control'
.form-group.row .form-group.row
= label_tag :email, 'FogBugz Email', class: 'col-form-label col-md-2' = label_tag :email, _('FogBugz Email'), class: 'col-form-label col-md-2'
.col-md-4 .col-md-4
= text_field_tag :email, nil, class: 'form-control' = text_field_tag :email, nil, class: 'form-control'
.form-group.row .form-group.row
= label_tag :password, 'FogBugz Password', class: 'col-form-label col-md-2' = label_tag :password, _('FogBugz Password'), class: 'col-form-label col-md-2'
.col-md-4 .col-md-4
= password_field_tag :password, nil, class: 'form-control' = password_field_tag :password, nil, class: 'form-control'
.form-actions .form-actions
= submit_tag 'Continue to the next step', class: 'btn btn-create' = submit_tag _('Continue to the next step'), class: 'btn btn-create'
- page_title 'User map', 'FogBugz import' - page_title _('User map'), _('FogBugz import')
- header_title "Projects", root_path - header_title _("Projects"), root_path
%h3.page-title %h3.page-title
%i.fa.fa-bug %i.fa.fa-bug
Import projects from FogBugz = _('Import projects from FogBugz')
%hr %hr
= form_tag create_user_map_import_fogbugz_path do = form_tag create_user_map_import_fogbugz_path do
%p %p
Customize how FogBugz email addresses and usernames are imported into GitLab. = _("Customize how FogBugz email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import.")
In the next step, you'll be able to select the projects you want to import.
%p %p
The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below. = _("The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below.")
%ul %ul
%li %li
%strong Default: Map a FogBugz account ID to a full name %strong= _("Default: Map a FogBugz account ID to a full name")
%p %p
An empty GitLab User field will add the FogBugz user's full name = _("An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator.")
(e.g. "By John Smith") in the description of all issues and comments.
It will also associate and/or assign these issues and comments with
the project creator.
%li %li
%strong Map a FogBugz account ID to a GitLab user %strong= _("Map a FogBugz account ID to a GitLab user")
%p %p
Selecting a GitLab user will add a link to the GitLab user in the descriptions = _('Selecting a GitLab user will add a link to the GitLab user in the descriptions of issues and comments (e.g. "By <a href="#">@johnsmith</a>"). It will also associate and/or assign these issues and comments with the selected user.').html_safe
of issues and comments (e.g. "By <a href="#">@johnsmith</a>"). It will also
associate and/or assign these issues and comments with the selected user.
.table-holder .table-holder
%table.table %table.table
%thead %thead
%tr %tr
%th ID %th= _("ID")
%th Name %th= _("Name")
%th Email %th= _("Email")
%th GitLab User %th= _("GitLab User")
%tbody %tbody
- @user_map.each do |id, user| - @user_map.each do |id, user|
%tr %tr
...@@ -45,4 +39,4 @@ ...@@ -45,4 +39,4 @@
scope: :all, email_user: true, selected: user[:gitlab_user]) scope: :all, email_user: true, selected: user[:gitlab_user])
.form-actions .form-actions
= submit_tag 'Continue to the next step', class: 'btn btn-create' = submit_tag _('Continue to the next step'), class: 'btn btn-create'
- page_title "FogBugz import" - page_title _("FogBugz import")
- header_title "Projects", root_path - header_title _("Projects"), root_path
%h3.page-title %h3.page-title
%i.fa.fa-bug %i.fa.fa-bug
Import projects from FogBugz = _('Import projects from FogBugz')
- if @repos.any? - if @repos.any?
%p.light %p.light
Select projects you want to import. = _('Select projects you want to import.')
%p.light %p.light
Optionally, you can - link_to_customize = link_to('customize', new_user_map_import_fogbugz_path)
= link_to 'customize', new_user_map_import_fogbugz_path = _('Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab.').html_safe % { link_to_customize: link_to_customize }
how FogBugz email addresses and usernames are imported into GitLab.
%hr %hr
%p %p
= button_tag class: 'btn btn-import btn-success js-import-all' do = button_tag class: 'btn btn-import btn-success js-import-all' do
Import all projects = _('Import all projects')
= icon("spinner spin", class: "loading-icon") = icon("spinner spin", class: "loading-icon")
.table-responsive .table-responsive
...@@ -24,9 +23,9 @@ ...@@ -24,9 +23,9 @@
%colgroup.import-jobs-status-col %colgroup.import-jobs-status-col
%thead %thead
%tr %tr
%th From FogBugz %th= _("From FogBugz")
%th To GitLab %th= _("To GitLab")
%th Status %th= _("Status")
%tbody %tbody
- @already_added_projects.each do |project| - @already_added_projects.each do |project|
%tr{ id: "project_#{project.id}", class: "#{project_status_css_class(project.import_status)}" } %tr{ id: "project_#{project.id}", class: "#{project_status_css_class(project.import_status)}" }
...@@ -38,10 +37,10 @@ ...@@ -38,10 +37,10 @@
- if project.import_status == 'finished' - if project.import_status == 'finished'
%span %span
%i.fa.fa-check %i.fa.fa-check
done = _("done")
- elsif project.import_status == 'started' - elsif project.import_status == 'started'
%i.fa.fa-spinner.fa-spin %i.fa.fa-spinner.fa-spin
started = _("started")
- else - else
= project.human_import_status_name = project.human_import_status_name
...@@ -53,7 +52,7 @@ ...@@ -53,7 +52,7 @@
#{current_user.username}/#{repo.name} #{current_user.username}/#{repo.name}
%td.import-actions.job-status %td.import-actions.job-status
= button_tag class: "btn btn-import js-add-to-import" do = button_tag class: "btn btn-import js-add-to-import" do
Import = _("Import")
= icon("spinner spin", class: "loading-icon") = icon("spinner spin", class: "loading-icon")
.js-importer-status{ data: { jobs_import_path: "#{jobs_import_fogbugz_path}", import_path: "#{import_fogbugz_path}" } } .js-importer-status{ data: { jobs_import_path: "#{jobs_import_fogbugz_path}", import_path: "#{import_fogbugz_path}" } }
- page_title "Gitea Import" - page_title _("Gitea Import")
- header_title "Projects", root_path - header_title _("Projects"), root_path
%h3.page-title %h3.page-title
= custom_icon('go_logo') = custom_icon('go_logo')
Import Projects from Gitea = _('Import Projects from Gitea')
%p %p
To get started, please enter your Gitea Host URL and a - link_to_personal_token = link_to(_('Personal Access Token'), 'https://github.com/gogits/go-gogs-client/wiki#access-token')
= succeed '.' do = _('To get started, please enter your Gitea Host URL and a %{link_to_personal_token}.').html_safe % { link_to_personal_token: link_to_personal_token }
= link_to 'Personal Access Token', 'https://github.com/gogits/go-gogs-client/wiki#access-token'
= form_tag personal_access_token_import_gitea_path do = form_tag personal_access_token_import_gitea_path do
.form-group.row .form-group.row
= label_tag :gitea_host_url, 'Gitea Host URL', class: 'col-form-label col-sm-2' = label_tag :gitea_host_url, _('Gitea Host URL'), class: 'col-form-label col-sm-2'
.col-sm-4 .col-sm-4
= text_field_tag :gitea_host_url, nil, placeholder: 'https://try.gitea.io', class: 'form-control' = text_field_tag :gitea_host_url, nil, placeholder: 'https://try.gitea.io', class: 'form-control'
.form-group.row .form-group.row
= label_tag :personal_access_token, 'Personal Access Token', class: 'col-form-label col-sm-2' = label_tag :personal_access_token, _('Personal Access Token'), class: 'col-form-label col-sm-2'
.col-sm-4 .col-sm-4
= text_field_tag :personal_access_token, nil, class: 'form-control' = text_field_tag :personal_access_token, nil, class: 'form-control'
.form-actions .form-actions
= submit_tag 'List Your Gitea Repositories', class: 'btn btn-create' = submit_tag _('List Your Gitea Repositories'), class: 'btn btn-create'
- page_title "Gitea Import" - page_title _("Gitea Import")
- header_title "Projects", root_path - header_title _("Projects"), root_path
%h3.page-title %h3.page-title
= custom_icon('go_logo') = custom_icon('go_logo')
Import Projects from Gitea = _('Import Projects from Gitea')
= render 'import/githubish_status', provider: 'gitea' = render 'import/githubish_status', provider: 'gitea'
- title = has_ci_cd_only_params? ? _('Connect repositories from GitHub') : _('GitHub import') - title = has_ci_cd_only_params? ? _('Connect repositories from GitHub') : _('GitHub import')
- page_title title - page_title title
- breadcrumb_title title - breadcrumb_title title
- header_title "Projects", root_path - header_title _("Projects"), root_path
%h3.page-title %h3.page-title
= icon 'github', text: import_github_title = icon 'github', text: import_github_title
......
- title = has_ci_cd_only_params? ? _('Connect repositories from GitHub') : _('GitHub import') - title = has_ci_cd_only_params? ? _('Connect repositories from GitHub') : _('GitHub import')
- page_title title - page_title title
- breadcrumb_title title - breadcrumb_title title
- header_title "Projects", root_path - header_title _("Projects"), root_path
%h3.page-title %h3.page-title
= icon 'github', text: import_github_title = icon 'github', text: import_github_title
......
- page_title "GitLab.com import" - page_title _("GitLab.com import")
- header_title "Projects", root_path - header_title _("Projects"), root_path
%h3.page-title %h3.page-title
%i.fa.fa-heart %i.fa.fa-heart
Import projects from GitLab.com = _('Import projects from GitLab.com')
%p.light %p.light
Select projects you want to import. = _('Select projects you want to import.')
%hr %hr
%p %p
= button_tag class: "btn btn-import btn-success js-import-all" do = button_tag class: "btn btn-import btn-success js-import-all" do
Import all projects = _('Import all projects')
= icon("spinner spin", class: "loading-icon") = icon("spinner spin", class: "loading-icon")
.table-responsive .table-responsive
...@@ -19,9 +19,9 @@ ...@@ -19,9 +19,9 @@
%colgroup.import-jobs-status-col %colgroup.import-jobs-status-col
%thead %thead
%tr %tr
%th From GitLab.com %th= _('From GitLab.com')
%th To this GitLab instance %th= _('To this GitLab instance')
%th Status %th= _('Status')
%tbody %tbody
- @already_added_projects.each do |project| - @already_added_projects.each do |project|
%tr{ id: "project_#{project.id}", class: "#{project_status_css_class(project.import_status)}" } %tr{ id: "project_#{project.id}", class: "#{project_status_css_class(project.import_status)}" }
...@@ -33,10 +33,10 @@ ...@@ -33,10 +33,10 @@
- if project.import_status == 'finished' - if project.import_status == 'finished'
%span %span
%i.fa.fa-check %i.fa.fa-check
done = _('done')
- elsif project.import_status == 'started' - elsif project.import_status == 'started'
%i.fa.fa-spinner.fa-spin %i.fa.fa-spinner.fa-spin
started = _('started')
- else - else
= project.human_import_status_name = project.human_import_status_name
...@@ -48,7 +48,7 @@ ...@@ -48,7 +48,7 @@
= import_project_target(repo['namespace']['path'], repo['name']) = import_project_target(repo['namespace']['path'], repo['name'])
%td.import-actions.job-status %td.import-actions.job-status
= button_tag class: "btn btn-import js-add-to-import" do = button_tag class: "btn btn-import js-add-to-import" do
Import = _('Import')
= icon("spinner spin", class: "loading-icon") = icon("spinner spin", class: "loading-icon")
.js-importer-status{ data: { jobs_import_path: "#{jobs_import_gitlab_path}", import_path: "#{import_gitlab_path}" } } .js-importer-status{ data: { jobs_import_path: "#{jobs_import_gitlab_path}", import_path: "#{import_gitlab_path}" } }
- page_title "GitLab Import" - page_title _("GitLab Import")
- header_title "Projects", root_path - header_title _("Projects"), root_path
%h3.page-title %h3.page-title
= icon('gitlab') = icon('gitlab')
Import an exported GitLab project = _('Import an exported GitLab project')
%hr %hr
= form_tag import_gitlab_project_path, class: 'new_project', multipart: true do = form_tag import_gitlab_project_path, class: 'new_project', multipart: true do
...@@ -24,19 +24,19 @@ ...@@ -24,19 +24,19 @@
#{user_url(current_user.username)}/ #{user_url(current_user.username)}/
= hidden_field_tag :namespace_id, value: current_user.namespace_id = hidden_field_tag :namespace_id, value: current_user.namespace_id
.form-group.col-12.col-sm-6.project-path .form-group.col-12.col-sm-6.project-path
= label_tag :path, 'Project name', class: 'label-light' = label_tag :path, _('Project name'), class: 'label-light'
= text_field_tag :path, @path, placeholder: "my-awesome-project", class: "js-path-name form-control", tabindex: 2, autofocus: true, required: true = text_field_tag :path, @path, placeholder: "my-awesome-project", class: "js-path-name form-control", tabindex: 2, autofocus: true, required: true
.row .row
.form-group.col-md-12 .form-group.col-md-12
To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here. = _("To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here.")
.row .row
.form-group.col-sm-12 .form-group.col-sm-12
= hidden_field_tag :namespace_id, @namespace.id = hidden_field_tag :namespace_id, @namespace.id
= label_tag :file, 'GitLab project export', class: 'label-light' = label_tag :file, _('GitLab project export'), class: 'label-light'
.form-group .form-group
= file_field_tag :file, class: '' = file_field_tag :file, class: ''
.row .row
.form-actions.col-sm-12 .form-actions.col-sm-12
= submit_tag 'Import project', class: 'btn btn-create' = submit_tag _('Import project'), class: 'btn btn-create'
= link_to 'Cancel', new_project_path, class: 'btn btn-cancel' = link_to _('Cancel'), new_project_path, class: 'btn btn-cancel'
- page_title "Google Code import" - page_title _("Google Code import")
- header_title "Projects", root_path - header_title _("Projects"), root_path
%h3.page-title %h3.page-title
%i.fa.fa-google %i.fa.fa-google
Import projects from Google Code = _('Import projects from Google Code')
%hr %hr
= form_tag callback_import_google_code_path, multipart: true do = form_tag callback_import_google_code_path, multipart: true do
%p %p
Follow the steps below to export your Google Code project data. = _('Follow the steps below to export your Google Code project data.')
In the next step, you'll be able to select the projects you want to import. = _("In the next step, you'll be able to select the projects you want to import.")
%ol %ol
%li %li
%p %p
Go to - link_to_google_takeout = link_to(_("Google Takeout"), "https://www.google.com/settings/takeout", target: '_blank', rel: 'noopener noreferrer')
#{link_to "Google Takeout", "https://www.google.com/settings/takeout", target: '_blank', rel: 'noopener noreferrer'}. = _("Go to %{link_to_google_takeout}.").html_safe % { link_to_google_takeout: link_to_google_takeout }
%li %li
%p %p
Make sure you're logged into the account that owns the projects you'd like to import. = _("Make sure you're logged into the account that owns the projects you'd like to import.")
%li %li
%p %p
Click the <strong>Select none</strong> button on the right, since we only need "Google Code Project Hosting". = _('Click the <strong>Select none</strong> button on the right, since we only need "Google Code Project Hosting".').html_safe
%li %li
%p %p
Scroll down to <strong>Google Code Project Hosting</strong> and enable the switch on the right. = _('Scroll down to <strong>Google Code Project Hosting</strong> and enable the switch on the right.').html_safe
%li %li
%p %p
Choose <strong>Next</strong> at the bottom of the page. = _('Choose <strong>Next</strong> at the bottom of the page.').html_safe
%li %li
%p %p
Leave the "File type" and "Delivery method" options on their default values. = _('Leave the "File type" and "Delivery method" options on their default values.')
%li %li
%p %p
Choose <strong>Create archive</strong> and wait for archiving to complete. = _('Choose <strong>Create archive</strong> and wait for archiving to complete.').html_safe
%li %li
%p %p
Click the <strong>Download</strong> button and wait for downloading to complete. = _('Click the <strong>Download</strong> button and wait for downloading to complete.').html_safe
%li %li
%p %p
Find the downloaded ZIP file and decompress it. = _('Find the downloaded ZIP file and decompress it.')
%li %li
%p %p
Find the newly extracted <code>Takeout/Google Code Project Hosting/GoogleCodeProjectHosting.json</code> file. = _('Find the newly extracted <code>Takeout/Google Code Project Hosting/GoogleCodeProjectHosting.json</code> file.').html_safe
%li %li
%p %p
Upload <code>GoogleCodeProjectHosting.json</code> here: = _('Upload <code>GoogleCodeProjectHosting.json</code> here:').html_safe
%p %p
%input{ type: "file", name: "dump_file", id: "dump_file" } %input{ type: "file", name: "dump_file", id: "dump_file" }
%li %li
%p %p
Do you want to customize how Google Code email addresses and usernames are imported into GitLab? = _('Do you want to customize how Google Code email addresses and usernames are imported into GitLab?')
%p %p
= label_tag :create_user_map_0 do = label_tag :create_user_map_0 do
= radio_button_tag :create_user_map, 0, true = radio_button_tag :create_user_map, 0, true
No, directly import the existing email addresses and usernames. = _('No, directly import the existing email addresses and usernames.')
%p %p
= label_tag :create_user_map_1 do = label_tag :create_user_map_1 do
= radio_button_tag :create_user_map, 1, false = radio_button_tag :create_user_map, 1, false
Yes, let me map Google Code users to full names or GitLab users. = _('Yes, let me map Google Code users to full names or GitLab users.')
%li %li
%p %p
= submit_tag 'Continue to the next step', class: "btn btn-create" = submit_tag _('Continue to the next step'), class: "btn btn-create"
- page_title "User map", "Google Code import" - page_title _("User map"), _("Google Code import")
- header_title "Projects", root_path - header_title _("Projects"), root_path
%h3.page-title %h3.page-title
%i.fa.fa-google %i.fa.fa-google
Import projects from Google Code = _('Import projects from Google Code')
%hr %hr
= form_tag create_user_map_import_google_code_path do = form_tag create_user_map_import_google_code_path do
%p %p
Customize how Google Code email addresses and usernames are imported into GitLab. = _("Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import.")
In the next step, you'll be able to select the projects you want to import.
%p %p
The user map is a JSON document mapping the Google Code users that participated on your projects to the way their email addresses and usernames will be imported into GitLab. You can change this by changing the value on the right hand side of <code>:</code>. Be sure to preserve the surrounding double quotes, other punctuation and the email address or username on the left hand side. = _("The user map is a JSON document mapping the Google Code users that participated on your projects to the way their email addresses and usernames will be imported into GitLab. You can change this by changing the value on the right hand side of <code>:</code>. Be sure to preserve the surrounding double quotes, other punctuation and the email address or username on the left hand side.").html_safe
%ul %ul
%li %li
%strong Default: Directly import the Google Code email address or username %strong= _("Default: Directly import the Google Code email address or username")
%p %p
<code>"johnsmith@example.com": "johnsm...@example.com"</code> = _('<code>"johnsmith@example.com": "johnsm...@example.com"</code> will add "By johnsm...@example.com" to all issues and comments originally created by johnsmith@example.com. The email address or username is masked to ensure the user\'s privacy.').html_safe
will add "By johnsm...@example.com" to all issues and comments originally created by johnsmith@example.com.
The email address or username is masked to ensure the user's privacy.
%li %li
%strong Map a Google Code user to a GitLab user %strong= _("Map a Google Code user to a GitLab user")
%p %p
<code>"johnsmith@example.com": "@johnsmith"</code> = _('<code>"johnsmith@example.com": "@johnsmith"</code> will add "By <a href="#">@johnsmith</a>" to all issues and comments originally created by johnsmith@example.com, and will set <a href="#">@johnsmith</a> as the assignee on all issues originally assigned to johnsmith@example.com.').html_safe
will add "By <a href="#">@johnsmith</a>" to all issues and comments originally created by johnsmith@example.com,
and will set <a href="#">@johnsmith</a> as the assignee on all issues originally assigned to johnsmith@example.com.
%li %li
%strong Map a Google Code user to a full name %strong= _("Map a Google Code user to a full name")
%p %p
<code>"johnsmith@example.com": "John Smith"</code> = _('<code>"johnsmith@example.com": "John Smith"</code> will add "By John Smith" to all issues and comments originally created by johnsmith@example.com.').html_safe
will add "By John Smith" to all issues and comments originally created by johnsmith@example.com.
%li %li
%strong Map a Google Code user to a full email address %strong= _("Map a Google Code user to a full email address")
%p %p
<code>"johnsmith@example.com": "johnsmith@example.com"</code> = _('<code>"johnsmith@example.com": "johnsmith@example.com"</code> will add "By <a href="#">johnsmith@example.com</a>" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user\'s privacy. Use this option if you want to show the full email address.').html_safe
will add "By <a href="#">johnsmith@example.com</a>" to all issues and comments originally created by johnsmith@example.com.
By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address.
.form-group.row .form-group.row
.col-sm-12 .col-sm-12
= text_area_tag :user_map, JSON.pretty_generate(@user_map), class: 'form-control', rows: 15 = text_area_tag :user_map, JSON.pretty_generate(@user_map), class: 'form-control', rows: 15
.form-actions .form-actions
= submit_tag 'Continue to the next step', class: "btn btn-create" = submit_tag _('Continue to the next step'), class: "btn btn-create"
- page_title "Google Code import" - page_title _("Google Code import")
- header_title "Projects", root_path - header_title _("Projects"), root_path
%h3.page-title %h3.page-title
%i.fa.fa-google %i.fa.fa-google
Import projects from Google Code = _('Import projects from Google Code')
- if @repos.any? - if @repos.any?
%p.light %p.light
Select projects you want to import. = _('Select projects you want to import.')
%p.light %p.light
Optionally, you can - link_to_customize = link_to(_("customize"), new_user_map_import_google_code_path)
= link_to "customize", new_user_map_import_google_code_path = _("Optionally, you can %{link_to_customize} how Google Code email addresses and usernames are imported into GitLab.").html_safe % { link_to_customize: link_to_customize }
how Google Code email addresses and usernames are imported into GitLab.
%hr %hr
%p %p
- if @incompatible_repos.any? - if @incompatible_repos.any?
= button_tag class: "btn btn-import btn-success js-import-all" do = button_tag class: "btn btn-import btn-success js-import-all" do
Import all compatible projects = _("Import all compatible projects")
= icon("spinner spin", class: "loading-icon") = icon("spinner spin", class: "loading-icon")
- else - else
= button_tag class: "btn btn-import btn-success js-import-all" do = button_tag class: "btn btn-import btn-success js-import-all" do
Import all projects = _("Import all projects")
= icon("spinner spin", class: "loading-icon") = icon("spinner spin", class: "loading-icon")
.table-responsive .table-responsive
...@@ -29,9 +28,9 @@ ...@@ -29,9 +28,9 @@
%colgroup.import-jobs-status-col %colgroup.import-jobs-status-col
%thead %thead
%tr %tr
%th From Google Code %th= _("From Google Code")
%th To GitLab %th= _("To GitLab")
%th Status %th= _("Status")
%tbody %tbody
- @already_added_projects.each do |project| - @already_added_projects.each do |project|
%tr{ id: "project_#{project.id}", class: "#{project_status_css_class(project.import_status)}" } %tr{ id: "project_#{project.id}", class: "#{project_status_css_class(project.import_status)}" }
...@@ -43,10 +42,10 @@ ...@@ -43,10 +42,10 @@
- if project.import_status == 'finished' - if project.import_status == 'finished'
%span %span
%i.fa.fa-check %i.fa.fa-check
done = _("done")
- elsif project.import_status == 'started' - elsif project.import_status == 'started'
%i.fa.fa-spinner.fa-spin %i.fa.fa-spinner.fa-spin
started = _("started")
- else - else
= project.human_import_status_name = project.human_import_status_name
...@@ -58,7 +57,7 @@ ...@@ -58,7 +57,7 @@
#{current_user.username}/#{repo.name} #{current_user.username}/#{repo.name}
%td.import-actions.job-status %td.import-actions.job-status
= button_tag class: "btn btn-import js-add-to-import" do = button_tag class: "btn btn-import js-add-to-import" do
Import = _("Import")
= icon("spinner spin", class: "loading-icon") = icon("spinner spin", class: "loading-icon")
- @incompatible_repos.each do |repo| - @incompatible_repos.each do |repo|
%tr{ id: "repo_#{repo.id}" } %tr{ id: "repo_#{repo.id}" }
...@@ -66,15 +65,12 @@ ...@@ -66,15 +65,12 @@
= link_to repo.name, "https://code.google.com/p/#{repo.name}", target: "_blank", rel: 'noopener noreferrer' = link_to repo.name, "https://code.google.com/p/#{repo.name}", target: "_blank", rel: 'noopener noreferrer'
%td.import-target %td.import-target
%td.import-actions-job-status %td.import-actions-job-status
= label_tag "Incompatible Project", nil, class: "label badge-danger" = label_tag _("Incompatible Project"), nil, class: "label badge-danger"
- if @incompatible_repos.any? - if @incompatible_repos.any?
%p %p
One or more of your Google Code projects cannot be imported into GitLab = _("One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git.")
directly because they use Subversion or Mercurial for version control, - link_to_import_flow = link_to(_("import flow"), new_import_google_code_path)
rather than Git. Please convert them to Git on Google Code, and go = _("Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again.").html_safe % { link_to_import_flow: link_to_import_flow }
through the
= link_to "import flow", new_import_google_code_path
again.
.js-importer-status{ data: { jobs_import_path: "#{jobs_import_google_code_path}", import_path: "#{import_google_code_path}" } } .js-importer-status{ data: { jobs_import_path: "#{jobs_import_google_code_path}", import_path: "#{import_google_code_path}" } }
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
? ?
.modal-body .modal-body
%p= s_('Environments|Are you sure you want to stop this environment?') %p= s_('Environments|Are you sure you want to stop this environment?')
- unless @environment.stop_action? - unless @environment.stop_action_available?
.warning_message .warning_message
%p= s_('Environments|Note that this action will stop the environment, but it will %{emphasis_start}not%{emphasis_end} have an effect on any existing deployment due to no “stop environment action” being defined in the %{ci_config_link_start}.gitlab-ci.yml%{ci_config_link_end} file.').html_safe % { emphasis_start: '<strong>'.html_safe, %p= s_('Environments|Note that this action will stop the environment, but it will %{emphasis_start}not%{emphasis_end} have an effect on any existing deployment due to no “stop environment action” being defined in the %{ci_config_link_start}.gitlab-ci.yml%{ci_config_link_end} file.').html_safe % { emphasis_start: '<strong>'.html_safe,
emphasis_end: '</strong>'.html_safe, emphasis_end: '</strong>'.html_safe,
......
...@@ -6,5 +6,5 @@ ...@@ -6,5 +6,5 @@
%td %td
= hidden_field_tag "allowed_to_push_#{protected_branch.id}", protected_branch.push_access_levels.first.access_level = hidden_field_tag "allowed_to_push_#{protected_branch.id}", protected_branch.push_access_levels.first.access_level
= dropdown_tag( (protected_branch.push_access_levels.first.humanize || 'Select') , = dropdown_tag( (protected_branch.push_access_levels.first.humanize || 'Select') ,
options: { toggle_class: 'js-allowed-to-push qa-allowed-to-push', dropdown_class: 'dropdown-menu-selectable js-allowed-to-push-container capitalize-header', options: { toggle_class: 'js-allowed-to-push', dropdown_class: 'dropdown-menu-selectable js-allowed-to-push-container capitalize-header',
data: { field_name: "allowed_to_push_#{protected_branch.id}", access_level_id: protected_branch.push_access_levels.first.id }}) data: { field_name: "allowed_to_push_#{protected_branch.id}", access_level_id: protected_branch.push_access_levels.first.id }})
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
%tr.js-protected-branch-edit-form{ data: { url: namespace_project_protected_branch_path(@project.namespace, @project, protected_branch) } } %tr.js-protected-branch-edit-form{ data: { url: namespace_project_protected_branch_path(@project.namespace, @project, protected_branch) } }
%td %td
%span.ref-name.qa-protected-branch-name= protected_branch.name %span.ref-name= protected_branch.name
- if @project.root_ref?(protected_branch.name) - if @project.root_ref?(protected_branch.name)
%span.badge.badge-info.prepend-left-5 default %span.badge.badge-info.prepend-left-5 default
......
---
title: Add uploader support to Import/Export uploads
merge_request: 20484
author:
type: added
---
title: Fix typo in CSS transform property for Memory Graph component
merge_request: 20650
author:
type: fixed
---
title: Fix archived parameter for projects API
merge_request: 20566
author: Peter Marko
type: fixed
---
title: Enable frozen string in apps/uploaders/*.rb
merge_request: 20401
author: gfyoung
type: other
---
title: Add a 10 ms bucket for SQL timings
merge_request:
author:
type: changed
---
title: Update issue closing pattern
merge_request: 20554
author: George Tsiolis
type: changed
...@@ -135,7 +135,7 @@ Settings.gitlab['signup_enabled'] ||= true if Settings.gitlab['signup_enabled']. ...@@ -135,7 +135,7 @@ Settings.gitlab['signup_enabled'] ||= true if Settings.gitlab['signup_enabled'].
Settings.gitlab['signin_enabled'] ||= true if Settings.gitlab['signin_enabled'].nil? Settings.gitlab['signin_enabled'] ||= true if Settings.gitlab['signin_enabled'].nil?
Settings.gitlab['restricted_visibility_levels'] = Settings.__send__(:verify_constant_array, Gitlab::VisibilityLevel, Settings.gitlab['restricted_visibility_levels'], []) Settings.gitlab['restricted_visibility_levels'] = Settings.__send__(:verify_constant_array, Gitlab::VisibilityLevel, Settings.gitlab['restricted_visibility_levels'], [])
Settings.gitlab['username_changing_enabled'] = true if Settings.gitlab['username_changing_enabled'].nil? Settings.gitlab['username_changing_enabled'] = true if Settings.gitlab['username_changing_enabled'].nil?
Settings.gitlab['issue_closing_pattern'] = '((?:[Cc]los(?:e[sd]?|ing)|[Ff]ix(?:e[sd]|ing)?|[Rr]esolv(?:e[sd]?|ing)|[Ii]mplement(?:s|ed|ing)?)(:?) +(?:(?:issues? +)?%{issue_ref}(?:(?: *,? +and +| *, *)?)|([A-Z][A-Z0-9_]+-\d+))+)' if Settings.gitlab['issue_closing_pattern'].nil? Settings.gitlab['issue_closing_pattern'] = '((?:[Cc]los(?:e[sd]?|ing)|[Ff]ix(?:e[sd]|ing)?|[Rr]esolv(?:e[sd]?|ing)|[Ii]mplement(?:s|ed|ing)?)(:?) +(?:(?:issues? +)?%{issue_ref}(?:(?: *,? +and +| *,? *)?)|([A-Z][A-Z0-9_]+-\d+))+)' if Settings.gitlab['issue_closing_pattern'].nil?
Settings.gitlab['default_projects_features'] ||= {} Settings.gitlab['default_projects_features'] ||= {}
Settings.gitlab['webhook_timeout'] ||= 10 Settings.gitlab['webhook_timeout'] ||= 10
Settings.gitlab['max_attachment_size'] ||= 10 Settings.gitlab['max_attachment_size'] ||= 10
......
...@@ -38,12 +38,14 @@ def check_changelog(path) ...@@ -38,12 +38,14 @@ def check_changelog(path)
if yaml["merge_request"].nil? if yaml["merge_request"].nil?
message "Consider setting `merge_request` to #{gitlab.mr_json["iid"]} in #{gitlab.html_link(path)}. #{SEE_DOC}" message "Consider setting `merge_request` to #{gitlab.mr_json["iid"]} in #{gitlab.html_link(path)}. #{SEE_DOC}"
elsif yaml["merge_request"] != gitlab.mr_json["iid"] && !ce_port_changelog?(changelog_path) elsif yaml["merge_request"] != gitlab.mr_json["iid"] && !ce_port_changelog?(path)
fail "Merge request ID was not set to #{gitlab.mr_json["iid"]}! #{SEE_DOC}" fail "Merge request ID was not set to #{gitlab.mr_json["iid"]}! #{SEE_DOC}"
end end
rescue StandardError rescue Psych::SyntaxError, Psych::DisallowedClass, Psych::BadAlias
# YAML could not be parsed, fail the build. # YAML could not be parsed, fail the build.
fail "#{gitlab.html_link(path)} isn't valid YAML! #{SEE_DOC}" fail "#{gitlab.html_link(path)} isn't valid YAML! #{SEE_DOC}"
rescue StandardError => e
warn "There was a problem trying to check the Changelog. Exception: #{e.name} - #{e.message}"
end end
def presented_no_changelog_labels def presented_no_changelog_labels
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment