Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Didier WECKMANN
groupfork
Commits
951f2590
Commit
951f2590
authored
Jun 24, 2020
by
Didier WECKMANN
Browse files
feat(core): initial commit
parent
8ceb6106
Changes
1
Hide whitespace changes
Inline
Side-by-side
groupfork.py
0 → 100755
View file @
951f2590
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import
argparse
import
os
import
time
import
gitlab
def
main
():
"""
Main function
"""
# Get application arguments
parsed_arguments
=
parse_arguments
()
# Initialize gitlab API
gitlab_instance
=
initialize_gitlab
(
parsed_arguments
)
duplicate_group
(
parsed_arguments
,
gitlab_instance
,
parsed_arguments
.
from_group
,
parsed_arguments
.
to_group
)
def
parse_arguments
(
arguments
=
None
):
"""
Parse command line arguments
Args:
arguments: optional argument list, to allow unit testing
Returns:
ArgumentParser object
"""
# Arguments parsing
parser
=
argparse
.
ArgumentParser
(
description
=
'Perform various git or conan task on Sight GitLab repositories.'
)
parser
.
add_argument
(
'--gitlab_config'
,
type
=
str
,
help
=
'GitLab Python API configuration path. Default to ~/.python-gitlab.cfg'
)
parser
.
add_argument
(
'--gitlab_config_section'
,
type
=
str
,
default
=
'ircad.fr'
,
help
=
'GitLab Python API configuration section in configuration file.'
)
parser
.
add_argument
(
'--gitlab_url'
,
type
=
str
,
help
=
'GitLab URL. Default to https://git.ircad.fr'
)
parser
.
add_argument
(
'--gitlab_token'
,
type
=
str
,
help
=
'GitLab private access token.'
)
parser
.
add_argument
(
'--dry'
,
action
=
'store_true'
,
default
=
False
,
help
=
'do nothing but print things.'
)
parser
.
add_argument
(
'--force'
,
action
=
'store_true'
,
default
=
False
,
help
=
'be careless and overwrite things like existing merge request.'
)
parser
.
add_argument
(
'--verbose'
,
action
=
'store_true'
,
default
=
False
,
help
=
'prints some stuff.'
)
parser
.
add_argument
(
'--from_group'
,
type
=
str
,
help
=
'Group source.'
)
parser
.
add_argument
(
'--to_group'
,
type
=
str
,
help
=
'Group destination.'
)
# arguments is not None if coming from tests
if
arguments
is
None
:
parsed_arguments
=
parser
.
parse_args
()
else
:
parsed_arguments
=
parser
.
parse_args
(
arguments
)
return
parsed_arguments
def
initialize_gitlab
(
parsed_arguments
):
"""
Return an initialized gitlab object
Args:
parsed_arguments: parsed arguments from command line
Returns:
GitLab instance object
"""
gitlab_config
=
parsed_arguments
.
gitlab_config
gitlab_url
=
parsed_arguments
.
gitlab_url
gitlab_token
=
parsed_arguments
.
gitlab_token
# Use default value for configuration if not given as argument
if
not
gitlab_config
or
not
os
.
path
.
exists
(
gitlab_config
):
gitlab_config
=
os
.
path
.
join
(
os
.
path
.
expanduser
(
'~'
),
'.python-gitlab.cfg'
)
# Use default value for url if the url is not given as argument
if
not
gitlab_url
:
gitlab_url
=
'https://git.ircad.fr'
# Use default value for token if not given as argument
if
not
gitlab_token
:
gitlab_token
=
os
.
getenv
(
'GITLAB_TOKEN'
)
# If an url or a token has been specified or the config cannot be opened
if
parsed_arguments
.
gitlab_url
or
parsed_arguments
.
gitlab_token
or
not
os
.
path
.
exists
(
gitlab_config
):
return
gitlab
.
Gitlab
(
gitlab_url
,
private_token
=
gitlab_token
,
ssl_verify
=
False
,
api_version
=
'4'
)
else
:
return
gitlab
.
Gitlab
.
from_config
(
parsed_arguments
.
gitlab_config_section
,
gitlab_config
)
def
duplicate_group
(
parsed_arguments
,
gitlab_instance
,
from_group
,
to_group
):
"""
Duplicate a group and all its projects.
Args:
parsed_arguments: parsed arguments from command line
gitlab_instance: the gitlab instance
from_group: the origin group
to_group: the target group
"""
# Get the conan group
from_gitlab_group
=
gitlab_instance
.
groups
.
get
(
from_group
,
lazy
=
True
)
# Get or create the target group
try
:
to_gitlab_group
=
gitlab_instance
.
groups
.
get
(
to_group
)
except
Exception
:
to_gitlab_group
=
None
pass
if
to_gitlab_group
:
if
parsed_arguments
.
dry
or
parsed_arguments
.
verbose
:
print
(
"delete existing target group {0}"
.
format
(
to_group
))
if
not
parsed_arguments
.
dry
:
to_gitlab_group
.
delete
()
time
.
sleep
(
10
)
# Wait a bit
try
:
while
gitlab_instance
.
groups
.
get
(
to_group
):
time
.
sleep
(
10
)
except
:
pass
if
parsed_arguments
.
dry
or
parsed_arguments
.
verbose
:
print
(
"create group {0}"
.
format
(
to_group
))
# Create the new group
if
not
parsed_arguments
.
dry
:
retry
=
0
while
retry
<
10
:
try
:
to_gitlab_group
=
gitlab_instance
.
groups
.
create
({
'name'
:
to_group
,
'path'
:
to_group
})
retry
=
99
except
Exception
as
e
:
if
parsed_arguments
.
verbose
:
print
(
"
\n
WAITING for 'gitlab_instance.groups.create()' ({0})... {1}"
.
format
(
retry
,
e
))
retry
=
retry
+
1
time
.
sleep
(
10
)
pass
if
retry
!=
99
:
raise
ValueError
(
"Cannot create group {0}. Aborting..."
.
format
(
to_group
))
# For each project
from_group_projects
=
from_gitlab_group
.
projects
.
list
(
as_list
=
False
,
lazy
=
True
)
projects_count
=
len
(
from_group_projects
)
for
group_project
in
from_group_projects
:
# Get the project instance
project
=
gitlab_instance
.
projects
.
get
(
group_project
.
id
,
lazy
=
True
)
if
parsed_arguments
.
dry
or
parsed_arguments
.
verbose
:
print
(
"fork project {0}"
.
format
(
group_project
.
path_with_namespace
))
if
not
parsed_arguments
.
dry
:
fork
=
project
.
forks
.
create
({
'namespace'
:
to_group
})
time
.
sleep
(
1
)
# Delete fork relation
forked_project
=
gitlab_instance
.
projects
.
get
(
fork
.
id
,
lazy
=
True
)
forked_project
.
delete_fork_relation
()
time
.
sleep
(
1
)
# This should not exist, but unfortunately, the group duplication is not instantaneous
# and we got http error 500, time to time.
retry
=
0
while
retry
<
50
:
try
:
group
=
gitlab_instance
.
groups
.
get
(
parsed_arguments
.
to_group
)
group_projects
=
group
.
projects
.
list
(
as_list
=
False
,
lazy
=
True
)
if
projects_count
!=
len
(
group_projects
):
raise
LookupError
(
"Not the same number of project in group {0} ({1}) and in group {2} ({3})..."
.
format
(
from_group
,
projects_count
,
to_group
,
len
(
group_projects
)
)
)
for
group_project
in
group_projects
:
if
parsed_arguments
.
verbose
:
print
(
"
\n
Project {0} forked !"
.
format
(
group_project
.
name
))
project
=
gitlab_instance
.
projects
.
get
(
group_project
.
id
)
project_branches
=
project
.
branches
.
list
()
for
project_branch
in
project_branches
:
if
parsed_arguments
.
verbose
:
print
(
"
\t
...with branch {0}"
.
format
(
project_branch
.
name
))
retry
=
99
except
Exception
as
e
:
if
not
parsed_arguments
.
dry
:
retry
=
retry
+
1
if
parsed_arguments
.
verbose
:
print
(
"
\n
WAITING for 'gitlab_instance.projects.get()' ({0})... {1}"
.
format
(
retry
,
e
))
time
.
sleep
(
60
)
pass
else
:
exit
(
0
)
if
retry
!=
99
:
raise
LookupError
(
"Cannot lookup all projects and branches on group {0}..."
.
format
(
to_group
))
if
__name__
==
"__main__"
:
main
()
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new 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