def clone(ws_id: int, url: str, name: str = None): """ Clones a repository by url into given workspace :param name: Optional name of the local repository name, otherwise the remote name is taken :param user_data: Session data to get access token for GitHub :param ws_id: Destination workspace to clone :param url: URL of the source repository :return: True if successful, otherwise NameConflict is thrown """ workspace = get_workspace(ws_id) url_decode = parse.urlparse(url) if is_github(url_decode.netloc): # Take the suffix of url as first name candidate github_project_name = name if github_project_name is None: github_project_name = _repo_name_from_url(url_decode) dbsession = db_session() pj = dbsession.query(Project).join(Workspace)\ .filter(Workspace.id == workspace.id).filter( Project.name == github_project_name).first() dbsession.commit() # Error when the project name in given workspace already exists if pj is not None: raise NameConflict('A project with name {} already exists'.format(github_project_name)) project_target_path = os.path.join(workspace.path, PROJECT_REL_PATH, github_project_name) logger.info('Cloning from github repo...') # If url in GitHub domain, access by token url_with_token = _get_repo_url(url_decode) out, err, exitcode = git_command(['clone', url_with_token, project_target_path]) if exitcode is 0: setup_git_user_email(project_target_path) # Check if the project is a valid son project check_son_validity(project_target_path) # Create project and scan it. dbsession = db_session() try: pj = Project(github_project_name, github_project_name, workspace) pj.repo_url = url sync_project_descriptor(pj) dbsession.add(pj) scan_project_dir(project_target_path, pj) dbsession.commit() # Check if the project is valid result = create_info_dict(out=out) result["id"] = pj.id return result except: dbsession.rollback() shutil.rmtree(project_target_path) raise Exception("Scan project failed") else: return create_info_dict(err=err, exitcode=exitcode) raise NotImplemented("Cloning from other is not implemented yet. Only github is supported for now.")
def _scan_workspace_dir(ws_path, ws): """ Scan a workspace directory Scans the workspace directory for any projects. Will visit every one to add new functions and services via scan_project_dir :param ws_path: the workspaces path to scan :param ws: the current workspace from the database to attach the projects to """ from son_editor.models.project import Project session = db_session() # Scan private catalogue in workspace _scan_private_catalogue(ws_path + "/catalogues", ws) for project_name in os.listdir(os.path.join(ws_path, "projects")): if not Path(os.path.join(ws_path, "projects", project_name)).is_dir(): continue pj = session.query(Project). \ filter(Project.name == project_name). \ filter(Project.workspace == ws).first() if pj is None: logger.info("Found project in Workspace {}: {}".format( ws_path, project_name)) pj = Project(project_name, project_name, ws) sync_project_descriptor(pj) session.add(pj) session.commit() scan_project_dir(os.path.join(ws_path, "projects", project_name), pj)
def set_data(project: Project, project_data: dict) -> None: """ Extracts the data from the dictionary and sets it on the database model :param project: The project database model :param project_data: The project data dictionary from the frontend """ if "description" in project_data: project.description = project_data['description'] if "maintainer" in project_data: project.maintainer = project_data['maintainer'] if "publish_to" in project_data: project.publish_to = ",".join(project_data['publish_to']) if "vendor" in project_data: project.vendor = project_data['vendor'] if "version" in project_data: project.version = project_data['version']
def set_data(project: Project, project_data: dict) -> None: """ Extracts the data from the dictionary and sets it on the database model :param project: The project database model :param project_data: The project data dictionary from the frontend :return: """ if "description" in project_data: project.description = project_data['description'] if "maintainer" in project_data: project.maintainer = project_data['maintainer'] if "publish_to" in project_data: project.publish_to = ",".join(project_data['publish_to']) if "vendor" in project_data: project.vendor = project_data['vendor'] if "version" in project_data: project.version = project_data['version']
def setUp(self): # Initializes test context self.app = init_test_context() self.project = Project(name="Project A") self.workspace = Workspace(name="Workspace A") self.service = Service(name="Service A") self.function = Function(name="Function A") self.catalogue = Catalogue(name="Catalogue A", url="") self.platform = Catalogue(name="Platform A", url="") self.user = User(name="User A")
def _scan_workspace_dir(ws_path, ws): from son_editor.models.project import Project session = db_session() # Scan private catalogue in workspace _scan_private_catalogue(ws_path + "/catalogues", ws) for project_name in os.listdir(os.path.join(ws_path, "projects")): if not Path(os.path.join(ws_path, "projects", project_name)).is_dir(): continue pj = session.query(Project). \ filter(Project.name == project_name). \ filter(Project.workspace == ws).first() if pj is None: logger.info("Found project in Workspace {}: {}".format( ws_path, project_name)) pj = Project(project_name, project_name, ws) sync_project_descriptor(pj) session.add(pj) session.commit() scan_project_dir(os.path.join(ws_path, "projects", project_name), pj)
def create_project(ws_id: int, project_data: dict) -> dict: """ Create a new Project in this workspace :param ws_id: The workpace ID :param project_data: The project data to create :return: The new project descriptor as a dict """ project_name = shlex.quote(project_data["name"]) repo = None if "repo" in project_data: repo = project_data["repo"] if repo: return gitimpl.clone(ws_id, repo, project_name) session = db_session() # test if ws Name exists in database workspace = session.query(Workspace). \ filter(Workspace.id == ws_id).first() if workspace is None: raise NotFound("No workspace with id {} was found".format(ws_id)) existing_projects = list(session.query(Project) .filter(Project.workspace == workspace) .filter(Project.name == project_name)) if len(existing_projects) > 0: raise NameConflict("Project with name '{}' already exists in this workspace".format(project_name)) # prepare db insert try: project = Project(name=project_name, rel_path=project_name, workspace=workspace) set_data(project, project_data) session.add(project) except: session.rollback() raise # create workspace on disk proc = Popen(['son-workspace', '--workspace', workspace.path, '--project', get_project_path(workspace.path, project_name)], stdout=PIPE, stderr=PIPE) out, err = proc.communicate() exitcode = proc.returncode if err.decode().find('exists') >= 0: project_exists = True else: project_exists = False if exitcode == 0 and not project_exists: sync_project_descriptor(project) session.commit() scan_project_dir(get_project_path(workspace.path, project_name), project) return project.as_dict() else: session.rollback() if project_exists: raise NameConflict("Project with name '{}' already exists in this workspace".format(project_name)) raise Exception(err.decode(), out.decode())
def create_project(ws_id: int, project_data: dict) -> dict: """ Create a new Project in this workspace :param ws_id: :param project_data: :return: The new project descriptor as a dict """ project_name = shlex.quote(project_data["name"]) repo = None if "repo" in project_data: repo = project_data["repo"] if repo: return gitimpl.clone(ws_id, repo, project_name) session = db_session() # test if ws Name exists in database workspace = session.query(Workspace). \ filter(Workspace.id == ws_id).first() if workspace is None: raise NotFound("No workspace with id {} was found".format(ws_id)) existing_projects = list(session.query(Project) .filter(Project.workspace == workspace) .filter(Project.name == project_name)) if len(existing_projects) > 0: raise NameConflict("Project with name '{}' already exists in this workspace".format(project_name)) # prepare db insert try: project = Project(name=project_name, rel_path=project_name, workspace=workspace) set_data(project, project_data) session.add(project) except: session.rollback() raise # create workspace on disk proc = Popen(['son-workspace', '--workspace', workspace.path, '--project', get_project_path(workspace.path, project_name)], stdout=PIPE, stderr=PIPE) out, err = proc.communicate() exitcode = proc.returncode if err.decode().find('exists') >= 0: project_exists = True else: project_exists = False if exitcode == 0 and not project_exists: sync_project_descriptor(project) session.commit() scan_project_dir(get_project_path(workspace.path, project_name), project) return project.as_dict() else: session.rollback() if project_exists: raise NameConflict("Project with name '{}' already exists in this workspace".format(project_name)) raise Exception(err.decode(), out.decode())