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
Boxiang Sun
gitlab-ce
Commits
327a9898
Commit
327a9898
authored
Nov 30, 2017
by
Nick Thomas
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix the fork project functionality for projects with hashed storage
Note the dependency on gitlab-shell v5.10.0
parent
e0f84130
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
61 additions
and
72 deletions
+61
-72
GITLAB_SHELL_VERSION
GITLAB_SHELL_VERSION
+1
-1
app/models/project.rb
app/models/project.rb
+1
-2
app/workers/repository_fork_worker.rb
app/workers/repository_fork_worker.rb
+6
-6
changelogs/unreleased/40711-fix-forking-hashed-projects.yml
changelogs/unreleased/40711-fix-forking-hashed-projects.yml
+5
-0
lib/gitlab/shell.rb
lib/gitlab/shell.rb
+15
-8
spec/lib/gitlab/shell_spec.rb
spec/lib/gitlab/shell_spec.rb
+4
-4
spec/models/project_spec.rb
spec/models/project_spec.rb
+1
-2
spec/workers/repository_fork_worker_spec.rb
spec/workers/repository_fork_worker_spec.rb
+28
-49
No files found.
GITLAB_SHELL_VERSION
View file @
327a9898
5.
9.4
5.
10.0
app/models/project.rb
View file @
327a9898
...
@@ -562,8 +562,7 @@ class Project < ActiveRecord::Base
...
@@ -562,8 +562,7 @@ class Project < ActiveRecord::Base
if
forked?
if
forked?
RepositoryForkWorker
.
perform_async
(
id
,
RepositoryForkWorker
.
perform_async
(
id
,
forked_from_project
.
repository_storage_path
,
forked_from_project
.
repository_storage_path
,
forked_from_project
.
full_path
,
forked_from_project
.
disk_path
)
self
.
namespace
.
full_path
)
else
else
RepositoryImportWorker
.
perform_async
(
self
.
id
)
RepositoryImportWorker
.
perform_async
(
self
.
id
)
end
end
...
...
app/workers/repository_fork_worker.rb
View file @
327a9898
...
@@ -8,18 +8,18 @@ class RepositoryForkWorker
...
@@ -8,18 +8,18 @@ class RepositoryForkWorker
sidekiq_options
status_expiration:
StuckImportJobsWorker
::
IMPORT_JOBS_EXPIRATION
sidekiq_options
status_expiration:
StuckImportJobsWorker
::
IMPORT_JOBS_EXPIRATION
def
perform
(
project_id
,
forked_from_repository_storage_path
,
source_
path
,
target
_path
)
def
perform
(
project_id
,
forked_from_repository_storage_path
,
source_
disk
_path
)
project
=
Project
.
find
(
project_id
)
project
=
Project
.
find
(
project_id
)
return
unless
start_fork
(
project
)
return
unless
start_fork
(
project
)
Gitlab
::
Metrics
.
add_event
(
:fork_repository
,
Gitlab
::
Metrics
.
add_event
(
:fork_repository
,
source_path:
source_path
,
source_path:
source_
disk_
path
,
target_path:
target
_path
)
target_path:
project
.
disk
_path
)
result
=
gitlab_shell
.
fork_repository
(
forked_from_repository_storage_path
,
source_path
,
result
=
gitlab_shell
.
fork_repository
(
forked_from_repository_storage_path
,
source_
disk_
path
,
project
.
repository_storage_path
,
target
_path
)
project
.
repository_storage_path
,
project
.
disk
_path
)
raise
ForkError
,
"Unable to fork project
#{
project_id
}
for repository
#{
source_
path
}
->
#{
target
_path
}
"
unless
result
raise
ForkError
,
"Unable to fork project
#{
project_id
}
for repository
#{
source_
disk_path
}
->
#{
project
.
disk
_path
}
"
unless
result
project
.
repository
.
after_import
project
.
repository
.
after_import
raise
ForkError
,
"Project
#{
project_id
}
had an invalid repository after fork"
unless
project
.
valid_repo?
raise
ForkError
,
"Project
#{
project_id
}
had an invalid repository after fork"
unless
project
.
valid_repo?
...
...
changelogs/unreleased/40711-fix-forking-hashed-projects.yml
0 → 100644
View file @
327a9898
---
title
:
Fix the fork project functionality for projects with hashed storage
merge_request
:
15671
author
:
type
:
fixed
lib/gitlab/shell.rb
View file @
327a9898
...
@@ -143,20 +143,27 @@ module Gitlab
...
@@ -143,20 +143,27 @@ module Gitlab
storage
,
"
#{
path
}
.git"
,
"
#{
new_path
}
.git"
])
storage
,
"
#{
path
}
.git"
,
"
#{
new_path
}
.git"
])
end
end
# Fork repository to new
namespace
# Fork repository to new
path
# forked_from_storage - forked-from project's storage path
# forked_from_storage - forked-from project's storage path
#
path - project path with namespace
#
forked_from_disk_path - project disk path
# forked_to_storage - forked-to project's storage path
# forked_to_storage - forked-to project's storage path
# fork
_namespace - namespace for forked project
# fork
ed_to_disk_path - forked project disk path
#
#
# Ex.
# Ex.
# fork_repository("/path/to/forked_from/storage", "gitlab/gitlab-ci", "/path/to/forked_to/storage", "
randx
")
# fork_repository("/path/to/forked_from/storage", "gitlab/gitlab-ci", "/path/to/forked_to/storage", "
new-namespace/gitlab-ci
")
#
#
# Gitaly note: JV: not easy to migrate because this involves two Gitaly servers, not one.
# Gitaly note: JV: not easy to migrate because this involves two Gitaly servers, not one.
def
fork_repository
(
forked_from_storage
,
path
,
forked_to_storage
,
fork_namespace
)
def
fork_repository
(
forked_from_storage
,
forked_from_disk_path
,
forked_to_storage
,
forked_to_disk_path
)
gitlab_shell_fast_execute
([
gitlab_shell_projects_path
,
'fork-project'
,
gitlab_shell_fast_execute
(
forked_from_storage
,
"
#{
path
}
.git"
,
forked_to_storage
,
[
fork_namespace
])
gitlab_shell_projects_path
,
'fork-repository'
,
forked_from_storage
,
"
#{
forked_from_disk_path
}
.git"
,
forked_to_storage
,
"
#{
forked_to_disk_path
}
.git"
]
)
end
end
# Remove repository from file system
# Remove repository from file system
...
...
spec/lib/gitlab/shell_spec.rb
View file @
327a9898
...
@@ -200,18 +200,18 @@ describe Gitlab::Shell do
...
@@ -200,18 +200,18 @@ describe Gitlab::Shell do
describe
'#fork_repository'
do
describe
'#fork_repository'
do
it
'returns true when the command succeeds'
do
it
'returns true when the command succeeds'
do
expect
(
Gitlab
::
Popen
).
to
receive
(
:popen
)
expect
(
Gitlab
::
Popen
).
to
receive
(
:popen
)
.
with
([
projects_path
,
'fork-
project'
,
'current/storage'
,
'project/path.git'
,
'new/storage'
,
'new-namespace
'
],
.
with
([
projects_path
,
'fork-
repository'
,
'current/storage'
,
'project/path.git'
,
'new/storage'
,
'fork/path.git
'
],
nil
,
popen_vars
).
and_return
([
nil
,
0
])
nil
,
popen_vars
).
and_return
([
nil
,
0
])
expect
(
gitlab_shell
.
fork_repository
(
'current/storage'
,
'project/path'
,
'new/storage'
,
'
new-namespace
'
)).
to
be
true
expect
(
gitlab_shell
.
fork_repository
(
'current/storage'
,
'project/path'
,
'new/storage'
,
'
fork/path
'
)).
to
be
true
end
end
it
'return false when the command fails'
do
it
'return false when the command fails'
do
expect
(
Gitlab
::
Popen
).
to
receive
(
:popen
)
expect
(
Gitlab
::
Popen
).
to
receive
(
:popen
)
.
with
([
projects_path
,
'fork-
project'
,
'current/storage'
,
'project/path.git'
,
'new/storage'
,
'new-namespace
'
],
.
with
([
projects_path
,
'fork-
repository'
,
'current/storage'
,
'project/path.git'
,
'new/storage'
,
'fork/path.git
'
],
nil
,
popen_vars
).
and_return
([
"error"
,
1
])
nil
,
popen_vars
).
and_return
([
"error"
,
1
])
expect
(
gitlab_shell
.
fork_repository
(
'current/storage'
,
'project/path'
,
'new/storage'
,
'
new-namespace
'
)).
to
be
false
expect
(
gitlab_shell
.
fork_repository
(
'current/storage'
,
'project/path'
,
'new/storage'
,
'
fork/path
'
)).
to
be
false
end
end
end
end
...
...
spec/models/project_spec.rb
View file @
327a9898
...
@@ -1717,8 +1717,7 @@ describe Project do
...
@@ -1717,8 +1717,7 @@ describe Project do
expect
(
RepositoryForkWorker
).
to
receive
(
:perform_async
).
with
(
expect
(
RepositoryForkWorker
).
to
receive
(
:perform_async
).
with
(
project
.
id
,
project
.
id
,
forked_from_project
.
repository_storage_path
,
forked_from_project
.
repository_storage_path
,
forked_from_project
.
disk_path
,
forked_from_project
.
disk_path
).
and_return
(
import_jid
)
project
.
namespace
.
full_path
).
and_return
(
import_jid
)
expect
(
project
.
add_import_job
).
to
eq
(
import_jid
)
expect
(
project
.
add_import_job
).
to
eq
(
import_jid
)
end
end
...
...
spec/workers/repository_fork_worker_spec.rb
View file @
327a9898
require
'spec_helper'
require
'spec_helper'
describe
RepositoryForkWorker
do
describe
RepositoryForkWorker
do
let
(
:project
)
{
create
(
:project
,
:repository
,
:import_scheduled
)
}
let
(
:project
)
{
create
(
:project
,
:repository
)
}
let
(
:fork_project
)
{
create
(
:project
,
:repository
,
forked_from_project:
project
)
}
let
(
:fork_project
)
{
create
(
:project
,
:repository
,
:import_scheduled
,
forked_from_project:
project
)
}
let
(
:shell
)
{
Gitlab
::
Shell
.
new
}
let
(
:shell
)
{
Gitlab
::
Shell
.
new
}
subject
{
described_class
.
new
}
subject
{
described_class
.
new
}
...
@@ -12,50 +12,39 @@ describe RepositoryForkWorker do
...
@@ -12,50 +12,39 @@ describe RepositoryForkWorker do
end
end
describe
"#perform"
do
describe
"#perform"
do
def
perform!
subject
.
perform
(
fork_project
.
id
,
'/test/path'
,
project
.
disk_path
)
end
def
expect_fork_repository
expect
(
shell
).
to
receive
(
:fork_repository
).
with
(
'/test/path'
,
project
.
disk_path
,
fork_project
.
repository_storage_path
,
fork_project
.
disk_path
)
end
describe
'when a worker was reset without cleanup'
do
describe
'when a worker was reset without cleanup'
do
let
(
:jid
)
{
'12345678'
}
let
(
:jid
)
{
'12345678'
}
let
(
:started_project
)
{
create
(
:project
,
:repository
,
:import_started
)
}
it
'creates a new repository from a fork'
do
it
'creates a new repository from a fork'
do
allow
(
subject
).
to
receive
(
:jid
).
and_return
(
jid
)
allow
(
subject
).
to
receive
(
:jid
).
and_return
(
jid
)
expect
(
shell
).
to
receive
(
:fork_repository
).
with
(
expect_fork_repository
.
and_return
(
true
)
'/test/path'
,
project
.
full_path
,
perform!
project
.
repository_storage_path
,
fork_project
.
namespace
.
full_path
).
and_return
(
true
)
subject
.
perform
(
project
.
id
,
'/test/path'
,
project
.
full_path
,
fork_project
.
namespace
.
full_path
)
end
end
end
end
it
"creates a new repository from a fork"
do
it
"creates a new repository from a fork"
do
expect
(
shell
).
to
receive
(
:fork_repository
).
with
(
expect_fork_repository
.
and_return
(
true
)
'/test/path'
,
project
.
full_path
,
project
.
repository_storage_path
,
fork_project
.
namespace
.
full_path
).
and_return
(
true
)
subject
.
perform
(
perform!
project
.
id
,
'/test/path'
,
project
.
full_path
,
fork_project
.
namespace
.
full_path
)
end
end
it
'flushes various caches'
do
it
'flushes various caches'
do
expect
(
shell
).
to
receive
(
:fork_repository
).
with
(
expect_fork_repository
.
and_return
(
true
)
'/test/path'
,
project
.
full_path
,
project
.
repository_storage_path
,
fork_project
.
namespace
.
full_path
).
and_return
(
true
)
expect_any_instance_of
(
Repository
).
to
receive
(
:expire_emptiness_caches
)
expect_any_instance_of
(
Repository
).
to
receive
(
:expire_emptiness_caches
)
.
and_call_original
.
and_call_original
...
@@ -63,32 +52,22 @@ describe RepositoryForkWorker do
...
@@ -63,32 +52,22 @@ describe RepositoryForkWorker do
expect_any_instance_of
(
Repository
).
to
receive
(
:expire_exists_cache
)
expect_any_instance_of
(
Repository
).
to
receive
(
:expire_exists_cache
)
.
and_call_original
.
and_call_original
subject
.
perform
(
project
.
id
,
'/test/path'
,
project
.
full_path
,
perform!
fork_project
.
namespace
.
full_path
)
end
end
it
"handles bad fork"
do
it
"handles bad fork"
do
source_path
=
project
.
full_path
error_message
=
"Unable to fork project
#{
fork_project
.
id
}
for repository
#{
project
.
full_path
}
->
#{
fork_project
.
full_path
}
"
target_path
=
fork_project
.
namespace
.
full_path
error_message
=
"Unable to fork project
#{
project
.
id
}
for repository
#{
source_path
}
->
#{
target_path
}
"
expect
(
shell
).
to
receive
(
:fork_repository
)
.
and_return
(
false
)
expect
_fork_repository
.
and_return
(
false
)
expect
do
expect
{
perform!
}.
to
raise_error
(
RepositoryForkWorker
::
ForkError
,
error_message
)
subject
.
perform
(
project
.
id
,
'/test/path'
,
source_path
,
target_path
)
end
.
to
raise_error
(
RepositoryForkWorker
::
ForkError
,
error_message
)
end
end
it
'handles unexpected error'
do
it
'handles unexpected error'
do
source_path
=
project
.
full_path
expect_fork_repository
.
and_raise
(
RuntimeError
)
target_path
=
fork_project
.
namespace
.
full_path
allow_any_instance_of
(
Gitlab
::
Shell
).
to
receive
(
:fork_repository
).
and_raise
(
RuntimeError
)
expect
do
expect
{
perform!
}.
to
raise_error
(
RepositoryForkWorker
::
ForkError
)
subject
.
perform
(
project
.
id
,
'/test/path'
,
source_path
,
target_path
)
expect
(
fork_project
.
reload
.
import_status
).
to
eq
(
'failed'
)
end
.
to
raise_error
(
RepositoryForkWorker
::
ForkError
)
expect
(
project
.
reload
.
import_status
).
to
eq
(
'failed'
)
end
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