Skip to content

Instantly share code, notes, and snippets.

@patrislav1
Created February 18, 2022 17:40
Show Gist options
  • Save patrislav1/b93fbaa66fea992a35a6740ba8027472 to your computer and use it in GitHub Desktop.
Save patrislav1/b93fbaa66fea992a35a6740ba8027472 to your computer and use it in GitHub Desktop.
Show GitLab project tree as markdown
#!/usr/bin/env python3
import requests
import sys
from sortedcontainers import SortedDict, SortedList
class GitlabApi:
API_LINK = 'api/v4'
def __init__(self, url, token=""):
self.url = url
self.headers = {}
if token:
self.headers['PRIVATE-TOKEN'] = token
def get_all(self, keyword):
result = []
page = 1
while True:
api_url = '/'.join((self.url, self.API_LINK,
keyword)) + f'?page={page}'
print(f'GET {api_url}', file=sys.stderr)
response = requests.get(api_url, headers=self.headers)
response = response.json()
if not response:
break
result += response
page += 1
return result
class ProjectGroup:
def __init__(self):
self.url = None
self.subgroups = SortedDict()
self.repos = SortedList()
class ProjectTree:
def __init__(self, api):
self.api = api
self.tree = ProjectGroup()
def _add_grp_to_tree(self, tree, keys, url):
if not keys:
tree.url = url
return
if keys[0] not in tree.subgroups:
tree.subgroups[keys[0]] = ProjectGroup()
self._add_grp_to_tree(tree.subgroups[keys[0]], keys[1:], url)
def _add_proj_to_tree(self, tree, keys, url):
if not keys:
return
if len(keys) > 1:
if keys[0] not in tree.subgroups:
print(f'Key error: {keys[0]}', file=sys.stderr)
return
self._add_proj_to_tree(tree.subgroups[keys[0]], keys[1:], url)
else:
tree.repos.add((keys[0], url))
def get_groups(self):
groups = self.api.get_all('groups')
for group in groups:
grp_path = [n.strip() for n in group['full_name'].split('/')]
grp_url = group['web_url']
self._add_grp_to_tree(self.tree, grp_path, grp_url)
def get_projects(self):
projects = self.api.get_all('projects')
for project in projects:
proj_path = [n.strip()
for n in project['name_with_namespace'].split('/')]
proj_url = project['web_url']
self._add_proj_to_tree(self.tree, proj_path, proj_url)
class ProjectTreeDump:
def __init__(self, tree):
self.tree = tree
def do_dump_text(self, tree):
pad = ' ' * self.indent
self.indent += 1
for r in tree.repos:
print(f'{pad}* [{r[0]}]({r[1]})')
for k, v in tree.subgroups.items():
if not v.repos and not v.subgroups:
continue
print(f'{pad}* [**{k}**]({v.url}):')
self.do_dump_text(v)
self.indent -= 1
def dump_text(self):
self.indent = 0
self.do_dump_text(self.tree)
with open('token.txt') as f:
token = f.read().strip()
api = GitlabApi('https://msktechvcs.desy.de', token)
tree = ProjectTree(api)
tree.get_groups()
tree.get_projects()
dump = ProjectTreeDump(tree.tree)
dump.dump_text()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment