From 9632874369753767a42d5617ee0ea888bf1b18b4 Mon Sep 17 00:00:00 2001 From: Ben Brown Date: Tue, 26 Apr 2016 09:48:13 +0100 Subject: Workaround for GitLab's lack of multi-level namespacing Change-Id: Ic1ef8b983cc84b0ce75dc57f9e05b5cdda343dc6 --- lorrycontroller/gitlab.py | 42 +++++++++++++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/lorrycontroller/gitlab.py b/lorrycontroller/gitlab.py index 659d179..b22bb30 100644 --- a/lorrycontroller/gitlab.py +++ b/lorrycontroller/gitlab.py @@ -14,6 +14,7 @@ # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. from __future__ import absolute_import +import re import urlparse import itertools try: @@ -47,24 +48,25 @@ class Gitlab(object): def first(self, predicate, iterable): return next(itertools.ifilter(predicate, iterable)) - def split_path(self, path): - return path.rsplit('/', 1) + def split_and_unslashify_path(self, path): + group, project = path.split('/', 1) + return group, project.replace('/', '_') - def find_project(self, group, project): + 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)) def has_project(self, repo_path): - group, project = self.split_path(repo_path) - try: - return bool(self.find_project(group, project)) + return bool(self.find_project(repo_path)) except StopIteration: return False def create_project(self, repo_path): - group_name, project_name = self.split_path(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) @@ -79,12 +81,31 @@ class Gitlab(object): 'name': project_name, 'public': True, 'merge_requests_enabled': False, - 'namespace_id': group.id + '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 (self.try_get_original_path(project.description) or + project.path_with_namespace) + def list_projects(self): - return [x.path_with_namespace for x in self.gl.projects.list()] + '''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. + ''' + + return [self.suitable_path(x) for x in self.gl.projects.list()] def get_project_url(self, protocol, project_path): '''Return the clone url for a GitLab project. @@ -99,8 +120,7 @@ class Gitlab(object): format matching 'http(s)://host/group/project.git'. ''' - group, project = self.split_path(project_path) - project = self.find_project(group, project) + project = self.find_project(project_path) if protocol == 'ssh': return project.ssh_url_to_repo -- cgit v1.2.1