Example #1
0
    def create_grading_repo(cls, config, course, team, registration, staging_only):
        base_dir = config.work_dir
        
        if not staging_only:
            conn_server = create_connection(course, config)
            if conn_server is None:
                raise ChisubmitException("Could not connect to git server")
        
        conn_staging = create_connection(course, config, staging = True)
        if conn_staging is None:
            raise ChisubmitException("Could not connect to git staging server")        
        
        repo_path = cls.get_grading_repo_path(base_dir, course, team, registration)
        staging_url = conn_staging.get_repository_git_url(course, team)

        if staging_only:
            repo = LocalGitRepo.create_repo(repo_path, clone_from_url = staging_url)
        else:
            server_url = conn_server.get_repository_git_url(course, team)
            repo = LocalGitRepo.create_repo(repo_path, clone_from_url = server_url, remotes = [("staging", staging_url)])

        if registration.final_submission is None:
            commit_sha = None
        else:
            commit_sha = registration.final_submission.commit_sha        
        return cls(team, registration, repo, repo_path, commit_sha, staging_only)
Example #2
0
    def create_grading_repo(cls, config, course, team, registration,
                            staging_only):
        base_dir = config.work_dir

        if not staging_only:
            conn_server = create_connection(course, config)
            if conn_server is None:
                raise ChisubmitException("Could not connect to git server")

        conn_staging = create_connection(course, config, staging=True)
        if conn_staging is None:
            raise ChisubmitException("Could not connect to git staging server")

        repo_path = cls.get_grading_repo_path(base_dir, course, team,
                                              registration)
        staging_url = conn_staging.get_repository_git_url(course, team)

        if staging_only:
            repo = LocalGitRepo.create_repo(repo_path,
                                            clone_from_url=staging_url)
        else:
            server_url = conn_server.get_repository_git_url(course, team)
            repo = LocalGitRepo.create_repo(repo_path,
                                            clone_from_url=server_url,
                                            remotes=[("staging", staging_url)])

        if registration.final_submission is None:
            commit_sha = None
        else:
            commit_sha = registration.final_submission.commit_sha
        return cls(team, registration, repo, repo_path, commit_sha,
                   staging_only)
Example #3
0
def student_repo_pristine_clone(ctx, course, team_id):
    team = get_team_or_exit(ctx, course, team_id)
    
    conn = create_connection(course, ctx.obj['config'])
    
    if conn is None:
        ctx.exit(CHISUBMIT_FAIL)

    if not conn.exists_team_repository(course, team):
        print("The repository for '%s' does not exist or you do not have permission to access it." % team_id)
        ctx.exit(CHISUBMIT_FAIL)

    tempdir = tempfile.mkdtemp(prefix="%s-%s-" % (course.course_id, team.team_id))
    
    repo_url = conn.get_repository_git_url(course, team)
    
    try:
        LocalGitRepo.create_repo(tempdir, clone_from_url=repo_url)
    except Exception as e:
        print("Unable to create a clone of repository %s" % repo_url)
        ctx.exit(CHISUBMIT_FAIL)
        
    print("A pristine clone of your repository has been created in %s" % tempdir)    

    return CHISUBMIT_SUCCESS
Example #4
0
def instructor_grading_list_submissions(ctx, course, assignment_id):
    assignment = course.get_assignment(assignment_id)
    if assignment is None:
        print "Assignment %s does not exist" % assignment_id
        ctx.exit(CHISUBMIT_FAIL)

    teams = get_teams(course, assignment)
    teams.sort(key=operator.attrgetter("id"))

    conn = create_connection(course, ctx.obj['config'])

    if conn is None:
        print "Could not connect to git server."
        ctx.exit(CHISUBMIT_FAIL)

    for team in teams:
        ta = team.get_assignment(assignment.id)

        if ta.submitted_at is None:
            print "%25s NOT SUBMITTED" % team.id
        else:
            submission_commit = conn.get_commit(course, team, ta.commit_sha)
            if submission_commit is not None:
                if team.has_assignment_ready_for_grading(assignment):
                    print "%25s SUBMITTED (READY for grading)" % team.id
                else:
                    print "%25s SUBMITTED (NOT READY for grading)" % team.id
            else:
                print "%25s ERROR: Submitted but commit %s not found in repository" % (
                    team.id, ta.commit_sha)

    return CHISUBMIT_SUCCESS
Example #5
0
def student_repo_pristine_clone(ctx, course, team_id):
    team = get_team_or_exit(ctx, course, team_id)

    conn = create_connection(course, ctx.obj['config'])

    if conn is None:
        ctx.exit(CHISUBMIT_FAIL)

    if not conn.exists_team_repository(course, team):
        print(
            "The repository for '%s' does not exist or you do not have permission to access it."
            % team_id)
        ctx.exit(CHISUBMIT_FAIL)

    tempdir = tempfile.mkdtemp(prefix="%s-%s-" %
                               (course.course_id, team.team_id))

    repo_url = conn.get_repository_git_url(course, team)

    try:
        LocalGitRepo.create_repo(tempdir, clone_from_url=repo_url)
    except Exception as e:
        print("Unable to create a clone of repository %s" % repo_url)
        ctx.exit(CHISUBMIT_FAIL)

    print("A pristine clone of your repository has been created in %s" %
          tempdir)

    return CHISUBMIT_SUCCESS
Example #6
0
def instructor_grading_list_submissions(ctx, course, assignment_id):
    assignment = get_assignment_or_exit(ctx, course, assignment_id)

    teams_registrations = get_teams_registrations(course, assignment)
    teams = sorted(teams_registrations.keys(), key=operator.attrgetter("team_id"))

    conn = create_connection(course, ctx.obj['config'])
    
    if conn is None:
        print "Could not connect to git server."
        ctx.exit(CHISUBMIT_FAIL)

    for team in teams:
        registration = teams_registrations[team]

        if registration.final_submission is None:
            print "%25s NOT SUBMITTED" % team.team_id
        else:
            submission_commit = conn.get_commit(course, team, registration.final_submission.commit_sha)
            if submission_commit is not None:
                if registration.is_ready_for_grading():
                    print "%25s SUBMITTED (READY for grading)" % team.team_id
                else:
                    print "%25s SUBMITTED (NOT READY for grading)" % team.team_id
            else:
                print "%25s ERROR: Submitted but commit %s not found in repository" % (team.team_id, registration.final_submission.commit_sha)
    
    return CHISUBMIT_SUCCESS
Example #7
0
def instructor_grading_list_submissions(ctx, course, assignment_id):
    assignment = get_assignment_or_exit(ctx, course, assignment_id)

    teams_registrations = get_teams_registrations(course, assignment)
    teams = sorted(list(teams_registrations.keys()),
                   key=operator.attrgetter("team_id"))

    conn = create_connection(course, ctx.obj['config'])

    if conn is None:
        print("Could not connect to git server.")
        ctx.exit(CHISUBMIT_FAIL)

    for team in teams:
        registration = teams_registrations[team]

        if registration.final_submission is None:
            print("%25s NOT SUBMITTED" % team.team_id)
        else:
            submission_commit = conn.get_commit(
                course, team, registration.final_submission.commit_sha)
            if submission_commit is not None:
                if registration.is_ready_for_grading():
                    print("%25s SUBMITTED (READY for grading)" % team.team_id)
                else:
                    print("%25s SUBMITTED (NOT READY for grading)" %
                          team.team_id)
            else:
                print(
                    "%25s ERROR: Submitted but commit %s not found in repository"
                    % (team.team_id, registration.final_submission.commit_sha))

    return CHISUBMIT_SUCCESS
Example #8
0
def instructor_grading_list_submissions(ctx, course, assignment_id):
    assignment = course.get_assignment(assignment_id)
    if assignment is None:
        print "Assignment %s does not exist" % assignment_id
        ctx.exit(CHISUBMIT_FAIL)

    teams = get_teams(course, assignment)
    teams.sort(key=operator.attrgetter("id"))

    conn = create_connection(course, ctx.obj['config'])
    
    if conn is None:
        print "Could not connect to git server."
        ctx.exit(CHISUBMIT_FAIL)

    for team in teams:
        ta = team.get_assignment(assignment.id)

        if ta.submitted_at is None:
            print "%25s NOT SUBMITTED" % team.id
        else:
            submission_commit = conn.get_commit(course, team, ta.commit_sha)
            if submission_commit is not None:
                if team.has_assignment_ready_for_grading(assignment):
                    print "%25s SUBMITTED (READY for grading)" % team.id
                else:
                    print "%25s SUBMITTED (NOT READY for grading)" % team.id
            else:
                print "%25s ERROR: Submitted but commit %s not found in repository" % (team.id, ta.commit_sha)
    
    return CHISUBMIT_SUCCESS
Example #9
0
def admin_course_create_repos(ctx, course_id, staging):
    course = get_course_or_exit(ctx, course_id)

    teams = course.get_teams()

    if len(teams) == 0:
        print "Course %s has no teams. No repositories to create." % course_id
        ctx.exit(CHISUBMIT_FAIL)

    max_len = max([len(t.team_id) for t in teams])

    conn = create_connection(course, ctx.obj['config'], staging)

    if conn is None:
        print "Could not connect to git server."
        ctx.exit(CHISUBMIT_FAIL)

    v = ctx.obj["verbose"]
    already_has_repository = 0
    warning = 0
    created = 0
    for team in sorted(teams, key=operator.attrgetter("team_id")):
        if conn.exists_team_repository(course, team):
            already_has_repository += 1
            if v:
                print "%-*s  SKIPPING. Already has a repository." % (
                    max_len, team.team_id)
            continue

        team_members = team.get_team_members()
        unconfirmed_students = [tm for tm in team_members if not tm.confirmed]

        if len(unconfirmed_students) > 0:
            usernames = [tm.student.username for tm in unconfirmed_students]
            warning += 1
            print "%-*s  WARNING. Team has unconfirmed students: %s" % (
                max_len, team.team_id, ",".join(usernames))
            continue

        if not staging:
            missing = []
            for tm in team_members:
                if course.git_usernames == "custom":
                    if tm.student.git_username is None:
                        missing.append(tm.student.username)

            if len(missing) > 0:
                warning += 1
                print "%-20s WARNING. These students haven't set their git usernames: %s" % (
                    team.id, ",".join(missing))
                continue

        try:
            conn.create_team_repository(course, team)
            created += 1
            print "%-20s CREATED" % team.team_id
        except Exception, e:
            print "%-20s Unexpected exception %s: %s" % (
                team.team_id, e.__class__.__name__, e.message)
Example #10
0
def instructor_team_pull_repos(ctx, course, assignment_id, directory, only_ready_for_grading, reset, only):
    assignment = course.get_assignment(assignment_id)
    if assignment is None:
        print "Assignment %s does not exist" % assignment_id
        ctx.exit(CHISUBMIT_FAIL)

    conn = create_connection(course, ctx.obj['config'])
    
    if conn is None:
        print "Could not connect to git server."
        ctx.exit(CHISUBMIT_FAIL)

    teams = get_teams(course, assignment, only = only)

    directory = os.path.expanduser(directory)
    
    if not os.path.exists(directory):
        os.makedirs(directory)

    max_len = max([len(t.id) for t in teams])

    for team in sorted([t for t in teams if t.active], key=operator.attrgetter("id")):
        team_dir = "%s/%s" % (directory, team.id)
        team_git_url = conn.get_repository_git_url(course, team) 
        ta = team.get_assignment(assignment.id)

        if not team.has_assignment_ready_for_grading(assignment) and only_ready_for_grading:
            print "%-*s  SKIPPING (not ready for grading)" % (max_len, team.id)
            continue
        
        try:
            msg = ""
            if not os.path.exists(team_dir):
                r = LocalGitRepo.create_repo(team_dir, clone_from_url=team_git_url)
                msg = "Cloned repo"
            else:
                r = LocalGitRepo(team_dir)
                if reset:
                    r.fetch("origin")
                    r.reset_branch("origin", "master")
                    msg = "Reset to match origin/master" 
                else:
                    if r.repo.is_dirty():
                        print "%-*s  ERROR: Cannot pull. Local repository has unstaged changes." % (max_len, team.id)
                        continue
                    r.checkout_branch("master")
                    r.pull("origin", "master")
                    msg = "Pulled latest changes"
            if only_ready_for_grading:
                r.checkout_commit(ta.commit_sha)
                msg += " and checked out commit %s" % (ta.commit_sha)               
            print "%-*s  %s" % (max_len, team.id, msg)
        except ChisubmitException, ce:
            print "%-*s  ERROR: Could not checkout or pull master branch (%s)" % (max_len, team.id, ce.message)
        except GitCommandError, gce:
            print "%-*s  ERROR: Could not checkout or pull master branch" % (max_len, team.id)
            print gce
Example #11
0
    def create_grading_repo(cls, config, course, team, assignment):
        base_dir = config["directory"]
        
        conn_server = create_connection(course, config)
        if conn_server is None:
            raise ChisubmitException("Could not connect to git server")
        
        conn_staging = create_connection(course, config, staging = True)
        if conn_server is None:
            raise ChisubmitException("Could not connect to git staging server")        
        
        repo_path = cls.get_grading_repo_path(base_dir, course, team, assignment)
        server_url = conn_server.get_repository_git_url(course, team)
        staging_url = conn_staging.get_repository_git_url(course, team)

        ta = team.get_assignment(assignment.id)

        repo = LocalGitRepo.create_repo(repo_path, clone_from_url = server_url, remotes = [("staging", staging_url)])
        return cls(team, assignment, repo, repo_path, ta.commit_sha)
Example #12
0
def admin_course_create_repos(ctx, course_id, staging):
    course = get_course_or_exit(ctx, course_id)

    teams = course.get_teams()

    if len(teams) == 0:
        print "Course %s has no teams. No repositories to create." % course_id
        ctx.exit(CHISUBMIT_FAIL)  

    max_len = max([len(t.team_id) for t in teams])

    conn = create_connection(course, ctx.obj['config'], staging)
    
    if conn is None:
        print "Could not connect to git server."
        ctx.exit(CHISUBMIT_FAIL)
    
    v = ctx.obj["verbose"]
    already_has_repository = 0
    warning = 0
    created = 0
    for team in sorted(teams, key=operator.attrgetter("team_id")):
        if conn.exists_team_repository(course, team):
            already_has_repository += 1
            if v: print "%-*s  SKIPPING. Already has a repository." % (max_len, team.team_id)
            continue

        team_members = team.get_team_members()
        unconfirmed_students = [tm for tm in team_members if not tm.confirmed]
        
        if len(unconfirmed_students) > 0:
            usernames = [tm.student.username for tm in unconfirmed_students]
            warning += 1
            print "%-*s  WARNING. Team has unconfirmed students: %s" % (max_len, team.team_id, ",".join(usernames))
            continue


        if not staging:        
            missing = []
            for tm in team_members:
                if course.git_usernames == "custom":
                    if tm.student.git_username is None:
                        missing.append(tm.student.username)
                    
            if len(missing) > 0:
                warning += 1
                print "%-20s WARNING. These students haven't set their git usernames: %s" % (team.id, ",".join(missing))
                continue
        
        try:
            conn.create_team_repository(course, team)
            created += 1
            print "%-20s CREATED" % team.team_id
        except Exception, e:
            print "%-20s Unexpected exception %s: %s" % (team.team_id, e.__class__.__name__, e.message)
Example #13
0
def admin_course_update_repo_access(ctx, course_id, staging):
    course = get_course_or_exit(ctx, course_id)
    
    conn = create_connection(course, ctx.obj['config'], staging)
    
    if conn is None:
        print "Could not connect to git server."
        ctx.exit(CHISUBMIT_FAIL)
    
    conn.update_instructors(course)
    conn.update_graders(course)
Example #14
0
def admin_course_update_repo_access(ctx, course_id, staging):
    course = get_course_or_exit(ctx, course_id)

    conn = create_connection(course, ctx.obj['config'], staging)

    if conn is None:
        print "Could not connect to git server."
        ctx.exit(CHISUBMIT_FAIL)

    conn.update_instructors(course)
    conn.update_graders(course)
Example #15
0
def admin_course_create_repos(ctx, course_id, staging):
    course = Course.from_id(course_id)
    if course is None:
        print "Course %s does not exist" % course_id
        ctx.exit(CHISUBMIT_FAIL)    

    teams = course.get_teams()

    if len(teams) == 0:
        print "Course %s has no teams. No repositories to create." % course_id
        ctx.exit(CHISUBMIT_FAIL)  

    max_len = max([len(t.id) for t in teams])

    conn = create_connection(course, ctx.obj['config'], staging)
    
    if conn is None:
        print "Could not connect to git server."
        ctx.exit(CHISUBMIT_FAIL)
    
    v = ctx.obj["verbose"]
    already_has_repository = 0
    warning = 0
    created = 0
    for team in sorted(teams, key=operator.attrgetter("id")):
        if not team.is_complete():
            warning += 1
            print "%-*s  WARNING. Team registration is incomplete." % (max_len, team.id)
            continue
        
        if conn.exists_team_repository(course, team):
            already_has_repository += 1
            if v: print "%-*s  SKIPPING. Already has a repository." % (max_len, team.id)
            continue

        if not staging:        
            students = [s for s in course.students if s.user.id in [ts.user.id for ts in team.students]]
                
            missing = []
            for s in students:
                if not hasattr(s, "repo_info") or s.repo_info is None or not s.repo_info.has_key("git-username"):
                    missing.append(s.user.id)
                    
            if len(missing) > 0:
                warning += 1
                print "%-20s WARNING. These students haven't set their git usernames: %s" % (team.id, ",".join(missing))
                continue
        
        try:
            conn.create_team_repository(course, team)
            created += 1
            print "%-20s CREATED" % team.id
        except Exception, e:
            print "%-20s Unexpected exception %s: %s" % (team.id, e.__class__.__name__, e.message)
Example #16
0
def admin_course_unsetup_repo(ctx, course_id, staging):
    course = get_course_or_exit(ctx, course_id)

    conn = create_connection(course, ctx.obj['config'], staging)

    if conn is None:
        print("Could not connect to git server.")
        ctx.exit(CHISUBMIT_FAIL)

    conn.deinit_course(course)

    return CHISUBMIT_SUCCESS
Example #17
0
def admin_course_unsetup_repo(ctx, course_id, staging):
    course = get_course_or_exit(ctx, course_id)

    conn = create_connection(course, ctx.obj['config'], staging)
    
    if conn is None:
        print "Could not connect to git server."
        ctx.exit(CHISUBMIT_FAIL)

    conn.deinit_course(course)

    return CHISUBMIT_SUCCESS
Example #18
0
def instructor_team_pull_repos(ctx, course, assignment_id, directory, only_ready_for_grading, reset, only):
    assignment = get_assignment_or_exit(ctx, course, assignment_id)

    conn = create_connection(course, ctx.obj['config'])
    
    teams_registrations = get_teams_registrations(course, assignment, only = only)

    directory = os.path.expanduser(directory)
    
    if not os.path.exists(directory):
        os.makedirs(directory)

    teams = sorted([t for t in teams_registrations.keys() if t.active], key = operator.attrgetter("team_id"))

    max_len = max([len(t.team_id) for t in teams])

    for team in teams:
        registration = teams_registrations[team]
        team_dir = "%s/%s" % (directory, team.team_id)
        team_git_url = conn.get_repository_git_url(course, team) 

        if not registration.is_ready_for_grading() and only_ready_for_grading:
            print "%-*s  SKIPPING (not ready for grading)" % (max_len, team.team_id)
            continue
        
        try:
            msg = ""
            if not os.path.exists(team_dir):
                r = LocalGitRepo.create_repo(team_dir, clone_from_url=team_git_url)
                msg = "Cloned repo"
            else:
                r = LocalGitRepo(team_dir)
                if reset:
                    r.fetch("origin")
                    r.reset_branch("origin", "master")
                    msg = "Reset to match origin/master" 
                else:
                    if r.repo.is_dirty():
                        print "%-*s  ERROR: Cannot pull. Local repository has unstaged changes." % (max_len, team.team_id)
                        continue
                    r.checkout_branch("master")
                    r.pull("origin", "master")
                    msg = "Pulled latest changes"
            if only_ready_for_grading:
                r.checkout_commit(registration.final_submission.commit_sha)
                msg += " and checked out commit %s" % (registration.final_submission.commit_sha)               
            print "%-*s  %s" % (max_len, team.team_id, msg)
        except ChisubmitException, ce:
            print "%-*s  ERROR: Could not checkout or pull master branch (%s)" % (max_len, team.team_id, ce.message)
        except GitCommandError, gce:
            print "%-*s  ERROR: Could not checkout or pull master branch" % (max_len, team.team_id)
            print gce
Example #19
0
    def create_grading_repo(cls, config, course, team, assignment):
        base_dir = config["directory"]

        conn_server = create_connection(course, config)
        if conn_server is None:
            raise ChisubmitException("Could not connect to git server")

        conn_staging = create_connection(course, config, staging=True)
        if conn_server is None:
            raise ChisubmitException("Could not connect to git staging server")

        repo_path = cls.get_grading_repo_path(base_dir, course, team,
                                              assignment)
        server_url = conn_server.get_repository_git_url(course, team)
        staging_url = conn_staging.get_repository_git_url(course, team)

        ta = team.get_assignment(assignment.id)

        repo = LocalGitRepo.create_repo(repo_path,
                                        clone_from_url=server_url,
                                        remotes=[("staging", staging_url)])
        return cls(team, assignment, repo, repo_path, ta.commit_sha)
Example #20
0
def admin_course_setup_repo(ctx, course_id, staging):
    course = Course.from_id(course_id)
    if course is None:
        print "Course %s does not exist" % course_id
        ctx.exit(CHISUBMIT_FAIL)    

    conn = create_connection(course, ctx.obj['config'], staging)
    
    if conn is None:
        print "Could not connect to git server."
        ctx.exit(CHISUBMIT_FAIL)

    conn.init_course(course)

    return CHISUBMIT_SUCCESS
Example #21
0
def admin_course_unsetup_repo(ctx, course_id, staging):
    course = Course.from_id(course_id)
    if course is None:
        print "Course %s does not exist" % course_id
        ctx.exit(CHISUBMIT_FAIL)    

    conn = create_connection(course, ctx.obj['config'], staging)
    
    if conn is None:
        print "Could not connect to git server."
        ctx.exit(CHISUBMIT_FAIL)

    conn.deinit_course(course)

    return CHISUBMIT_SUCCESS
Example #22
0
def admin_course_team_repo_update(ctx, course_id, team_id):
    course = get_course_or_exit(ctx, course_id)
    team = get_team_or_exit(ctx, course, team_id)

    #if team.github_repo is None:
    #    print "Team %s does not have a repository." % team.id
    #    return CHISUBMIT_FAIL

    conn = create_connection(course, ctx.obj['config'], staging=False)

    if conn is None:
        print("Could not connect to git server.")
        ctx.exit(CHISUBMIT_FAIL)

    conn.update_team_repository(course, team)
    return CHISUBMIT_SUCCESS
Example #23
0
def admin_course_team_repo_update(ctx, course_id, team_id):
    course = get_course_or_exit(ctx, course_id) 
    team = get_team_or_exit(ctx, course, team_id) 

    #if team.github_repo is None:
    #    print "Team %s does not have a repository." % team.id
    #    return CHISUBMIT_FAIL

    conn = create_connection(course, ctx.obj['config'], staging = False)
    
    if conn is None:
        print "Could not connect to git server."
        ctx.exit(CHISUBMIT_FAIL)

    conn.update_team_repository(course, team)
    return CHISUBMIT_SUCCESS
Example #24
0
def admin_course_team_repo_remove(ctx, course_id, team_id, ignore_non_existing, staging):
    course = get_course_or_exit(ctx, course_id) 
    team = get_team_or_exit(ctx, course, team_id) 

    conn = create_connection(course, ctx.obj['config'], staging)
    
    if conn is None:
        print "Could not connect to git server."
        ctx.exit(CHISUBMIT_FAIL)

    if not conn.exists_team_repository(course, team) and not ignore_non_existing:
        print "WARNING: Cannot delete repository because it doesn't exist"
        ctx.exit(CHISUBMIT_FAIL)
    else:
        conn.delete_team_repository(course, team, fail_if_not_exists = not ignore_non_existing)

    return CHISUBMIT_SUCCESS
Example #25
0
def admin_course_team_repo_create(ctx, course_id, team_id, ignore_existing, public, staging):
    course = get_course_or_exit(ctx, course_id) 
    team = get_team_or_exit(ctx, course, team_id) 

    conn = create_connection(course, ctx.obj['config'], staging)
    
    if conn is None:
        print "Could not connect to git server."
        ctx.exit(CHISUBMIT_FAIL)
    
    if conn.exists_team_repository(course, team) and not ignore_existing:
        print "Team %s already has a repository" % team_id
        ctx.exit(CHISUBMIT_FAIL)
    else:
        conn.create_team_repository(course, team, fail_if_exists = not ignore_existing, private = not public)

    return CHISUBMIT_SUCCESS
Example #26
0
def student_repo_check(ctx, course, team_id):
    team = get_team_or_exit(ctx, course, team_id)
    
    conn = create_connection(course, ctx.obj['config'])
    
    if conn is None:
        ctx.exit(CHISUBMIT_FAIL)

    if not conn.exists_team_repository(course, team):
        print "The repository for '%s' does not exist or you do not have permission to access it." % team_id
        ctx.exit(CHISUBMIT_FAIL)

    # TODO: Check that the user actually has push access
    print "Your repository exists and you have access to it."
    http_url = conn.get_repository_http_url(course, team)
    if http_url is not None:
        print "Repository website: %s" % conn.get_repository_http_url(course, team)
    print "Repository URL: %s" % conn.get_repository_git_url(course, team)

    return CHISUBMIT_SUCCESS
Example #27
0
def student_repo_check(ctx, course, team_id):
    team = get_team_or_exit(ctx, course, team_id)

    conn = create_connection(course, ctx.obj['config'])

    if conn is None:
        ctx.exit(CHISUBMIT_FAIL)

    if not conn.exists_team_repository(course, team):
        print "The repository for '%s' does not exist or you do not have permission to access it." % team_id
        ctx.exit(CHISUBMIT_FAIL)

    # TODO: Check that the user actually has push access
    print "Your repository exists and you have access to it."
    http_url = conn.get_repository_http_url(course, team)
    if http_url is not None:
        print "Repository website: %s" % conn.get_repository_http_url(
            course, team)
    print "Repository URL: %s" % conn.get_repository_git_url(course, team)

    return CHISUBMIT_SUCCESS
Example #28
0
def admin_course_team_repo_remove(ctx, course_id, team_id, ignore_non_existing,
                                  staging):
    course = get_course_or_exit(ctx, course_id)
    team = get_team_or_exit(ctx, course, team_id)

    conn = create_connection(course, ctx.obj['config'], staging)

    if conn is None:
        print("Could not connect to git server.")
        ctx.exit(CHISUBMIT_FAIL)

    if not conn.exists_team_repository(course,
                                       team) and not ignore_non_existing:
        print("WARNING: Cannot delete repository because it doesn't exist")
        ctx.exit(CHISUBMIT_FAIL)
    else:
        conn.delete_team_repository(course,
                                    team,
                                    fail_if_not_exists=not ignore_non_existing)

    return CHISUBMIT_SUCCESS
Example #29
0
def admin_course_team_repo_create(ctx, course_id, team_id, ignore_existing,
                                  public, staging):
    course = get_course_or_exit(ctx, course_id)
    team = get_team_or_exit(ctx, course, team_id)

    conn = create_connection(course, ctx.obj['config'], staging)

    if conn is None:
        print("Could not connect to git server.")
        ctx.exit(CHISUBMIT_FAIL)

    if conn.exists_team_repository(course, team) and not ignore_existing:
        print("Team %s already has a repository" % team_id)
        ctx.exit(CHISUBMIT_FAIL)
    else:
        conn.create_team_repository(course,
                                    team,
                                    fail_if_exists=not ignore_existing,
                                    private=not public)

    return CHISUBMIT_SUCCESS
Example #30
0
def admin_course_create_git_users(ctx, course_id, staging, dry_run, all_types,
                                  only_type):
    course = get_course_or_exit(ctx, course_id)

    if all_types and only_type is not None:
        print("You cannot specify both --all-types and --only-type")
        ctx.exit(CHISUBMIT_FAIL)

    if staging and only_type == "student":
        print("You cannot create student accounts on the staging server.")
        ctx.exit(CHISUBMIT_FAIL)

    conn = create_connection(course, ctx.obj['config'], staging)

    users = []

    if not staging and (all_types or only_type == "student"):
        users += course.get_students()

    if all_types or only_type == "grader":
        users += course.get_graders()

    if all_types or only_type == "instructor":
        users += course.get_instructors()

    for user in users:
        if conn.exists_user(course, user):
            print("[SKIP] User '%s' already exists" % user.username)
        else:
            if dry_run:
                print("[OK] Created user %s" % user.username)
            else:
                try:
                    conn.create_user(course, user)
                    print("[OK] Created user %s" % user.username)
                except ChisubmitException as ce:
                    print("[ERROR] Couldn't create user '%s': %s" %
                          (user.username, ce))
Example #31
0
def student_repo_pristine_clone(ctx, course, team_id):
    team = course.get_team(team_id)
    if team is None:
        print "Team %s does not exist or you do not have access to it" % team_id
        ctx.exit(CHISUBMIT_FAIL)

    conn = create_connection(course, ctx.obj['config'])

    if conn is None:
        ctx.exit(CHISUBMIT_FAIL)

    if not conn.exists_team_repository(course, team):
        print "The repository for '%s' does not exist or you do not have permission to access it." % team_id
        ctx.exit(CHISUBMIT_FAIL)

    tempdir = tempfile.mkdtemp(prefix="%s-%s-" % (course.id, team.id))

    repo_url = conn.get_repository_git_url(course, team)

    try:
        LocalGitRepo.create_repo(tempdir, clone_from_url=repo_url)
    except Exception, e:
        print "Unable to create a clone of repository %s" % repo_url
        ctx.exit(CHISUBMIT_FAIL)
Example #32
0
def admin_course_create_git_users(ctx, course_id, staging, dry_run, all_types, only_type):   
    course = get_course_or_exit(ctx, course_id)    
                
    if all_types and only_type is not None:
        print "You cannot specify both --all-types and --only-type"
        ctx.exit(CHISUBMIT_FAIL)
        
    if staging and only_type == "student":
        print "You cannot create student accounts on the staging server."
        ctx.exit(CHISUBMIT_FAIL)
          
    conn = create_connection(course, ctx.obj['config'], staging)          
          
    users = []
    
    if not staging and (all_types or only_type == "student"):
        users += course.get_students()

    if all_types or only_type == "grader":
        users += course.get_graders()

    if all_types or only_type == "instructor":
        users += course.get_instructors()

    for user in users:
        if conn.exists_user(course, user):
            print "[SKIP] User '%s' already exists" % user.username
        else:
            if dry_run:
                print "[OK] Created user %s" % user.username
            else:
                try:
                    conn.create_user(course, user)
                    print "[OK] Created user %s" % user.username
                except ChisubmitException, ce:
                    print "[ERROR] Couldn't create user '%s': %s" % (user.username, ce.message)
Example #33
0
def instructor_team_pull_repos(ctx, course, directory, assignment, only_ready_for_grading, reset, only):
    if only_ready_for_grading and assignment is None:
        print("--only-ready-for-grading can only be used with --assignment option")
        ctx.exit(CHISUBMIT_FAIL)
    
    if assignment is not None:
        assignment = get_assignment_or_exit(ctx, course, assignment)

    conn = create_connection(course, ctx.obj['config'])

    directory = os.path.expanduser(directory)
    if not os.path.exists(directory):
        os.makedirs(directory)
    
    if assignment is None:
        teams = sorted(course.get_teams(), key = operator.attrgetter("team_id"))
    else:
        teams_registrations = get_teams_registrations(course, assignment, only = only)
        teams = sorted([t for t in list(teams_registrations.keys()) if t.active], key = operator.attrgetter("team_id"))

    max_len = max([len(t.team_id) for t in teams])

    for team in teams:
        team_dir = "%s/%s" % (directory, team.team_id)
        team_git_url = conn.get_repository_git_url(course, team) 

        if only_ready_for_grading:
            registration = teams_registrations[team]
    
            if not registration.is_ready_for_grading() and only_ready_for_grading:
                print("%-*s  SKIPPING (not ready for grading)" % (max_len, team.team_id))
                continue
        
        try:
            msg = ""
            if not os.path.exists(team_dir):
                r = LocalGitRepo.create_repo(team_dir, clone_from_url=team_git_url)
                msg = "Cloned repo"
            else:
                r = LocalGitRepo(team_dir)
                if reset:
                    r.fetch("origin")
                    r.reset_branch("origin", "master")
                    msg = "Reset to match origin/master" 
                else:
                    if r.repo.is_dirty():
                        print("%-*s  ERROR: Cannot pull. Local repository has unstaged changes." % (max_len, team.team_id))
                        continue
                    r.checkout_branch("master")
                    r.pull("origin", "master")
                    msg = "Pulled latest changes"
            if only_ready_for_grading:
                r.checkout_commit(registration.final_submission.commit_sha)
                msg += " and checked out commit %s" % (registration.final_submission.commit_sha)               
            print("%-*s  %s" % (max_len, team.team_id, msg))
        except ChisubmitException as ce:
            print("%-*s  ERROR: Could not checkout or pull master branch (%s)" % (max_len, team.team_id, ce))
        except GitCommandError as gce:
            print("%-*s  ERROR: Could not checkout or pull master branch" % (max_len, team.team_id))
            print(gce)
        except InvalidGitRepositoryError as igre:
            print("%-*s  ERROR: Directory %s exists but does not contain a valid git repository"  % (max_len, team.team_id, team_dir))
        except Exception as e:
            print("%-*s  ERROR: Unexpected exception when trying to checkout/pull" % (max_len, team.team_id))
            raise
    
    return CHISUBMIT_SUCCESS
Example #34
0
def student_assignment_submit(ctx, course, team_id, assignment_id, commit_sha, extensions, force, yes):
    assignment = course.get_assignment(assignment_id)
    if assignment is None:
        print "Assignment %s does not exist" % assignment_id
        ctx.exit(CHISUBMIT_FAIL)
    
    team = course.get_team(team_id)
    if team is None:
        print "Team %s does not exist" % team_id
        ctx.exit(CHISUBMIT_FAIL)
    
    ta = team.get_assignment(assignment_id)
    if ta is None:
        print "Team %s is not registered for assignment %s" % (team_id, assignment_id)
        ctx.exit(CHISUBMIT_FAIL)
        
    if team.has_assignment_ready_for_grading(assignment):
        print "You cannot re-submit this assignment."
        print "You made a submission before the deadline, and the deadline has passed."

        ctx.exit(CHISUBMIT_FAIL)
        
    conn = create_connection(course, ctx.obj['config'])
    
    if conn is None:
        print "Could not connect to git server."
        ctx.exit(CHISUBMIT_FAIL)
    
    commit = conn.get_commit(course, team, commit_sha)
    
    if commit is None:
        print "Commit %s does not exist in repository" % commit_sha
        ctx.exit(CHISUBMIT_FAIL)

    response = assignment.submit(team_id, commit_sha, extensions, dry_run=True)

    success = response["success"]
    dry_run = response["dry_run"]

    deadline_utc = parse(response["submission"]["deadline"])
    
    submitted_at_utc = parse(response["submission"]["submitted_at"])
    extensions_needed = response["submission"]["extensions_needed"]
    extensions_requested = response["submission"]["extensions_requested"]    

    extensions_available_before = response["team"]["extensions_available_before"]
    extensions_available = response["team"]["extensions_available"]

    if response["prior_submission"]["submitted_at"] is not None:    
        prior_submitted_at_utc = parse(response["prior_submission"]["submitted_at"])
        prior_submitted_at_local = convert_datetime_to_local(prior_submitted_at_utc)
    prior_commit_sha = response["prior_submission"]["commit_sha"]
    prior_extensions_used = response["prior_submission"]["extensions_used"]

    deadline_local = convert_datetime_to_local(deadline_utc)
    submitted_at_local = convert_datetime_to_local(submitted_at_utc)
        
    if not success:
        if extensions_needed > extensions_available:
            msg1 = "You do not have enough extensions to submit this assignment."
            msg2 = "You would need %i extensions to submit this assignment at this " \
                   "time, but you only have %i left" % (extensions_needed, extensions_available)
        elif extensions_requested < extensions_needed:
            msg1 = "The number of extensions you have requested is insufficient."
            msg2 = "You need to request %s extensions." % extensions_needed
        elif extensions_requested > extensions_needed:
            msg1 = "The number of extensions you have requested is excessive."
            msg2 = "You only need to request %s extensions." % extensions_needed

        print
        print msg1
        print            
        print "     Deadline (UTC): %s" % deadline_utc.isoformat(sep=" ")
        print "          Now (UTC): %s" % submitted_at_utc.isoformat(sep=" ")
        print 
        print "   Deadline (Local): %s" % deadline_local.isoformat(sep=" ")
        print "        Now (Local): %s" % submitted_at_local.isoformat(sep=" ")
        print 
        print msg2 
        print

        ctx.exit(CHISUBMIT_FAIL)
    else:             
        if prior_commit_sha is not None:
            submission_commit = conn.get_commit(course, team, prior_commit_sha)
            
            if prior_commit_sha == commit_sha:
                print "You have already submitted assignment %s" % assignment.id
                print "You submitted the following commit on %s:" % prior_submitted_at_local
                print
                if submission_commit is None:
                    print "WARNING: Previously submitted commit '%s' is not in the repository!" % prior_commit_sha
                else:
                    print_commit(submission_commit)
                print
                print "You are trying to submit the same commit again (%s)" % prior_commit_sha
                print "If you want to re-submit, please specify a different commit"
                ctx.exit(CHISUBMIT_FAIL)
                
            if not force:
                print        
                print "You have already submitted assignment %s" % assignment.id
                print "You submitted the following commit on %s:" % prior_submitted_at_local
                print
                if submission_commit is None:
                    print "WARNING: Previously submitted commit '%s' is not in the repository!" % prior_commit_sha
                else:
                    print_commit(submission_commit)
                print
                print "If you want to submit again, please use the --force option"
                ctx.exit(CHISUBMIT_FAIL)
            else:
                print
                print "WARNING: You have already submitted assignment %s and you" % assignment.id 
                print "are about to overwrite the previous submission of the following commit:"
                print
                if submission_commit is None:
                    print "WARNING: Previously submitted commit '%s' is not in the repository!" % prior_commit_sha
                else:
                    print_commit(submission_commit)
                print
    
        if prior_commit_sha is not None and force:
            msg = "THE ABOVE SUBMISSION FOR %s (%s) WILL BE CANCELLED." % (assignment.id, assignment.name)
            
            print "!"*len(msg)
            print msg
            print "!"*len(msg)
            print
            print "If you continue, your submission for %s (%s)" % (assignment.id, assignment.name)
            print "will now point to the following commit:"                
        else:
            print "You are going to make a submission for %s (%s)." % (assignment.id, assignment.name)
            print "The commit you are submitting is the following:"
        print
        print_commit(commit)
        print
        print "PLEASE VERIFY THIS IS THE EXACT COMMIT YOU WANT TO SUBMIT"
        print
        print "Your team currently has %i extensions" % (extensions_available_before)
        print
        if prior_commit_sha is not None:
            print "You used %i extensions in your previous submission of this assignment." % prior_extensions_used
            print "and you are going to use %i additional extensions now." % (extensions_needed - prior_extensions_used)
        else:
            print "You are going to use %i extensions on this submission." % extensions_needed
        print
        print "You will have %i extensions left after this submission." % extensions_available
        print 
        print "Are you sure you want to continue? (y/n): ", 
        
        if not yes:
            yesno = raw_input()
        else:
            yesno = 'y'
            print 'y'
        
        if yesno in ('y', 'Y', 'yes', 'Yes', 'YES'):
            response = assignment.submit(team_id, commit_sha, extensions, dry_run=False)
              
            # TODO: Can't do this until GitLab supports updating tags
            #    
            # message = "Extensions: %i\n" % extensions_requested
            # if submission_tag is None:
            #     conn.create_submission_tag(course, team, tag_name, message, commit.sha)
            # else:
            #     conn.update_submission_tag(course, team, tag_name, message, commit.sha)
                
            print
            if response["success"]:
                print "Your submission has been completed."
            else:
                print "ERROR: Your submission was not completed."
            
        return CHISUBMIT_SUCCESS
Example #35
0
def admin_course_setup(ctx, config_file, skip_user_creation,
                       skip_repo_creation):
    with open(config_file, "r") as f:
        conf = yaml.load(f)

    config_dir = os.path.dirname(os.path.realpath(config_file))

    for field in ("course_id", "course_name", "upstream_repo",
                  "individual_repos", "staging_repos", "git_connstr"):
        if field not in conf:
            print("ERROR: Configuration file is missing '%s' field" % field)
            ctx.exit(CHISUBMIT_FAIL)

    staff_file = config_dir + "/" + conf.get("staff_file", "staff.csv")
    students_file = config_dir + "/" + conf.get("students_file",
                                                "students.csv")

    course_id = conf["course_id"]
    course_name = conf["course_name"]

    # Create the course
    try:
        course = ctx.obj["client"].get_course(course_id=course_id)
        print("- Course with course_id = %s already exists." % course_id)
    except UnknownObjectException as uoe:
        course = ctx.obj["client"].create_course(course_id=course_id,
                                                 name=course_name)
        print("- Created new course %s" % course_id)

    # Set the Git connection string
    api_obj_set_attribute(ctx, course, "git_server_connstr",
                          conf["git_connstr"])

    # Setup the Git server
    conn = create_connection(course, ctx.obj['config'], False)

    if conn is None:
        print("Could not connect to git server.")
        ctx.exit(CHISUBMIT_FAIL)

    rv = conn.init_course(course, fail_if_exists=False)
    if rv:
        print("- Git server setup complete")
    else:
        print("- Git server is already setup")

    print("- Creating/updating staff users")
    print("===============================")
    print()
    with open(staff_file, "r") as f:
        ctx.invoke(admin_course_load_users,
                   course_id=course_id,
                   csv_file=f,
                   csv_username_column="username",
                   csv_fname_column="fname",
                   csv_lname_column="lname",
                   csv_email_column="email",
                   user_type="column",
                   user_type_column="type")
    print()
    print("===============================")
    print("- Staff user creation/update complete.")

    print("- Creating instructor git users")
    print("===============================")
    print()
    ctx.invoke(admin_course_create_git_users,
               course_id=course_id,
               only_type="instructor")
    print()
    print("===============================")

    print("- Creating grader git users")
    print("===========================")
    print()
    ctx.invoke(admin_course_create_git_users,
               course_id=course_id,
               only_type="grader")
    print()
    print("===========================")

    conn.update_instructors(course)
    print("- Updated instructor access privileges on Git server")

    # Setup staging Git server
    if conf["staging_repos"] == True:
        git_staging_connstr = conf.get("git_staging_connstr",
                                       conf["git_connstr"])
        api_obj_set_attribute(ctx, course, "git_staging_connstr",
                              git_staging_connstr)

        staging_conn = create_connection(course, ctx.obj['config'], True)

        if staging_conn is None:
            print("Could not connect to staging git server.")
            ctx.exit(CHISUBMIT_FAIL)

        rv = staging_conn.init_course(course, fail_if_exists=False)

        if rv:
            print("- Staging Git server setup complete")
        else:
            print("- Staging Git server is already setup")

        staging_conn.update_instructors(course)
        staging_conn.update_graders(course)
        print(
            "- Updated instructor/grader access privileges on staging Git server"
        )
    else:
        print("- This course does not need staging repos")

    print("- Creating/updating student users")
    print("=================================")
    print()
    with open(students_file, "r") as f:
        ctx.invoke(admin_course_load_users,
                   course_id=course_id,
                   csv_file=f,
                   csv_username_column="username",
                   csv_fname_column="fname",
                   csv_lname_column="lname",
                   csv_email_column="email",
                   user_type="student",
                   sync=True)
    print()
    print("===============================")
    print("- Student user creation/update complete.")
    print("- Creating student git users")
    print("===========================")
    print()
    ctx.invoke(admin_course_create_git_users,
               course_id=course_id,
               only_type="student")
    print()
    print("===========================")

    if conf["individual_repos"] == True:
        print("- Creating individual teams")
        print("===========================")
        print()
        ctx.invoke(admin_course_create_individual_teams, course_id=course_id)
        print()
        print("===========================")
        print("- Individual team creation complete.")

    print("- Creating repos")
    print("================")
    print()
    ctx.invoke(admin_course_create_repos, course_id=course_id)
    print()
    print("================")
    print("- Repo creation complete.")

    if conf["staging_repos"] == True:
        print("- Creating staging repos")
        print("========================")
        print()
        ctx.invoke(admin_course_create_repos,
                   course_id=course_id,
                   staging=True)
        print()
        print("========================")
        print("- Repo creation complete.")

    return CHISUBMIT_SUCCESS
Example #36
0
def student_assignment_submit(ctx, course, assignment_id, commit_sha, yes):
    assignment = get_assignment_or_exit(ctx, course, assignment_id)

    # Determine team for this assignment
    team, registration = get_team_registration_from_user(ctx, course, assignment)
    team_members = team.get_team_members()    
                
    title = "SUBMISSION FOR ASSIGNMENT %s (%s)" % (assignment.assignment_id, assignment.name)
    print title
    print "-" * len(title)
    print
    if len(team_members) == 1:
        student = team_members[0].student
        individual = True
        print "This is an INDIVIDUAL submission for %s %s" % (student.user.first_name, student.user.last_name)
    else:
        students = [tm.student for tm in team_members]
        individual = False
        print "This is a TEAM submission for team %s with the following students:" % team.team_id
        for s in students:
            print " - %s %s" % (s.user.first_name, s.user.last_name)
    print
                
    conn = create_connection(course, ctx.obj['config'])
    
    if conn is None:
        print "Could not connect to git server."
        ctx.exit(CHISUBMIT_FAIL)
    
    if commit_sha is None:
        commit = conn.get_latest_commit(course, team)

        if commit is None:
            print "It seems there are no commits in your repository, so I cannot submit anything"
            ctx.exit(CHISUBMIT_FAIL)
                
        user_specified_commit = False
    else:    
        commit = conn.get_commit(course, team, commit_sha)
        
        if commit is None:
            print "Commit %s does not exist in repository" % commit_sha
            ctx.exit(CHISUBMIT_FAIL)

        user_specified_commit = True
        
    try:
        submit_response = registration.submit(commit.sha, dry_run = True)
    except BadRequestException, bre:
        response_data = bre.json
        
        if "extensions_needed" in response_data and "extensions_available" in response_data:
            extensions_needed = response_data["extensions_needed"]
            extensions_available = response_data["extensions_available"]
            
            deadline_utc = parse(response_data["deadline"])
            submitted_at_utc = parse(response_data["submitted_at"])
            deadline_local = convert_datetime_to_local(deadline_utc)
            submitted_at_local = convert_datetime_to_local(submitted_at_utc)        
            
            if extensions_needed > extensions_available:
                msg1 = "You do not have enough extensions to submit this assignment."
                msg2 = "You would need %i extensions to submit this assignment at this " \
                       "time, but you only have %i left" % (extensions_needed, extensions_available)
    
                print
                print msg1
                print            
                print "     Deadline (UTC): %s" % deadline_utc.isoformat(sep=" ")
                print "          Now (UTC): %s" % submitted_at_utc.isoformat(sep=" ")
                print 
                print "   Deadline (Local): %s" % deadline_local.isoformat(sep=" ")
                print "        Now (Local): %s" % submitted_at_local.isoformat(sep=" ")
                print 
                print msg2 
                print
            else:
                print "ERROR: Your submission cannot be completed. The server reported the following:"
                print
                bre.print_errors()
        else:
            print "ERROR: Your submission cannot be completed. The server reported the following:"
            print
            bre.print_errors()

        ctx.exit(CHISUBMIT_FAIL)
Example #37
0
def student_assignment_cancel_submit(ctx, course, assignment_id, yes):
    assignment = get_assignment_or_exit(ctx, course, assignment_id)

    # Determine team for this assignment
    team, registration = get_team_registration_from_user(ctx, course, assignment)
    team_members = team.get_team_members()    
    
    if len(team_members) == 1:
        individual = True
    else:
        individual = False    
    
    if registration.final_submission is None:
        if individual:
            print "You have not made a submission for assignment %s," % assignment_id
        else:
            print "Team %s has not made a submission for assignment %s," % (team.team_id, assignment_id)
        print "so there is nothing to cancel."
        ctx.exit(CHISUBMIT_FAIL)
        
    if is_submission_ready_for_grading(assignment_deadline=registration.assignment.deadline, 
                                       submission_date=registration.final_submission.submitted_at,
                                       extensions_used=registration.final_submission.extensions_used):
        print "You cannot cancel this submission."
        print "You made a submission before the deadline, and the deadline has passed."

        ctx.exit(CHISUBMIT_FAIL)        
            
    conn = create_connection(course, ctx.obj['config'])
    
    if conn is None:
        print "Could not connect to git server."
        ctx.exit(CHISUBMIT_FAIL)
        
    submission_commit = conn.get_commit(course, team, registration.final_submission.commit_sha)
        
    print
    print "This is your existing submission for assignment %s:" % assignment_id
    print
    if submission_commit is None:
        print "WARNING: Previously submitted commit '%s' is not in the repository!" % registration.final_submission.commit_sha
    else:
        print_commit(submission_commit)
    print    

    print "Are you sure you want to cancel this submission? (y/n): ", 
    
    if not yes:
        yesno = raw_input()
    else:
        yesno = 'y'
        print 'y'
    
    if yesno in ('y', 'Y', 'yes', 'Yes', 'YES'):
        registration.final_submission_id = None
        
        # TODO: Can't do this until GitLab supports updating tags
        #    
        # message = "Extensions: %i\n" % extensions_requested
        # if submission_tag is None:
        #     conn.create_submission_tag(course, team, tag_name, message, commit.sha)
        # else:
        #     conn.update_submission_tag(course, team, tag_name, message, commit.sha)
        print
        print "Your submission has been cancelled."
Example #38
0
def instructor_assignment_submit(ctx, course, team_id, assignment_id, commit_sha, extensions):
    team = get_team_or_exit(ctx, course, team_id)
    registration = get_assignment_registration_or_exit(ctx, team, assignment_id)
            
    conn = create_connection(course, ctx.obj['config'])
    
    if conn is None:
        print("Could not connect to git server.")
        ctx.exit(CHISUBMIT_FAIL)
    
    commit = conn.get_commit(course, team, commit_sha)
    
    if commit is None:
        print("Commit %s does not exist in repository" % commit_sha)
        ctx.exit(CHISUBMIT_FAIL)
    
    if registration.final_submission is not None:
        prior_commit_sha = registration.final_submission.commit_sha
        prior_submitted_at_utc = registration.final_submission.submitted_at
        prior_submitted_at_local = convert_datetime_to_local(prior_submitted_at_utc)            
        
        submission_commit = conn.get_commit(course, team, prior_commit_sha)            
        
        if prior_commit_sha == commit_sha:
            print("The team has already submitted assignment %s" % registration.assignment.assignment_id)
            print("They submitted the following commit on %s:" % prior_submitted_at_local)
            print()
            if submission_commit is None:
                print("WARNING: Previously submitted commit '%s' is not in the repository!" % prior_commit_sha)
            else:
                print_commit(submission_commit)
            print()
            print("You are trying to submit the same commit again (%s)" % prior_commit_sha)
            print("If you want to re-submit, please specify a different commit")
            ctx.exit(CHISUBMIT_FAIL)
            
        print()
        print("WARNING: This team has already submitted assignment %s and you" % registration.assignment.assignment_id) 
        print("are about to overwrite the previous submission of the following commit:")
        print()
        if submission_commit is None:
            print("WARNING: Previously submitted commit '%s' is not in the repository!" % prior_commit_sha)
        else:
            print_commit(submission_commit)
        print()

    if registration.final_submission is not None:
        msg = "THE ABOVE SUBMISSION FOR %s (%s) WILL BE CANCELLED." % (registration.assignment.assignment_id, registration.assignment.name)
        
        print("!"*len(msg))
        print(msg)
        print("!"*len(msg))
        print()
        print("If you continue, their submission for %s (%s)" % (registration.assignment.assignment_id, registration.assignment.name))
        print("will now point to the following commit:")                
    else:
        print("You are going to make a submission for %s (%s)." % (registration.assignment.assignment_id, registration.assignment.name))
        print("The commit you are submitting is the following:")
    print()
    print_commit(commit)
    print()
    print("PLEASE VERIFY THIS IS THE EXACT COMMIT YOU WANT TO SUBMIT")
    print()
    print("Are you sure you want to continue? (y/n): ", end=' ') 
    
    yesno = input()
    
    if yesno in ('y', 'Y', 'yes', 'Yes', 'YES'):
        try:
            submit_response = registration.submit(commit_sha, extensions_override = extensions, dry_run=False)
                        
            print("The submission has been completed.")
            return CHISUBMIT_SUCCESS

        except BadRequestException as bre:        
            print("ERROR: The submission was not completed. The server reported the following errors:")
            bre.print_errors()
            ctx.exit(CHISUBMIT_FAIL)
Example #39
0
def instructor_team_pull_repos(ctx, course, directory, assignment,
                               only_ready_for_grading, reset, only):
    if only_ready_for_grading and assignment is None:
        print(
            "--only-ready-for-grading can only be used with --assignment option"
        )
        ctx.exit(CHISUBMIT_FAIL)

    if assignment is not None:
        assignment = get_assignment_or_exit(ctx, course, assignment)

    conn = create_connection(course, ctx.obj['config'])

    directory = os.path.expanduser(directory)
    if not os.path.exists(directory):
        os.makedirs(directory)

    if assignment is None:
        teams = sorted(course.get_teams(), key=operator.attrgetter("team_id"))
    else:
        teams_registrations = get_teams_registrations(course,
                                                      assignment,
                                                      only=only)
        teams = sorted(
            [t for t in list(teams_registrations.keys()) if t.active],
            key=operator.attrgetter("team_id"))

    max_len = max([len(t.team_id) for t in teams])

    for team in teams:
        team_dir = "%s/%s" % (directory, team.team_id)
        team_git_url = conn.get_repository_git_url(course, team)

        if only_ready_for_grading:
            registration = teams_registrations[team]

            if not registration.is_ready_for_grading(
            ) and only_ready_for_grading:
                print("%-*s  SKIPPING (not ready for grading)" %
                      (max_len, team.team_id))
                continue

        try:
            msg = ""
            if not os.path.exists(team_dir):
                r = LocalGitRepo.create_repo(team_dir,
                                             clone_from_url=team_git_url)
                msg = "Cloned repo"
            else:
                r = LocalGitRepo(team_dir)
                if reset:
                    r.fetch("origin")
                    r.reset_branch("origin", "master")
                    msg = "Reset to match origin/master"
                else:
                    if r.repo.is_dirty():
                        print(
                            "%-*s  ERROR: Cannot pull. Local repository has unstaged changes."
                            % (max_len, team.team_id))
                        continue
                    r.checkout_branch("master")
                    r.pull("origin", "master")
                    msg = "Pulled latest changes"
            if only_ready_for_grading:
                r.checkout_commit(registration.final_submission.commit_sha)
                msg += " and checked out commit %s" % (
                    registration.final_submission.commit_sha)
            print("%-*s  %s" % (max_len, team.team_id, msg))
        except ChisubmitException as ce:
            print(
                "%-*s  ERROR: Could not checkout or pull master branch (%s)" %
                (max_len, team.team_id, ce))
        except GitCommandError as gce:
            print("%-*s  ERROR: Could not checkout or pull master branch" %
                  (max_len, team.team_id))
            print(gce)
        except InvalidGitRepositoryError as igre:
            print(
                "%-*s  ERROR: Directory %s exists but does not contain a valid git repository"
                % (max_len, team.team_id, team_dir))
        except Exception as e:
            print(
                "%-*s  ERROR: Unexpected exception when trying to checkout/pull"
                % (max_len, team.team_id))
            raise

    return CHISUBMIT_SUCCESS
Example #40
0
def student_assignment_submit(ctx, course, assignment_id, commit_sha, yes):
    assignment = get_assignment_or_exit(ctx, course, assignment_id)

    # Determine team for this assignment
    team, registration = get_team_registration_from_user(ctx, course, assignment)
    team_members = team.get_team_members()    
                
    title = "SUBMISSION FOR ASSIGNMENT %s (%s)" % (assignment.assignment_id, assignment.name)
    print(title)
    print("-" * len(title))
    print()
    if len(team_members) == 1:
        student = team_members[0].student
        individual = True
        print("This is an INDIVIDUAL submission for %s %s" % (student.user.first_name, student.user.last_name))
    else:
        students = [tm.student for tm in team_members]
        individual = False
        print("This is a TEAM submission for team %s with the following students:" % team.team_id)
        for s in students:
            print(" - %s %s" % (s.user.first_name, s.user.last_name))
    print()
                
    conn = create_connection(course, ctx.obj['config'])
    
    if conn is None:
        print("Could not connect to git server.")
        ctx.exit(CHISUBMIT_FAIL)
    
    if commit_sha is None:
        commit = conn.get_latest_commit(course, team)

        if commit is None:
            print("It seems there are no commits in your repository, so I cannot submit anything")
            ctx.exit(CHISUBMIT_FAIL)
                
        user_specified_commit = False
    else:    
        commit = conn.get_commit(course, team, commit_sha)
        
        if commit is None:
            print("Commit %s does not exist in repository" % commit_sha)
            ctx.exit(CHISUBMIT_FAIL)

        user_specified_commit = True
        
    try:
        submit_response = registration.submit(commit.sha, dry_run = True)
    except BadRequestException as bre:
        response_data = bre.json
        
        if "extensions_needed" in response_data and "extensions_available" in response_data:
            extensions_needed = response_data["extensions_needed"]
            extensions_available = response_data["extensions_available"]
            
            deadline_utc = parse(response_data["deadline"])
            submitted_at_utc = parse(response_data["submitted_at"])
            deadline_local = convert_datetime_to_local(deadline_utc)
            submitted_at_local = convert_datetime_to_local(submitted_at_utc)        
            
            if extensions_needed > extensions_available:
                msg1 = "You do not have enough extensions to submit this assignment."
                msg2 = "You would need %i extensions to submit this assignment at this " \
                       "time, but you only have %i left" % (extensions_needed, extensions_available)
    
                print()
                print(msg1)
                print()            
                print("     Deadline (UTC): %s" % deadline_utc.isoformat(sep=" "))
                print("          Now (UTC): %s" % submitted_at_utc.isoformat(sep=" "))
                print() 
                print("   Deadline (Local): %s" % deadline_local.isoformat(sep=" "))
                print("        Now (Local): %s" % submitted_at_local.isoformat(sep=" "))
                print() 
                print(msg2) 
                print()
            else:
                print("ERROR: Your submission cannot be completed. The server reported the following:")
                print()
                bre.print_errors()
        else:
            print("ERROR: Your submission cannot be completed. The server reported the following:")
            print()
            bre.print_errors()

        ctx.exit(CHISUBMIT_FAIL)
    
    if registration.final_submission is not None:
        prior_commit_sha = registration.final_submission.commit_sha
        prior_extensions_used = registration.final_submission.extensions_used             
        prior_submitted_at_utc = registration.final_submission.submitted_at
        prior_submitted_at_local = convert_datetime_to_local(prior_submitted_at_utc)            
        
        submission_commit = conn.get_commit(course, team, prior_commit_sha)            
        
        if prior_commit_sha == commit.sha:
            print("You have already submitted assignment %s" % registration.assignment.assignment_id)
            print()
            print("You submitted the following commit on %s:" % prior_submitted_at_local)
            print()
            if submission_commit is None:
                print("WARNING: Previously submitted commit '%s' is not in the repository!" % prior_commit_sha)
            else:
                print_commit(submission_commit)
            print()
            if user_specified_commit:
                print("You are trying to submit the same commit again (%s)" % prior_commit_sha)
                print("If you want to re-submit, please specify a different commit.")
            else:
                print("The above commit is the latest commit in your repository.")
                print()
                print("If you were expecting to see a different commit, make sure you've pushed")
                print("your latest code to your repository.")
            ctx.exit(CHISUBMIT_FAIL)
            
        print("You have already submitted assignment %s" % registration.assignment.assignment_id)
        print()
        print("You submitted the following commit on %s:" % prior_submitted_at_local)
        print()
        if submission_commit is None:
            print("WARNING: Previously submitted commit '%s' is not in the repository!" % prior_commit_sha)
        else:
            print_commit(submission_commit)
        print()

        msg = "IF YOU CONTINUE, THE ABOVE SUBMISSION FOR %s (%s) WILL BE CANCELLED." % (registration.assignment.assignment_id, registration.assignment.name)
        
        print("!"*len(msg))
        print(msg)
        print("!"*len(msg))
        print()        
        if not user_specified_commit:
            print("If you continue, your submission will instead point to the latest commit in your repository:")
        else:
            print("If you continue, your submission will instead point to the following commit:")                
    else:
        if not user_specified_commit:
            print("The latest commit in your repository is the following:")
        else:
            print("The commit you are submitting is the following:")
    print()
    print_commit(commit)
    print()
    print("PLEASE VERIFY THIS IS THE EXACT COMMIT YOU WANT TO SUBMIT")
    print()
    if individual:
        print("You currently have %i extensions" % (submit_response.extensions_before))
    else:
        print("Your team currently has %i extensions" % (submit_response.extensions_before))
    print()
    if registration.final_submission is not None:
        print("You used %i extensions in your previous submission of this assignment." % prior_extensions_used)
        print("and you are going to use %i additional extensions now." % (submit_response.extensions_needed - prior_extensions_used))
    else:
        print("You are going to use %i extensions on this submission." % submit_response.extensions_needed)
    print()
    print("You will have %i extensions left after this submission." % submit_response.extensions_after)
    print()
    
    if submit_response.in_grace_period:
        print("NOTE: You are submitting after the deadline, but the instructor has")
        print("allowed some extra time after the deadline for students to submit")
        print("without having to consume an extension.")
        print()
     
    print("Are you sure you want to continue? (y/n): ", end=' ') 
    
    if not yes:
        yesno = input()
    else:
        yesno = 'y'
        print('y')
    
    if yesno in ('y', 'Y', 'yes', 'Yes', 'YES'):
        try:
            submit_response = registration.submit(commit.sha, dry_run=False)
            
            # TODO: Can't do this until GitLab supports updating tags
            #    
            # message = "Extensions: %i\n" % extensions_requested
            # if submission_tag is None:
            #     conn.create_submission_tag(course, team, tag_name, message, commit.sha)
            # else:
            #     conn.update_submission_tag(course, team, tag_name, message, commit.sha)
            
            print()
            print("Your submission has been completed.")

            if submit_response.in_grace_period:
                print()
                print("Your submission was made during the deadline's grace period. This means")
                print("that, although your submission was technically made *after* the")
                print("deadline, we are counting it as if it had been made before the deadline.")
                print()
                print("In the future, you should not rely on the presence of this grace period!")
                print("Your instructor may choose not to use one in future assignments, or may")
                print("use a shorter grace period. Your instructor is also aware of what")
                print("submissions are made during the grace period; if you repeatedly submit")
                print("during the grace period, your instructor may charge you an extension")
                print("or refuse to accept your assignment if you are out of extensions.")
            
            return CHISUBMIT_SUCCESS

        except BadRequestException as bre:
            print()        
            print("ERROR: Your submission was not completed. The server reported the following errors:")
            bre.print_errors()
            ctx.exit(CHISUBMIT_FAIL)
    else:
        print("Your submission has not been completed.")
        print()
        print("If you chose not to proceed because the above commit is not the one you wanted")
        print("to submit, make sure you've pushed your latest code to your repository before")
        print("attempting to submit again.")
        print()
        print("If you want to submit a different commit from your latest commit (e.g., an earlier")
        print("commit), you can use the --commit-sha option to specify a different commit.")
        ctx.exit(CHISUBMIT_FAIL)
Example #41
0
def student_assignment_cancel_submit(ctx, course, team_id, assignment_id, yes):
    assignment = course.get_assignment(assignment_id)
    if assignment is None:
        print "Assignment %s does not exist" % assignment_id
        ctx.exit(CHISUBMIT_FAIL)
    
    team = course.get_team(team_id)
    if team is None:
        print "Team %s does not exist" % team_id
        ctx.exit(CHISUBMIT_FAIL)
        
    ta = team.get_assignment(assignment_id)
    if ta is None:
        print "Team %s is not registered for assignment %s" % (team_id, assignment_id)
        ctx.exit(CHISUBMIT_FAIL)
        
    if ta.submitted_at is None:
        print "Team %s has not made a submission for assignment %s," % (team_id, assignment_id)
        print "so there is nothing to cancel."
        ctx.exit(CHISUBMIT_FAIL)
        
    if ta.submitted_at is not None:
        now = get_datetime_now_utc()
        deadline = assignment.deadline + timedelta(days=ta.extensions_used)
        
        if now > deadline:
            print "You cannot cancel this submission."
            print "You made a submission before the deadline, and the deadline has passed."

            ctx.exit(CHISUBMIT_FAIL)        
            
    conn = create_connection(course, ctx.obj['config'])
    
    if conn is None:
        print "Could not connect to git server."
        ctx.exit(CHISUBMIT_FAIL)
        
    submission_commit = conn.get_commit(course, team, ta.commit_sha)
        
    print
    print "This is your existing submission for assignment %s:" % assignment.id 
    print
    if submission_commit is None:
        print "WARNING: Previously submitted commit '%s' is not in the repository!" % ta.commit_sha
    else:
        print_commit(submission_commit)
    print    

    print "Are you sure you want to cancel this submission? (y/n): ", 
    
    if not yes:
        yesno = raw_input()
    else:
        yesno = 'y'
        print 'y'
    
    if yesno in ('y', 'Y', 'yes', 'Yes', 'YES'):
        response = assignment.cancel(team_id)
        
        # TODO: Can't do this until GitLab supports updating tags
        #    
        # message = "Extensions: %i\n" % extensions_requested
        # if submission_tag is None:
        #     conn.create_submission_tag(course, team, tag_name, message, commit.sha)
        # else:
        #     conn.update_submission_tag(course, team, tag_name, message, commit.sha)
            
        print
        if response["success"]:
            print "Your submission has been cancelled."
        else:
            print "ERROR: Your submission was not cancelled."
Example #42
0
def student_assignment_submit(ctx, course, team_id, assignment_id, commit_sha,
                              extensions, force, yes):
    assignment = course.get_assignment(assignment_id)
    if assignment is None:
        print "Assignment %s does not exist" % assignment_id
        ctx.exit(CHISUBMIT_FAIL)

    team = course.get_team(team_id)
    if team is None:
        print "Team %s does not exist" % team_id
        ctx.exit(CHISUBMIT_FAIL)

    ta = team.get_assignment(assignment_id)
    if ta is None:
        print "Team %s is not registered for assignment %s" % (team_id,
                                                               assignment_id)
        ctx.exit(CHISUBMIT_FAIL)

    if team.has_assignment_ready_for_grading(assignment):
        print "You cannot re-submit this assignment."
        print "You made a submission before the deadline, and the deadline has passed."

        ctx.exit(CHISUBMIT_FAIL)

    conn = create_connection(course, ctx.obj['config'])

    if conn is None:
        print "Could not connect to git server."
        ctx.exit(CHISUBMIT_FAIL)

    commit = conn.get_commit(course, team, commit_sha)

    if commit is None:
        print "Commit %s does not exist in repository" % commit_sha
        ctx.exit(CHISUBMIT_FAIL)

    response = assignment.submit(team_id, commit_sha, extensions, dry_run=True)

    success = response["success"]
    dry_run = response["dry_run"]

    deadline_utc = parse(response["submission"]["deadline"])

    submitted_at_utc = parse(response["submission"]["submitted_at"])
    extensions_needed = response["submission"]["extensions_needed"]
    extensions_requested = response["submission"]["extensions_requested"]

    extensions_available_before = response["team"][
        "extensions_available_before"]
    extensions_available = response["team"]["extensions_available"]

    if response["prior_submission"]["submitted_at"] is not None:
        prior_submitted_at_utc = parse(
            response["prior_submission"]["submitted_at"])
        prior_submitted_at_local = convert_datetime_to_local(
            prior_submitted_at_utc)
    prior_commit_sha = response["prior_submission"]["commit_sha"]
    prior_extensions_used = response["prior_submission"]["extensions_used"]

    deadline_local = convert_datetime_to_local(deadline_utc)
    submitted_at_local = convert_datetime_to_local(submitted_at_utc)

    if not success:
        if extensions_needed > extensions_available:
            msg1 = "You do not have enough extensions to submit this assignment."
            msg2 = "You would need %i extensions to submit this assignment at this " \
                   "time, but you only have %i left" % (extensions_needed, extensions_available)
        elif extensions_requested < extensions_needed:
            msg1 = "The number of extensions you have requested is insufficient."
            msg2 = "You need to request %s extensions." % extensions_needed
        elif extensions_requested > extensions_needed:
            msg1 = "The number of extensions you have requested is excessive."
            msg2 = "You only need to request %s extensions." % extensions_needed

        print
        print msg1
        print
        print "     Deadline (UTC): %s" % deadline_utc.isoformat(sep=" ")
        print "          Now (UTC): %s" % submitted_at_utc.isoformat(sep=" ")
        print
        print "   Deadline (Local): %s" % deadline_local.isoformat(sep=" ")
        print "        Now (Local): %s" % submitted_at_local.isoformat(sep=" ")
        print
        print msg2
        print

        ctx.exit(CHISUBMIT_FAIL)
    else:
        if prior_commit_sha is not None:
            submission_commit = conn.get_commit(course, team, prior_commit_sha)

            if prior_commit_sha == commit_sha:
                print "You have already submitted assignment %s" % assignment.id
                print "You submitted the following commit on %s:" % prior_submitted_at_local
                print
                if submission_commit is None:
                    print "WARNING: Previously submitted commit '%s' is not in the repository!" % prior_commit_sha
                else:
                    print_commit(submission_commit)
                print
                print "You are trying to submit the same commit again (%s)" % prior_commit_sha
                print "If you want to re-submit, please specify a different commit"
                ctx.exit(CHISUBMIT_FAIL)

            if not force:
                print
                print "You have already submitted assignment %s" % assignment.id
                print "You submitted the following commit on %s:" % prior_submitted_at_local
                print
                if submission_commit is None:
                    print "WARNING: Previously submitted commit '%s' is not in the repository!" % prior_commit_sha
                else:
                    print_commit(submission_commit)
                print
                print "If you want to submit again, please use the --force option"
                ctx.exit(CHISUBMIT_FAIL)
            else:
                print
                print "WARNING: You have already submitted assignment %s and you" % assignment.id
                print "are about to overwrite the previous submission of the following commit:"
                print
                if submission_commit is None:
                    print "WARNING: Previously submitted commit '%s' is not in the repository!" % prior_commit_sha
                else:
                    print_commit(submission_commit)
                print

        if prior_commit_sha is not None and force:
            msg = "THE ABOVE SUBMISSION FOR %s (%s) WILL BE CANCELLED." % (
                assignment.id, assignment.name)

            print "!" * len(msg)
            print msg
            print "!" * len(msg)
            print
            print "If you continue, your submission for %s (%s)" % (
                assignment.id, assignment.name)
            print "will now point to the following commit:"
        else:
            print "You are going to make a submission for %s (%s)." % (
                assignment.id, assignment.name)
            print "The commit you are submitting is the following:"
        print
        print_commit(commit)
        print
        print "PLEASE VERIFY THIS IS THE EXACT COMMIT YOU WANT TO SUBMIT"
        print
        print "Your team currently has %i extensions" % (
            extensions_available_before)
        print
        if prior_commit_sha is not None:
            print "You used %i extensions in your previous submission of this assignment." % prior_extensions_used
            print "and you are going to use %i additional extensions now." % (
                extensions_needed - prior_extensions_used)
        else:
            print "You are going to use %i extensions on this submission." % extensions_needed
        print
        print "You will have %i extensions left after this submission." % extensions_available
        print
        print "Are you sure you want to continue? (y/n): ",

        if not yes:
            yesno = raw_input()
        else:
            yesno = 'y'
            print 'y'

        if yesno in ('y', 'Y', 'yes', 'Yes', 'YES'):
            response = assignment.submit(team_id,
                                         commit_sha,
                                         extensions,
                                         dry_run=False)

            # TODO: Can't do this until GitLab supports updating tags
            #
            # message = "Extensions: %i\n" % extensions_requested
            # if submission_tag is None:
            #     conn.create_submission_tag(course, team, tag_name, message, commit.sha)
            # else:
            #     conn.update_submission_tag(course, team, tag_name, message, commit.sha)

            print
            if response["success"]:
                print "Your submission has been completed."
            else:
                print "ERROR: Your submission was not completed."

        return CHISUBMIT_SUCCESS
Example #43
0
def instructor_assignment_submit(ctx, course, team_id, assignment_id,
                                 commit_sha, extensions):
    team = get_team_or_exit(ctx, course, team_id)
    registration = get_assignment_registration_or_exit(ctx, team,
                                                       assignment_id)

    conn = create_connection(course, ctx.obj['config'])

    if conn is None:
        print "Could not connect to git server."
        ctx.exit(CHISUBMIT_FAIL)

    commit = conn.get_commit(course, team, commit_sha)

    if commit is None:
        print "Commit %s does not exist in repository" % commit_sha
        ctx.exit(CHISUBMIT_FAIL)

    if registration.final_submission is not None:
        prior_commit_sha = registration.final_submission.commit_sha
        prior_submitted_at_utc = registration.final_submission.submitted_at
        prior_submitted_at_local = convert_datetime_to_local(
            prior_submitted_at_utc)

        submission_commit = conn.get_commit(course, team, prior_commit_sha)

        if prior_commit_sha == commit_sha:
            print "The team has already submitted assignment %s" % registration.assignment.assignment_id
            print "They submitted the following commit on %s:" % prior_submitted_at_local
            print
            if submission_commit is None:
                print "WARNING: Previously submitted commit '%s' is not in the repository!" % prior_commit_sha
            else:
                print_commit(submission_commit)
            print
            print "You are trying to submit the same commit again (%s)" % prior_commit_sha
            print "If you want to re-submit, please specify a different commit"
            ctx.exit(CHISUBMIT_FAIL)

        print
        print "WARNING: This team has already submitted assignment %s and you" % registration.assignment.assignment_id
        print "are about to overwrite the previous submission of the following commit:"
        print
        if submission_commit is None:
            print "WARNING: Previously submitted commit '%s' is not in the repository!" % prior_commit_sha
        else:
            print_commit(submission_commit)
        print

    if registration.final_submission is not None:
        msg = "THE ABOVE SUBMISSION FOR %s (%s) WILL BE CANCELLED." % (
            registration.assignment.assignment_id,
            registration.assignment.name)

        print "!" * len(msg)
        print msg
        print "!" * len(msg)
        print
        print "If you continue, their submission for %s (%s)" % (
            registration.assignment.assignment_id,
            registration.assignment.name)
        print "will now point to the following commit:"
    else:
        print "You are going to make a submission for %s (%s)." % (
            registration.assignment.assignment_id,
            registration.assignment.name)
        print "The commit you are submitting is the following:"
    print
    print_commit(commit)
    print
    print "PLEASE VERIFY THIS IS THE EXACT COMMIT YOU WANT TO SUBMIT"
    print
    print "Are you sure you want to continue? (y/n): ",

    yesno = raw_input()

    if yesno in ('y', 'Y', 'yes', 'Yes', 'YES'):
        try:
            submit_response = registration.submit(
                commit_sha, extensions_override=extensions, dry_run=False)

            print "The submission has been completed."
            return CHISUBMIT_SUCCESS

        except BadRequestException, bre:
            print "ERROR: The submission was not completed. The server reported the following errors:"
            bre.print_errors()
            return CHISUBMIT_FAIL
Example #44
0
def student_assignment_cancel_submit(ctx, course, team_id, assignment_id, yes):
    assignment = course.get_assignment(assignment_id)
    if assignment is None:
        print "Assignment %s does not exist" % assignment_id
        ctx.exit(CHISUBMIT_FAIL)

    team = course.get_team(team_id)
    if team is None:
        print "Team %s does not exist" % team_id
        ctx.exit(CHISUBMIT_FAIL)

    ta = team.get_assignment(assignment_id)
    if ta is None:
        print "Team %s is not registered for assignment %s" % (team_id,
                                                               assignment_id)
        ctx.exit(CHISUBMIT_FAIL)

    if ta.submitted_at is None:
        print "Team %s has not made a submission for assignment %s," % (
            team_id, assignment_id)
        print "so there is nothing to cancel."
        ctx.exit(CHISUBMIT_FAIL)

    if ta.submitted_at is not None:
        now = get_datetime_now_utc()
        deadline = assignment.deadline + timedelta(days=ta.extensions_used)

        if now > deadline:
            print "You cannot cancel this submission."
            print "You made a submission before the deadline, and the deadline has passed."

            ctx.exit(CHISUBMIT_FAIL)

    conn = create_connection(course, ctx.obj['config'])

    if conn is None:
        print "Could not connect to git server."
        ctx.exit(CHISUBMIT_FAIL)

    submission_commit = conn.get_commit(course, team, ta.commit_sha)

    print
    print "This is your existing submission for assignment %s:" % assignment.id
    print
    if submission_commit is None:
        print "WARNING: Previously submitted commit '%s' is not in the repository!" % ta.commit_sha
    else:
        print_commit(submission_commit)
    print

    print "Are you sure you want to cancel this submission? (y/n): ",

    if not yes:
        yesno = raw_input()
    else:
        yesno = 'y'
        print 'y'

    if yesno in ('y', 'Y', 'yes', 'Yes', 'YES'):
        response = assignment.cancel(team_id)

        # TODO: Can't do this until GitLab supports updating tags
        #
        # message = "Extensions: %i\n" % extensions_requested
        # if submission_tag is None:
        #     conn.create_submission_tag(course, team, tag_name, message, commit.sha)
        # else:
        #     conn.update_submission_tag(course, team, tag_name, message, commit.sha)

        print
        if response["success"]:
            print "Your submission has been cancelled."
        else:
            print "ERROR: Your submission was not cancelled."
Example #45
0
def instructor_assignment_cancel_submit(ctx, course, team_id, assignment_id,
                                        yes):
    assignment = get_assignment_or_exit(ctx, course, assignment_id)
    team = get_team_or_exit(ctx, course, team_id)
    registration = get_assignment_registration_or_exit(
        ctx, team, assignment.assignment_id)

    if registration.final_submission is None:
        print("Team %s has not made a submission for assignment %s," %
              (team.team_id, assignment_id))
        print("so there is nothing to cancel.")
        ctx.exit(CHISUBMIT_FAIL)

    if registration.grader_username is not None:
        print("This submission has already been assigned a grader (%s)" %
              registration.grader_username)
        print(
            "Make sure the grader has been notified to discard this submission."
        )
        print(
            "You must also remove the existing grading branch from the staging server."
        )

        print("Are you sure you want to proceed? (y/n): ", end=' ')

        if not yes:
            yesno = input()
        else:
            yesno = 'y'
            print('y')

        if yesno not in ('y', 'Y', 'yes', 'Yes', 'YES'):
            ctx.exit(CHISUBMIT_FAIL)
        else:
            print()

    if is_submission_ready_for_grading(
            assignment_deadline=registration.assignment.deadline,
            submission_date=registration.final_submission.submitted_at,
            extensions_used=registration.final_submission.extensions_used):
        print(
            "WARNING: You are canceling a submission that is ready for grading!"
        )

    conn = create_connection(course, ctx.obj['config'])

    if conn is None:
        print("Could not connect to git server.")
        ctx.exit(CHISUBMIT_FAIL)

    submission_commit = conn.get_commit(
        course, team, registration.final_submission.commit_sha)

    print()
    print("This is the existing submission for assignment %s:" % assignment_id)
    print()
    if submission_commit is None:
        print(
            "WARNING: Previously submitted commit '%s' is not in the repository!"
            % registration.final_submission.commit_sha)
    else:
        print_commit(submission_commit)
    print()

    print("Are you sure you want to cancel this submission? (y/n): ", end=' ')

    if not yes:
        yesno = input()
    else:
        yesno = 'y'
        print('y')

    if yesno in ('y', 'Y', 'yes', 'Yes', 'YES'):
        registration.final_submission_id = None
        registration.grader_username = None
        registration.grading_started = False

        print()
        print("The submission has been cancelled.")
Example #46
0
def admin_course_setup(ctx, config_file, skip_user_creation, skip_repo_creation):
    with open(config_file, "r") as f:
        conf = yaml.load(f)

    config_dir = os.path.dirname(os.path.realpath(config_file))
    
    for field in ("course_id", "course_name", "upstream_repo", "individual_repos",
                  "staging_repos", "git_connstr"):
        if field not in conf:
            print("ERROR: Configuration file is missing '%s' field" % field)
            ctx.exit(CHISUBMIT_FAIL)
    
    staff_file = config_dir + "/" + conf.get("staff_file", "staff.csv")
    students_file = config_dir + "/" + conf.get("students_file", "students.csv")
    
    course_id = conf["course_id"]
    course_name = conf["course_name"]

    # Create the course    
    try:
        course = ctx.obj["client"].get_course(course_id = course_id)
        print("- Course with course_id = %s already exists." % course_id)
    except UnknownObjectException as uoe:
        course = ctx.obj["client"].create_course(course_id = course_id,
                                                 name = course_name)
        print("- Created new course %s" % course_id)
        
    # Set the Git connection string
    api_obj_set_attribute(ctx, course, "git_server_connstr", conf["git_connstr"])
    
    # Setup the Git server
    conn = create_connection(course, ctx.obj['config'], False)
    
    if conn is None:
        print("Could not connect to git server.")
        ctx.exit(CHISUBMIT_FAIL)

    rv = conn.init_course(course, fail_if_exists=False)
    if rv:    
        print("- Git server setup complete")
    else:
        print("- Git server is already setup")
    
    print("- Creating/updating staff users")
    print("===============================")
    print()
    with open(staff_file, "r") as f:
        ctx.invoke(admin_course_load_users, 
                   course_id = course_id,
                   csv_file = f,
                   csv_username_column = "username",
                   csv_fname_column = "fname",
                   csv_lname_column = "lname",
                   csv_email_column = "email",
                   user_type = "column",
                   user_type_column = "type"
                   )
    print()
    print("===============================")
    print("- Staff user creation/update complete.")

    print("- Creating instructor git users")
    print("===============================")
    print()
    ctx.invoke(admin_course_create_git_users, 
               course_id = course_id,
               only_type = "instructor")
    print()
    print("===============================")

    print("- Creating grader git users")
    print("===========================")
    print()
    ctx.invoke(admin_course_create_git_users, 
               course_id = course_id,
               only_type = "grader")
    print()
    print("===========================")
    
    conn.update_instructors(course)
    print("- Updated instructor access privileges on Git server")
    
    # Setup staging Git server
    if conf["staging_repos"] == True:
        git_staging_connstr = conf.get("git_staging_connstr", conf["git_connstr"])
        api_obj_set_attribute(ctx, course, "git_staging_connstr", git_staging_connstr)

        staging_conn = create_connection(course, ctx.obj['config'], True)
    
        if staging_conn is None:
            print("Could not connect to staging git server.")
            ctx.exit(CHISUBMIT_FAIL)

        rv = staging_conn.init_course(course, fail_if_exists=False)        
        
        if rv:    
            print("- Staging Git server setup complete")
        else:
            print("- Staging Git server is already setup")
        
        staging_conn.update_instructors(course)
        staging_conn.update_graders(course)
        print("- Updated instructor/grader access privileges on staging Git server")
    else:
        print("- This course does not need staging repos")

    print("- Creating/updating student users")
    print("=================================")    
    print()
    with open(students_file, "r") as f:
        ctx.invoke(admin_course_load_users, 
                   course_id = course_id,
                   csv_file = f,
                   csv_username_column = "username",
                   csv_fname_column = "fname",
                   csv_lname_column = "lname",
                   csv_email_column = "email",
                   user_type = "student",
                   sync = True
                   )
    print()
    print("===============================")
    print("- Student user creation/update complete.")
    print("- Creating student git users")
    print("===========================")
    print()
    ctx.invoke(admin_course_create_git_users, 
               course_id = course_id,
               only_type = "student")
    print()
    print("===========================")

    if conf["individual_repos"] == True:
        print("- Creating individual teams")
        print("===========================")
        print()
        ctx.invoke(admin_course_create_individual_teams, 
                   course_id = course_id
                   )
        print()
        print("===========================")
        print("- Individual team creation complete.")

    print("- Creating repos")
    print("================")
    print()
    ctx.invoke(admin_course_create_repos, 
               course_id = course_id
               )
    print()
    print("================")
    print("- Repo creation complete.")

    if conf["staging_repos"] == True:
        print("- Creating staging repos")
        print("========================")
        print()
        ctx.invoke(admin_course_create_repos, 
                   course_id = course_id,
                   staging = True
                   )
        print()
        print("========================")
        print("- Repo creation complete.")     
    
    return CHISUBMIT_SUCCESS
Example #47
0
def student_assignment_cancel_submit(ctx, course, assignment_id, yes):
    assignment = get_assignment_or_exit(ctx, course, assignment_id)

    # Determine team for this assignment
    team, registration = get_team_registration_from_user(ctx, course, assignment)
    team_members = team.get_team_members()    
    
    if len(team_members) == 1:
        individual = True
    else:
        individual = False    
    
    if registration.final_submission is None:
        if individual:
            print("You have not made a submission for assignment %s," % assignment_id)
        else:
            print("Team %s has not made a submission for assignment %s," % (team.team_id, assignment_id))
        print("so there is nothing to cancel.")
        ctx.exit(CHISUBMIT_FAIL)
        
    if registration.grading_started:
        print("You cannot cancel this submission.")
        print("You made a submission and it has already been sent to the graders for grading.")
        print("Please contact an instructor if you wish to amend your submission.")

        ctx.exit(CHISUBMIT_FAIL)        
            
    conn = create_connection(course, ctx.obj['config'])
    
    if conn is None:
        print("Could not connect to git server.")
        ctx.exit(CHISUBMIT_FAIL)
        
    submission_commit = conn.get_commit(course, team, registration.final_submission.commit_sha)
        
    print()
    print("This is your existing submission for assignment %s:" % assignment_id)
    print()
    if submission_commit is None:
        print("WARNING: Previously submitted commit '%s' is not in the repository!" % registration.final_submission.commit_sha)
    else:
        print_commit(submission_commit)
    print()    

    print("Are you sure you want to cancel this submission? (y/n): ", end=' ') 
    
    if not yes:
        yesno = input()
    else:
        yesno = 'y'
        print('y')
    
    if yesno in ('y', 'Y', 'yes', 'Yes', 'YES'):
        registration.final_submission_id = None
        
        # TODO: Can't do this until GitLab supports updating tags
        #    
        # message = "Extensions: %i\n" % extensions_requested
        # if submission_tag is None:
        #     conn.create_submission_tag(course, team, tag_name, message, commit.sha)
        # else:
        #     conn.update_submission_tag(course, team, tag_name, message, commit.sha)
        print()
        print("Your submission has been cancelled.")
Example #48
0
def instructor_assignment_cancel_submit(ctx, course, team_id, assignment_id, yes):
    assignment = get_assignment_or_exit(ctx, course, assignment_id)
    team = get_team_or_exit(ctx, course, team_id)
    registration = get_assignment_registration_or_exit(ctx, team, assignment.assignment_id)
        
    if registration.final_submission is None:
        print("Team %s has not made a submission for assignment %s," % (team.team_id, assignment_id))
        print("so there is nothing to cancel.")
        ctx.exit(CHISUBMIT_FAIL)
        
    if registration.grader_username is not None:
        print("This submission has already been assigned a grader (%s)" % registration.grader_username)
        print("Make sure the grader has been notified to discard this submission.")
        print("You must also remove the existing grading branch from the staging server.")
        
        print("Are you sure you want to proceed? (y/n): ", end=' ') 
        
        if not yes:
            yesno = input()
        else:
            yesno = 'y'
            print('y')
        
        if yesno not in ('y', 'Y', 'yes', 'Yes', 'YES'):
            ctx.exit(CHISUBMIT_FAIL)
        else:
            print()
        
    if is_submission_ready_for_grading(assignment_deadline=registration.assignment.deadline, 
                                       submission_date=registration.final_submission.submitted_at,
                                       extensions_used=registration.final_submission.extensions_used):
        print("WARNING: You are canceling a submission that is ready for grading!")
            
    conn = create_connection(course, ctx.obj['config'])
    
    if conn is None:
        print("Could not connect to git server.")
        ctx.exit(CHISUBMIT_FAIL)
        
    submission_commit = conn.get_commit(course, team, registration.final_submission.commit_sha)
        
    print()
    print("This is the existing submission for assignment %s:" % assignment_id)
    print()
    if submission_commit is None:
        print("WARNING: Previously submitted commit '%s' is not in the repository!" % registration.final_submission.commit_sha)
    else:
        print_commit(submission_commit)
    print()    

    print("Are you sure you want to cancel this submission? (y/n): ", end=' ') 
    
    if not yes:
        yesno = input()
    else:
        yesno = 'y'
        print('y')
    
    if yesno in ('y', 'Y', 'yes', 'Yes', 'YES'):
        registration.final_submission_id = None
        registration.grader_username = None
        registration.grading_started = False
        
        print()
        print("The submission has been cancelled.")
Example #49
0
def student_assignment_submit(ctx, course, assignment_id, commit_sha, yes):
    assignment = get_assignment_or_exit(ctx, course, assignment_id)

    # Determine team for this assignment
    team, registration = get_team_registration_from_user(
        ctx, course, assignment)
    team_members = team.get_team_members()

    title = "SUBMISSION FOR ASSIGNMENT %s (%s)" % (assignment.assignment_id,
                                                   assignment.name)
    print(title)
    print("-" * len(title))
    print()
    if len(team_members) == 1:
        student = team_members[0].student
        individual = True
        print("This is an INDIVIDUAL submission for %s %s" %
              (student.user.first_name, student.user.last_name))
    else:
        students = [tm.student for tm in team_members]
        individual = False
        print(
            "This is a TEAM submission for team %s with the following students:"
            % team.team_id)
        for s in students:
            print(" - %s %s" % (s.user.first_name, s.user.last_name))
    print()

    conn = create_connection(course, ctx.obj['config'])

    if conn is None:
        print("Could not connect to git server.")
        ctx.exit(CHISUBMIT_FAIL)

    if commit_sha is None:
        commit = conn.get_latest_commit(course, team)

        if commit is None:
            print(
                "It seems there are no commits in your repository, so I cannot submit anything"
            )
            ctx.exit(CHISUBMIT_FAIL)

        user_specified_commit = False
    else:
        commit = conn.get_commit(course, team, commit_sha)

        if commit is None:
            print("Commit %s does not exist in repository" % commit_sha)
            ctx.exit(CHISUBMIT_FAIL)

        user_specified_commit = True

    try:
        submit_response = registration.submit(commit.sha, dry_run=True)
    except BadRequestException as bre:
        response_data = bre.json

        if "extensions_needed" in response_data and "extensions_available" in response_data:
            extensions_needed = response_data["extensions_needed"]
            extensions_available = response_data["extensions_available"]

            deadline_utc = parse(response_data["deadline"])
            submitted_at_utc = parse(response_data["submitted_at"])
            deadline_local = convert_datetime_to_local(deadline_utc)
            submitted_at_local = convert_datetime_to_local(submitted_at_utc)

            if extensions_needed > extensions_available:
                msg1 = "You do not have enough extensions to submit this assignment."
                msg2 = "You would need %i extensions to submit this assignment at this " \
                       "time, but you only have %i left" % (extensions_needed, extensions_available)

                print()
                print(msg1)
                print()
                print("     Deadline (UTC): %s" %
                      deadline_utc.isoformat(sep=" "))
                print("          Now (UTC): %s" %
                      submitted_at_utc.isoformat(sep=" "))
                print()
                print("   Deadline (Local): %s" %
                      deadline_local.isoformat(sep=" "))
                print("        Now (Local): %s" %
                      submitted_at_local.isoformat(sep=" "))
                print()
                print(msg2)
                print()
            else:
                print(
                    "ERROR: Your submission cannot be completed. The server reported the following:"
                )
                print()
                bre.print_errors()
        else:
            print(
                "ERROR: Your submission cannot be completed. The server reported the following:"
            )
            print()
            bre.print_errors()

        ctx.exit(CHISUBMIT_FAIL)

    if registration.final_submission is not None:
        prior_commit_sha = registration.final_submission.commit_sha
        prior_extensions_used = registration.final_submission.extensions_used
        prior_submitted_at_utc = registration.final_submission.submitted_at
        prior_submitted_at_local = convert_datetime_to_local(
            prior_submitted_at_utc)

        submission_commit = conn.get_commit(course, team, prior_commit_sha)

        if prior_commit_sha == commit.sha:
            print("You have already submitted assignment %s" %
                  registration.assignment.assignment_id)
            print()
            print("You submitted the following commit on %s:" %
                  prior_submitted_at_local)
            print()
            if submission_commit is None:
                print(
                    "WARNING: Previously submitted commit '%s' is not in the repository!"
                    % prior_commit_sha)
            else:
                print_commit(submission_commit)
            print()
            if user_specified_commit:
                print("You are trying to submit the same commit again (%s)" %
                      prior_commit_sha)
                print(
                    "If you want to re-submit, please specify a different commit."
                )
            else:
                print(
                    "The above commit is the latest commit in your repository."
                )
                print()
                print(
                    "If you were expecting to see a different commit, make sure you've pushed"
                )
                print("your latest code to your repository.")
            ctx.exit(CHISUBMIT_FAIL)

        print("You have already submitted assignment %s" %
              registration.assignment.assignment_id)
        print()
        print("You submitted the following commit on %s:" %
              prior_submitted_at_local)
        print()
        if submission_commit is None:
            print(
                "WARNING: Previously submitted commit '%s' is not in the repository!"
                % prior_commit_sha)
        else:
            print_commit(submission_commit)
        print()

        msg = "IF YOU CONTINUE, THE ABOVE SUBMISSION FOR %s (%s) WILL BE CANCELLED." % (
            registration.assignment.assignment_id,
            registration.assignment.name)

        print("!" * len(msg))
        print(msg)
        print("!" * len(msg))
        print()
        if not user_specified_commit:
            print(
                "If you continue, your submission will instead point to the latest commit in your repository:"
            )
        else:
            print(
                "If you continue, your submission will instead point to the following commit:"
            )
    else:
        if not user_specified_commit:
            print("The latest commit in your repository is the following:")
        else:
            print("The commit you are submitting is the following:")
    print()
    print_commit(commit)
    print()
    print("PLEASE VERIFY THIS IS THE EXACT COMMIT YOU WANT TO SUBMIT")
    print()
    if individual:
        print("You currently have %i extensions" %
              (submit_response.extensions_before))
    else:
        print("Your team currently has %i extensions" %
              (submit_response.extensions_before))
    print()
    if registration.final_submission is not None:
        print(
            "You used %i extensions in your previous submission of this assignment."
            % prior_extensions_used)
        print("and you are going to use %i additional extensions now." %
              (submit_response.extensions_needed - prior_extensions_used))
    else:
        print("You are going to use %i extensions on this submission." %
              submit_response.extensions_needed)
    print()
    print("You will have %i extensions left after this submission." %
          submit_response.extensions_after)
    print()

    if submit_response.in_grace_period:
        print(
            "NOTE: You are submitting after the deadline, but the instructor has"
        )
        print(
            "allowed some extra time after the deadline for students to submit"
        )
        print("without having to consume an extension.")
        print()

    print("Are you sure you want to continue? (y/n): ", end=' ')

    if not yes:
        yesno = input()
    else:
        yesno = 'y'
        print('y')

    if yesno in ('y', 'Y', 'yes', 'Yes', 'YES'):
        try:
            submit_response = registration.submit(commit.sha, dry_run=False)

            # TODO: Can't do this until GitLab supports updating tags
            #
            # message = "Extensions: %i\n" % extensions_requested
            # if submission_tag is None:
            #     conn.create_submission_tag(course, team, tag_name, message, commit.sha)
            # else:
            #     conn.update_submission_tag(course, team, tag_name, message, commit.sha)

            print()
            print("Your submission has been completed.")

            if submit_response.in_grace_period:
                print()
                print(
                    "Your submission was made during the deadline's grace period. This means"
                )
                print(
                    "that, although your submission was technically made *after* the"
                )
                print(
                    "deadline, we are counting it as if it had been made before the deadline."
                )
                print()
                print(
                    "In the future, you should not rely on the presence of this grace period!"
                )
                print(
                    "Your instructor may choose not to use one in future assignments, or may"
                )
                print(
                    "use a shorter grace period. Your instructor is also aware of what"
                )
                print(
                    "submissions are made during the grace period; if you repeatedly submit"
                )
                print(
                    "during the grace period, your instructor may charge you an extension"
                )
                print(
                    "or refuse to accept your assignment if you are out of extensions."
                )

            return CHISUBMIT_SUCCESS

        except BadRequestException as bre:
            print()
            print(
                "ERROR: Your submission was not completed. The server reported the following errors:"
            )
            bre.print_errors()
            ctx.exit(CHISUBMIT_FAIL)
    else:
        print("Your submission has not been completed.")
        print()
        print(
            "If you chose not to proceed because the above commit is not the one you wanted"
        )
        print(
            "to submit, make sure you've pushed your latest code to your repository before"
        )
        print("attempting to submit again.")
        print()
        print(
            "If you want to submit a different commit from your latest commit (e.g., an earlier"
        )
        print(
            "commit), you can use the --commit-sha option to specify a different commit."
        )
        ctx.exit(CHISUBMIT_FAIL)
Example #50
0
def student_assignment_cancel_submit(ctx, course, assignment_id, yes):
    assignment = get_assignment_or_exit(ctx, course, assignment_id)

    # Determine team for this assignment
    team, registration = get_team_registration_from_user(
        ctx, course, assignment)
    team_members = team.get_team_members()

    if len(team_members) == 1:
        individual = True
    else:
        individual = False

    if registration.final_submission is None:
        if individual:
            print("You have not made a submission for assignment %s," %
                  assignment_id)
        else:
            print("Team %s has not made a submission for assignment %s," %
                  (team.team_id, assignment_id))
        print("so there is nothing to cancel.")
        ctx.exit(CHISUBMIT_FAIL)

    if registration.grading_started:
        print("You cannot cancel this submission.")
        print(
            "You made a submission and it has already been sent to the graders for grading."
        )
        print(
            "Please contact an instructor if you wish to amend your submission."
        )

        ctx.exit(CHISUBMIT_FAIL)

    conn = create_connection(course, ctx.obj['config'])

    if conn is None:
        print("Could not connect to git server.")
        ctx.exit(CHISUBMIT_FAIL)

    submission_commit = conn.get_commit(
        course, team, registration.final_submission.commit_sha)

    print()
    print("This is your existing submission for assignment %s:" %
          assignment_id)
    print()
    if submission_commit is None:
        print(
            "WARNING: Previously submitted commit '%s' is not in the repository!"
            % registration.final_submission.commit_sha)
    else:
        print_commit(submission_commit)
    print()

    print("Are you sure you want to cancel this submission? (y/n): ", end=' ')

    if not yes:
        yesno = input()
    else:
        yesno = 'y'
        print('y')

    if yesno in ('y', 'Y', 'yes', 'Yes', 'YES'):
        registration.final_submission_id = None

        # TODO: Can't do this until GitLab supports updating tags
        #
        # message = "Extensions: %i\n" % extensions_requested
        # if submission_tag is None:
        #     conn.create_submission_tag(course, team, tag_name, message, commit.sha)
        # else:
        #     conn.update_submission_tag(course, team, tag_name, message, commit.sha)
        print()
        print("Your submission has been cancelled.")