summaryrefslogtreecommitdiff
path: root/lorrycontroller
diff options
context:
space:
mode:
authorBen Hutchings <ben.hutchings@codethink.co.uk>2020-06-01 15:31:02 +0100
committerBen Hutchings <ben.hutchings@codethink.co.uk>2020-06-01 15:31:02 +0100
commit47c49a46f3614db55d7926ee27b3b889b1479a7f (patch)
tree71fa90852c95d9ae47f6aa17868482e6ced29a81 /lorrycontroller
parent6f237b32894e1fc1973834d6adc1c597ea0fa5f3 (diff)
parent85476070627f6478d236580fc3286f700e30c4ae (diff)
downloadlorry-controller-47c49a46f3614db55d7926ee27b3b889b1479a7f.tar.gz
Merge branch 'bwh/update-gitlab' into bwh/cleanup-host-types
Diffstat (limited to 'lorrycontroller')
-rw-r--r--lorrycontroller/gitlab.py85
1 files changed, 29 insertions, 56 deletions
diff --git a/lorrycontroller/gitlab.py b/lorrycontroller/gitlab.py
index 6938cae..13becfe 100644
--- a/lorrycontroller/gitlab.py
+++ b/lorrycontroller/gitlab.py
@@ -16,7 +16,7 @@
import re
import urllib.parse
-import itertools
+
try:
import gitlab
except ImportError:
@@ -45,79 +45,52 @@ class Gitlab(object):
raise MissingGitlabModuleError('gitlab module missing\n'
'\tpython-gitlab is required with GitLab as the git server')
- def first(self, predicate, iterable):
- return next(filter(predicate, iterable))
-
- def split_and_unslashify_path(self, path):
- group, project = path.split('/', 1)
- return group, project.replace('/', '_')
-
def find_project(self, repo_path):
- group, project = self.split_and_unslashify_path(repo_path)
- predicate = lambda x: x.namespace.name == group and x.name == project
-
- return self.first(predicate, self.gl.projects.search(project))
+ return self.gl.projects.get(repo_path)
def has_project(self, repo_path):
try:
- return bool(self.find_project(repo_path))
- except StopIteration:
+ self.find_project(repo_path)
+ return True
+ except gitlab.GitlabGetError:
return False
def create_project(self, repo_path):
- # GitLab only supports one level of namespacing.
- group_name, project_name = self.split_and_unslashify_path(repo_path)
- group = None
- try:
- group = self.gl.groups.get(group_name)
- except gitlab.GitlabGetError as e:
- if e.response_code == 404:
- group = self.gl.groups.create(
- {'name': group_name, 'path': group_name})
+ path_comps = repo_path.split('/')
+
+ if len(path_comps) < 2:
+ raise ValueError('cannot create GitLab project outside a group')
+
+ # Create hierarchy of groups as necessary
+ parent_group = None
+ for group_name in path_comps[:-1]:
+ if parent_group is None:
+ group_path = group_name
else:
- raise
+ group_path = parent_group.full_path + '/' + group_name
+ try:
+ group = self.gl.groups.get(group_path)
+ except gitlab.GitlabGetError as e:
+ if e.response_code != 404:
+ raise
+ data = {'name': group_name, 'path': group_name}
+ if parent_group is not None:
+ data['parent_id'] = parent_group.id
+ group = self.gl.groups.create(data)
+ parent_group = group
project = {
- 'name': project_name,
+ 'name': path_comps[-1],
'public': True,
'merge_requests_enabled': False,
'namespace_id': group.id,
- # Set the original path in the description. We will use this to
- # work around lack of multi-level namespacing.
- 'description': 'original_path: %s' % repo_path
}
self.gl.projects.create(project)
- def try_get_original_path(self, project_description):
- match = re.search('original_path:\s(.*)', str(project_description))
- if match:
- return match.groups()[0]
-
- def suitable_path(self, project):
- '''Return a path for a downstream Lorry Controller instance to consume.
-
- Should the path that was lorried have contained more than one level of
- namespacing (more than one '/' within the repository path), then for
- GitLab to handle this, we replace any '/'s (remaining in the project
- name after extracting the group name) with underscores (_). To preserve
- the original path, we set the 'original_path' within the project
- description.
- This method will attempt to return 'original_path' if it was set,
- otherwise it will return the 'path_with_namespace', being of the format
- 'group_name/project_name', rather than 'group_name/project/name'.
- '''
- return (self.try_get_original_path(project.description) or
- project.path_with_namespace)
-
def list_projects(self):
- '''List projects on a GitLab instance.
-
- In attempt to handle GitLab's current lack of multi-level namespacing
- (see: https://gitlab.com/gitlab-org/gitlab-ce/issues/2772), return
- the 'original_path' stored in a project's description, if it exists.
- '''
+ '''List projects on a GitLab instance.'''
- return [self.suitable_path(x) for x in self.gl.projects.list()]
+ return [x.path_with_namespace for x in self.gl.projects.list()]
def get_project_url(self, protocol, project_path):
'''Return the clone url for a GitLab project.