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
1
Merge Requests
1
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
nexedi
gitlab-ce
Commits
ecfdb165
Commit
ecfdb165
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
b6ca1ab2
Changes
8
Show 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 @
ecfdb165
5.
9.4
5.
10.0
app/models/project.rb
View file @
ecfdb165
...
...
@@ -569,8 +569,7 @@ class Project < ActiveRecord::Base
if
forked?
RepositoryForkWorker
.
perform_async
(
id
,
forked_from_project
.
repository_storage_path
,
forked_from_project
.
full_path
,
self
.
namespace
.
full_path
)
forked_from_project
.
disk_path
)
else
RepositoryImportWorker
.
perform_async
(
self
.
id
)
end
...
...
app/workers/repository_fork_worker.rb
View file @
ecfdb165
...
...
@@ -8,18 +8,18 @@ class RepositoryForkWorker
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
)
return
unless
start_fork
(
project
)
Gitlab
::
Metrics
.
add_event
(
:fork_repository
,
source_path:
source_path
,
target_path:
target
_path
)
source_path:
source_
disk_
path
,
target_path:
project
.
disk
_path
)
result
=
gitlab_shell
.
fork_repository
(
forked_from_repository_storage_path
,
source_path
,
project
.
repository_storage_path
,
target
_path
)
raise
ForkError
,
"Unable to fork project
#{
project_id
}
for repository
#{
source_
path
}
->
#{
target
_path
}
"
unless
result
result
=
gitlab_shell
.
fork_repository
(
forked_from_repository_storage_path
,
source_
disk_
path
,
project
.
repository_storage_path
,
project
.
disk
_path
)
raise
ForkError
,
"Unable to fork project
#{
project_id
}
for repository
#{
source_
disk_path
}
->
#{
project
.
disk
_path
}
"
unless
result
project
.
repository
.
after_import
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 @
ecfdb165
---
title
:
Fix the fork project functionality for projects with hashed storage
merge_request
:
15671
author
:
type
:
fixed
lib/gitlab/shell.rb
View file @
ecfdb165
...
...
@@ -158,20 +158,27 @@ module Gitlab
current_storage
,
"
#{
path
}
.git"
,
new_storage
])
end
# Fork repository to new
namespace
# Fork repository to new
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
# fork
_namespace - namespace for forked project
# fork
ed_to_disk_path - forked project disk path
#
# 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.
def
fork_repository
(
forked_from_storage
,
path
,
forked_to_storage
,
fork_namespace
)
gitlab_shell_fast_execute
([
gitlab_shell_projects_path
,
'fork-project'
,
forked_from_storage
,
"
#{
path
}
.git"
,
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-repository'
,
forked_from_storage
,
"
#{
forked_from_disk_path
}
.git"
,
forked_to_storage
,
"
#{
forked_to_disk_path
}
.git"
]
)
end
# Remove repository from file system
...
...
spec/lib/gitlab/shell_spec.rb
View file @
ecfdb165
...
...
@@ -518,18 +518,18 @@ describe Gitlab::Shell do
describe
'#fork_repository'
do
it
'returns true when the command succeeds'
do
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
])
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
it
'return false when the command fails'
do
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
])
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
...
...
spec/models/project_spec.rb
View file @
ecfdb165
...
...
@@ -1934,8 +1934,7 @@ describe Project do
expect
(
RepositoryForkWorker
).
to
receive
(
:perform_async
).
with
(
project
.
id
,
forked_from_project
.
repository_storage_path
,
forked_from_project
.
disk_path
,
project
.
namespace
.
full_path
).
and_return
(
import_jid
)
forked_from_project
.
disk_path
).
and_return
(
import_jid
)
expect
(
project
.
add_import_job
).
to
eq
(
import_jid
)
end
...
...
spec/workers/repository_fork_worker_spec.rb
View file @
ecfdb165
require
'spec_helper'
describe
RepositoryForkWorker
do
let
(
:project
)
{
create
(
:project
,
:repository
,
:import_scheduled
)
}
let
(
:fork_project
)
{
create
(
:project
,
:repository
,
forked_from_project:
project
)
}
let
(
:project
)
{
create
(
:project
,
:repository
)
}
let
(
:fork_project
)
{
create
(
:project
,
:repository
,
:import_scheduled
,
forked_from_project:
project
)
}
let
(
:shell
)
{
Gitlab
::
Shell
.
new
}
subject
{
described_class
.
new
}
...
...
@@ -12,50 +12,39 @@ describe RepositoryForkWorker do
end
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
let
(
:jid
)
{
'12345678'
}
let
(
:started_project
)
{
create
(
:project
,
:repository
,
:import_started
)
}
it
'creates a new repository from a fork'
do
allow
(
subject
).
to
receive
(
:jid
).
and_return
(
jid
)
expect
(
shell
).
to
receive
(
:fork_repository
).
with
(
'/test/path'
,
project
.
full_path
,
project
.
repository_storage_path
,
fork_project
.
namespace
.
full_path
).
and_return
(
true
)
expect_fork_repository
.
and_return
(
true
)
subject
.
perform
(
project
.
id
,
'/test/path'
,
project
.
full_path
,
fork_project
.
namespace
.
full_path
)
perform!
end
end
it
"creates a new repository from a fork"
do
expect
(
shell
).
to
receive
(
:fork_repository
).
with
(
'/test/path'
,
project
.
full_path
,
project
.
repository_storage_path
,
fork_project
.
namespace
.
full_path
).
and_return
(
true
)
expect_fork_repository
.
and_return
(
true
)
subject
.
perform
(
project
.
id
,
'/test/path'
,
project
.
full_path
,
fork_project
.
namespace
.
full_path
)
perform!
end
it
'flushes various caches'
do
expect
(
shell
).
to
receive
(
:fork_repository
).
with
(
'/test/path'
,
project
.
full_path
,
project
.
repository_storage_path
,
fork_project
.
namespace
.
full_path
).
and_return
(
true
)
expect_fork_repository
.
and_return
(
true
)
expect_any_instance_of
(
Repository
).
to
receive
(
:expire_emptiness_caches
)
.
and_call_original
...
...
@@ -63,32 +52,22 @@ describe RepositoryForkWorker do
expect_any_instance_of
(
Repository
).
to
receive
(
:expire_exists_cache
)
.
and_call_original
subject
.
perform
(
project
.
id
,
'/test/path'
,
project
.
full_path
,
fork_project
.
namespace
.
full_path
)
perform!
end
it
"handles bad fork"
do
source_path
=
project
.
full_path
target_path
=
fork_project
.
namespace
.
full_path
error_message
=
"Unable to fork project
#{
project
.
id
}
for repository
#{
source_path
}
->
#{
target_path
}
"
error_message
=
"Unable to fork project
#{
fork_project
.
id
}
for repository
#{
project
.
full_path
}
->
#{
fork_project
.
full_path
}
"
expect
(
shell
).
to
receive
(
:fork_repository
)
.
and_return
(
false
)
expect
_fork_repository
.
and_return
(
false
)
expect
do
subject
.
perform
(
project
.
id
,
'/test/path'
,
source_path
,
target_path
)
end
.
to
raise_error
(
RepositoryForkWorker
::
ForkError
,
error_message
)
expect
{
perform!
}.
to
raise_error
(
RepositoryForkWorker
::
ForkError
,
error_message
)
end
it
'handles unexpected error'
do
source_path
=
project
.
full_path
target_path
=
fork_project
.
namespace
.
full_path
allow_any_instance_of
(
Gitlab
::
Shell
).
to
receive
(
:fork_repository
).
and_raise
(
RuntimeError
)
expect_fork_repository
.
and_raise
(
RuntimeError
)
expect
do
subject
.
perform
(
project
.
id
,
'/test/path'
,
source_path
,
target_path
)
end
.
to
raise_error
(
RepositoryForkWorker
::
ForkError
)
expect
(
project
.
reload
.
import_status
).
to
eq
(
'failed'
)
expect
{
perform!
}.
to
raise_error
(
RepositoryForkWorker
::
ForkError
)
expect
(
fork_project
.
reload
.
import_status
).
to
eq
(
'failed'
)
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