def open_assignment(conf, args): """Adds each student in the roster to their respective homework repositories as Developers so they can pull/commit/push their work. """ hw_name = args.name host = conf.gitlab_host namespace = conf.namespace token = conf.token semester = conf.semester roster = get_filtered_roster(conf.roster, args.section, args.student) count = 0 for student in roster: username = student["username"] student_section = student["section"] full_name = StudentRepo.name(semester, student_section, hw_name, username) try: repo = StudentRepo(host, namespace, full_name, token) if "id" not in student: student["id"] = Repo.get_user_id(username, host, token) repo.add_member(student["id"], Access.developer) count += 1 except RepoError: logging.warn("Could not add {} to {}.".format(username, full_name)) except HTTPError: raise print("Granted access to {} repositories.".format(count))
def manage_users(args, level): if args.dry_run: raise NotImplementedError("'--dry-run' is not implemented") if args.student: raise NotImplementedError("'--student' is not implemented") with config(args.config) as conf: count = 0 for student in conf['roster']: name = StudentRepo.name(conf['semester'], student['section'], args.name, student['username']) if 'id' in student: try: repo = StudentRepo(conf['gitlab-host'], conf['namespace'], name, conf['token']) repo.edit_member(student['id'], level) count += 1 except HTTPError as e: raise if e.response.status_code == 404: logging.warning("Repository %s does not exist.", name) else: raise else: logging.warning("Student %s does not have a gitlab account.", student['username']) print("Changed ", count, " repositories.")
def manage_repos(conf, args, action): """Performs an action (archive|unarchive) on all student repos """ hw_name = args.name dry_run = args.dry_run if dry_run: raise NotImplementedError("'--dry-run' is not implemented") if action not in ['archive', 'unarchive']: raise ValueError("Unexpected action '{}', accepted actions are 'archive' and 'unarchive'.".format(action)) host = conf.gitlab_host namespace = conf.namespace token = conf.token semester = conf.semester roster = get_filtered_roster(conf.roster, args.section, args.student) count = 0 for student in roster: username = student["username"] student_section = student["section"] if "id" not in student: logging.warning( "Student {} does not have a gitlab account.".format(username) ) continue full_name = StudentRepo.name(semester, student_section, hw_name, username) try: repo = StudentRepo(host, namespace, full_name, token) if action == 'archive': repo.archive() else: repo.unarchive() count += 1 except HTTPError: raise print("Changed {} repositories.".format(count))
def assign(args): if args.dry_run: raise NotImplementedError("'--dry-run' is not implemented") if args.student: raise NotImplementedError("'--student' is not implemented") with config(args.config) as conf, tempfile.TemporaryDirectory() as tmpdirname: base = BaseRepo(conf['gitlab-host'], conf['namespace'], args.name, conf['token']) base.clone_to(tmpdirname) count = 0 for student in conf['roster']: try: name = StudentRepo.name(conf['semester'], student['section'], args.name, student['username']) repo = StudentRepo(conf['gitlab-host'], conf['namespace'], name, conf['token']) repo.info logging.warning("Student repository %s already exists.", repo.name) if args.force: logging.warning("Deleting...") repo.delete() repo = StudentRepo.new(base, conf['semester'], student['section'], student['username'], conf['token']) repo.push(base) count += 1 else: logging.warning("Skipping...") except HTTPError as e: if e.response.status_code == 404: repo = StudentRepo.new(base, conf['semester'], student['section'], student['username'], conf['token']) repo.push(base) count += 1 else: raise print("Assigned homework ", args.name, " to ", count, " students")
def open_assignment(args): with config(args.config) as conf: count = 0 for student in conf['roster']: name = StudentRepo.name(conf['semester'], student['section'], args.name, student['username']) try: repo = StudentRepo(conf['gitlab-host'], conf['namespace'], name, conf['token']) if 'id' not in student: student['id'] = Repo.get_user_id(student['username'], conf['gitlab-host'], conf['token']) repo.add_member(student['id'], Access.developer) count += 1 except RepoError: logging.warn("Could not add %s to %s", student['username'], name) except HTTPError as e: raise if e.response.status_code == 404: logging.warn("Repository %s does not exist.", name) else: raise print("Granted access to ", count, " repositories")
def get(args): if args.student: raise NotImplementedError("'--student' is not implemented") with config(args.config) as conf: path = os.path.join(args.path, args.name) os.makedirs(path, mode=0o700, exist_ok=True) count = 0 for student in conf['roster']: name = StudentRepo.name(conf['semester'], student['section'], args.name, student['username']) try: repo = StudentRepo(conf['gitlab-host'], conf['namespace'], name, conf['token']) repo.clone_to(os.path.join(path, student['username'])) count += 1 except HTTPError as e: if e.response.status_code == 404: logging.warn("Repository %s does not exist.", name) else: raise print("Cloned ", count, " repositories")
def manage_users(conf, args, level): """Creates a folder for the assignment in the CWD (or <path>, if specified) and clones each students' repository into subfolders. """ hw_name = args.name dry_run = args.dry_run if dry_run: raise NotImplementedError("'--dry-run' is not implemented") host = conf.gitlab_host namespace = conf.namespace token = conf.token semester = conf.semester roster = get_filtered_roster(conf.roster, args.section, args.student) count = 0 for student in roster: username = student["username"] student_section = student["section"] if "id" not in student: logging.warning( "Student {} does not have a gitlab account.".format(username) ) continue full_name = StudentRepo.name(semester, student_section, hw_name, username) try: repo = StudentRepo(host, namespace, full_name, token) repo.edit_member(student["id"], level) count += 1 except HTTPError: raise print("Changed {} repositories.".format(count))
def get(conf, args): """Creates a folder for the assignment in the CWD (or <path>, if specified) and clones each students' repository into subfolders. """ hw_name = args.name hw_path = args.path host = conf.gitlab_host namespace = conf.namespace token = conf.token semester = conf.semester roster = get_filtered_roster(conf.roster, args.section, args.student) path = os.path.join(hw_path, hw_name) os.makedirs(path, mode=0o700, exist_ok=True) count = 0 for student in roster: username = student["username"] student_section = student["section"] full_name = StudentRepo.name(semester, student_section, hw_name, username) try: repo = StudentRepo(host, namespace, full_name, token) repo.clone_to(os.path.join(path, username)) count += 1 except RepoError as e: logging.warn(str(e)) except HTTPError as e: if e.response.status_code == 404: logging.warn("Repository {} does not exist.".format(full_name)) else: raise print("Cloned {} repositories.".format(count))
def assign(conf, args): """Creates homework repositories for an assignment for each student in the roster. """ hw_name = args.name if args.branch: branch = args.branch else: branch = "master" dry_run = args.dry_run force = args.force host = conf.gitlab_host namespace = conf.namespace token = conf.token semester = conf.semester roster = get_filtered_roster(conf.roster, args.section, args.student) actual_count = 0 # Represents the number of repos actually pushed to student_count = len(roster) with tempfile.TemporaryDirectory() as tmpdirname: print("Assigning '{}' to {} student{} in {}.".format( hw_name, student_count, "s" if student_count != 1 else "", "section " + args.section if args.section else "all sections") ) base = BaseRepo(host, namespace, hw_name, token) if not dry_run: base.clone_to(tmpdirname, branch) if force: logging.warning("Repos will be overwritten.") for i, student in enumerate(roster): username = student["username"] student_section = student["section"] full_name = StudentRepo.name(semester, student_section, hw_name, username) repo = StudentRepo(host, namespace, full_name, token) print("{}/{} - {}".format(i+1, student_count, full_name)) if not repo.already_exists(): if not dry_run: repo = StudentRepo.new(base, semester, student_section, username, token) repo.push(base, branch) actual_count += 1 logging.debug("Assigned.") elif force: logging.info("{}: Already exists.".format(full_name)) logging.info("{}: Deleting...".format(full_name)) if not dry_run: repo.delete() # HACK: Gitlab will throw a 400 if you delete and immediately recreate a repo. # A bit more than half a second was experimentally determined to prevent this issue. time.sleep(0.55) repo = StudentRepo.new(base, semester, student_section, username, token) repo.push(base, branch) actual_count += 1 logging.debug("Assigned.") elif args.branch: logging.info("{}: Already exists.".format(full_name)) # If we have an explicit branch, push anyways repo.push(base, branch) if not dry_run else None actual_count += 1 logging.debug("Assigned.") else: logging.warning("Skipping...") i += 1 print("Assigned '{}' to {} student{}.".format( hw_name, actual_count, "s" if actual_count != 1 else "" )) if actual_count == 0: logging.warning( "Consider using --force if you want to override existing repos." )