예제 #1
0
    def get_class_repositories(self, class_dir):
        repos = []

        class_path = os.path.join(self.home_dir, class_dir)
        if not directory_exists(class_path, ssh=self.ssh):
            return repos

        for name in list_directory(class_path, ssh=self.ssh):
            path = os.path.join(class_path, name)
            if directory_exists(path, ssh=self.ssh) and name.endswith('.git'):
                assignment, _ = os.path.splitext(name)
                if self.ssh is not None:
                    repos.append(
                        Repository(path,
                                   assignment,
                                   is_bare=True,
                                   is_local=False,
                                   ssh=self.ssh,
                                   student_username=self.username))
                else:
                    repos.append(
                        Repository(path,
                                   assignment,
                                   is_bare=True,
                                   student_username=self.username))

        return repos
def create_student_directories(class_name, parent_dir):

    if not directory_exists(parent_dir):
        try:
            os.makedirs(parent_dir)
        except OSError as e:
            sys.exit('Error creating{0}:\n{1}'.format(parent_dir, e))

    try:
        config = GraderConfiguration(single_class_name=class_name)
    except ConfigurationError as e:
        sys.exit(e)

    if class_name not in config.students_by_class:
        sys.exit('class {0} does not exist'.format(class_name))

    for student in config.students_by_class[class_name]:
        path = os.path.join(parent_dir, student.get_last_first_username())

        if directory_exists(path):
            print('{0} already exists, skipping'.format(path))
            continue

        try:
            os.makedirs(path)
        except OSError as e:
            print('Error creating {0}:\n{1}'.format(path, e))
예제 #3
0
def initialize_class(class_name):
    try:
        config = GraderConfiguration(single_class_name=class_name)
    except ConfigurationError as e:
        sys.exit('Config error: {0}'.format(e))

    if class_name not in config.students_by_class:
        sys.exit('No student CSV file for {0}'.format(class_name))

    try:
        home_dir = home_dir_from_username(config.username, config.username,
                                          config.host)
    except CommandError as e:
        sys.exit('Error getting remote home dir for {0}:\n{1}'
                 .format(config.username, e))

    class_path = os.path.join(home_dir, class_name)

    if directory_exists(class_path, config.username, config.host):
        sys.exit('{0} already exists'.format(class_path))

    print('Initializing class', class_name, 'on', config.host)

    assignments_path = os.path.join(class_path, 'assignments')

    for dir_path in [class_path, assignments_path]:
        if directory_exists(dir_path, config.username, config.host):
            sys.exit('{0} already exists'.format(dir_path))
        try:
            create_directory(dir_path, config.username, config.host)
        except CommandError as e:
            sys.exit('Error creating {0}: {1}'.format(dir_path, e))

        print('Created', dir_path)

    try:
        remote_home_dir = home_dir_from_username(config.username,
                                                 config.username,
                                                 config.host)
        remote_config_dir = os.path.join(remote_home_dir, '.config/grader')

        scp_file(config.students_csv_filenames_by_class[class_name],
                 config.username, config.host, remote_config_dir)
    except CommandError as e:
        sys.exit('Error copying student file:\n{0}'.format(e))

    print('Copied', config.students_csv_filenames_by_class[class_name], 'to',
          class_path, 'on', config.host)

    print('Class', class_name, 'initialized on', config.host)
    print()
    print('Next, run populate_students.py on', config.host)
def initialize_class(class_name):
    try:
        config = GraderConfiguration(single_class_name=class_name)
    except ConfigurationError as e:
        sys.exit('Config error: {0}'.format(e))

    if class_name not in config.students_by_class:
        sys.exit('No student CSV file for {0}'.format(class_name))

    try:
        home_dir = home_dir_from_username(config.username, config.username,
                                          config.host)
    except CommandError as e:
        sys.exit('Error getting remote home dir for {0}:\n{1}'.format(
            config.username, e))

    class_path = os.path.join(home_dir, class_name)

    if directory_exists(class_path, config.username, config.host):
        sys.exit('{0} already exists'.format(class_path))

    print('Initializing class', class_name, 'on', config.host)

    assignments_path = os.path.join(class_path, 'assignments')

    for dir_path in [class_path, assignments_path]:
        if directory_exists(dir_path, config.username, config.host):
            sys.exit('{0} already exists'.format(dir_path))
        try:
            create_directory(dir_path, config.username, config.host)
        except CommandError as e:
            sys.exit('Error creating {0}: {1}'.format(dir_path, e))

        print('Created', dir_path)

    try:
        remote_home_dir = home_dir_from_username(config.username,
                                                 config.username, config.host)
        remote_config_dir = os.path.join(remote_home_dir, '.config/grader')

        scp_file(config.students_csv_filenames_by_class[class_name],
                 config.username, config.host, remote_config_dir)
    except CommandError as e:
        sys.exit('Error copying student file:\n{0}'.format(e))

    print('Copied', config.students_csv_filenames_by_class[class_name], 'to',
          class_path, 'on', config.host)

    print('Class', class_name, 'initialized on', config.host)
    print()
    print('Next, run populate_students.py on', config.host)
예제 #5
0
def send_feedback(class_name, assignment_name, feedback_dir):

    if not directory_exists(feedback_dir):
        sys.exit('{0} does not exist'.format(feedback_dir))

    try:
        config = GraderConfiguration(single_class_name=class_name)
    except ConfigurationError as e:
        sys.exit(e)

    if class_name not in config.students_by_class:
        sys.exit('class {0} does not exist'.format(class_name))

    email_queue = Queue()
    email_thread = Thread(target=process_email_queue,
                          args=(email_queue, class_name, config))
    email_thread.start()

    subdirs = os.listdir(feedback_dir)

    for subdir in subdirs:
        for student in config.students_by_class[class_name]:
            if student.username in subdir:
                try:
                    email = create_feedback_email(
                        student, assignment_name,
                        os.path.join(feedback_dir, subdir))
                    if email is not None:
                        email_queue.put(email)
                except EmailException as e:
                    print('Error creating email:\n{0}'.format(e))

    email_queue.put(None)
    email_thread.join()
예제 #6
0
def send_feedback(class_name, assignment_name, feedback_dir):

    if not directory_exists(feedback_dir):
        sys.exit('{0} does not exist'.format(feedback_dir))

    try:
        config = GraderConfiguration(single_class_name=class_name)
    except ConfigurationError as e:
        sys.exit(e)

    if class_name not in config.students_by_class:
        sys.exit('class {0} does not exist'.format(class_name))

    email_queue = Queue()
    email_thread = Thread(target=process_email_queue, args=(email_queue,
                                                            class_name,
                                                            config))
    email_thread.start()

    subdirs = os.listdir(feedback_dir)

    for subdir in subdirs:
        for student in config.students_by_class[class_name]:
            if student.username in subdir:
                try:
                    email = create_feedback_email(student, assignment_name,
                                                  os.path.join(feedback_dir,
                                                  subdir))
                    if email is not None:
                        email_queue.put(email)
                except EmailException as e:
                    print('Error creating email:\n{0}'.format(e))

    email_queue.put(None)
    email_thread.join()
예제 #7
0
    def get_assignments(self, class_name):
        assignments_dir = os.path.join(self.home_dir, class_name, 'assignments')

        if not directory_exists(assignments_dir, ssh=self.ssh):
            raise ConfigurationError('{0} does not exist'
                                     .format(assignments_dir))

        return list_directory(assignments_dir, ssh=self.ssh)
예제 #8
0
    def get_class_repositories(self, class_dir):
        repos = []

        class_path = os.path.join(self.home_dir, class_dir)
        if not directory_exists(class_path, ssh=self.ssh):
            return repos

        for name in list_directory(class_path, ssh=self.ssh):
            path = os.path.join(class_path, name)
            if directory_exists(path, ssh=self.ssh) and name.endswith('.git'):
                assignment, _ = os.path.splitext(name)
                if self.ssh is not None:
                    repos.append(Repository(path, assignment, is_bare=True,
                                            is_local=False, ssh=self.ssh,
                                            student_username=self.username))
                else:
                    repos.append(Repository(path, assignment, is_bare=True,
                                            student_username=self.username))

        return repos
예제 #9
0
    def init(self):
        if not directory_exists(self.path, self.remote_user, self.remote_host,
                                self.ssh):
            create_directory(self.path, self.remote_user, self.remote_host,
                             self.ssh)

        if self.is_local and not self.is_bare:
            git_init(self.path)
        elif not self.is_local and self.is_bare:
            git_init_bare(self.path, self.remote_user, self.remote_host,
                          self.ssh)
        else:
            assert False
예제 #10
0
    def init(self):
        if not directory_exists(self.path, self.remote_user, self.remote_host,
                                self.ssh):
            create_directory(self.path, self.remote_user, self.remote_host,
                             self.ssh)

        if self.is_local and not self.is_bare:
            git_init(self.path)
        elif not self.is_local and self.is_bare:
            git_init_bare(self.path, self.remote_user, self.remote_host,
                          self.ssh)
        else:
            assert False
예제 #11
0
def update_assignment_tests(class_name, local_assignment_dir):

    local_assignment_dir = os.path.expanduser(local_assignment_dir)
    local_assignment_dir = os.path.abspath(local_assignment_dir)

    assignment = os.path.basename(local_assignment_dir.rstrip('/'))

    test_code_dir = os.path.join(local_assignment_dir, 'tests')

    if not os.path.isdir(test_code_dir):
        sys.exit('{0} does not exist'.format(test_code_dir))

    action_file_path = os.path.join(test_code_dir, 'action.sh')

    if not os.path.isfile(action_file_path):
        sys.exit('No action.sh in {0}'.format(test_code_dir))

    try:
        config = GraderConfiguration(single_class_name=class_name)
    except ConfigurationError as e:
        sys.exit(e)

    try:
        ssh = SSHClient()
        ssh.load_system_host_keys()
        ssh.connect(config.host, username=config.username)
    except OSError as e:
        sys.exit('Error opening SSH connection:\n{0}'.format(e))

    if class_name not in config.students_by_class:
        sys.exit('Class {0} does not exist'.format(class_name))

    test_code_repo_tempdir = TemporaryDirectory()

    try:
        test_code_repo = copy_and_create_repo(test_code_dir,
                                              test_code_repo_tempdir.name,
                                              assignment)
    except CommandError as e:
        error = 'Error copying test code repo:\n{0}'.format(e)
        sys.exit(error)

    try:
        remote_home_dir = home_dir_from_username(config.username, ssh=ssh)

    except CommandError as e:
        sys.exit('Error getting remote home dir for {0}:\n{1}'.format(
            config.username, e))

    remote_assignment_dir = os.path.join(remote_home_dir, class_name,
                                         'assignments', assignment)

    tests_bare_repo_dir = os.path.join(remote_assignment_dir,
                                       '{0}_tests.git'.format(assignment))

    if not directory_exists(tests_bare_repo_dir, ssh=ssh):
        sys.exit('{0} does not exist on {1}'.format(tests_bare_repo_dir,
                                                    config.host))

    print('Updating test repo for assignment', assignment)

    tests_bare_repo = Repository(tests_bare_repo_dir,
                                 assignment,
                                 is_local=False,
                                 is_bare=True,
                                 remote_host=config.host,
                                 remote_user=config.username)

    try:
        test_code_repo.push(tests_bare_repo, force=True)
        print('Pushed tests to', tests_bare_repo_dir)
    except CommandError as e:
        sys.exit('Error pushing test repo:\n{0}'.format(e))

    print(assignment, 'tests updated successfully')
예제 #12
0
def upload_handout(class_name, local_handout_dir):

    local_handout_dir = os.path.expanduser(local_handout_dir)
    local_handout_dir = os.path.abspath(local_handout_dir)

    handout_name = os.path.basename(local_handout_dir.rstrip('/'))

    if handout_name.count(' ') != 0:
        sys.exit('NO spaces allowed in handout directory')

    if not os.path.isdir(local_handout_dir):
        sys.exit('{0} does not exist'.format(local_handout_dir))

    try:
        config = GraderConfiguration(single_class_name=class_name)
    except ConfigurationError as e:
        sys.exit(e)

    if class_name not in config.students_by_class:
        sys.exit('Class {0} does not exist'.format(class_name))

    remote_handout_repo_basename = handout_name + '.git'
    remote_handout_repo_dir = os.path.join('/home/git', class_name,
                                           remote_handout_repo_basename)

    if directory_exists(remote_handout_repo_dir, ssh=config.ssh):
        sys.exit(
            '{0} already exists on the grader'.format(remote_handout_repo_dir))

    local_handout_repo = Repository(local_handout_dir, handout_name)
    if not local_handout_repo.is_initialized():
        print('Initializing local git repository in {0}'.format(
            local_handout_dir))
        try:
            local_handout_repo.init()
            local_handout_repo.add_all_and_commit('Initial commit')
        except CommandError as e:
            sys.exit('Error initializing local repository:\n{0}'.format(e))
    else:
        print('{0} is already a git repository, it will be pushed'.format(
            local_handout_dir))

    print('Creating a bare repository on the grader at this path:\n{0}'.format(
        remote_handout_repo_dir))

    remote_handout_repo = Repository(remote_handout_repo_dir,
                                     handout_name,
                                     is_local=False,
                                     is_bare=True,
                                     remote_user=config.username,
                                     remote_host=config.host,
                                     ssh=config.ssh)
    try:
        remote_handout_repo.init()
    except CommandError as e:
        sys.exit('Error initializing remote bare repository:\n{0}'.format(e))

    print('Setting the remote of the local repository')
    try:
        local_handout_repo.set_remote(remote_handout_repo)
    except CommandError as e:
        print('Error setting remote:\n{0}'.format(e))
        print('Set the remote manually if need be')

    print('Pushing local handout to the grader')
    try:
        local_handout_repo.push(remote_handout_repo)
    except CommandError as e:
        sys.exit('Error pushing handout:\n{0}'.format(e))

    email_queue = Queue()
    email_thread = Thread(target=process_email_queue,
                          args=(email_queue, class_name, config))
    email_thread.start()

    for student in config.students_by_class[class_name]:
        assert isinstance(student, Student)
        clone_url = '{0}@{1}:{2}'.format(student.username, config.host,
                                         remote_handout_repo_dir)
        body = 'Clone URL:\n{0}'.format(clone_url)
        subject = 'New handout: {0}'.format(handout_name)

        email_queue.put(Email(student.email_address, subject, body))

    email_queue.put(None)
    email_thread.join()
예제 #13
0
 def is_initialized(self):
     assert not self.is_bare
     return directory_exists(os.path.join(self.path, '.git'),
                             self.remote_user, self.remote_host, self.ssh)
예제 #14
0
def upload_handout(class_name, local_handout_dir):

    local_handout_dir = os.path.expanduser(local_handout_dir)
    local_handout_dir = os.path.abspath(local_handout_dir)

    handout_name = os.path.basename(local_handout_dir.rstrip('/'))

    if handout_name.count(' ') != 0:
        sys.exit('NO spaces allowed in handout directory')

    if not os.path.isdir(local_handout_dir):
        sys.exit('{0} does not exist'.format(local_handout_dir))

    try:
        config = GraderConfiguration(single_class_name=class_name)
    except ConfigurationError as e:
        sys.exit(e)

    if class_name not in config.students_by_class:
        sys.exit('Class {0} does not exist'.format(class_name))

    remote_handout_repo_basename = handout_name + '.git'
    remote_handout_repo_dir = os.path.join('/home/git', class_name,
                                           remote_handout_repo_basename)

    if directory_exists(remote_handout_repo_dir, ssh=config.ssh):
        sys.exit('{0} already exists on the grader'
                 .format(remote_handout_repo_dir))

    local_handout_repo = Repository(local_handout_dir, handout_name)
    if not local_handout_repo.is_initialized():
        print('Initializing local git repository in {0}'
              .format(local_handout_dir))
        try:
            local_handout_repo.init()
            local_handout_repo.add_all_and_commit('Initial commit')
        except CommandError as e:
            sys.exit('Error initializing local repository:\n{0}'
                     .format(e))
    else:
        print('{0} is already a git repository, it will be pushed'
              .format(local_handout_dir))

    print('Creating a bare repository on the grader at this path:\n{0}'
          .format(remote_handout_repo_dir))

    remote_handout_repo = Repository(remote_handout_repo_dir, handout_name,
                                     is_local=False, is_bare=True,
                                     remote_user=config.username,
                                     remote_host=config.host,
                                     ssh=config.ssh)
    try:
        remote_handout_repo.init()
    except CommandError as e:
        sys.exit('Error initializing remote bare repository:\n{0}'.format(e))

    print('Setting the remote of the local repository')
    try:
        local_handout_repo.set_remote(remote_handout_repo)
    except CommandError as e:
        print('Error setting remote:\n{0}'.format(e))
        print('Set the remote manually if need be')

    print('Pushing local handout to the grader')
    try:
        local_handout_repo.push(remote_handout_repo)
    except CommandError as e:
        sys.exit('Error pushing handout:\n{0}'.format(e))

    email_queue = Queue()
    email_thread = Thread(target=process_email_queue, args=(email_queue,
                                                            class_name,
                                                            config))
    email_thread.start()

    for student in config.students_by_class[class_name]:
        assert isinstance(student, Student)
        clone_url = '{0}@{1}:{2}'.format(student.username, config.host,
                                         remote_handout_repo_dir)
        body = 'Clone URL:\n{0}'.format(clone_url)
        subject = 'New handout: {0}'.format(handout_name)

        email_queue.put(Email(student.email_address, subject, body))

    email_queue.put(None)
    email_thread.join()
예제 #15
0
def update_assignment_tests(class_name, local_assignment_dir):

    local_assignment_dir = os.path.expanduser(local_assignment_dir)
    local_assignment_dir = os.path.abspath(local_assignment_dir)

    assignment = os.path.basename(local_assignment_dir.rstrip('/'))

    test_code_dir = os.path.join(local_assignment_dir, 'tests')

    if not os.path.isdir(test_code_dir):
        sys.exit('{0} does not exist'.format(test_code_dir))

    action_file_path = os.path.join(test_code_dir, 'action.sh')

    if not os.path.isfile(action_file_path):
        sys.exit('No action.sh in {0}'.format(test_code_dir))

    try:
        config = GraderConfiguration(single_class_name=class_name)
    except ConfigurationError as e:
        sys.exit(e)

    try:
        ssh = SSHClient()
        ssh.load_system_host_keys()
        ssh.connect(config.host, username=config.username)
    except OSError as e:
        sys.exit('Error opening SSH connection:\n{0}'.format(e))

    if class_name not in config.students_by_class:
        sys.exit('Class {0} does not exist'.format(class_name))

    test_code_repo_tempdir = TemporaryDirectory()

    try:
        test_code_repo = copy_and_create_repo(test_code_dir,
                                              test_code_repo_tempdir.name,
                                              assignment)
    except CommandError as e:
        error = 'Error copying test code repo:\n{0}'.format(e)
        sys.exit(error)

    try:
        remote_home_dir = home_dir_from_username(config.username, ssh=ssh)

    except CommandError as e:
        sys.exit('Error getting remote home dir for {0}:\n{1}'
                 .format(config.username, e))

    remote_assignment_dir = os.path.join(remote_home_dir, class_name,
                                         'assignments', assignment)

    tests_bare_repo_dir = os.path.join(remote_assignment_dir,
                                       '{0}_tests.git'.format(assignment))

    if not directory_exists(tests_bare_repo_dir, ssh=ssh):
        sys.exit('{0} does not exist on {1}'.format(tests_bare_repo_dir,
                                                    config.host))

    print('Updating test repo for assignment', assignment)

    tests_bare_repo = Repository(tests_bare_repo_dir, assignment,
                                 is_local=False, is_bare=True,
                                 remote_host=config.host,
                                 remote_user=config.username)

    try:
        test_code_repo.push(tests_bare_repo, force=True)
        print('Pushed tests to', tests_bare_repo_dir)
    except CommandError as e:
        sys.exit('Error pushing test repo:\n{0}'.format(e))

    print(assignment, 'tests updated successfully')
def upload_assignment(class_name, grader_project):

    grader_project_path = os.path.dirname(sys.argv[0])
    post_update_path = os.path.join(grader_project_path, 'post-update')

    local_assignment_dir = os.path.expanduser(grader_project)
    local_assignment_dir = os.path.abspath(local_assignment_dir)

    assignment = os.path.basename(local_assignment_dir.rstrip('/'))

    base_code_dir = os.path.join(local_assignment_dir, 'base_code')
    test_code_dir = os.path.join(local_assignment_dir, 'tests')

    if not os.path.isdir(base_code_dir):
        sys.exit('{0} does not exist'.format(base_code_dir))

    if not os.path.isdir(test_code_dir):
        sys.exit('{0} does not exist'.format(test_code_dir))

    action_file_path = os.path.join(test_code_dir, 'action.sh')

    if not os.path.isfile(action_file_path):
        sys.exit('No action.sh in {0}'.format(test_code_dir))

    email_file_path = os.path.join(local_assignment_dir, 'email.txt')

    if not os.path.isfile(email_file_path):
        sys.exit('{0} does not exist'.format(email_file_path))

    try:
        config = GraderConfiguration(single_class_name=class_name)
    except ConfigurationError as e:
        sys.exit(e)

    if class_name not in config.students_by_class:
        sys.exit('Class {0} does not exist'.format(class_name))

    base_code_repo_tempdir = TemporaryDirectory()

    try:
        base_code_repo = copy_and_create_repo(base_code_dir,
                                              base_code_repo_tempdir.name,
                                              assignment, 'created assignment')
    except CommandError as e:
        error = 'Error copying base code repo:\n{0}'.format(e)
        sys.exit(error)

    test_code_repo_tempdir = TemporaryDirectory()

    try:
        test_code_repo = copy_and_create_repo(test_code_dir,
                                              test_code_repo_tempdir.name,
                                              assignment)
    except CommandError as e:
        error = 'Error copying test code repo:\n{0}'.format(e)
        sys.exit(error)

    try:
        remote_home_dir = home_dir_from_username(config.username,
                                                 config.username, config.host)
    except CommandError as e:
        sys.exit('Error getting remote home dir for {0}:\n{1}'.format(
            config.username, e))

    remote_assignment_dir = os.path.join(remote_home_dir, class_name,
                                         'assignments', assignment)

    tests_bare_repo_dir = os.path.join(remote_assignment_dir,
                                       '{0}_tests.git'.format(assignment))
    reports_bare_repo_dir = os.path.join(remote_assignment_dir,
                                         '{0}_reports.git'.format(assignment))

    if directory_exists(tests_bare_repo_dir, config.username, config.host):
        sys.exit('{0} already exists on {1}'.format(tests_bare_repo_dir,
                                                    config.host))
    if directory_exists(reports_bare_repo_dir, config.username, config.host):
        sys.exit('{0} already exists on {1}'.format(reports_bare_repo_dir,
                                                    config.host))

    print('Uploading assignment', assignment)

    reports_repo_tempdir = TemporaryDirectory()
    reports_repo_dir = reports_repo_tempdir.name

    reports_repo = Repository(reports_repo_dir, assignment)
    reports_repo.init()

    for student in config.students_by_class[class_name]:
        assert isinstance(student, Student)
        bare_repo_dir = student.get_bare_repo_dir(class_name, assignment)
        if directory_exists(bare_repo_dir, config.username, config.host):
            sys.exit('{0} already exists on {1}'.format(
                bare_repo_dir, config.host))
        student_repo = Repository(bare_repo_dir,
                                  assignment,
                                  is_local=False,
                                  is_bare=True,
                                  remote_user=config.username,
                                  remote_host=config.host,
                                  student_username=student.username)
        try:
            student_repo.init()
            student_repo.add_update_flag_hook(post_update_path)
            base_code_repo.push(student_repo)
            chmod_world_writable_recursive(student_repo.path,
                                           remote_user=config.username,
                                           remote_host=config.host)
            print('Pushed base code to', bare_repo_dir)
        except CommandError as e:
            sys.exit('Error creating {0} on {1}:\n{2}'.format(
                bare_repo_dir, config.host, e))

        student_report_dir = os.path.join(reports_repo_dir,
                                          student.get_last_first_username())
        os.makedirs(student_report_dir)
        placeholder_path = os.path.join(student_report_dir, '.placeholder')
        touch(placeholder_path)

    reports_bare_repo = Repository(reports_bare_repo_dir,
                                   assignment,
                                   is_local=False,
                                   is_bare=True,
                                   remote_user=config.username,
                                   remote_host=config.host)

    try:
        reports_repo.add_all_and_commit('added student directories')
        reports_bare_repo.init()
        reports_repo.push(reports_bare_repo)
        print('Created reports repository in', reports_bare_repo_dir)
    except CommandError as e:
        sys.exit('Error creating reports repository:\n{0}'.format(e))

    tests_bare_repo = Repository(tests_bare_repo_dir,
                                 assignment,
                                 is_local=False,
                                 is_bare=True,
                                 remote_user=config.username,
                                 remote_host=config.host)

    try:
        tests_bare_repo.init()
        test_code_repo.push(tests_bare_repo)
        print('Pushed tests to', tests_bare_repo_dir)
    except CommandError as e:
        sys.exit('Error creating {0} on {1}\n{2}'.format(
            tests_bare_repo_dir, test_code_dir, e))

    scp_file(email_file_path, config.username, config.host,
             remote_assignment_dir)

    print(assignment, 'uploaded successfully')
    print('Reports repo clone URL:', reports_bare_repo.url)
예제 #17
0
def delete_assignment(class_name, assignment):

    timestamp = strftime('%Y-%m-%d-%H:%M:%S-%Z')

    try:
        config = GraderConfiguration(single_class_name=class_name)
    except ConfigurationError as e:
        sys.exit(e)

    if class_name not in config.students_by_class:
        sys.exit('class {0} does not exist'.format(class_name))

    if assignment not in config.get_assignments(class_name):
        sys.exit('assignment {0} not in class {1}'.format(assignment,
                                                          class_name))

    paths_source_dest = []

    grader_assignment_path = os.path.join(config.home_dir, class_name,
                                          'assignments', assignment)

    if not directory_exists(grader_assignment_path, ssh=config.ssh):
        sys.exit('{0} does not exist'.format(grader_assignment_path))

    trash_dir = os.path.join(config.home_dir, class_name, 'trash')

    if not directory_exists(trash_dir):
        create_directory(trash_dir, ssh=config.ssh)

    grader_assignment_dest = trash_dest(trash_dir, grader_assignment_path,
                                        timestamp)

    paths_source_dest.append((grader_assignment_path, grader_assignment_dest))

    for student in config.students_by_class[class_name]:
        student_repos = student.get_class_repositories(class_name)

        for repo in student_repos:
            assert isinstance(repo, Repository)
            if repo.assignment == assignment:
                student_source = repo.path
                student_dest = trash_dest(trash_dir, repo.path, timestamp,
                                          student.username)
                paths_source_dest.append((student_source, student_dest))

    print('These directories will be moved to the trash:')
    for source, dest in paths_source_dest:
        print('{0} -> {1}'.format(source, dest))

    answer = input('Proceed? Type yes to continue: ')

    answer = answer.strip()

    if answer.lower() != 'yes':
        sys.exit('Aborting')

    for source, dest in paths_source_dest:
        assert assignment in source
        try:
            move_directory(source, dest, ssh=config.ssh)
            print('moved {0}'.format(source))
        except CommandError as e:
            print('Error moving {0} to {1}:\n{2}'.format(source, dest, e))
def fetch_assignment(assignment, dest_dir, class_name,
                     config: GraderConfiguration):
    remote_reports_repo_dir = config.get_reports_repo_dir(
        class_name, assignment)

    if not directory_exists(remote_reports_repo_dir, ssh=config.ssh):
        print('Assignment {0} does not exist, skipping'.format(assignment))
        return

    print('Fetching assignment {0}'.format(assignment))

    remote_reports_repo = Repository(remote_reports_repo_dir,
                                     assignment,
                                     is_local=False,
                                     is_bare=True,
                                     remote_user=config.username,
                                     remote_host=config.host,
                                     ssh=config.ssh)

    assignment_dir = os.path.join(dest_dir, assignment)
    submissions_dir = os.path.join(assignment_dir, 'submissions')

    if not directory_exists(submissions_dir):
        os.makedirs(submissions_dir)
        print('Created {0}'.format(submissions_dir))

    reports_repo_dir = os.path.join(assignment_dir, 'reports')
    reports_repo = Repository(reports_repo_dir, assignment, ssh=config.ssh)

    try:
        action = clone_or_pull_repo(reports_repo, remote_reports_repo)

        if action == 'clone':
            print('Cloned new reports for {0}'.format(assignment))
        elif action == 'pull':
            print('Pulled new reports for {0}'.format(assignment))
    except CommandError as e:
        print('Error in reports repo for {0}:\n{1}'.format(assignment, e),
              file=sys.stderr)
        return

    assert class_name in config.students_by_class

    for student in config.students_by_class[class_name]:
        assert isinstance(student, Student)

        username = student.username

        remote_assignment_repo_dir = student.get_bare_repo_dir(
            class_name, assignment)
        remote_assignment_repo = Repository(remote_assignment_repo_dir,
                                            assignment,
                                            is_local=False,
                                            is_bare=True,
                                            remote_user=config.username,
                                            remote_host=config.host,
                                            ssh=config.ssh,
                                            student_username=username)

        assignment_repo_dir = os.path.join(submissions_dir,
                                           student.get_last_first_username())
        assignment_repo = Repository(assignment_repo_dir,
                                     assignment,
                                     ssh=config.ssh,
                                     student_username=username)

        try:
            action = clone_or_pull_repo(assignment_repo,
                                        remote_assignment_repo)

            if action == 'clone':
                print('Cloned assignment {0} for {1}'.format(
                    assignment, student))
            elif action == 'pull':
                print('Pulled new submission of {0} from {1}'.format(
                    assignment, student))
        except CommandError as e:
            print('Error fetching {0} for {1}'.format(assignment, student))
예제 #19
0
def populate_students(class_name):

    try:
        config = GraderConfiguration(on_grading_server=True)
    except ConfigurationError as e:
        sys.exit('Config error: {0}'.format(e))

    home_dir = home_dir_from_username(config.username)

    grader_class_path = os.path.join(home_dir, class_name)

    if not directory_exists(grader_class_path):
        sys.exit(
            '{0} does not exist.\nClass appears to be uninitialized.'.format(
                grader_class_path))

    print('Creating student directories for class', class_name)

    students = config.students_by_class[class_name]

    if len(students) == 0:
        sys.exit('No students found for class {0}'.format(class_name))

    create_users = False
    for student in students:
        assert isinstance(student, Student)
        if not user_exists(student.username):
            if not create_users:
                print('User', student.username, 'does not exist')
                if y_or_n('Create nonexistent users? (y/n) '):
                    create_users = True
            if create_users:
                try:
                    create_user(student.username)
                    home_dir = home_dir_from_username(student.username)
                    chown(home_dir, student.username, config.group)
                    chmod(home_dir, '770', sudo=True)
                    print('Created user', student.username)
                except CommandError as e:
                    sys.exit('Error creating user {0}:\n{1}'.format(
                        student.username, e))
            else:
                sys.exit('Not creating users, exiting')

        home_dir = home_dir_from_username(student.username)

        student_class_path = os.path.join(home_dir, class_name)

        if directory_exists(student_class_path):
            print('{0} already exists, skipping'.format(student_class_path))
            continue

        try:
            create_directory(student_class_path)
            chmod(student_class_path, '775')
            print('Created', student_class_path)
        except OSError as e:
            error = 'Error creating {0}: {1}'.format(student_class_path, e)
            sys.exit(error)

    print('Student directories created successfully')
    print('You may now start the grader daemon')
예제 #20
0
def populate_students(class_name):

    try:
        config = GraderConfiguration(on_grading_server=True)
    except ConfigurationError as e:
        sys.exit('Config error: {0}'.format(e))

    home_dir = home_dir_from_username(config.username)

    grader_class_path = os.path.join(home_dir, class_name)

    if not directory_exists(grader_class_path):
        sys.exit('{0} does not exist.\nClass appears to be uninitialized.'
                 .format(grader_class_path))

    print('Creating student directories for class', class_name)

    students = config.students_by_class[class_name]

    if len(students) == 0:
        sys.exit('No students found for class {0}'.format(class_name))

    create_users = False
    for student in students:
        assert isinstance(student, Student)
        if not user_exists(student.username):
            if not create_users:
                print('User', student.username, 'does not exist')
                if y_or_n('Create nonexistent users? (y/n) '):
                    create_users = True
            if create_users:
                try:
                    create_user(student.username)
                    home_dir = home_dir_from_username(student.username)
                    chown(home_dir, student.username, config.group)
                    chmod(home_dir, '770', sudo=True)
                    print('Created user', student.username)
                except CommandError as e:
                    sys.exit('Error creating user {0}:\n{1}'
                             .format(student.username, e))
            else:
                sys.exit('Not creating users, exiting')

        home_dir = home_dir_from_username(student.username)

        student_class_path = os.path.join(home_dir, class_name)

        if directory_exists(student_class_path):
            print('{0} already exists, skipping'.format(student_class_path))
            continue

        try:
            create_directory(student_class_path)
            chmod(student_class_path, '775')
            print('Created', student_class_path)
        except OSError as e:
            error = 'Error creating {0}: {1}'.format(student_class_path, e)
            sys.exit(error)

    print('Student directories created successfully')
    print('You may now start the grader daemon')
예제 #21
0
 def is_initialized(self):
     assert not self.is_bare
     return directory_exists(os.path.join(self.path, '.git'),
                             self.remote_user, self.remote_host, self.ssh)