Ejemplo n.º 1
0
def set_up_new_course(request):
    # type: (http.HttpRequest) -> http.HttpResponse
    if request.method == "POST":
        form = CourseCreationForm(request.POST)

        if form.is_valid():
            new_course = form.save(commit=False)

            from course.content import get_course_repo_path
            repo_path = get_course_repo_path(new_course)

            try:
                import os
                os.makedirs(repo_path)

                repo = None

                try:
                    with transaction.atomic():
                        repo = Repo.init(repo_path)

                        client, remote_path = \
                            get_dulwich_client_and_remote_path_from_course(
                                    new_course)

                        remote_refs = client.fetch(remote_path, repo)
                        if remote_refs is None:
                            raise RuntimeError(
                                _("No refs found in remote repository"
                                  " (i.e. no master branch, no HEAD). "
                                  "This looks very much like a blank repository. "
                                  "Please create course.yml in the remote "
                                  "repository before creating your course."))

                        transfer_remote_refs(repo, remote_refs)
                        new_sha = repo[b"HEAD"] = remote_refs[b"HEAD"]

                        vrepo = repo
                        if new_course.course_root_path:
                            from course.content import SubdirRepoWrapper
                            vrepo = SubdirRepoWrapper(
                                vrepo, new_course.course_root_path)

                        from course.validation import validate_course_content
                        validate_course_content(  # type: ignore
                            vrepo, new_course.course_file,
                            new_course.events_file, new_sha)

                        del vrepo

                        new_course.active_git_commit_sha = new_sha.decode()
                        new_course.save()

                        # {{{ set up a participation for the course creator

                        part = Participation()
                        part.user = request.user
                        part.course = new_course
                        part.status = participation_status.active
                        part.save()

                        part.roles.set([
                            # created by signal handler for course creation
                            ParticipationRole.objects.get(
                                course=new_course, identifier="instructor")
                        ])

                        # }}}

                        messages.add_message(
                            request, messages.INFO,
                            _("Course content validated, creation "
                              "succeeded."))
                except:
                    # Don't coalesce this handler with the one below. We only want
                    # to delete the directory if we created it. Trust me.

                    # Work around read-only files on Windows.
                    # https://docs.python.org/3.5/library/shutil.html#rmtree-example

                    import os
                    import stat
                    import shutil

                    # Make sure files opened for 'repo' above are actually closed.
                    if repo is not None:  # noqa
                        repo.close()  # noqa

                    def remove_readonly(func, path, _):  # noqa
                        "Clear the readonly bit and reattempt the removal"
                        os.chmod(path, stat.S_IWRITE)
                        func(path)

                    try:
                        shutil.rmtree(repo_path, onerror=remove_readonly)
                    except OSError:
                        messages.add_message(
                            request, messages.WARNING,
                            ugettext("Failed to delete unused "
                                     "repository directory '%s'.") % repo_path)

                    raise

            except Exception as e:
                from traceback import print_exc
                print_exc()

                messages.add_message(
                    request, messages.ERROR,
                    string_concat(_("Course creation failed"),
                                  ": %(err_type)s: %(err_str)s") % {
                                      "err_type": type(e).__name__,
                                      "err_str": str(e)
                                  })
            else:
                return redirect("relate-course_page", new_course.identifier)

    else:
        form = CourseCreationForm()

    return render(request, "generic-form.html", {
        "form_description": _("Set up new course"),
        "form": form
    })
Ejemplo n.º 2
0
def set_up_new_course(request):
    if not request.user.is_staff:
        raise PermissionDenied(_("only staff may create courses"))

    if request.method == "POST":
        form = CourseCreationForm(request.POST)

        if form.is_valid():
            new_course = form.save(commit=False)

            from course.content import get_course_repo_path
            repo_path = get_course_repo_path(new_course)

            try:
                import os
                os.makedirs(repo_path)

                try:
                    with transaction.atomic():
                        from dulwich.repo import Repo
                        repo = Repo.init(repo_path)

                        client, remote_path = \
                            get_dulwich_client_and_remote_path_from_course(
                                    new_course)

                        remote_refs = client.fetch(remote_path, repo)
                        new_sha = repo["HEAD"] = remote_refs["HEAD"]

                        vrepo = repo
                        if new_course.course_root_path:
                            from course.content import SubdirRepoWrapper
                            vrepo = SubdirRepoWrapper(
                                vrepo, new_course.course_root_path)

                        from course.validation import validate_course_content
                        validate_course_content(vrepo, new_course.course_file,
                                                new_course.events_file,
                                                new_sha)

                        del repo
                        del vrepo

                        new_course.valid = True
                        new_course.active_git_commit_sha = new_sha
                        new_course.save()

                        # {{{ set up a participation for the course creator

                        part = Participation()
                        part.user = request.user
                        part.course = new_course
                        part.role = participation_role.instructor
                        part.status = participation_status.active
                        part.save()

                        # }}}

                        messages.add_message(
                            request, messages.INFO,
                            _("Course content validated, creation "
                              "succeeded."))
                except:
                    # Don't coalesce this handler with the one below. We only want
                    # to delete the directory if we created it. Trust me.

                    # Work around read-only files on Windows.
                    # https://docs.python.org/3.5/library/shutil.html#rmtree-example

                    import os
                    import stat
                    import shutil

                    # Make sure files opened for 'repo' above are actually closed.
                    import gc
                    gc.collect()

                    def remove_readonly(func, path, _):  # noqa
                        "Clear the readonly bit and reattempt the removal"
                        os.chmod(path, stat.S_IWRITE)
                        func(path)

                    try:
                        shutil.rmtree(repo_path, onerror=remove_readonly)
                    except OSError:
                        messages.add_message(
                            request, messages.WARNING,
                            ugettext("Failed to delete unused "
                                     "repository directory '%s'.") % repo_path)

                    raise

            except Exception as e:
                from traceback import print_exc
                print_exc()

                messages.add_message(
                    request, messages.ERROR,
                    string_concat(_("Course creation failed"),
                                  ": %(err_type)s: %(err_str)s") % {
                                      "err_type": type(e).__name__,
                                      "err_str": str(e)
                                  })
            else:
                return redirect("relate-course_page", new_course.identifier)

    else:
        form = CourseCreationForm()

    return render(request, "generic-form.html", {
        "form_description": _("Set up new course"),
        "form": form
    })