first commit
This commit is contained in:
commit
8b02d3c4f1
|
@ -0,0 +1,218 @@
|
|||
# ---> Python
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
*.bk
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
pip-wheel-metadata/
|
||||
share/python-wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
MANIFEST
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.nox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
*.py,cover
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
db.sqlite3
|
||||
db.sqlite3-journal
|
||||
|
||||
# Flask stuff:
|
||||
instance/
|
||||
.webassets-cache
|
||||
|
||||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
target/
|
||||
|
||||
# Jupyter Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# IPython
|
||||
profile_default/
|
||||
ipython_config.py
|
||||
|
||||
# pyenv
|
||||
.python-version
|
||||
|
||||
# pipenv
|
||||
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||
# install all needed dependencies.
|
||||
#Pipfile.lock
|
||||
|
||||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
|
||||
__pypackages__/
|
||||
|
||||
# Celery stuff
|
||||
celerybeat-schedule
|
||||
celerybeat.pid
|
||||
|
||||
# SageMath parsed files
|
||||
*.sage.py
|
||||
|
||||
# Environments
|
||||
.env
|
||||
.venv
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
.spyproject
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
||||
|
||||
# mkdocs documentation
|
||||
/site
|
||||
|
||||
# mypy
|
||||
.mypy_cache/
|
||||
.dmypy.json
|
||||
dmypy.json
|
||||
|
||||
# Pyre type checker
|
||||
.pyre/
|
||||
|
||||
# ---> Emacs
|
||||
# -*- mode: gitignore; -*-
|
||||
*~
|
||||
\#*\#
|
||||
/.emacs.desktop
|
||||
/.emacs.desktop.lock
|
||||
*.elc
|
||||
auto-save-list
|
||||
tramp
|
||||
.\#*
|
||||
|
||||
# Org-mode
|
||||
.org-id-locations
|
||||
*_archive
|
||||
|
||||
# flymake-mode
|
||||
*_flymake.*
|
||||
|
||||
# eshell files
|
||||
/eshell/history
|
||||
/eshell/lastdir
|
||||
|
||||
# elpa packages
|
||||
/elpa/
|
||||
|
||||
# reftex files
|
||||
*.rel
|
||||
|
||||
# AUCTeX auto folder
|
||||
/auto/
|
||||
|
||||
# cask packages
|
||||
.cask/
|
||||
dist/
|
||||
|
||||
# Flycheck
|
||||
flycheck_*.el
|
||||
|
||||
# server auth directory
|
||||
/server/
|
||||
|
||||
# projectiles files
|
||||
.projectile
|
||||
|
||||
# directory configuration
|
||||
.dir-locals.el
|
||||
|
||||
# network security
|
||||
/network-security.data
|
||||
|
||||
|
||||
# ---> Vim
|
||||
# Swap
|
||||
[._]*.s[a-v][a-z]
|
||||
!*.svg # comment out if you don't need vector files
|
||||
[._]*.sw[a-p]
|
||||
[._]s[a-rt-v][a-z]
|
||||
[._]ss[a-gi-z]
|
||||
[._]sw[a-p]
|
||||
|
||||
# Session
|
||||
Session.vim
|
||||
Sessionx.vim
|
||||
|
||||
# Temporary
|
||||
.netrwhist
|
||||
*~
|
||||
# Auto-generated tag files
|
||||
tags
|
||||
# Persistent undo
|
||||
[._]*.un~
|
||||
|
||||
# ---> VirtualEnv
|
||||
# Virtualenv
|
||||
# http://iamzed.com/2009/05/07/a-primer-on-virtualenv/
|
||||
.Python
|
||||
[Bb]in
|
||||
[Ii]nclude
|
||||
[Ll]ib
|
||||
[Ll]ib64
|
||||
[Ll]ocal
|
||||
[Ss]cripts
|
||||
pyvenv.cfg
|
||||
.venv
|
||||
pip-selfcheck.json
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
Copyright (C) 2021 Alnus Tmp <alnus@disroot.org>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
@ -0,0 +1,32 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Multi migrate git to Gitea
|
||||
Copyright (C) 2019 Jovany Leandro G.C
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
|
@ -0,0 +1,203 @@
|
|||
import requests
|
||||
import json
|
||||
import click
|
||||
|
||||
__provider_git = {
|
||||
'bitbucket' : {
|
||||
'host' : 'https://api.bitbucket.org',
|
||||
'page_url' : '%s/2.0/repositories/%s?pagelen=100&fields=next,values.slug,values.links',
|
||||
'next_page_url' : None,
|
||||
'repo_name' : 'slug',
|
||||
'repo_url' : None,},
|
||||
'github' : {
|
||||
'host' : 'https://api.github.com',
|
||||
'page_url' : '%s/orgs/%s/repos?&per_page=100&page=1',
|
||||
'next_page_url' : '%s/orgs/%s/repos?&per_page=100&page=%s',
|
||||
'repo_name' : 'name',
|
||||
'repo_url' : 'clone_url',},
|
||||
'github_user' : {
|
||||
'host' : 'https://api.github.com',
|
||||
'page_url' : '%s/users/%s/repos?&per_page=100&page=1',
|
||||
'next_page_url' : '%s/users/%s/repos?&per_page=100&page=%s',
|
||||
'repo_name' : 'name',
|
||||
'repo_url' : 'clone_url',},
|
||||
'gitlab' : {
|
||||
'host' : 'https://gitlab.com/api/v4/groups/',
|
||||
'page_url' : '%s/%s/projects?per_page=100&page=1',
|
||||
'next_page_url' : '%s/%s/projects?per_page=100&page=%s',
|
||||
'repo_name' : 'name',
|
||||
'repo_url' : 'web_url', },
|
||||
}
|
||||
|
||||
@click.group()
|
||||
def cli():
|
||||
pass
|
||||
|
||||
def listRepos(provider_git, team_org, verbose = False):
|
||||
count = 1
|
||||
host = __provider_git[provider_git]['host']
|
||||
repo_name = __provider_git[provider_git]['repo_name']
|
||||
page_url = __provider_git[provider_git]['page_url'] % (host, team_org)
|
||||
response = requests.get(page_url)
|
||||
page_json = response.json()
|
||||
repos = {}
|
||||
print(page_url)
|
||||
if provider_git == 'bitbucket':
|
||||
while page_url is not None:
|
||||
response = requests.get(page_url)
|
||||
page_json = response.json()
|
||||
# Parse repositories from the JSON
|
||||
if "error" not in page_json:
|
||||
for repo in page_json['values']:
|
||||
if verbose:
|
||||
print(repo[repo_name])
|
||||
repos[repo[repo_name]] = repo['links']['clone'][0]['href']
|
||||
page_url = page_json.get('next', None)
|
||||
else:
|
||||
page_url = None
|
||||
else:
|
||||
while len(page_json) >= count:
|
||||
for repo in page_json:
|
||||
if isinstance(repo, dict):
|
||||
if verbose:
|
||||
print(repo[repo_name])
|
||||
repo_url = repo[__provider_git[provider_git]['repo_url']]
|
||||
repos[repo[repo_name]] = repo_url
|
||||
count += 1
|
||||
next_page_url = __provider_git[provider_git]['next_page_url'] % (host, team_org, count)
|
||||
response = requests.get(next_page_url)
|
||||
page_json = response.json()
|
||||
return repos
|
||||
|
||||
class Gitea():
|
||||
|
||||
def listORGS(host, headers = None):
|
||||
ORGS_URI = "/orgs"
|
||||
ENDPOINT_ORGS = "%s%s" % (host, ORGS_URI)
|
||||
|
||||
try:
|
||||
r = requests.get(url=url, headers=headers)
|
||||
if r.status_code != 200:
|
||||
return r.content
|
||||
else:
|
||||
return "Done: %s" % (r.content)
|
||||
except Not_Connect:
|
||||
print("Fail")
|
||||
|
||||
def listRepo(host, team, headers, verbose = False):
|
||||
next_page_url = '%s/orgs/%s/repos?page=1&limit=50' % (host, team)
|
||||
response = requests.get(next_page_url, headers = headers)
|
||||
page_json = response.json()
|
||||
|
||||
count = 1
|
||||
repos = {}
|
||||
|
||||
while len(page_json) >= count:
|
||||
for repo in page_json:
|
||||
if isinstance(repo, dict):
|
||||
if verbose:
|
||||
print(repo['name'])
|
||||
repos[repo['name']] = repo['clone_url']
|
||||
count += 1
|
||||
next_page_url = '%s/orgs/%s/repos?limit=50&page=%s' % (host, team, count)
|
||||
response = requests.get(next_page_url, headers = headers)
|
||||
page_json = response.json()
|
||||
return repos
|
||||
|
||||
def foundBranch(url, branch, headers = None, repo = None):
|
||||
url_branch = "%s/%s/branches/%s" % (url, repo, branch)
|
||||
try:
|
||||
r = requests.get(url=url_branch, headers=headers)
|
||||
if r.status_code == 200:
|
||||
return repo
|
||||
except Not_Connect:
|
||||
print("Fail")
|
||||
|
||||
def createMirror(team, clone_addr, repo_name, uid, private, url, headers = None):
|
||||
migrate_data = {}
|
||||
migrate_data["mirror"] = True
|
||||
migrate_data["UID"] = uid
|
||||
migrate_data["repo_name"] = repo_name
|
||||
migrate_data["clone_addr"] = clone_addr
|
||||
migrate_data["private"] = private
|
||||
migrate_data["repo_owner"] = team
|
||||
|
||||
try:
|
||||
r = requests.post(url=url, data=json.dumps(migrate_data), headers=headers)
|
||||
if r.status_code != 200 or r.status_code != 201:
|
||||
return "Non-OK Response: %s" % (r.content)
|
||||
else:
|
||||
return "Done: %s" % (r.status_code)
|
||||
except Not_Connect:
|
||||
print("Fail")
|
||||
|
||||
@click.command()
|
||||
@click.option('--provider_git',
|
||||
type=click.Choice([*__provider_git],
|
||||
case_sensitive=False),
|
||||
required=True)
|
||||
@click.option('--team_org', required=True)
|
||||
@click.option('--verbose', default=False)
|
||||
def list_repo(provider_git, team_org, verbose):
|
||||
listRepos(provider_git, team_org, verbose)
|
||||
|
||||
@click.command()
|
||||
@click.option('--domain', required=True)
|
||||
@click.option('--team_org', required=True)
|
||||
@click.option('--access_token', default=None)
|
||||
def list_repo_token(domain, team_org, access_token):
|
||||
HOST = "https://%s/api/v1" % (domain)
|
||||
HEADERS = { "accept": "application/json", "content-type": "application/json" }
|
||||
HEADERS["Authorization"] = "token %s" % (access_token)
|
||||
Gitea.listRepo(host = HOST, team = team_org, headers = HEADERS)
|
||||
|
||||
@click.command()
|
||||
@click.option('--domain', required=True)
|
||||
@click.option('--provider_git',
|
||||
type=click.Choice([*__provider_git],
|
||||
case_sensitive=False),
|
||||
required=True)
|
||||
@click.option('--team_org_source', required=True)
|
||||
@click.option('--team_org_dest', required=True)
|
||||
@click.option('--access_token', default=None)
|
||||
@click.option('--private', default=True)
|
||||
@click.option('--verbose', default=False)
|
||||
def mirror_repo(domain, provider_git, team_org_source,
|
||||
team_org_dest, access_token, private, verbose):
|
||||
repos = listRepos(provider_git, team_org_source, verbose)
|
||||
HOST = "https://%s/api/v1" % (domain)
|
||||
MIGRATE_URI = "/repos/migrate"
|
||||
ENDPOINT_MIGRATE = "%s%s" % (HOST, MIGRATE_URI)
|
||||
HEADERS = { "accept": "application/json", "content-type": "application/json" }
|
||||
HEADERS["Authorization"] = "token %s" % (access_token)
|
||||
count = 0
|
||||
for repo in repos:
|
||||
count += 1
|
||||
print(Gitea.createMirror(team_org_dest, repos[repo],
|
||||
repo, 1, private, ENDPOINT_MIGRATE, headers = HEADERS))
|
||||
|
||||
@click.command()
|
||||
@click.option('--domain', required=True)
|
||||
@click.option('--team_org', required=True)
|
||||
@click.option('--access_token', default=None)
|
||||
@click.option('--private', default=True)
|
||||
@click.option('--branch', required=True)
|
||||
def get_branch_repo_gitea(domain, team_org, access_token,
|
||||
private, branch):
|
||||
HOST = "https://%s/api/v1" % (domain)
|
||||
BRANCH_URI = "/repos/%s" % (team_org)
|
||||
ENDPOINT_BRANCH = "%s%s" % (HOST, BRANCH_URI)
|
||||
HEADERS = { "accept": "application/json", "content-type": "application/json" }
|
||||
HEADERS["Authorization"] = "token %s" % (access_token)
|
||||
repos = Gitea.listRepo(HOST, team_org, HEADERS)
|
||||
for repo in repos:
|
||||
if Gitea.foundBranch(ENDPOINT_BRANCH, branch, HEADERS, repo):
|
||||
print(repo)
|
||||
|
||||
cli.add_command(list_repo)
|
||||
cli.add_command(list_repo_token)
|
||||
cli.add_command(mirror_repo)
|
||||
cli.add_command(get_branch_repo_gitea)
|
||||
|
||||
if __name__ == '__main__':
|
||||
cli()
|
|
@ -0,0 +1,44 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from setuptools import setup, find_packages
|
||||
|
||||
with open('README.md') as readme_file:
|
||||
readme = readme_file.read()
|
||||
|
||||
with open('HISTORY.rst') as history_file:
|
||||
history = history_file.read()
|
||||
|
||||
requirements = ['Click==8.0.3',
|
||||
'requests==2.26.0']
|
||||
|
||||
setup(
|
||||
author="Alnus Tmp",
|
||||
author_email='alnus@disroot.org',
|
||||
classifiers=[
|
||||
'Development Status :: 2 - Pre-Alpha',
|
||||
'Intended Audience :: Developers',
|
||||
'License :: OSI Approved :: GNU General Public License v3 (GPLv3)',
|
||||
'Natural Language :: English',
|
||||
'Programming Language :: Python :: 3',
|
||||
'Programming Language :: Python :: 3.4',
|
||||
'Programming Language :: Python :: 3.5',
|
||||
'Programming Language :: Python :: 3.6',
|
||||
'Programming Language :: Python :: 3.7',
|
||||
],
|
||||
description="Multi migrate git hosted to Gitea",
|
||||
py_modules=['migrate_to_gitea'],
|
||||
entry_points={
|
||||
'console_scripts': [
|
||||
'migrate_to_gitea=migrate_to_gitea:cli',
|
||||
],
|
||||
},
|
||||
install_requires=requirements,
|
||||
license="GNU General Public License v3",
|
||||
long_description=readme + '\n\n' + history,
|
||||
long_description_content_type='text/x-rst',
|
||||
keywords='migrate, gitea',
|
||||
name='multimigrate_to_gitea',
|
||||
url='https://github.com/bit4bit/facho',
|
||||
version='0.1.0'
|
||||
)
|
Loading…
Reference in New Issue