Skip to content
Snippets Groups Projects
Commit 57ec2a6e authored by nimrod's avatar nimrod
Browse files

rcfiles Python module.

- New Python module for rcfiles script.
- Move some code from git-namespace-backup to the new module in
  preperation for more Git infrastructure work.
parent 6fa9f281
No related branches found
No related tags found
No related merge requests found
...@@ -14,11 +14,14 @@ import pathlib ...@@ -14,11 +14,14 @@ import pathlib
import sys import sys
import os import os
import os.path import os.path
import re
import gitlab # pylint: disable=import-error
import sh # pylint: disable=import-error import sh # pylint: disable=import-error
from sh.contrib import git # pylint: disable=import-error from sh.contrib import git # pylint: disable=import-error
sys.path.append(os.path.expanduser("~/Documents/bin"))
import rcfiles.git # noqa: E402 pylint: disable=wrong-import-position
import rcfiles.gitlab # noqa: E402 pylint: disable=wrong-import-position
def namespace_path(namespace): def namespace_path(namespace):
"""Returns the full path to the namespace. """Returns the full path to the namespace.
...@@ -35,92 +38,55 @@ def namespace_path(namespace): ...@@ -35,92 +38,55 @@ def namespace_path(namespace):
return path return path
def name_to_path(name): def list_repositories(namespace):
"""Converts a name to valid path in GitLab.""" """Returns a list of paths under the namespace that are Git
return re.sub("[^a-zA-Z0-9_-]", "-", name).lower() repositories."""
return [x for x in namespace.iterdir() if rcfiles.git.is_repo(x)]
def get_group(lab, name): if __name__ == "__main__":
"""Returns a GitLab group object. parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("namespace", type=namespace_path)
args = parser.parse_args()
If a group with that name already exists, return that. Otherwise create a with rcfiles.gitlab.connect() as conn:
new group and return that instead. group = rcfiles.gitlab.get_group(conn, args.namespace.name)
""" if group is None:
for i in lab.groups.list(): group = rcfiles.gitlab.create_group(
if i.name == name: conn, args.namespace.name, visibility="internal"
print(
"Using existing group id: {}, name: {}, path: {}.".format(
i.id, i.name, i.path
),
file=sys.stderr,
)
return i
new_group = lab.groups.create(
{
"name": name,
"path": name_to_path(name),
"visivility": "internal",
}
) )
print( print(
"Created new group id: {}, name: {}, path: {}.".format( "Created new group id: {}, name: {}, path: {}.".format(
new_group.id, new_group.name, new_group.path group.id, group.name, group.path
), ),
file=sys.stderr, file=sys.stderr,
) )
return group else:
def get_project(group, name): # pylint: disable=redefined-outer-name
"""Returns a GitLab project.
If a project with that name already exists, return that. Otherwise create a
new project and return that instead.
"""
for i in group.projects.list():
if i.name == name:
print( print(
"Using existing project id: {}, name: {}, path: {}.".format( "Using existing group id: {}, name: {}, path: {}.".format(
i.id, i.name, i.path group.id, group.name, group.path
), ),
file=sys.stderr, file=sys.stderr,
) )
return i for repo in list_repositories(args.namespace):
new_project = group.projects.gitlab.projects.create( project = rcfiles.gitlab.get_project(conn, group.name, repo.name)
{"name": name, "namespace_id": group.id} if project is None:
project = rcfiles.gitlab.create_project(
conn, repo.name, group.name
) )
print( print(
"Created new project id: {}, name: {}, path: {}.".format( "Created new project id: {}, name: {}, path: {}.".format(
new_project.id, new_project.name, new_project.path project.id, project.name, project.path
),
file=sys.stderr,
)
else:
print(
"Using existing project id: {}, name: {}, path: {}.".format( # noqa: E501
project.id, project.name, project.path
), ),
file=sys.stderr, file=sys.stderr,
) )
return project
def is_git_repo(path):
"""Returns a boolean if the path is a Git repo."""
return path.is_dir() and pathlib.Path(path, ".git").is_dir()
def list_repositories(namespace):
"""Returns a list of paths under the namespace that are Git
repositories."""
return [x for x in namespace.iterdir() if is_git_repo(x)]
TOKEN = os.environ["GITLAB_PRIVATE_TOKEN"]
URL = os.environ["GITLAB_BASE_URL"].removesuffix("api/v4")
if __name__ == "__main__":
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("namespace", type=namespace_path)
args = parser.parse_args()
with gitlab.Gitlab(url=URL, private_token=TOKEN) as Lab:
group = get_group(Lab, args.namespace.name)
for repo in list_repositories(args.namespace):
project = get_project(group, repo.name)
with sh.pushd(repo): with sh.pushd(repo):
if "shore.co.il" in git.remote().splitlines(): if "shore.co.il" in git.remote().splitlines():
print( print(
......
"""Git repository related functions."""
import os.path
import pathlib
def is_repo(path):
"""Returns a boolean if the path is a Git repo."""
return os.path.isdir(path) and pathlib.Path(path, ".git").is_dir()
def in_repo():
"""Is the current working directory a git repo?
Because we invoke the command as a Git command (git foo) it is run from
the root of the repository if inside a repository so there's no need to
traverse up the directory hierarchy to find if we're in a Git repository,
it's enough to just check if the .git directory exists where we are.
"""
return is_repo(".")
"""A bunch of convenience functions to deal with GitLab."""
import os
import re
import gitlab # pylint: disable=import-error
def name_to_path(name):
"""Converts a name to valid path in GitLab."""
return re.sub("[^a-zA-Z0-9_-]", "-", name).lower()
def get_url():
"""Return the GitLab URL."""
return os.getenv(
"GITLAB_BASE_URL", "https://git.shore.co.il/"
).removesuffix("api/v4")
def connect():
"""Return the GitLab object."""
try:
token = os.environ["GITLAB_TOKEN"]
except KeyError:
raise Exception("GITLAB_TOKEN environment variable not set.")
url = get_url()
conn = gitlab.Gitlab(url=url, private_token=token)
conn.auth()
return conn
def get_group(conn, name):
"""Return the GitLab group object with the given name."""
for group in conn.groups.list(all=True):
if group.name == name:
return group
return None
def create_group(conn, name, visibility=None, description=None):
"""Create a new GitLab group and return that object."""
data = {
"name": name,
"path": name_to_path(name),
"visibility": "public" if visibility is None else visibility,
}
if description is not None:
data["description"] = description
return conn.groups.create(data)
def get_project(conn, group, name):
"""Returns a GitLab project."""
# pylint: disable=invalid-name
g = get_group(conn, group)
if g is None:
return None
for p in g.projects.list(all=True):
if p.name == name:
return p
return None
def create_project(conn, name, group=None, description=None, visibility=None):
"""Create a new GitLab project and return that object."""
# pylint: disable=invalid-name
data = {
"name": name,
}
if group is not None:
g = get_group(conn, group)
if g is None:
return None
data["namespace_id"] = g.id
if description is not None:
data["description"] = description
if visibility is not None:
data["visibility"] = visibility
return conn.projects.create(data)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment