-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathclassroom.sh
executable file
·216 lines (181 loc) · 4.65 KB
/
classroom.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
#!/bin/bash
# -----------------------------------------------------------------------------
# Github Classroom collect homework
#
# with thanks to: Keith Chappelow on Education GitHub forums.
# (https://education.github.community/t/
# automatically-gathering-collecting-assignments/2595/8)
# -----------------------------------------------------------------------------
function print_usage {
echo "usage: classroom mode class_data homework_name [due_date]"
echo " 'mode' can be one of \"collect\", \"grade\", or \"return\"."
echo " \"collect\": clones/pulls all matching repos."
echo " \"grade\": Requires due_date. Branches off most recent"
echo " commit before due_date"
echo " \"return\": Merges graded into master, pushes to origin."
echo " 'class_data' is a file whose first line is the classroom"
echo " organization. Subsequent lines are student usernames."
echo " 'homework_name' name of the assignment. Prefix to repo names."
echo " 'due_date' Date from which to start grading branch"
}
## Parse arguments ##
logfile="class.log"
collect_mode="collect"
grade_mode="grade"
return_mode="return"
grade_branch="grading-branch"
host="[email protected]"
# Check basic arguments
if [ "$#" -lt 3 ]
then
print_usage
exit 1
fi
mode=$1
classdata=$2
prefix=$3
# Check due date given if in 'grade' mode.
if [ "$mode" = "$grade_mode" ]
then
if [ "$#" -lt 4 ]
then
echo "ERROR: \"grade\" mode requires due date"
print_usage
exit 1
else
duedate="$4"
fi
fi
# Check class data file valid.
if [ ! -r "$classdata" ]
then
echo "ERROR: $classdata is not a readable file"
print_usage
exit 1
fi
#Get organization name.
read -r org < $classdata
## Work functions. Meat and potatoes.
# Pulls or clones (as appropriate) given repo.
function collect {
workdir=$(pwd)
log="$workdir/$logfile"
repo="$prefix-$1"
echo -n "$repo"
echo "collect $repo" >> "$log"
if [ -d $repo ]
then
echo -n " updating"
cd "$repo"
git pull "$host":"$org"/"$repo" >> "$log" 2>&1
cd "$workdir"
else
echo -n " cloning"
git clone "$host":"$org"/"$repo" >> "$log" 2>&1
if [ $? -ne 0 ]
then
echo " ERROR"
return 1
fi
fi
echo ""
return 0
}
# Finds first commit before due date, tags it, and starts a grading branch.
function grade {
workdir=$(pwd)
log="$workdir/$logfile"
repo="$prefix-$1"
echo -n "$repo"
echo "grade $repo" >> "$log"
if [ ! -d "$repo" ]
then
echo " DOES NOT EXIST"
return 1
fi
cd "$repo"
if [ "$duedate" ]
then
commit=$(git rev-list -n 1 --before="$duedate" HEAD 2>>"$log")
else
commit="HEAD"
fi
if [ -z "$commit" ]
then
echo " LATE: no commits before date $duedate"
cd "$workdir"
return 1
fi
git tag -a Graded -m "This version is graded." "$commit" >> "$log" 2>&1
git checkout -b $grade_branch "$commit" >> "$log" 2>&1
echo ""
cd "$workdir"
return 0
}
# Merge grading branch into master, push to github if successful.
function returnFunc {
workdir=$(pwd)
log="$workdir/$logfile"
repo="$prefix-$1"
echo -n "$repo"
echo "return $repo" >> "$log"
if [ ! -d "$repo" ]
then
echo " DOES NOT EXIST"
return 1
fi
cd "$repo"
echo -n " checkout"
git checkout master >> "$log" 2>&1
if [ ! $? -eq 0 ]
then
echo " CANNOT CHECKOUT MASTER"
cd "$workdir"
return 1
fi
echo -n " pull"
git pull origin master >> "$log" 2>&1
if [ ! $? -eq 0 ]
then
echo " CANNOT PULL"
cd "$workdir"
return 1
fi
git merge "$grade_branch" >> "$log" 2>&1
if [ $? -eq 0 ]
then
echo -n " push"
git push origin master >> "$log" 2>&1
else
echo " MERGE CONFLICT"
cd "$workdir"
return 1
fi
echo ""
cd "$workdir"
return 0
}
# Print running parameters
echo "mode: $mode"
echo "org: $org"
echo "hw prefix: $prefix"
if [ "$mode" = "$grade_mode" ]
then
echo "duedate: $duedate"
fi
# Loop through all students (lines in classdata after the first)
# and run mode function on each.
sed 1d $classdata | while IFS='' read -r line || [[ -n "$line" ]];
do
if [ "$mode" = "$collect_mode" ]
then
collect $line
elif [ "$mode" = "$grade_mode" ]
then
grade $line
elif [ "$mode" = "$return_mode" ]
then
returnFunc $line
fi
done
exit 0