Пример #1
0
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.")
Пример #2
0
def pull(ws_id: int, project_id: int):
    """
    Pulls data from the given project_id.
    :param user_data: Session data to get access token for GitHub
    :param ws_id: Workspace of the project
    :param project_id: Project to pull.
    :return:
    """
    dbsession = db_session()
    project = get_project(ws_id, project_id, session=dbsession)

    project_full_path = os.path.join(project.workspace.path, PROJECT_REL_PATH, project.rel_path)

    # Error handling
    if not os.path.isdir(project_full_path):
        raise Exception("Could not find project directory {}".format(project_full_path))

    if not project.repo_url:
        raise InvalidArgument("Project with id {} is missing the repo attribute".format(project_id))

    # Pull in project directory
    # If url in GitHub domain, access by token
    out, err, exitcode = git_command(['pull', project.repo_url], cwd=project_full_path)

    # Return error if pull failed.
    if exitcode is not 0:
        return create_info_dict(err=err, exitcode=exitcode)

    # Rescan project
    try:
        sync_project_descriptor(project)
        dbsession.add(project)
        scan_project_dir(project_full_path, project)
        dbsession.commit()
    except:
        dbsession.rollback()
        raise Exception("Could not scan the project after pull.")

    return create_info_dict(out=out)
Пример #3
0
def pull(ws_id: int, project_id: int):
    """
    Pulls data from the given project_id.
    :param ws_id: Workspace of the project
    :param project_id: Project to pull.
    :return: a dictionary containing the result of the operation
    """
    dbsession = db_session()
    project = get_project(ws_id, project_id, session=dbsession)

    project_full_path = os.path.join(project.workspace.path, PROJECT_REL_PATH, project.rel_path)

    # Error handling
    if not os.path.isdir(project_full_path):
        raise Exception("Could not find project directory {}".format(project_full_path))

    if not project.repo_url:
        raise InvalidArgument("Project with id {} is missing the repo attribute".format(project_id))

    # Pull in project directory
    # If url in GitHub domain, access by token
    out, err, exitcode = git_command(['pull', project.repo_url], cwd=project_full_path)

    # Return error if pull failed.
    if exitcode is not 0:
        return create_info_dict(err=err, exitcode=exitcode)

    # Rescan project
    try:
        sync_project_descriptor(project)
        dbsession.add(project)
        scan_project_dir(project_full_path, project)
        dbsession.commit()
    except:
        dbsession.rollback()
        raise Exception("Could not scan the project after pull.")

    return create_info_dict(out=out)
Пример #4
0
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())