Skip to content

Commit 97e5e8d

Browse files
committed
Commit command to commit changes to local student repos
1 parent 196141a commit 97e5e8d

File tree

3 files changed

+129
-0
lines changed

3 files changed

+129
-0
lines changed

assigner/__init__.py

+1
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
"assign",
4343
"open",
4444
"get",
45+
"commit",
4546
"push",
4647
"lock",
4748
"unlock",

assigner/baserepo.py

+6
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,12 @@ def already_exists(self):
179179
return True
180180
return False
181181

182+
def get_index(self):
183+
if self.repo is None:
184+
raise RepoError("No repo to get index from")
185+
186+
return self.repo.index
187+
182188
def get_head(self, branch):
183189
if self.repo is None:
184190
raise RepoError("No repo to get head from")

assigner/commands/commit.py

+122
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
import logging
2+
import os
3+
4+
from requests.exceptions import HTTPError
5+
from git.exc import NoSuchPathError
6+
7+
from assigner.roster_util import get_filtered_roster
8+
from assigner.baserepo import RepoError, StudentRepo
9+
from assigner.config import config_context
10+
from assigner.progress import Progress
11+
12+
help = "Add and commit changes to student repos"
13+
14+
logger = logging.getLogger(__name__)
15+
16+
17+
@config_context
18+
def push(conf, args):
19+
host = conf.gitlab_host
20+
namespace = conf.namespace
21+
token = conf.gitlab_token
22+
semester = conf.semester
23+
24+
hw_name = args.name
25+
hw_path = args.path
26+
message = args.message
27+
branch = args.branch
28+
add = args.add
29+
remove = args.remove
30+
update = args.update
31+
allow_empty = args.allow_empty
32+
33+
# Default behavior: commit changes to all tracked files
34+
if (add == []) and (remove == []):
35+
logging.debug("Nothing explicitly added or removed; defaulting to git add --update")
36+
update = True
37+
38+
path = os.path.join(hw_path, hw_name)
39+
40+
roster = get_filtered_roster(conf.roster, args.section, args.student)
41+
42+
progress = Progress()
43+
44+
for student in progress.iterate(roster):
45+
username = student["username"]
46+
student_section = student["section"]
47+
full_name = StudentRepo.build_name(semester, student_section,
48+
hw_name, username)
49+
50+
has_changes = False
51+
52+
try:
53+
repo = StudentRepo(host, namespace, full_name, token)
54+
repo_dir = os.path.join(path, username)
55+
repo.add_local_copy(repo_dir)
56+
57+
logging.debug("%s: checking out branch %s", full_name, branch)
58+
repo.get_head(branch).checkout()
59+
index = repo.get_index()
60+
61+
if update:
62+
# Stage modified and deleted files for commit
63+
# This exactly mimics the behavior of git add --update
64+
# (or the effect of doing git commit -a)
65+
for change in index.diff(None):
66+
has_changes = True
67+
if change.deleted_file:
68+
logging.debug("%s: git rm %s", full_name, change.b_path)
69+
index.remove([change.b_path])
70+
else:
71+
logging.debug("%s: git add %s", full_name, change.b_path)
72+
index.add([change.b_path])
73+
74+
if add:
75+
has_changes = True
76+
logging.debug("%s: adding %s", full_name, add)
77+
index.add(add)
78+
if remove:
79+
has_changes = True
80+
logging.debug("%s: removing %s", full_name, remove)
81+
index.remove(remove)
82+
83+
if has_changes or allow_empty:
84+
logging.debug("%s: committing changes with message %s", full_name, message)
85+
index.commit(message)
86+
else:
87+
logging.warning("%s: No changes in repo; skipping commit.", full_name)
88+
89+
except NoSuchPathError:
90+
logging.warning("Local repo for %s does not exist; skipping...", username)
91+
except RepoError as e:
92+
logging.warning(e)
93+
except HTTPError as e:
94+
if e.response.status_code == 404:
95+
logging.warning("Repository %s does not exist.", full_name)
96+
else:
97+
raise
98+
99+
progress.finish()
100+
101+
def setup_parser(parser):
102+
parser.add_argument("name",
103+
help="Name of the assignment to commit to.")
104+
parser.add_argument("message",
105+
help="Commit message")
106+
parser.add_argument("path", default=".", nargs="?",
107+
help="Path of student repositories to commit to")
108+
parser.add_argument("--branch", nargs="?", default="master",
109+
help="Local branch to commit to")
110+
parser.add_argument("-a", "--add", nargs="+", dest="add", default=[],
111+
help="Files to add before committing")
112+
parser.add_argument("-r", "--remove", nargs="+", dest="remove", default=[],
113+
help="Files to remove before committing")
114+
parser.add_argument("-u", "--update", action="store_true", dest="update",
115+
help="Include all changed files (i.e., git add -u or git commit -a)")
116+
parser.add_argument("-e", "--allow-empty", action="store_true", dest="allow_empty",
117+
help="Commit even if there are no changes to commit")
118+
parser.add_argument("--section", nargs="?",
119+
help="Section to commit to")
120+
parser.add_argument("--student", metavar="id",
121+
help="ID of student whose assignment is to be committed to.")
122+
parser.set_defaults(run=push)

0 commit comments

Comments
 (0)