Did a lot of work for project migration, fixed some stuff with user migration, optimized comparisons

This commit is contained in:
Enrico Ludwig 2024-07-18 18:20:30 +02:00
parent 14c9139718
commit 66db60e2ef

View File

@ -25,9 +25,13 @@
# --no-update-existing-users Do not update existing users on Gitea (default: False)
# --no-update-existing-projects Do not update existing projects on Gitea (default: False)
#
# --include-wiki Include wiki repositories (default: False) - not implemented yet
# --include-issues Include issues repositories (default: False) - not implemented yet
# --include-merge-requests Include merge requests repositories (default: False) - not implemented yet
#
# --override-groups Override existing groups on Gitea (default: False) - not implemented yet
# --override-users Override existing users on Gitea (default: False) - not implemented yet
# --override-projects Override existing projects on Gitea (default: False) - not implemented yet
# --override-projects Override existing projects on Gitea (default: False)
#
# --skip-empty-groups Skip empty groups (default: False) - not implemented yet
# --skip-empty-projects Skip empty projects (default: False) - not implemented yet
@ -73,9 +77,13 @@ NO_UPDATE_EXISTING_GROUPS = False
NO_UPDATE_EXISTING_USERS = False
NO_UPDATE_EXISTING_PROJECTS = False
OVERWRITE_EXISTING_GROUPS = False
OVERWRITE_EXISTING_USERS = False
OVERWRITE_EXISTING_PROJECTS = False
INCLUDE_WIKI = False
INCLUDE_ISSUES = False
INCLUDE_MERGE_REQUESTS = False
OVERRIDE_EXISTING_GROUPS = False
OVERRIDE_EXISTING_USERS = False
OVERRIDE_EXISTING_PROJECTS = False
ONLY_GROUPS = False
ONLY_USERS = False
@ -92,7 +100,52 @@ QUIET = False
# Internal variables - Do not change
APP_NAME = "GitLab2Gitea"
APP_VERSION = "1.0"
APP_AUTHOR = "Zion Networks"
GITEA_RESERVED_USERNAMES = ["ghost", "notifications"]
GITEA_RESERVED_ORGANAMES = [
"api",
"assets",
"attachments",
"avatar",
"commit",
"commits",
"debug",
"error",
"explore",
"faq",
"issues",
"mail",
"milestone",
"new",
"notifications",
"org",
"organizations",
"plugins",
"pull",
"pulls",
"repo",
"repositories",
"script",
"user",
"users",
]
GITEA_RESERVED_REPONAMES = [
"api",
"assets",
"issues",
"labels",
"milestones",
"notifications",
"projects",
"pr",
"pulls",
"repo",
"repos",
"settings",
"wiki",
]
# Imports
@ -101,6 +154,7 @@ import sys
import argparse
import requests
import traceback
import json
# Set cwd to script directory
@ -143,14 +197,23 @@ if "NO_UPDATE_EXISTING_USERS" in os.environ:
if "NO_UPDATE_EXISTING_PROJECTS" in os.environ:
NO_UPDATE_EXISTING_PROJECTS = bool(os.environ["NO_UPDATE_EXISTING_PROJECTS"])
if "INCLUDE_WIKI" in os.environ:
INCLUDE_WIKI = bool(os.environ["INCLUDE_WIKI"])
if "INCLUDE_ISSUES" in os.environ:
INCLUDE_ISSUES = bool(os.environ["INCLUDE_ISSUES"])
if "INCLUDE_MERGE_REQUESTS" in os.environ:
INCLUDE_MERGE_REQUESTS = bool(os.environ["INCLUDE_MERGE_REQUESTS"])
if "OVERWRITE_EXISTING_GROUPS" in os.environ:
OVERWRITE_EXISTING_GROUPS = bool(os.environ["OVERWRITE_EXISTING_GROUPS"])
OVERRIDE_EXISTING_GROUPS = bool(os.environ["OVERRIDE_EXISTING_GROUPS"])
if "OVERWRITE_EXISTING_USERS" in os.environ:
OVERWRITE_EXISTING_USERS = bool(os.environ["OVERWRITE_EXISTING_USERS"])
OVERRIDE_EXISTING_USERS = bool(os.environ["OVERRIDE_EXISTING_USERS"])
if "OVERWRITE_EXISTING_PROJECTS" in os.environ:
OVERWRITE_EXISTING_PROJECTS = bool(os.environ["OVERWRITE_EXISTING_PROJECTS"])
OVERRIDE_EXISTING_PROJECTS = bool(os.environ["OVERRIDE_EXISTING_PROJECTS"])
if "ONLY_GROUPS" in os.environ:
ONLY_GROUPS = bool(os.environ["ONLY_GROUPS"])
@ -232,17 +295,29 @@ if os.path.exists(".env"):
if value.lower() == "true" or value == "1":
NO_UPDATE_EXISTING_PROJECTS = True
if key == "OVERWRITE_EXISTING_GROUPS":
if key == "INCLUDE_WIKI":
if value.lower() == "true" or value == "1":
OVERWRITE_EXISTING_GROUPS = True
INCLUDE_WIKI = True
if key == "OVERWRITE_EXISTING_USERS":
if key == "INCLUDE_ISSUES":
if value.lower() == "true" or value == "1":
OVERWRITE_EXISTING_USERS = True
INCLUDE_ISSUES = True
if key == "OVERWRITE_EXISTING_PROJECTS":
if key == "INCLUDE_MERGE_REQUESTS":
if value.lower() == "true" or value == "1":
OVERWRITE_EXISTING_PROJECTS = True
INCLUDE_MERGE_REQUESTS = True
if key == "OVERRIDE_EXISTING_GROUPS":
if value.lower() == "true" or value == "1":
OVERRIDE_EXISTING_GROUPS = True
if key == "OVERRIDE_EXISTING_USERS":
if value.lower() == "true" or value == "1":
OVERRIDE_EXISTING_USERS = True
if key == "OVERRIDE_EXISTING_PROJECTS":
if value.lower() == "true" or value == "1":
OVERRIDE_EXISTING_PROJECTS = True
if key == "ONLY_GROUPS":
if value.lower() == "true" or value == "1":
@ -296,6 +371,9 @@ parser.add_argument("--no-create-missing-projects", help="Do not create missing
parser.add_argument("--no-update-existing-groups", help="Do not update existing groups on Gitea", action="store_true")
parser.add_argument("--no-update-existing-users", help="Do not update existing users on Gitea", action="store_true")
parser.add_argument("--no-update-existing-projects", help="Do not update existing projects on Gitea", action="store_true")
parser.add_argument("--include-wiki", help="Include wiki repositories", action="store_true")
parser.add_argument("--include-issues", help="Include issues repositories", action="store_true")
parser.add_argument("--include-merge-requests", help="Include merge requests repositories", action="store_true")
parser.add_argument("--override-groups", help="Override existing groups on Gitea", action="store_true")
parser.add_argument("--override-users", help="Override existing users on Gitea", action="store_true")
parser.add_argument("--override-projects", help="Override existing projects on Gitea", action="store_true")
@ -348,14 +426,23 @@ if args.no_update_existing_users:
if args.no_update_existing_projects:
NO_UPDATE_EXISTING_PROJECTS = True
if args.include_wiki:
INCLUDE_WIKI = True
if args.include_issues:
INCLUDE_ISSUES = True
if args.include_merge_requests:
INCLUDE_MERGE_REQUESTS = True
if args.override_groups:
OVERWRITE_EXISTING_GROUPS = True
OVERRIDE_EXISTING_GROUPS = True
if args.override_users:
OVERWRITE_EXISTING_USERS = True
OVERRIDE_EXISTING_USERS = True
if args.override_projects:
OVERWRITE_EXISTING_PROJECTS = True
OVERRIDE_EXISTING_PROJECTS = True
if args.only_groups:
ONLY_GROUPS = True
@ -398,37 +485,37 @@ if ONLY_USERS and ONLY_PROJECTS:
_error("Options --only-users and --only-projects are mutually exclusive!")
sys.exit(1)
if NO_CREATE_MISSING_GROUPS and OVERWRITE_EXISTING_GROUPS:
if NO_CREATE_MISSING_GROUPS and OVERRIDE_EXISTING_GROUPS:
_error(
"Options --no-create-missing-groups and --override-groups are mutually exclusive!"
)
sys.exit(1)
if NO_CREATE_MISSING_USERS and OVERWRITE_EXISTING_USERS:
if NO_CREATE_MISSING_USERS and OVERRIDE_EXISTING_USERS:
_error(
"Options --no-create-missing-users and --override-users are mutually exclusive!"
)
sys.exit(1)
if NO_CREATE_MISSING_PROJECTS and OVERWRITE_EXISTING_PROJECTS:
if NO_CREATE_MISSING_PROJECTS and OVERRIDE_EXISTING_PROJECTS:
_error(
"Options --no-create-missing-projects and --override-projects are mutually exclusive!"
)
sys.exit(1)
if NO_UPDATE_EXISTING_GROUPS and OVERWRITE_EXISTING_GROUPS:
if NO_UPDATE_EXISTING_GROUPS and OVERRIDE_EXISTING_GROUPS:
_error(
"Options --no-update-existing-groups and --override-groups are mutually exclusive!"
)
sys.exit(1)
if NO_UPDATE_EXISTING_USERS and OVERWRITE_EXISTING_USERS:
if NO_UPDATE_EXISTING_USERS and OVERRIDE_EXISTING_USERS:
_error(
"Options --no-update-existing-users and --override-users are mutually exclusive!"
)
sys.exit(1)
if NO_UPDATE_EXISTING_PROJECTS and OVERWRITE_EXISTING_PROJECTS:
if NO_UPDATE_EXISTING_PROJECTS and OVERRIDE_EXISTING_PROJECTS:
_error(
"Options --no-update-existing-projects and --override-projects are mutually exclusive!"
)
@ -510,7 +597,22 @@ def _exception(exception, custom_message=None):
def is_gitea_reserved_username(username: str) -> bool:
return username in GITEA_RESERVED_USERNAMES
return username.lower() in [name.lower() for name in GITEA_RESERVED_USERNAMES]
def is_gitea_reserved_organame(organame: str) -> bool:
return organame.lower() in [name.lower() for name in GITEA_RESERVED_ORGANAMES]
def is_gitea_reserved_reponame(reponame: str) -> bool:
return reponame.lower() in [name.lower() for name in GITEA_RESERVED_REPONAMES]
def is_gitlab_project_in_subgroup(project: dict) -> bool:
return (
project["namespace"]["kind"] == "group"
and project["namespace"]["parent_id"] is not None
)
def gitlab2gitea_visibility(visibility: str) -> str:
@ -704,6 +806,63 @@ def get_gitlab_projects() -> list:
return projects
# Endpoint: POST /api/{GITLAB_API_VERSION}/repos/migrate
def migrate_gitlab_project_to_gitea(gitlab_project: dict):
if not gitlab_project:
raise Exception("GitLab project is missing!")
# Create Gitea project
_debug(f"REQUEST: POST {GITEA_URL}/api/{GITEA_API_VERSION}/repos/migrate")
response = requests.post(
f"{GITEA_URL}/api/{GITEA_API_VERSION}/repos/migrate",
json={
"auth_token": GITEA_TOKEN,
"repo_name": gitlab_project["path"],
"repo_owner": (
gitlab_project["namespace"]["path"]
if gitlab_project["namespace"]["kind"] == "group"
else gitlab_project["owner"]["username"]
),
"description": gitlab_project["description"],
"clone_addr": gitlab_project["http_url_to_repo"],
"service": "gitlab",
"issues": INCLUDE_ISSUES,
"pull_requests": INCLUDE_MERGE_REQUESTS,
"wiki": INCLUDE_WIKI,
"releases": True,
"labels": True,
"lfs": True,
"milestones": True,
"mirror": False,
# fmt: off
"private": gitlab2gitea_visibility(gitlab_project["visibility"]) == "private",
# fmt: on
},
headers={
"Content-Type": "application/json",
"Accept": "application/json",
"Authorization": f"token {GITEA_TOKEN}",
},
)
_trace(f"RESPONSE: {response.json()}")
if response.status_code != 201:
response_message = (
response.json()["message"]
if "message" in response.json()
else "Unknown error"
)
raise Exception(f"Failed to create Gitea project: {response_message}")
else:
project = response.json()
return project
# Endpoint: POST /api/{GITEA_API_VERSION}/admin/users
def migrate_gitlab_user_to_gitea(user: dict):
@ -921,6 +1080,87 @@ def update_gitea_org(data: dict) -> dict:
return group
# Endpoint: PATCH /api/{GITEA_API_VERSION}/admin/users/{username}
def update_gitea_user(data: dict) -> dict:
if not data:
raise Exception("Data is missing!")
username = data["username"]
current_user = get_gitea_user(username)
updated_user = convert_gitlab_user_to_gitea(data)
to_compare = {
"active": True,
"login": True,
"login_name": True,
"username": True,
"email": True,
"full_name": True,
"admin": True,
"prohibit_login": True,
"restricted": True,
"website": True,
"visibility": True,
}
mapping = {
"is_admin": "admin",
}
ignore = {"allow_create_organization": True}
is_different, results = cmp_dicts(
current_user, updated_user, to_compare, mapping, ignore
)
_trace(f"COMPARISON: {results}")
if not is_different:
_info(f'User "{username}" is already up-to-date on Gitea')
return current_user
if is_gitea_reserved_username(username):
_warn(f'User "{username}" is a reserved username on Gitea!')
return None
if not current_user:
raise Exception(f'User "{username}" not found on Gitea!')
_debug(f"REQUEST: PATCH {GITEA_URL}/api/{GITEA_API_VERSION}/admin/users/{username}")
# TODO seems to have issues, since users do not get updated properly
response = requests.patch(
f"{GITEA_URL}/api/{GITEA_API_VERSION}/admin/users/{username}",
json=updated_user,
headers={
"Content-Type": "application/json",
"Accept": "application/json",
"Authorization": f"token {GITEA_TOKEN}",
},
)
_trace(f"RESPONSE: {response.json()}")
if response.status_code != 200:
response_message = (
response.json()["message"]
if "message" in response.json()
else "Unknown error"
)
raise Exception(f"Failed to update Gitea user: {response_message}")
else:
user = response.json()
return user
def update_gitea_project(data: dict) -> dict:
_warn("Function update_gitea_project is not implemented yet!")
pass
# Endpoint: GET /api/{GITEA_API_VERSION}/users/{username}
def get_gitea_user(username: str) -> dict:
@ -950,68 +1190,86 @@ def get_gitea_user(username: str) -> dict:
return user
# Endpoint: PATCH /api/{GITEA_API_VERSION}/admin/users/{username}
def update_gitea_user(data: dict) -> dict:
def remap_keys(d, mapping):
def nested_get(d, keys):
for key in keys.split("/"):
d = d[key]
return d
if not data:
raise Exception("Data is missing!")
def nested_set(d, keys, value):
keys = keys.split("/")
for key in keys[:-1]:
d = d.setdefault(key, {})
d[keys[-1]] = value
username = data["username"]
current_user = get_gitea_user(username)
updated_user = convert_gitlab_user_to_gitea(data, current_user)
if is_gitea_reserved_username(username):
_warn(f'User "{username}" is a reserved username on Gitea!')
return None
if not current_user:
raise Exception(f'User "{username}" not found on Gitea!')
_debug(f"REQUEST: PATCH {GITEA_URL}/api/{GITEA_API_VERSION}/admin/users/{username}")
response = requests.patch(
f"{GITEA_URL}/api/{GITEA_API_VERSION}/admin/users/{username}",
json=updated_user,
headers={
"Content-Type": "application/json",
"Accept": "application/json",
"Authorization": f"token {GITEA_TOKEN}",
remapped = {}
for k, v in d.items():
if k in mapping:
nested_set(remapped, mapping[k], v)
elif isinstance(v, dict):
remapped[k] = remap_keys(
v,
{
f"{k}/{subkey}": subvalue
for subkey, subvalue in mapping.items()
if subkey.startswith(f"{k}/")
},
)
_trace(f"RESPONSE: {response.json()}")
if response.status_code != 200:
response_message = (
response.json()["message"]
if "message" in response.json()
else "Unknown error"
)
raise Exception(f"Failed to update Gitea user: {response_message}")
else:
user = response.json()
return user
remapped[k] = v
return remapped
def cmp_gitea_userdata(userdata_a: dict, userdata_b: dict) -> bool:
def is_ignored(path_to_check, ignore_dict):
def nested_get(d, keys):
for key in keys:
if key in d:
d = d[key]
else:
return False
return True if isinstance(d, dict) and d else False
return nested_get(ignore_dict, path_to_check)
def cmp_dicts(
dict_a: dict,
dict_b: dict,
check: dict = None,
mapping: dict = None,
ignore: dict = None,
) -> bool:
result = {}
for key in userdata_a:
if key in userdata_b:
if userdata_a[key] != userdata_b[key]:
result[key] = True
else:
result[key] = False
else:
result[key] = True
if mapping:
dict_a = remap_keys(dict_a, mapping)
has_changes = False
for key in result:
if result[key]:
has_changes = True
break
def compare_dicts(a, b, to_check, path=[]):
all_keys = set(a.keys()).union(b.keys())
if to_check is not None:
all_keys = all_keys.intersection(to_check.keys())
for key in all_keys:
current_path = path + [key]
if ignore and is_ignored(current_path, ignore):
continue
if key in a and key in b:
if (
isinstance(a[key], dict)
and isinstance(b[key], dict)
and to_check
and key in to_check
):
compare_dicts(a[key], b[key], to_check[key], current_path)
else:
result[tuple(current_path)] = a[key] != b[key]
else:
result[tuple(current_path)] = True
compare_dicts(dict_a, dict_b, check)
has_changes = any(result.values())
return has_changes, result
@ -1020,15 +1278,17 @@ def convert_gitlab_user_to_gitea(user: dict, extra_data: dict = None) -> dict:
gitea_user = {
"active": user["state"] == "active",
"login": user["username"],
"login_name": user["username"],
"avatar_url": user["avatar_url"],
"created": user["created_at"],
"description": user["bio"],
"username": user["username"],
"email": user["email"],
"full_name": user["name"],
"is_admin": user["is_admin"],
"admin": user["is_admin"],
"prohibit_login": user["state"] == "blocked" or user["locked"],
"restricted": user["state"] == "blocked" or user["locked"],
"website": user["website_url"],
"visibility": "private" if user["private_profile"] else "public",
"allow_create_organization": user["can_create_group"],
}
if extra_data:
@ -1115,7 +1375,45 @@ def cmp_gitlab_gitea_users(gitlab_users: list, gitea_users: list) -> dict:
def cmp_gitlab_gitea_projects(gitlab_projects: list, gitea_projects: list) -> dict:
return {}, 0
compare_result = {}
missing_matches = 0
for gitlab_project in gitlab_projects:
exists = False
name = gitlab_project["path"]
owner = gitlab_project["namespace"]["path"]
for gitea_project in gitea_projects["data"]:
# fmt: off
if (name == gitea_project["name"] and owner == gitea_project["owner"]["username"]):
exists = True
break
if exists:
_info(f'GITLAB: Project "{owner}/{name}" exists on both GitLab and Gitea')
else:
_warn(f'GITLAB: Project "{owner}/{name}" exists on GitLab only')
missing_matches += 1
compare_result[name] = 0 if exists else 1
for gitea_project in gitea_projects["data"]:
exists = False
name = gitea_project["name"]
owner = gitea_project["owner"]["username"]
for gitlab_project in gitlab_projects:
# fmt: off
if name == gitlab_project["path"] and owner == gitlab_project["namespace"]["path"]:
exists = True
break
# fmt: on
if not exists:
_warn(f'GITEA: Project "{owner}/{name}" exists on Gitea only')
compare_result[name] = 2
return compare_result, missing_matches
def create_missing_groups(gitlab_groups: list, gitea_groups: list):
@ -1129,10 +1427,15 @@ def create_missing_groups(gitlab_groups: list, gitea_groups: list):
exists = True
break
if is_gitea_reserved_organame(name):
_warn(f'Skipping group "{name}": Group name is reserved on Gitea!')
continue
if not exists:
_info(f'Creating missing group "{name}" on Gitea...')
try:
_info(f'Migrating Gitlab group "{name}" to Gitea...')
migrate_gitlab_group_to_gitea(gitlab_group)
except Exception as e:
_exception(f'Failed to create Gitea group "{name}": {e}', e)
@ -1160,20 +1463,61 @@ def create_missing_users(gitlab_users: list, gitea_users: list):
continue
if is_gitea_reserved_username(name):
_warn(f'User "{name}" is a reserved username on Gitea!')
_warn(f'Skipping user "{name}": Username is reserved on Gitea!')
continue
if not exists:
_info(f'Creating missing user "{name}" on Gitea...')
try:
_info(f'Migrating Gitlab user "{name}" to Gitea...')
migrate_gitlab_user_to_gitea(gitlab_user)
except Exception as e:
_exception(f'Failed to create Gitea user "{name}": {e}', e)
def create_missing_projects(gitlab_projects: list, gitea_projects: list):
pass
for gitlab_project in gitlab_projects:
exists = False
name = gitlab_project["path"]
group = gitlab_project["namespace"]["path"]
for gitea_project in gitea_projects["data"]:
if (
name == gitea_project["name"]
and group == gitea_project["owner"]["username"]
):
exists = True
break
if is_gitea_reserved_reponame(name):
_warn(f'Skipping project "{name}": Project name is reserved on Gitea!')
continue
if is_gitlab_project_in_subgroup(gitlab_project):
_warn(
f'Skipping project "{name}": Project is in a subgroup and not supported by Gitea!'
)
continue
if not exists:
_info(f'Creating missing project "{name}" on Gitea...')
try:
_info(f'Migrating Gitlab project "{name}" to Gitea...')
migrate_gitlab_project_to_gitea(gitlab_project)
if DEBUG:
_warn("DEBUG MODE ENABLED - BREAKING AFTER FIRST PROJECT")
break
except Exception as e:
_exception(f'Failed to create Gitea project "{name}": {e}', e)
if DEBUG:
_warn("DEBUG MODE ENABLED - BREAKING AFTER FIRST PROJECT")
break
def update_existing_groups(gitlab_groups: list, gitea_groups: list):
@ -1186,10 +1530,13 @@ def update_existing_groups(gitlab_groups: list, gitea_groups: list):
exists = True
break
if exists:
_info(f'Updating existing group "{name}" on Gitea...')
if is_gitea_reserved_organame(name):
_warn(f'Skipping group "{name}": Group name is reserved on Gitea!')
continue
if exists:
try:
_info(f'Updating existing group "{name}" on Gitea...')
update_gitea_org(
{
"path": gitlab_group["path"],
@ -1226,9 +1573,13 @@ def update_existing_users(gitlab_users: list, gitea_users: list):
_warn(f'User "{name}" does not have a username and will not be updated!')
continue
if is_gitea_reserved_username(name):
_warn(f'Skipping user "{name}": Username is reserved on Gitea!')
continue
if exists:
_info(f'Updating existing user "{name}" on Gitea...')
try:
_info(f'Updating existing user "{name}" on Gitea...')
update_gitea_user(gitlab_user)
except Exception as e:
_exception(f'Failed to update Gitea user "{name}": {e}', e)
@ -1237,10 +1588,86 @@ def update_existing_users(gitlab_users: list, gitea_users: list):
def update_existing_projects(gitlab_projects: list, gitea_projects: list):
pass
# update existing projects
for gitlab_project in gitlab_projects:
exists = False
name = gitlab_project["path"]
group = gitlab_project["namespace"]["path"]
for gitea_project in gitea_projects["data"]:
if (
name == gitea_project["name"]
and group == gitea_project["owner"]["username"]
):
exists = True
break
if is_gitea_reserved_reponame(name):
_warn(f'Skipping project "{name}": Project name is reserved on Gitea!')
continue
if is_gitlab_project_in_subgroup(gitlab_project):
_warn(
f'Skipping project "{name}": Project is in a subgroup and not supported by Gitea!'
)
continue
if exists:
try:
_info(f'Updating existing project "{name}" on Gitea...')
if OVERRIDE_EXISTING_PROJECTS:
delete_gitea_project(gitea_project)
migrate_gitlab_project_to_gitea(gitlab_project)
else:
update_gitea_project(gitlab_project)
if DEBUG:
_warn("DEBUG MODE ENABLED - BREAKING AFTER FIRST PROJECT")
break
except Exception as e:
_exception(f'Failed to update Gitea project "{name}": {e}', e)
if DEBUG:
_warn("DEBUG MODE ENABLED - BREAKING AFTER FIRST PROJECT")
break
else:
_warn(f'Project "{name}" does not exist on Gitea!')
# ENDPOINT: DELETE /api/{GITEA_API_VERSION}/repos/{owner}/{repo}
def delete_gitea_project(project: dict):
owner = project["owner"]["username"]
repo = project["name"]
_debug(f"REQUEST: DELETE {GITEA_URL}/api/{GITEA_API_VERSION}/repos/{owner}/{repo}")
response = requests.delete(
f"{GITEA_URL}/api/{GITEA_API_VERSION}/repos/{owner}/{repo}",
headers={
"Content-Type": "application/json",
"Accept": "application/json",
"Authorization": f"token {GITEA_TOKEN}",
},
)
_trace(f"RESPONSE: {response.json()}")
if response.status_code != 204:
response_message = (
response.json()["message"]
if "message" in response.json()
else "Unknown error"
)
raise Exception(f"Failed to delete Gitea project: {response_message}")
else:
_info(f'Project "{owner}/{repo}" deleted on Gitea')
def migrate_groups():
gitlab_groups = get_gitlab_groups()
gitea_groups = get_gitea_groups()
@ -1332,12 +1759,14 @@ def migrate_users():
def migrate_projects():
if OVERRIDE_EXISTING_PROJECTS:
_warn("EXISTING PROJECTS WILL BE OVERRIDDEN!")
gitlab_projects = get_gitlab_projects()
gitea_projects = get_gitea_projects()
# dump the projects to json files
import json
with open("gitlab_projects.json", "w") as f:
json.dump(gitlab_projects, f, indent=4)
@ -1419,8 +1848,10 @@ def run_migration():
def main():
_info("Gitlab2Gitea v1.0 - by Zion Networks")
_info("------------------------------------")
header_info = f"{APP_NAME} v{APP_VERSION} - by {APP_AUTHOR}"
_info(f"{header_info}")
_info("-" * len(header_info))
_info("")
if sys.version_info < (3, 6):