Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Jérome Perrin
gitlab-ce
Commits
9e6fa996
Commit
9e6fa996
authored
Aug 04, 2017
by
Gabriel Mazetto
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
New storage is now "Hashed" instead of "UUID"
parent
53403399
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
203 additions
and
88 deletions
+203
-88
app/models/concerns/storage/hashed_project.rb
app/models/concerns/storage/hashed_project.rb
+19
-5
app/models/concerns/storage/legacy_project.rb
app/models/concerns/storage/legacy_project.rb
+11
-1
app/models/project.rb
app/models/project.rb
+5
-3
db/migrate/20170802013652_add_storage_fields_to_project.rb
db/migrate/20170802013652_add_storage_fields_to_project.rb
+2
-22
db/schema.rb
db/schema.rb
+2
-3
lib/gitlab/import_export/import_export.yml
lib/gitlab/import_export/import_export.yml
+1
-0
spec/factories/projects.rb
spec/factories/projects.rb
+4
-0
spec/models/project_spec.rb
spec/models/project_spec.rb
+159
-54
No files found.
app/models/concerns/storage/
uui
d_project.rb
→
app/models/concerns/storage/
hashe
d_project.rb
View file @
9e6fa996
module
Storage
module
Storage
module
UUID
Project
module
Hashed
Project
extend
ActiveSupport
::
Concern
extend
ActiveSupport
::
Concern
def
uuid_dir
# Base directory
%Q(
#{
uuid
[
0
..
1
]
}
/
#{
uuid
[
2
..
3
]
}
)
#
# @return [String] directory where repository is stored
def
base_dir
%Q(
#{
disk_hash
[
0
..
1
]
}
/
#{
disk_hash
[
2
..
3
]
}
)
if
disk_hash
end
end
# Disk path is used to build repository and project's wiki path on disk
#
# @return [String] combination of base_dir and the repository own name without `.git` or `.wiki.git` extensions
def
disk_path
def
disk_path
%Q(
#{
uuid_dir
}
/
#{
uuid
}
)
%Q(
#{
base_dir
}
/
#{
disk_hash
}
)
end
end
def
ensure_storage_path_exist
def
ensure_storage_path_exist
gitlab_shell
.
add_namespace
(
repository_storage_path
,
uuid
_dir
)
gitlab_shell
.
add_namespace
(
repository_storage_path
,
base
_dir
)
end
end
def
rename_repo
def
rename_repo
...
@@ -54,5 +60,13 @@ module Storage
...
@@ -54,5 +60,13 @@ module Storage
Gitlab
::
UploadsTransfer
.
new
.
rename_project
(
path_was
,
path
,
namespace
.
full_path
)
Gitlab
::
UploadsTransfer
.
new
.
rename_project
(
path_was
,
path
,
namespace
.
full_path
)
Gitlab
::
PagesTransfer
.
new
.
rename_project
(
path_was
,
path
,
namespace
.
full_path
)
Gitlab
::
PagesTransfer
.
new
.
rename_project
(
path_was
,
path
,
namespace
.
full_path
)
end
end
private
# Generates the hash for the project path and name on disk
# If you need to refer to the repository on disk, use the `#disk_path`
def
disk_hash
@disk_hash
||=
Digest
::
SHA2
.
hexdigest
(
self
.
id
.
to_s
)
if
self
.
id
end
end
end
end
end
app/models/concerns/storage/legacy_project.rb
View file @
9e6fa996
...
@@ -2,12 +2,22 @@ module Storage
...
@@ -2,12 +2,22 @@ module Storage
module
LegacyProject
module
LegacyProject
extend
ActiveSupport
::
Concern
extend
ActiveSupport
::
Concern
# Base directory
#
# @return [String] directory where repository is stored
def
base_dir
namespace
.
full_path
end
# Disk path is used to build repository and project's wiki path on disk
#
# @return [String] combination of base_dir and the repository own name without `.git` or `.wiki.git` extensions
def
disk_path
def
disk_path
full_path
full_path
end
end
def
ensure_storage_path_exist
def
ensure_storage_path_exist
gitlab_shell
.
add_namespace
(
repository_storage_path
,
namespace
.
full_path
)
gitlab_shell
.
add_namespace
(
repository_storage_path
,
base_dir
)
end
end
def
rename_repo
def
rename_repo
...
...
app/models/project.rb
View file @
9e6fa996
...
@@ -1424,10 +1424,12 @@ class Project < ActiveRecord::Base
...
@@ -1424,10 +1424,12 @@ class Project < ActiveRecord::Base
private
private
def
load_storage
def
load_storage
if
self
.
storage_version
>
1
return
unless
has_attribute?
(
:storage_version
)
self
.
class
.
include
Storage
::
UUIDProject
if
self
.
storage_version
&&
self
.
storage_version
>=
1
self
.
extend
Storage
::
HashedProject
else
else
self
.
class
.
include
Storage
::
LegacyProject
self
.
extend
Storage
::
LegacyProject
end
end
end
end
...
...
db/migrate/20170802013652_add_storage_fields_to_project.rb
View file @
9e6fa996
...
@@ -4,36 +4,16 @@
...
@@ -4,36 +4,16 @@
class
AddStorageFieldsToProject
<
ActiveRecord
::
Migration
class
AddStorageFieldsToProject
<
ActiveRecord
::
Migration
include
Gitlab
::
Database
::
MigrationHelpers
include
Gitlab
::
Database
::
MigrationHelpers
# Set this constant to true if this migration requires downtime.
DOWNTIME
=
false
DOWNTIME
=
false
# When a migration requires downtime you **must** uncomment the following
# constant and define a short and easy to understand explanation as to why the
# migration requires downtime.
# DOWNTIME_REASON = ''
# When using the methods "add_concurrent_index", "remove_concurrent_index" or
# "add_column_with_default" you must disable the use of transactions
# as these methods can not run in an existing transaction.
# When using "add_concurrent_index" or "remove_concurrent_index" methods make sure
# that either of them is the _only_ method called in the migration,
# any other changes should go in a separate migration.
# This ensures that upon failure _only_ the index creation or removing fails
# and can be retried or reverted easily.
#
# To disable transactions uncomment the following line and remove these
# comments:
disable_ddl_transaction!
disable_ddl_transaction!
def
up
def
up
# rubocop:disable Migration/AddColumnWithDefaultToLargeTable
# rubocop:disable Migration/AddColumnWithDefaultToLargeTable
add_column
:projects
,
:uuid
,
:uuid
add_column
:projects
,
:storage_version
,
:integer
,
limit:
2
add_column_with_default
:projects
,
:storage_version
,
:integer
,
default:
0
,
limit:
1
add_concurrent_index
:projects
,
:storage_version
add_concurrent_index
:projects
,
:uuid
end
end
def
down
def
down
remove_column
:projects
,
:uuid
remove_column
:projects
,
:storage_version
remove_column
:projects
,
:storage_version
end
end
end
end
db/schema.rb
View file @
9e6fa996
...
@@ -1208,8 +1208,7 @@ ActiveRecord::Schema.define(version: 20170820100558) do
...
@@ -1208,8 +1208,7 @@ ActiveRecord::Schema.define(version: 20170820100558) do
t
.
datetime
"last_repository_updated_at"
t
.
datetime
"last_repository_updated_at"
t
.
string
"ci_config_path"
t
.
string
"ci_config_path"
t
.
text
"delete_error"
t
.
text
"delete_error"
t
.
uuid
"uuid"
t
.
integer
"storage_version"
,
limit:
2
t
.
integer
"storage_version"
,
limit:
2
,
default:
0
,
null:
false
end
end
add_index
"projects"
,
[
"ci_id"
],
name:
"index_projects_on_ci_id"
,
using: :btree
add_index
"projects"
,
[
"ci_id"
],
name:
"index_projects_on_ci_id"
,
using: :btree
...
@@ -1226,7 +1225,7 @@ ActiveRecord::Schema.define(version: 20170820100558) do
...
@@ -1226,7 +1225,7 @@ ActiveRecord::Schema.define(version: 20170820100558) do
add_index
"projects"
,
[
"pending_delete"
],
name:
"index_projects_on_pending_delete"
,
using: :btree
add_index
"projects"
,
[
"pending_delete"
],
name:
"index_projects_on_pending_delete"
,
using: :btree
add_index
"projects"
,
[
"runners_token"
],
name:
"index_projects_on_runners_token"
,
using: :btree
add_index
"projects"
,
[
"runners_token"
],
name:
"index_projects_on_runners_token"
,
using: :btree
add_index
"projects"
,
[
"star_count"
],
name:
"index_projects_on_star_count"
,
using: :btree
add_index
"projects"
,
[
"star_count"
],
name:
"index_projects_on_star_count"
,
using: :btree
add_index
"projects"
,
[
"
uuid"
],
name:
"index_projects_on_uuid
"
,
using: :btree
add_index
"projects"
,
[
"
storage_version"
],
name:
"index_projects_on_storage_version
"
,
using: :btree
add_index
"projects"
,
[
"visibility_level"
],
name:
"index_projects_on_visibility_level"
,
using: :btree
add_index
"projects"
,
[
"visibility_level"
],
name:
"index_projects_on_visibility_level"
,
using: :btree
create_table
"protected_branch_merge_access_levels"
,
force: :cascade
do
|
t
|
create_table
"protected_branch_merge_access_levels"
,
force: :cascade
do
|
t
|
...
...
lib/gitlab/import_export/import_export.yml
View file @
9e6fa996
...
@@ -98,6 +98,7 @@ excluded_attributes:
...
@@ -98,6 +98,7 @@ excluded_attributes:
-
:last_activity_at
-
:last_activity_at
-
:last_repository_updated_at
-
:last_repository_updated_at
-
:last_repository_check_at
-
:last_repository_check_at
-
:storage_version
snippets
:
snippets
:
-
:expired_at
-
:expired_at
merge_request_diff
:
merge_request_diff
:
...
...
spec/factories/projects.rb
View file @
9e6fa996
...
@@ -81,6 +81,10 @@ FactoryGirl.define do
...
@@ -81,6 +81,10 @@ FactoryGirl.define do
archived
true
archived
true
end
end
trait
:hashed
do
storage_version
1
end
trait
:access_requestable
do
trait
:access_requestable
do
request_access_enabled
true
request_access_enabled
true
end
end
...
...
spec/models/project_spec.rb
View file @
9e6fa996
...
@@ -1251,60 +1251,6 @@ describe Project do
...
@@ -1251,60 +1251,6 @@ describe Project do
end
end
end
end
describe
'#rename_repo'
do
let
(
:project
)
{
create
(
:project
,
:repository
)
}
let
(
:gitlab_shell
)
{
Gitlab
::
Shell
.
new
}
before
do
# Project#gitlab_shell returns a new instance of Gitlab::Shell on every
# call. This makes testing a bit easier.
allow
(
project
).
to
receive
(
:gitlab_shell
).
and_return
(
gitlab_shell
)
allow
(
project
).
to
receive
(
:previous_changes
).
and_return
(
'path'
=>
[
'foo'
])
end
it
'renames a repository'
do
stub_container_registry_config
(
enabled:
false
)
expect
(
gitlab_shell
).
to
receive
(
:mv_repository
)
.
ordered
.
with
(
project
.
repository_storage_path
,
"
#{
project
.
namespace
.
full_path
}
/foo"
,
"
#{
project
.
full_path
}
"
)
.
and_return
(
true
)
expect
(
gitlab_shell
).
to
receive
(
:mv_repository
)
.
ordered
.
with
(
project
.
repository_storage_path
,
"
#{
project
.
namespace
.
full_path
}
/foo.wiki"
,
"
#{
project
.
full_path
}
.wiki"
)
.
and_return
(
true
)
expect_any_instance_of
(
SystemHooksService
)
.
to
receive
(
:execute_hooks_for
)
.
with
(
project
,
:rename
)
expect_any_instance_of
(
Gitlab
::
UploadsTransfer
)
.
to
receive
(
:rename_project
)
.
with
(
'foo'
,
project
.
path
,
project
.
namespace
.
full_path
)
expect
(
project
).
to
receive
(
:expire_caches_before_rename
)
expect
(
project
).
to
receive
(
:expires_full_path_cache
)
project
.
rename_repo
end
context
'container registry with images'
do
let
(
:container_repository
)
{
create
(
:container_repository
)
}
before
do
stub_container_registry_config
(
enabled:
true
)
stub_container_registry_tags
(
repository: :any
,
tags:
[
'tag'
])
project
.
container_repositories
<<
container_repository
end
subject
{
project
.
rename_repo
}
it
{
expect
{
subject
}.
to
raise_error
(
StandardError
)
}
end
end
describe
'#expire_caches_before_rename'
do
describe
'#expire_caches_before_rename'
do
let
(
:project
)
{
create
(
:project
,
:repository
)
}
let
(
:project
)
{
create
(
:project
,
:repository
)
}
let
(
:repo
)
{
double
(
:repo
,
exists?:
true
)
}
let
(
:repo
)
{
double
(
:repo
,
exists?:
true
)
}
...
@@ -2367,4 +2313,163 @@ describe Project do
...
@@ -2367,4 +2313,163 @@ describe Project do
expect
(
project
.
forks_count
).
to
eq
(
1
)
expect
(
project
.
forks_count
).
to
eq
(
1
)
end
end
end
end
context
'legacy storage'
do
let
(
:project
)
{
create
(
:project
,
:repository
)
}
let
(
:gitlab_shell
)
{
Gitlab
::
Shell
.
new
}
describe
'#base_dir'
do
it
'returns base_dir based on namespace only'
do
expect
(
project
.
base_dir
).
to
eq
(
project
.
namespace
.
full_path
)
end
end
describe
'#disk_path'
do
it
'returns disk_path based on namespace and project path'
do
expect
(
project
.
disk_path
).
to
eq
(
"
#{
project
.
namespace
.
full_path
}
/
#{
project
.
path
}
"
)
end
end
describe
'#ensure_storage_path_exist'
do
before
do
allow
(
project
).
to
receive
(
:gitlab_shell
).
and_return
(
gitlab_shell
)
end
it
'delegates to gitlab_shell to ensure namespace is created'
do
expect
(
gitlab_shell
).
to
receive
(
:add_namespace
).
with
(
project
.
repository_storage_path
,
project
.
base_dir
)
project
.
ensure_storage_path_exist
end
end
describe
'#rename_repo'
do
before
do
# Project#gitlab_shell returns a new instance of Gitlab::Shell on every
# call. This makes testing a bit easier.
allow
(
project
).
to
receive
(
:gitlab_shell
).
and_return
(
gitlab_shell
)
allow
(
project
).
to
receive
(
:previous_changes
).
and_return
(
'path'
=>
[
'foo'
])
end
it
'renames a repository'
do
stub_container_registry_config
(
enabled:
false
)
expect
(
gitlab_shell
).
to
receive
(
:mv_repository
)
.
ordered
.
with
(
project
.
repository_storage_path
,
"
#{
project
.
namespace
.
full_path
}
/foo"
,
"
#{
project
.
full_path
}
"
)
.
and_return
(
true
)
expect
(
gitlab_shell
).
to
receive
(
:mv_repository
)
.
ordered
.
with
(
project
.
repository_storage_path
,
"
#{
project
.
namespace
.
full_path
}
/foo.wiki"
,
"
#{
project
.
full_path
}
.wiki"
)
.
and_return
(
true
)
expect_any_instance_of
(
SystemHooksService
)
.
to
receive
(
:execute_hooks_for
)
.
with
(
project
,
:rename
)
expect_any_instance_of
(
Gitlab
::
UploadsTransfer
)
.
to
receive
(
:rename_project
)
.
with
(
'foo'
,
project
.
path
,
project
.
namespace
.
full_path
)
expect
(
project
).
to
receive
(
:expire_caches_before_rename
)
expect
(
project
).
to
receive
(
:expires_full_path_cache
)
project
.
rename_repo
end
context
'container registry with images'
do
let
(
:container_repository
)
{
create
(
:container_repository
)
}
before
do
stub_container_registry_config
(
enabled:
true
)
stub_container_registry_tags
(
repository: :any
,
tags:
[
'tag'
])
project
.
container_repositories
<<
container_repository
end
subject
{
project
.
rename_repo
}
it
{
expect
{
subject
}.
to
raise_error
(
StandardError
)
}
end
end
end
context
'hashed storage'
do
let
(
:project
)
{
create
(
:project
,
:repository
,
:hashed
)
}
let
(
:gitlab_shell
)
{
Gitlab
::
Shell
.
new
}
let
(
:hash
)
{
'6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b'
}
before
do
allow
(
Digest
::
SHA2
).
to
receive
(
:hexdigest
)
{
hash
}
end
describe
'#base_dir'
do
it
'returns base_dir based on hash of project id'
do
expect
(
project
.
base_dir
).
to
eq
(
'6b/86'
)
end
end
describe
'#disk_path'
do
it
'returns disk_path based on has of project id'
do
hashed_path
=
'6b/86/6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b'
expect
(
project
.
disk_path
).
to
eq
(
hashed_path
)
end
end
describe
'#ensure_storage_path_exist'
do
before
do
allow
(
project
).
to
receive
(
:gitlab_shell
).
and_return
(
gitlab_shell
)
end
it
'delegates to gitlab_shell to ensure namespace is created'
do
expect
(
gitlab_shell
).
to
receive
(
:add_namespace
).
with
(
project
.
repository_storage_path
,
'6b/86'
)
project
.
ensure_storage_path_exist
end
end
describe
'#rename_repo'
do
before
do
# Project#gitlab_shell returns a new instance of Gitlab::Shell on every
# call. This makes testing a bit easier.
allow
(
project
).
to
receive
(
:gitlab_shell
).
and_return
(
gitlab_shell
)
allow
(
project
).
to
receive
(
:previous_changes
).
and_return
(
'path'
=>
[
'foo'
])
end
it
'renames a repository'
do
stub_container_registry_config
(
enabled:
false
)
expect
(
gitlab_shell
).
not_to
receive
(
:mv_repository
)
expect_any_instance_of
(
SystemHooksService
)
.
to
receive
(
:execute_hooks_for
)
.
with
(
project
,
:rename
)
expect_any_instance_of
(
Gitlab
::
UploadsTransfer
)
.
to
receive
(
:rename_project
)
.
with
(
'foo'
,
project
.
path
,
project
.
namespace
.
full_path
)
expect
(
project
).
to
receive
(
:expire_caches_before_rename
)
expect
(
project
).
to
receive
(
:expires_full_path_cache
)
project
.
rename_repo
end
context
'container registry with images'
do
let
(
:container_repository
)
{
create
(
:container_repository
)
}
before
do
stub_container_registry_config
(
enabled:
true
)
stub_container_registry_tags
(
repository: :any
,
tags:
[
'tag'
])
project
.
container_repositories
<<
container_repository
end
subject
{
project
.
rename_repo
}
it
{
expect
{
subject
}.
to
raise_error
(
StandardError
)
}
end
end
end
end
end
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment