Commit bac4d96d authored by Nick Thomas's avatar Nick Thomas

Squash old migrations

Use the `squasher` gem to squash migrations older than 2018
parent d6a069fe
This diff is collapsed.
class FixNamespaces < ActiveRecord::Migration[4.2]
DOWNTIME = false
def up
namespaces = exec_query('SELECT id, path FROM namespaces WHERE name <> path and type is null')
namespaces.each do |row|
id = row['id']
path = row['path']
exec_query("UPDATE namespaces SET name = '#{path}' WHERE id = #{id}")
end
end
def down
end
end
class ChangeStateToAllowEmptyMergeRequestDiffs < ActiveRecord::Migration[4.2]
def up
change_column :merge_request_diffs, :state, :string, null: true,
default: nil
end
def down
change_column :merge_request_diffs, :state, :string, null: false,
default: 'collected'
end
end
# rubocop:disable all
class AddIndexOnIid < ActiveRecord::Migration[4.2]
def change
RemoveDuplicateIid.clean(Issue)
RemoveDuplicateIid.clean(MergeRequest, 'target_project_id')
RemoveDuplicateIid.clean(Milestone)
add_index :issues, [:project_id, :iid], unique: true
add_index :merge_requests, [:target_project_id, :iid], unique: true
add_index :milestones, [:project_id, :iid], unique: true
end
end
class RemoveDuplicateIid
def self.clean(klass, project_field = 'project_id')
duplicates = klass.find_by_sql("SELECT iid, #{project_field} FROM #{klass.table_name} GROUP BY #{project_field}, iid HAVING COUNT(*) > 1")
duplicates.each do |duplicate|
project_id = duplicate.send(project_field)
iid = duplicate.iid
items = klass.of_projects(project_id).where(iid: iid)
if items.size > 1
puts "Remove #{klass.name} duplicates for iid: #{iid} and project_id: #{project_id}"
items.shift
items.each do |item|
item.destroy
puts '.'
end
end
end
end
end
# rubocop:disable all
class IndexOnCurrentSignInAt < ActiveRecord::Migration[4.2]
def change
add_index :users, :current_sign_in_at
end
end
# rubocop:disable all
class AddNotesIndexUpdatedAt < ActiveRecord::Migration[4.2]
def change
add_index :notes, :updated_at
end
end
# rubocop:disable all
class AddRepoSizeToDb < ActiveRecord::Migration[4.2]
def change
add_column :projects, :repository_size, :float, default: 0
end
end
# rubocop:disable all
class MigrateRepoSize < ActiveRecord::Migration[4.2]
DOWNTIME = false
def up
project_data = execute('SELECT projects.id, namespaces.path AS namespace_path, projects.path AS project_path FROM projects LEFT JOIN namespaces ON projects.namespace_id = namespaces.id')
project_data.each do |project|
id = project['id']
namespace_path = project['namespace_path'] || ''
path = File.join(namespace_path, project['project_path'] + '.git')
begin
repo = Gitlab::Git::Repository.new('default', path, '', '')
if repo.empty?
print '-'
else
size = repo.size
print '.'
execute("UPDATE projects SET repository_size = #{size} WHERE id = #{id}")
end
rescue => e
puts "\nFailed to update project #{id}: #{e}"
end
end
puts "\nDone"
end
def down
end
end
# rubocop:disable all
class AddPositionToMergeRequest < ActiveRecord::Migration[4.2]
def change
add_column :merge_requests, :position, :integer, default: 0
end
end
# rubocop:disable all
class CreateUsersStarProjects < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
create_table :users_star_projects do |t|
t.integer :project_id, null: false
t.integer :user_id, null: false
t.timestamps null: true
end
add_index :users_star_projects, :user_id
add_index :users_star_projects, :project_id
add_index :users_star_projects, [:user_id, :project_id], unique: true
add_column :projects, :star_count, :integer, default: 0, null: false
add_index :projects, :star_count, using: :btree
end
end
# rubocop:disable all
class CreateLabels < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
create_table :labels do |t|
t.string :title
t.string :color
t.integer :project_id
t.timestamps null: true
end
end
end
# rubocop:disable all
class CreateLabelLinks < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
create_table :label_links do |t|
t.integer :label_id
t.integer :target_id
t.string :target_type
t.timestamps null: true
end
end
end
class MigrateProjectTags < ActiveRecord::Migration[4.2]
def up
ActsAsTaggableOn::Tagging.where(taggable_type: 'Project', context: 'labels').update_all(context: 'tags')
end
def down
ActsAsTaggableOn::Tagging.where(taggable_type: 'Project', context: 'tags').update_all(context: 'labels')
end
end
# rubocop:disable all
class MigrateTaggableLabels < ActiveRecord::Migration[4.2]
def up
taggings = ActsAsTaggableOn::Tagging.where(taggable_type: ['Issue', 'MergeRequest'], context: 'labels')
taggings.find_each(batch_size: 500) do |tagging|
# Clean up orphaned taggings while we are here
if tagging.taggable.blank? || tagging.tag.nil?
tagging.destroy
print 'D'
next
end
create_label_from_tagging(tagging)
end
end
def down
Label.destroy_all
LabelLink.destroy_all
end
private
def create_label_from_tagging(tagging)
target = tagging.taggable
label_name = tagging.tag.name
# '?', '&' and ',' are no longer allowed in label names so we remove them
label_name.tr!('?&,', '')
label = target.project.labels.find_or_create_by(title: label_name, color: Label::DEFAULT_COLOR)
if label.valid? && LabelLink.create(label: label, target: target)
print '.'
else
print 'F'
end
end
end
# rubocop:disable all
class AddIndexToLabels < ActiveRecord::Migration[4.2]
def change
add_index "labels", :project_id
add_index "label_links", :label_id
add_index "label_links", [:target_id, :target_type]
end
end
# rubocop:disable all
class MigrateToNewShell < ActiveRecord::Migration[4.2]
def change
return if Rails.env.test?
gitlab_shell_path = Gitlab.config.gitlab_shell.path
if system("#{gitlab_shell_path}/bin/create-hooks")
puts 'Repositories updated with new hooks'
else
raise 'Failed to rewrite gitlab-shell hooks in repositories'
end
end
end
# rubocop:disable all
class SerializeServiceProperties < ActiveRecord::Migration[4.2]
def change
unless column_exists?(:services, :properties)
add_column :services, :properties, :text
end
Service.reset_column_information
associations =
{
AssemblaService: [:token, :subdomain],
CampfireService: [:token, :subdomain, :room],
EmailsOnPushService: [:recipients],
FlowdockService: [:token],
GemnasiumService: [:api_key, :token],
GitlabCiService: [:token, :project_url],
HipchatService: [:token, :room],
PivotaltrackerService: [:token],
SlackService: [:subdomain, :token, :room],
JenkinsService: [:project_url],
JiraService: [:project_url, :username, :password,
:api_version, :jira_issue_transition_id],
}
Service.find_each(batch_size: 500).each do |service|
associations[service.type.to_sym].each do |attribute|
service.send("#{attribute}=", service.attributes[attribute.to_s])
end
service.save(validate: false)
end
if column_exists?(:services, :project_url)
remove_column :services, :project_url, :string
remove_column :services, :subdomain, :string
remove_column :services, :room, :string
remove_column :services, :recipients, :text
remove_column :services, :api_key, :string
remove_column :services, :token, :string
end
end
end
# rubocop:disable all
class AddMembersTable < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
create_table :members do |t|
t.integer :access_level, null: false
t.integer :source_id, null: false
t.string :source_type, null: false
t.integer :user_id, null: false
t.integer :notification_level, null: false
t.string :type
t.timestamps null: true
end
add_index :members, :type
add_index :members, :user_id
add_index :members, :access_level
add_index :members, [:source_id, :source_type]
end
end
# rubocop:disable all
class MigrateToNewMembersModel < ActiveRecord::Migration[4.2]
def up
execute "INSERT INTO members ( user_id, source_id, source_type, access_level, notification_level, type ) SELECT user_id, group_id, 'Namespace', group_access, notification_level, 'GroupMember' FROM users_groups"
execute "INSERT INTO members ( user_id, source_id, source_type, access_level, notification_level, type ) SELECT user_id, project_id, 'Project', project_access, notification_level, 'ProjectMember' FROM users_projects"
end
def down
Member.delete_all
end
end
# rubocop:disable all
class RemoveOldMemberTables < ActiveRecord::Migration[4.2]
DOWNTIME = false
def up
drop_table :users_groups
drop_table :users_projects
end
def down
create_table :users_groups do |t|
t.integer :group_access, null: false
t.integer :group_id, null: false
t.integer :user_id, null: false
t.integer :notification_level, null: false, default: 3
t.timestamps null: true
end
create_table :users_projects do |t|
t.integer :project_access, null: false
t.integer :project_id, null: false
t.integer :user_id, null: false
t.integer :notification_level, null: false, default: 3
t.timestamps null: true
end
end
end
# rubocop:disable all
class MoveSlackServiceToWebhook < ActiveRecord::Migration[4.2]
DOWNTIME = true
DOWNTIME_REASON = 'Move old fields "token" and "subdomain" to one single field "webhook"'
def change
SlackService.all.each do |slack_service|
if ["token", "subdomain"].all? { |property| slack_service.properties.key? property }
token = slack_service.properties['token']
subdomain = slack_service.properties['subdomain']
webhook = "https://#{subdomain}.slack.com/services/hooks/incoming-webhook?token=#{token}"
slack_service.properties['webhook'] = webhook
slack_service.properties.delete('token')
slack_service.properties.delete('subdomain')
# Room is configured on the Slack side
slack_service.properties.delete('room')
slack_service.save(validate: false)
end
end
end
end
# rubocop:disable all
class AddVisibilityLevelToSnippet < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
def up
add_column :snippets, :visibility_level, :integer, :default => 0, :null => false
execute("UPDATE snippets SET visibility_level = #{Gitlab::VisibilityLevel::PRIVATE} WHERE private = #{true_value}")
execute("UPDATE snippets SET visibility_level = #{Gitlab::VisibilityLevel::INTERNAL} WHERE private = #{false_value}")
add_index :snippets, :visibility_level
remove_column :snippets, :private
end
def down
add_column :snippets, :private, :boolean, :default => false, :null => false
execute("UPDATE snippets SET private = #{false_value} WHERE visibility_level = #{Gitlab::VisibilityLevel::INTERNAL}")
execute("UPDATE snippets SET private = #{true_value} WHERE visibility_level = #{Gitlab::VisibilityLevel::PRIVATE}")
remove_column :snippets, :visibility_level
end
end
# rubocop:disable all
class AddAuditEvent < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
create_table :audit_events do |t|
t.integer :author_id, null: false
t.string :type, null: false
# "Namespace" where the change occurs
# eg. On a project, group or user
t.integer :entity_id, null: false
t.string :entity_type, null: false
# Details for the event
t.text :details
t.timestamps null: true
end
add_index :audit_events, :author_id
add_index :audit_events, :type
add_index :audit_events, [:entity_id, :entity_type]
end
end
# In 20140914145549_migrate_to_new_members_model.rb we forgot to set the
# created_at and updated_at times for new records in the 'members' table. This
# became a problem after commit c8e78d972a5a628870eefca0f2ccea0199c55bda which
# was added in GitLab 7.5. With this migration we ensure that all rows in
# 'members' have at least some created_at and updated_at timestamp.
class AddTimestampsToMembers < ActiveRecord::Migration[4.2]
def up
execute "UPDATE members SET created_at = NOW() WHERE created_at is NULL"
execute "UPDATE members SET updated_at = NOW() WHERE updated_at is NULL"
end
def down
# no change
end
end
# rubocop:disable all
class AddIdentityTable < ActiveRecord::Migration[4.2]
def up
create_table :identities do |t|
t.string :extern_uid
t.string :provider
t.references :user
end
add_index :identities, :user_id
execute <<eos
INSERT INTO identities (provider, extern_uid, user_id)
SELECT provider, extern_uid, id FROM users
WHERE provider IS NOT NULL
eos
if index_exists?(:users, ["extern_uid", "provider"])
remove_index :users, ["extern_uid", "provider"]
end
remove_column :users, :extern_uid
remove_column :users, :provider
end
def down
add_column :users, :extern_uid, :string
add_column :users, :provider, :string
if ActiveRecord::Base.connection.adapter_name == 'PostgreSQL'
execute <<eos
UPDATE users u
SET provider = i.provider, extern_uid = i.extern_uid
FROM identities i
WHERE i.user_id = u.id
eos
else
execute "UPDATE users u, identities i SET u.provider = i.provider, u.extern_uid = i.extern_uid WHERE u.id = i.user_id"
end
drop_table :identities
unless index_exists?(:users, ["extern_uid", "provider"])
add_index "users", ["extern_uid", "provider"], name: "index_users_on_extern_uid_and_provider", unique: true, using: :btree
end
end
end
# rubocop:disable all
class AddMergeRequestRebaseEnabledToProjects < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
DOWNTIME = false
disable_ddl_transaction!
def up
add_column_with_default(:projects, :merge_requests_rebase_enabled, :boolean, default: false)
end
def down
remove_column(:projects, :merge_requests_rebase_enabled)
end
end
# rubocop:disable all
class AddLockedAtToMergeRequest < ActiveRecord::Migration[4.2]
def change
add_column :merge_requests, :locked_at, :datetime
end
end
# rubocop:disable all
class CreateDoorkeeperTables < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
create_table :oauth_applications do |t|
t.string :name, null: false
t.string :uid, null: false
t.string :secret, null: false
t.text :redirect_uri, null: false
t.string :scopes, null: false, default: ''
t.timestamps null: true
end
add_index :oauth_applications, :uid, unique: true
create_table :oauth_access_grants do |t|
t.integer :resource_owner_id, null: false
t.integer :application_id, null: false
t.string :token, null: false
t.integer :expires_in, null: false
t.text :redirect_uri, null: false
t.datetime :created_at, null: false
t.datetime :revoked_at
t.string :scopes
end
add_index :oauth_access_grants, :token, unique: true
create_table :oauth_access_tokens do |t|
t.integer :resource_owner_id
t.integer :application_id
t.string :token, null: false
t.string :refresh_token
t.integer :expires_in
t.datetime :revoked_at
t.datetime :created_at, null: false
t.string :scopes
end
add_index :oauth_access_tokens, :token, unique: true
add_index :oauth_access_tokens, :resource_owner_id
add_index :oauth_access_tokens, :refresh_token, unique: true
end
end
# rubocop:disable all
class AddOwnerToApplication < ActiveRecord::Migration[4.2]
def change
add_column :oauth_applications, :owner_id, :integer, null: true
add_column :oauth_applications, :owner_type, :string, null: true
add_index :oauth_applications, [:owner_id, :owner_type]
end
end
\ No newline at end of file
class AddImportDataToProjectTable < ActiveRecord::Migration[4.2]
def change
add_column :projects, :import_type, :string
add_column :projects, :import_source, :string
add_column :users, :github_access_token, :string
end
end
# rubocop:disable all
class AddDevelopersCanPushToProtectedBranches < ActiveRecord::Migration[4.2]
def change
add_column :protected_branches, :developers_can_push, :boolean, default: false, null: false
end
end
# rubocop:disable all
class CreateApplicationSettings < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
create_table :application_settings do |t|
t.integer :default_projects_limit
t.boolean :signup_enabled
t.boolean :signin_enabled
t.boolean :gravatar_enabled
t.text :sign_in_text
t.timestamps null: true
end
end
end
class AddHomePageUrlForApplicationSettings < ActiveRecord::Migration[4.2]
def change
add_column :application_settings, :home_page_url, :string
end
end
class AddGitlabAccessTokenToUser < ActiveRecord::Migration[4.2]
def change
add_column :users, :gitlab_access_token, :string
end
end
# rubocop:disable all
class AddDefaultBranchProtectionSetting < ActiveRecord::Migration[4.2]
def change
add_column :application_settings, :default_branch_protection, :integer, :default => 2
end
end
# rubocop:disable all
class AddTimestampsToIdentities < ActiveRecord::Migration[4.2]
def change
add_timestamps(:identities)
end
end
# rubocop:disable all
class AddIndexToCreatedAt < ActiveRecord::Migration[4.2]
def change
add_index "users", [:created_at, :id]
add_index "members", [:created_at, :id]
add_index "projects", [:created_at, :id]
add_index "issues", [:created_at, :id]
add_index "merge_requests", [:created_at, :id]
add_index "milestones", [:created_at, :id]
add_index "namespaces", [:created_at, :id]
add_index "notes", [:created_at, :id]
add_index "identities", [:created_at, :id]
add_index "keys", [:created_at, :id]
add_index "web_hooks", [:created_at, :id]
add_index "snippets", [:created_at, :id]
end
end
class AddNotificationEmailToUser < ActiveRecord::Migration[4.2]
def up
add_column :users, :notification_email, :string
execute "UPDATE users SET notification_email = email"
end
def down
remove_column :users, :notification_email
end
end
# rubocop:disable all
class AddMissingIndex < ActiveRecord::Migration[4.2]
def change
add_index "services", [:created_at, :id]
end
end
# rubocop:disable all
class AddTemplateToService < ActiveRecord::Migration[4.2]
def change
add_column :services, :template, :boolean, default: false
end
end
class AllowNullInServicesProjectId < ActiveRecord::Migration[4.2]
def change
change_column :services, :project_id, :integer, null: true
end
end
# rubocop:disable all
class AddTwitterSharingEnabledToApplicationSettings < ActiveRecord::Migration[4.2]
def change
add_column :application_settings, :twitter_sharing_enabled, :boolean, default: true
end
end
# rubocop:disable all
class AddHideNoPasswordToUser < ActiveRecord::Migration[4.2]
def change
add_column :users, :hide_no_password, :boolean, default: false
end
end
# rubocop:disable all
class AddPasswordAutomaticallySetToUser < ActiveRecord::Migration[4.2]
def change
add_column :users, :password_automatically_set, :boolean, default: false
end
end
class AddBitbucketAccessTokenAndSecretToUser < ActiveRecord::Migration[4.2]
def change
add_column :users, :bitbucket_access_token, :string
add_column :users, :bitbucket_access_token_secret, :string
end
end
# rubocop:disable all
class AddEventsToServices < ActiveRecord::Migration[4.2]
def change
add_column :services, :push_events, :boolean, :default => true
add_column :services, :issues_events, :boolean, :default => true
add_column :services, :merge_requests_events, :boolean, :default => true
add_column :services, :tag_push_events, :boolean, :default => true
end
end
class SetMissingLastActivityAt < ActiveRecord::Migration[4.2]
def up
execute "UPDATE projects SET last_activity_at = updated_at WHERE last_activity_at IS NULL"
end
def down
end
end
# rubocop:disable all
class AddNoteEventsToServices < ActiveRecord::Migration[4.2]
def change
add_column :services, :note_events, :boolean, default: true, null: false
end
end
class AddRestrictedVisibilityLevelsToApplicationSettings < ActiveRecord::Migration[4.2]
def change
add_column :application_settings, :restricted_visibility_levels, :text
end
end
# rubocop:disable all
class FixNamespaceDuplication < ActiveRecord::Migration[4.2]
def up
#fixes path duplication
select_all('SELECT MAX(id) max, COUNT(id) cnt, path FROM namespaces GROUP BY path HAVING COUNT(id) > 1').each do |nms|
bad_nms_ids = select_all("SELECT id FROM namespaces WHERE path = '#{nms['path']}' AND id <> #{nms['max']}").map{|x| x["id"]}
execute("UPDATE projects SET namespace_id = #{nms["max"]} WHERE namespace_id IN(#{bad_nms_ids.join(', ')})")
execute("DELETE FROM namespaces WHERE id IN(#{bad_nms_ids.join(', ')})")
end
#fixes name duplication
select_all('SELECT MAX(id) max, COUNT(id) cnt, name FROM namespaces GROUP BY name HAVING COUNT(id) > 1').each do |nms|
bad_nms_ids = select_all("SELECT id FROM namespaces WHERE name = '#{nms['name']}' AND id <> #{nms['max']}").map{|x| x["id"]}
execute("UPDATE projects SET namespace_id = #{nms["max"]} WHERE namespace_id IN(#{bad_nms_ids.join(', ')})")
execute("DELETE FROM namespaces WHERE id IN(#{bad_nms_ids.join(', ')})")
end
end
def down
# not implemented
end
end
# rubocop:disable all
class AddUniqueIndexToNamespace < ActiveRecord::Migration[4.2]
def change
remove_index :namespaces, column: :name if index_exists?(:namespaces, :name)
remove_index :namespaces, column: :path if index_exists?(:namespaces, :path)
add_index :namespaces, :name, unique: true
add_index :namespaces, :path, unique: true
end
end
# rubocop:disable all
class AddVersionCheckToApplicationSettings < ActiveRecord::Migration[4.2]
def change
add_column :application_settings, :version_check_enabled, :boolean, default: true
end
end
# rubocop:disable all
class CreateSubscriptionsTable < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
create_table :subscriptions do |t|
t.integer :user_id
t.references :subscribable, polymorphic: true
t.boolean :subscribed
t.timestamps null: true
end
add_index :subscriptions,
[:subscribable_id, :subscribable_type, :user_id],
unique: true,
name: 'subscriptions_user_id_and_ref_fields'
end
end
class AddLocationToUser < ActiveRecord::Migration[4.2]
def change
add_column :users, :location, :string
end
end
class SetIncorrectAssigneeIdToNull < ActiveRecord::Migration[4.2]
def up
execute "UPDATE issues SET assignee_id = NULL WHERE assignee_id = -1"
execute "UPDATE merge_requests SET assignee_id = NULL WHERE assignee_id = -1"
end
end
# rubocop:disable all
class AddPublicToKey < ActiveRecord::Migration[4.2]
def change
add_column :keys, :public, :boolean, default: false, null: false
end
end
class AddImportDataToProject < ActiveRecord::Migration[4.2]
def change
add_column :projects, :import_data, :text
end
end
class AddDeviseTwoFactorToUsers < ActiveRecord::Migration[4.2]
def change
add_column :users, :encrypted_otp_secret, :string
add_column :users, :encrypted_otp_secret_iv, :string
add_column :users, :encrypted_otp_secret_salt, :string
add_column :users, :otp_required_for_login, :boolean
end
end
class AddMaxAttachmentSizeToApplicationSettings < ActiveRecord::Migration[4.2]
def change
add_column :application_settings, :max_attachment_size, :integer, default: 10, null: false
end
end
class AddDeviseTwoFactorBackupableToUsers < ActiveRecord::Migration[4.2]
def change
add_column :users, :otp_backup_codes, :text
end
end
# rubocop:disable all
class AddInviteDataToMember < ActiveRecord::Migration[4.2]
def up
add_column :members, :created_by_id, :integer
add_column :members, :invite_email, :string
add_column :members, :invite_token, :string
add_column :members, :invite_accepted_at, :datetime
change_column :members, :user_id, :integer, null: true
add_index :members, :invite_token, unique: true
end
def down
remove_index :members, :invite_token
change_column :members, :user_id, :integer, null: false
remove_column :members, :invite_accepted_at
remove_column :members, :invite_token
remove_column :members, :invite_email
remove_column :members, :created_by_id
end
end
class FixIdentities < ActiveRecord::Migration[4.2]
def up
# Up until now, legacy 'ldap' references in the database were charitably
# interpreted to point to the first LDAP server specified in the GitLab
# configuration. So if the database said 'provider: ldap' but the first
# LDAP server was called 'ldapmain', then we would try to interpret
# 'provider: ldap' as if it said 'provider: ldapmain'. This migration (and
# accompanying changes in the GitLab LDAP code) get rid of this complicated
# behavior. Any database references to 'provider: ldap' get rewritten to
# whatever the code would have interpreted it as, i.e. as a reference to
# the first LDAP server specified in gitlab.yml / gitlab.rb.
new_provider = if Gitlab.config.ldap.enabled
first_ldap_server = Gitlab.config.ldap.servers.values.first
first_ldap_server['provider_name']
else
'ldapmain'
end
# Delete duplicate identities
# We use a sort of self-join to find rows in identities which match on
# user_id but where one has provider 'ldap'. We delete the duplicate row
# with provider 'ldap'.
delete_statement = ''
case adapter_name.downcase
when /^mysql/
delete_statement << 'DELETE FROM id1 USING identities AS id1, identities AS id2'
when 'postgresql'
delete_statement << 'DELETE FROM identities AS id1 USING identities AS id2'
else
raise "Unknown DB adapter: #{adapter_name}"
end
delete_statement << " WHERE id1.user_id = id2.user_id AND id1.provider = 'ldap' AND id2.provider = '#{new_provider}'"
execute delete_statement
# Update legacy identities
execute "UPDATE identities SET provider = '#{new_provider}' WHERE provider = 'ldap'"
if table_exists?('ldap_group_links')
execute "UPDATE ldap_group_links SET provider = '#{new_provider}' WHERE provider IS NULL OR provider = 'ldap'"
end
end
def down
end
end
class RenameBuildboxService < ActiveRecord::Migration[4.2]
def up
execute "UPDATE services SET type = 'BuildkiteService' WHERE type = 'BuildboxService';"
end
def down
execute "UPDATE services SET type = 'BuildboxService' WHERE type = 'BuildkiteService';"
end
end
# rubocop:disable all
class AddPublicEmailToUsers < ActiveRecord::Migration[4.2]
def change
add_column :users, :public_email, :string, default: "", null: false
end
end
class CreateProjectImportData < ActiveRecord::Migration[4.2]
def change
create_table :project_import_data do |t|
t.references :project
t.text :data
end
end
end
# rubocop:disable all
class RemoveImportDataFromProject < ActiveRecord::Migration[4.2]
def up
remove_column :projects, :import_data
end
def down
add_column :projects, :import_data, :text
end
end
# rubocop:disable all
class RemovePeriodsAtEndsOfUsernames < ActiveRecord::Migration[4.2]
include Gitlab::ShellAdapter
class Namespace < ActiveRecord::Base
class << self
def find_by_path_or_name(path)
find_by("lower(path) = :path OR lower(name) = :path", path: path.downcase)
end
def clean_path(path)
path = path.dup
# Get the email username by removing everything after an `@` sign.
path.gsub!(/@.*\z/, "")
# Usernames can't end in .git, so remove it.
path.gsub!(/\.git\z/, "")
# Remove dashes at the start of the username.
path.gsub!(/\A-+/, "")
# Remove periods at the end of the username.
path.gsub!(/\.+\z/, "")
# Remove everything that's not in the list of allowed characters.
path.gsub!(/[^a-zA-Z0-9_\-\.]/, "")
# Users with the great usernames of "." or ".." would end up with a blank username.
# Work around that by setting their username to "blank", followed by a counter.
path = "blank" if path.blank?
counter = 0
base = path
while Namespace.find_by_path_or_name(path)
counter += 1
path = "#{base}#{counter}"
end
path
end
end
end
def up
changed_paths = {}
select_all("SELECT id, username FROM users WHERE username LIKE '%.'").each do |user|
username_was = user["username"]
username = Namespace.clean_path(username_was)
changed_paths[username_was] = username
username = quote_string(username)
execute "UPDATE users SET username = '#{username}' WHERE id = #{user["id"]}"
execute "UPDATE namespaces SET path = '#{username}', name = '#{username}' WHERE type IS NULL AND owner_id = #{user["id"]}"
end
select_all("SELECT id, path FROM namespaces WHERE type = 'Group' AND path LIKE '%.'").each do |group|
path_was = group["path"]
path = Namespace.clean_path(path_was)
changed_paths[path_was] = path
path = quote_string(path)
execute "UPDATE namespaces SET path = '#{path}' WHERE id = #{group["id"]}"
end
changed_paths.each do |path_was, path|
# Don't attempt to move if original path only contains periods.
next if path_was =~ /\A\.+\z/
if gitlab_shell.mv_namespace(path_was, path)
# If repositories moved successfully we need to remove old satellites
# and send update instructions to users.
# However we cannot allow rollback since we moved namespace dir
# So we basically we mute exceptions in next actions
begin
gitlab_shell.rm_satellites(path_was)
# We cannot send update instructions since models and mailers
# can't safely be used from migrations as they may be written for
# later versions of the database.
# send_update_instructions
rescue
# Returning false does not rollback after_* transaction but gives
# us information about failing some of tasks
false
end
else
# if we cannot move namespace directory we should rollback
# db changes in order to prevent out of sync between db and fs
raise Exception.new('namespace directory cannot be moved')
end
end
end
end
class AddDefaultProjectVisibililtyToApplicationSettings < ActiveRecord::Migration[4.2]
def up
add_column :application_settings, :default_project_visibility, :integer
visibility = Settings.gitlab.default_projects_features['visibility_level']
execute("update application_settings set default_project_visibility = #{visibility}")
end
def down
remove_column :application_settings, :default_project_visibility
end
end
# This migration is a duplicate of 20150425164651_change_collation_for_tag_names.acts_as_taggable_on_engine.rb
# It shold be applied before the index additions to ensure that `name` is case sensitive.
class GitlabChangeCollationForTagNames < ActiveRecord::Migration[4.2]
def up
if ActsAsTaggableOn::Utils.using_mysql?
execute("ALTER TABLE tags MODIFY name varchar(255) CHARACTER SET utf8 COLLATE utf8_bin;")
end
end
end
# rubocop:disable all
class RemoveDuplicateTags < ActiveRecord::Migration[4.2]
def up
select_all("SELECT name, COUNT(id) as cnt FROM tags GROUP BY name HAVING COUNT(id) > 1").each do |tag|
tag_name = quote_string(tag["name"])
duplicate_ids = select_all("SELECT id FROM tags WHERE name = '#{tag_name}'").map{|tag| tag["id"]}
origin_tag_id = duplicate_ids.first
duplicate_ids.delete origin_tag_id
execute("UPDATE taggings SET tag_id = #{origin_tag_id} WHERE tag_id IN(#{duplicate_ids.join(",")})")
execute("DELETE FROM tags WHERE id IN(#{duplicate_ids.join(",")})")
end
end
def down
end
end
# rubocop:disable all
# This migration comes from acts_as_taggable_on_engine (originally 2)
class AddMissingUniqueIndices < ActiveRecord::Migration[4.2]
def self.up
add_index :tags, :name, unique: true
# pre-GitLab v6.7.0 may not have these indices since there were no
# migrations for them
if index_exists?(:taggings, :tag_id)
remove_index :taggings, :tag_id
end
if index_exists?(:taggings, [:taggable_id, :taggable_type, :context])
remove_index :taggings, [:taggable_id, :taggable_type, :context]
end
add_index :taggings,
[:tag_id, :taggable_id, :taggable_type, :context, :tagger_id, :tagger_type],
unique: true, name: 'taggings_idx'
end
def self.down
remove_index :tags, :name
remove_index :taggings, name: 'taggings_idx'
add_index :taggings, :tag_id
add_index :taggings, [:taggable_id, :taggable_type, :context]
end
end
# rubocop:disable all
# This migration comes from acts_as_taggable_on_engine (originally 3)
class AddTaggingsCounterCacheToTags < ActiveRecord::Migration[4.2]
def self.up
add_column :tags, :taggings_count, :integer, default: 0
ActsAsTaggableOn::Tag.reset_column_information
ActsAsTaggableOn::Tag.find_each do |tag|
ActsAsTaggableOn::Tag.reset_counters(tag.id, :taggings)
end
end
def self.down
remove_column :tags, :taggings_count
end
end
# This migration comes from acts_as_taggable_on_engine (originally 4)
class AddMissingTaggableIndex < ActiveRecord::Migration[4.2]
def self.up
add_index :taggings, [:taggable_id, :taggable_type, :context]
end
def self.down
remove_index :taggings, [:taggable_id, :taggable_type, :context]
end
end
# This migration comes from acts_as_taggable_on_engine (originally 5)
# This migration is added to circumvent issue #623 and have special characters
# work properly
class ChangeCollationForTagNames < ActiveRecord::Migration[4.2]
def up
if ActsAsTaggableOn::Utils.using_mysql?
execute("ALTER TABLE tags MODIFY name varchar(255) CHARACTER SET utf8 COLLATE utf8_bin;")
end
end
end
class AddDefaultSnippetVisibilityToAppSettings < ActiveRecord::Migration[4.2]
def up
add_column :application_settings, :default_snippet_visibility, :integer
visibility = Settings.gitlab.default_projects_features['visibility_level']
execute("update application_settings set default_snippet_visibility = #{visibility}")
end
def down
remove_column :application_settings, :default_snippet_visibility
end
end
class RemoveAbandonedGroupMembersRecords < ActiveRecord::Migration[4.2]
def up
execute("DELETE FROM members WHERE type = 'GroupMember' AND source_id NOT IN(\
SELECT id FROM namespaces WHERE type='Group')")
end
def down
end
end
class AddRestrictedSignupDomainsToApplicationSettings < ActiveRecord::Migration[4.2]
def change
add_column :application_settings, :restricted_signup_domains, :text
end
end
# Convert legacy Markdown-emphasized notes to the current, non-emphasized format
#
# _mentioned in 54f7727c850972f0401c1312a7c4a6a380de5666_
#
# becomes
#
# mentioned in 54f7727c850972f0401c1312a7c4a6a380de5666
class ConvertLegacyReferenceNotes < ActiveRecord::Migration[4.2]
def up
quoted_column_name = ActiveRecord::Base.connection.quote_column_name('system')
execute %Q{UPDATE notes SET note = trim(both '_' from note) WHERE #{quoted_column_name} = true AND note LIKE '\_%\_'}
end
def down
# noop
end
end
# rubocop:disable all
class AddNoteEventsToWebHooks < ActiveRecord::Migration[4.2]
def up
add_column :web_hooks, :note_events, :boolean, default: false, null: false
end
def down
remove_column :web_hooks, :note_events, :boolean
end
end
class AddUserOauthApplicationsToApplicationSettings < ActiveRecord::Migration[4.2]
def change
add_column :application_settings, :user_oauth_applications, :bool, default: true
end
end
# rubocop:disable all
class AddAfterSignOutPathForApplicationSettings < ActiveRecord::Migration[4.2]
def change
add_column :application_settings, :after_sign_out_path, :string
end
end
\ No newline at end of file
class AddSessionExpireDelayForApplicationSettings < ActiveRecord::Migration[4.2]
def change
unless column_exists?(:application_settings, :session_expire_delay)
add_column :application_settings, :session_expire_delay, :integer, default: 10080, null: false
end
end
end
# rubocop:disable all
class AddDashboardToUsers < ActiveRecord::Migration[4.2]
def up
add_column :users, :dashboard, :integer, default: 0
end
def down
remove_column :users, :dashboard
end
end
class AddDefaultOtpRequiredForLoginValue < ActiveRecord::Migration[4.2]
def up
execute %q{UPDATE users SET otp_required_for_login = FALSE WHERE otp_required_for_login IS NULL}
change_column :users, :otp_required_for_login, :boolean, default: false, null: false
end
def down
change_column :users, :otp_required_for_login, :boolean, null: true
end
end
# rubocop:disable all
class AddProjectViewToUsers < ActiveRecord::Migration[4.2]
def change
add_column :users, :project_view, :integer, default: 0
end
end
# rubocop:disable all
class AddCommitsCountToProject < ActiveRecord::Migration[4.2]
def change
add_column :projects, :commit_count, :integer, default: 0
end
end
class AddUpdatedByToIssuablesAndNotes < ActiveRecord::Migration[4.2]
def change
add_column :notes, :updated_by_id, :integer
add_column :issues, :updated_by_id, :integer
add_column :merge_requests, :updated_by_id, :integer
end
end
# rubocop:disable all
class CreateAbuseReports < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
create_table :abuse_reports do |t|
t.integer :reporter_id
t.integer :user_id
t.text :message
t.timestamps null: true
end
end
end
# rubocop:disable all
require 'yaml'
class AddSettingsImportSources < ActiveRecord::Migration[4.2]
def change
unless column_exists?(:application_settings, :import_sources)
add_column :application_settings, :import_sources, :text
import_sources = YAML::dump(Settings.gitlab['import_sources'])
execute("update application_settings set import_sources = '#{import_sources}'")
end
end
end
# rubocop:disable all
class RemoveOauthTokensFromUsers < ActiveRecord::Migration[4.2]
def change
remove_column :users, :github_access_token, :string
remove_column :users, :gitlab_access_token, :string
remove_column :users, :bitbucket_access_token, :string
remove_column :users, :bitbucket_access_token_secret, :string
end
end
# rubocop:disable all
class DeduplicateUserIdentities < ActiveRecord::Migration[4.2]
def change
execute 'DROP TABLE IF EXISTS tt_migration_DeduplicateUserIdentities;'
execute 'CREATE TABLE tt_migration_DeduplicateUserIdentities AS SELECT id,provider,user_id FROM identities;'
execute 'DELETE FROM identities WHERE id NOT IN ( SELECT MIN(id) FROM tt_migration_DeduplicateUserIdentities GROUP BY user_id, provider);'
execute 'DROP TABLE IF EXISTS tt_migration_DeduplicateUserIdentities;'
end
def down
# This is an irreversible migration;
# If someone is trying to rollback for other reasons, we should not throw an Exception.
# raise ActiveRecord::IrreversibleMigration
end
end
class AddSentNotifications < ActiveRecord::Migration[4.2]
def change
create_table :sent_notifications do |t|
t.references :project
t.references :noteable, polymorphic: true
t.references :recipient
t.string :commit_id
t.string :reply_key, null: false
end
add_index :sent_notifications, :reply_key, unique: true
end
end
# rubocop:disable all
class AddEnableSslVerification < ActiveRecord::Migration[4.2]
def change
add_column :web_hooks, :enable_ssl_verification, :boolean, default: false
end
end
# rubocop:disable all
class AddCiTables < ActiveRecord::Migration[4.2]
def change
create_table "ci_application_settings", force: true do |t|
t.boolean "all_broken_builds"
t.boolean "add_pusher"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "ci_builds", force: true do |t|
t.integer "project_id"
t.string "status"
t.datetime "finished_at"
t.text "trace"
t.datetime "created_at"
t.datetime "updated_at"
t.datetime "started_at"
t.integer "runner_id"
t.float "coverage"
t.integer "commit_id"
t.text "commands"
t.integer "job_id"
t.string "name"
t.boolean "deploy", default: false
t.text "options"
t.boolean "allow_failure", default: false, null: false
t.string "stage"
t.integer "trigger_request_id"
end
add_index "ci_builds", ["commit_id"], name: "index_ci_builds_on_commit_id", using: :btree
add_index "ci_builds", ["project_id", "commit_id"], name: "index_ci_builds_on_project_id_and_commit_id", using: :btree
add_index "ci_builds", ["project_id"], name: "index_ci_builds_on_project_id", using: :btree
add_index "ci_builds", ["runner_id"], name: "index_ci_builds_on_runner_id", using: :btree
create_table "ci_commits", force: true do |t|
t.integer "project_id"
t.string "ref"
t.string "sha"
t.string "before_sha"
t.text "push_data"
t.datetime "created_at"
t.datetime "updated_at"
t.boolean "tag", default: false
t.text "yaml_errors"
t.datetime "committed_at"
end
add_index "ci_commits", ["project_id", "committed_at"], name: "index_ci_commits_on_project_id_and_committed_at", using: :btree
add_index "ci_commits", ["project_id", "sha"], name: "index_ci_commits_on_project_id_and_sha", using: :btree
add_index "ci_commits", ["project_id"], name: "index_ci_commits_on_project_id", using: :btree
add_index "ci_commits", ["sha"], name: "index_ci_commits_on_sha", using: :btree
create_table "ci_events", force: true do |t|
t.integer "project_id"
t.integer "user_id"
t.integer "is_admin"
t.text "description"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "ci_events", ["created_at"], name: "index_ci_events_on_created_at", using: :btree
add_index "ci_events", ["is_admin"], name: "index_ci_events_on_is_admin", using: :btree
add_index "ci_events", ["project_id"], name: "index_ci_events_on_project_id", using: :btree
create_table "ci_jobs", force: true do |t|
t.integer "project_id", null: false
t.text "commands"
t.boolean "active", default: true, null: false
t.datetime "created_at"
t.datetime "updated_at"
t.string "name"
t.boolean "build_branches", default: true, null: false
t.boolean "build_tags", default: false, null: false
t.string "job_type", default: "parallel"
t.string "refs"
t.datetime "deleted_at"
end
add_index "ci_jobs", ["deleted_at"], name: "index_ci_jobs_on_deleted_at", using: :btree
add_index "ci_jobs", ["project_id"], name: "index_ci_jobs_on_project_id", using: :btree
create_table "ci_projects", force: true do |t|
t.string "name", null: false
t.integer "timeout", default: 3600, null: false
t.datetime "created_at"
t.datetime "updated_at"
t.string "token"
t.string "default_ref"
t.string "path"
t.boolean "always_build", default: false, null: false
t.integer "polling_interval"
t.boolean "public", default: false, null: false
t.string "ssh_url_to_repo"
t.integer "gitlab_id"
t.boolean "allow_git_fetch", default: true, null: false
t.string "email_recipients", default: "", null: false
t.boolean "email_add_pusher", default: true, null: false
t.boolean "email_only_broken_builds", default: true, null: false
t.string "skip_refs"
t.string "coverage_regex"
t.boolean "shared_runners_enabled", default: false
t.text "generated_yaml_config"
end
create_table "ci_runner_projects", force: true do |t|
t.integer "runner_id", null: false
t.integer "project_id", null: false
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "ci_runner_projects", ["project_id"], name: "index_ci_runner_projects_on_project_id", using: :btree
add_index "ci_runner_projects", ["runner_id"], name: "index_ci_runner_projects_on_runner_id", using: :btree
create_table "ci_runners", force: true do |t|
t.string "token"
t.datetime "created_at"
t.datetime "updated_at"
t.string "description"
t.datetime "contacted_at"
t.boolean "active", default: true, null: false
t.boolean "is_shared", default: false
t.string "name"
t.string "version"
t.string "revision"
t.string "platform"
t.string "architecture"
end
create_table "ci_services", force: true do |t|
t.string "type"
t.string "title"
t.integer "project_id", null: false
t.datetime "created_at"
t.datetime "updated_at"
t.boolean "active", default: false, null: false
t.text "properties"
end
add_index "ci_services", ["project_id"], name: "index_ci_services_on_project_id", using: :btree
create_table "ci_sessions", force: true do |t|
t.string "session_id", null: false
t.text "data"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "ci_sessions", ["session_id"], name: "index_ci_sessions_on_session_id", using: :btree
add_index "ci_sessions", ["updated_at"], name: "index_ci_sessions_on_updated_at", using: :btree
create_table "ci_trigger_requests", force: true do |t|
t.integer "trigger_id", null: false
t.text "variables"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "commit_id"
end
create_table "ci_triggers", force: true do |t|
t.string "token"
t.integer "project_id", null: false
t.datetime "deleted_at"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "ci_triggers", ["deleted_at"], name: "index_ci_triggers_on_deleted_at", using: :btree
create_table "ci_variables", force: true do |t|
t.integer "project_id", null: false
t.string "key"
t.text "value"
t.text "encrypted_value"
t.string "encrypted_value_salt"
t.string "encrypted_value_iv"
end
add_index "ci_variables", ["project_id"], name: "index_ci_variables_on_project_id", using: :btree
create_table "ci_web_hooks", force: true do |t|
t.string "url", null: false
t.integer "project_id", null: false
t.datetime "created_at"
t.datetime "updated_at"
end
end
end
# rubocop:disable all
class AddFastForwardOptionToProject < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
DOWNTIME = false
disable_ddl_transaction!
def up
# We put condition here because of a mistake we made a couple of years ago
# see https://gitlab.com/gitlab-org/gitlab-ce/issues/39382#note_45716103
unless column_exists?(:projects, :merge_requests_ff_only_enabled)
add_column_with_default(:projects, :merge_requests_ff_only_enabled, :boolean, default: false)
end
end
def down
if column_exists?(:projects, :merge_requests_ff_only_enabled)
remove_column(:projects, :merge_requests_ff_only_enabled)
end
end
end
# rubocop:disable all
class AddTemplateToLabel < ActiveRecord::Migration[4.2]
def change
add_column :labels, :template, :boolean, default: false
end
end
\ No newline at end of file
# rubocop:disable all
class AddCiTags < ActiveRecord::Migration[4.2]
def change
create_table "ci_taggings", force: true do |t|
t.integer "tag_id"
t.integer "taggable_id"
t.string "taggable_type"
t.integer "tagger_id"
t.string "tagger_type"
t.string "context", limit: 128
t.datetime "created_at"
end
add_index "ci_taggings", ["tag_id", "taggable_id", "taggable_type", "context", "tagger_id", "tagger_type"], name: "ci_taggings_idx", unique: true, using: :btree
add_index "ci_taggings", ["taggable_id", "taggable_type", "context"], name: "index_ci_taggings_on_taggable_id_and_taggable_type_and_context", using: :btree
create_table "ci_tags", force: true do |t|
t.string "name"
t.integer "taggings_count", default: 0
end
add_index "ci_tags", ["name"], name: "index_ci_tags_on_name", unique: true, using: :btree
end
end
class EnableSslVerificationByDefault < ActiveRecord::Migration[4.2]
def change
change_column :web_hooks, :enable_ssl_verification, :boolean, default: true
end
end
class EnableSslVerificationForWebHooks < ActiveRecord::Migration[4.2]
def up
execute("UPDATE web_hooks SET enable_ssl_verification = true")
end
def down
end
end
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.
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.
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.
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.
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