added bash script developed for computer engineering
This commit is contained in:
Executable
+300
@@ -0,0 +1,300 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
### TODO: ensure files deleted in the maintainer repository are
|
||||
### also deleted in the students repository
|
||||
|
||||
### WARN: this script will not work unless the remote name is `origin` (default).
|
||||
|
||||
### WARN: this script expects you to connect to github via ssh.
|
||||
### ensure you registered your public key.
|
||||
|
||||
# constant definitions
|
||||
|
||||
# WARN: make sure you understand the implications before
|
||||
# you change the value (or name) of a constant!
|
||||
|
||||
required_tools=(
|
||||
"cat"
|
||||
"dirname"
|
||||
"find"
|
||||
"git"
|
||||
"grep"
|
||||
"pandoc"
|
||||
"realpath"
|
||||
"sed"
|
||||
"tar"
|
||||
"tput"
|
||||
)
|
||||
common_dir="../common"
|
||||
laboratory_dir="./laboratories"
|
||||
student_repo_name="student-repository"
|
||||
student_repo_url="git@github.zhaw.ch:CT/ct1-students.git"
|
||||
code_start="STUDENTS: To be programmed"
|
||||
code_end="END: To be programmed"
|
||||
make_start="solution[s]*=start"
|
||||
make_end="solution[s]*=end"
|
||||
md_solution_start="solution[s]*=start"
|
||||
md_solution_end="solution[s]*=end"
|
||||
md_student_start="student[s]*=start"
|
||||
md_student_end="student[s]*=end"
|
||||
keili_dir_name="keil"
|
||||
archive_name="release.tar"
|
||||
exclude_file_name=".release-ignore"
|
||||
|
||||
# sanity checks for variables
|
||||
if [[ "${laboratory_dir}" =~ ".." ]]; then
|
||||
echo "'laboratory_dir' has to be a child directory of the one containing this script"
|
||||
fi
|
||||
if [[ "." != "$(dirname "${student_repo_name}")" ]]; then
|
||||
echo "'student_repo_name' may not contain directories!"
|
||||
exit 0
|
||||
fi
|
||||
if [[ "." != "$(dirname "${keili_dir_name}")" ]]; then
|
||||
echo "'keili_dir_name' may not contain directories!"
|
||||
exit 0
|
||||
fi
|
||||
if [[ "." != "$(dirname "${exclude_file_name}")" ]]; then
|
||||
echo "'exclude_file_name' may not contain directories!"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# helper function declarations
|
||||
|
||||
## print highlighted text
|
||||
##
|
||||
## used the same as `echo`
|
||||
function print_highlighted {
|
||||
if ! $(which tput &>/dev/null) || [[ -z "$(tput smso)" ]]; then
|
||||
echo "$*"
|
||||
return 0
|
||||
fi
|
||||
|
||||
tput smso
|
||||
echo "$*"
|
||||
tput sgr0
|
||||
}
|
||||
|
||||
## print yellow text
|
||||
##
|
||||
## used the same as `echo`
|
||||
function print_warning {
|
||||
if ! $(which tput &>/dev/null); then
|
||||
echo "$*"
|
||||
return 0
|
||||
fi
|
||||
|
||||
tput setaf 3
|
||||
echo "$*"
|
||||
tput sgr0
|
||||
}
|
||||
|
||||
## print red text
|
||||
##
|
||||
## used the same as `echo`
|
||||
function print_error {
|
||||
if ! $(which tput &>/dev/null); then
|
||||
echo "$*"
|
||||
return 0
|
||||
fi
|
||||
|
||||
tput setaf 1
|
||||
echo "$*"
|
||||
tput sgr0
|
||||
}
|
||||
|
||||
# main logic
|
||||
|
||||
# ensure the required tools are available
|
||||
unset error_message
|
||||
for tool in "${required_tools}"; do
|
||||
if ! $(which "${tool}" &>/dev/null); then
|
||||
error_message+="${tool}"
|
||||
fi
|
||||
done
|
||||
if [[ -n "${error_message}" ]]; then
|
||||
print_error "missing the following tools: [ ${error_message} ]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# ensure commands are executed in the directory where the
|
||||
# script is located
|
||||
root_dir="$(realpath "${BASH_SOURCE}" | dirname -)"
|
||||
cd "${root_dir}"
|
||||
|
||||
# check that there are no paths with spaces
|
||||
illegal_paths="$(find . -type d -name ".git" -prune -o -name "*" -print |
|
||||
sort | grep ' ')"
|
||||
if [[ -n "${illegal_paths}" ]]; then
|
||||
print_error "no spaces in paths allowed!"
|
||||
print_error "the following paths are illegal:"
|
||||
echo ""
|
||||
echo "${illegal_paths}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# ensure the working tree of the maintainer repository is not behind
|
||||
# no need to check the students repository, as it is derived from the
|
||||
# maintainer repository
|
||||
git fetch &>/dev/null
|
||||
if [[ -n "$(git diff origin/HEAD)" ]]; then
|
||||
print_warning "working tree of the maintainer repository differs from the remotes head."
|
||||
print_warning "pull and/or commit/push first to resolve the differences."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# remove trailing whitespace and convert to unix file format
|
||||
bash "${common_dir}/trailing-whitespace.sh" -u .
|
||||
|
||||
# ensure the students repository is checked out
|
||||
if [[ ! -d "${student_repo_name}" ]]; then
|
||||
print_highlighted "cloning students repository"
|
||||
git clone "${student_repo_url}" "${student_repo_name}"
|
||||
fi
|
||||
|
||||
# ensure the students repository is ignored
|
||||
if [[ -z "$(cat "./.gitignore" | grep "${student_repo_name}")" ]]; then
|
||||
echo "${student_repo_name}/" >>"./.gitignore"
|
||||
fi
|
||||
|
||||
# remove solutions from source code
|
||||
code_files=($(
|
||||
find "${laboratory_dir}" \
|
||||
-type f \
|
||||
-name "*.[chs]"
|
||||
))
|
||||
|
||||
for file in "${code_files[@]}"; do
|
||||
sed -i "
|
||||
/${code_start}/,/${code_end}/ {
|
||||
/${code_start}/n
|
||||
/${code_end}/!d
|
||||
}" ${file}
|
||||
|
||||
# add blank lines to show where code goes
|
||||
sed -i "/${code_start}/a\\\\" ${file}
|
||||
sed -i "/${code_start}/a\\\\" ${file}
|
||||
sed -i "/${code_start}/a\\\\" ${file}
|
||||
done
|
||||
|
||||
echo "> removed solutions from source files."
|
||||
|
||||
# removing solutions from makefiles
|
||||
make_files=($(
|
||||
find "${laboratory_dir}" \
|
||||
-type f \
|
||||
-name "Makefile" \
|
||||
-or \
|
||||
-name "*.mk"
|
||||
))
|
||||
|
||||
for file in "${make_files[@]}"; do
|
||||
sed -i "/${make_start}/,/${make_end}/d" ${file}
|
||||
done
|
||||
|
||||
# remove solutions from lab instructions
|
||||
md_files=($(
|
||||
find "${laboratory_dir}" \
|
||||
-type f \
|
||||
-name "*.md"
|
||||
))
|
||||
|
||||
for file in "${md_files[@]}"; do
|
||||
sed -i "/${md_solution_start}/,/${md_solution_end}/d" ${file}
|
||||
sed -i "/${md_student_start}/d" ${file}
|
||||
sed -i "/${md_student_end}/d" ${file}
|
||||
done
|
||||
|
||||
echo "> removed solutions from lab instructions."
|
||||
|
||||
# convert readmes from `pandoc markdown` to `github flavoured markdown` and pdf
|
||||
echo "converting markdown files to pdfs"
|
||||
echo "(this may take a while)"
|
||||
|
||||
template="$(realpath "${common_dir}/template.tex")"
|
||||
unset pdf_files
|
||||
for file in "${md_files[@]}"; do
|
||||
filename="${file##*/}"
|
||||
pushd "${file%/*}" &>/dev/null
|
||||
pandoc \
|
||||
-f markdown \
|
||||
-t pdf \
|
||||
--pdf-engine pdflatex \
|
||||
--listings \
|
||||
--template "${template}" \
|
||||
"${filename}" \
|
||||
-o "${filename/%md/pdf}"
|
||||
pandoc \
|
||||
-f markdown \
|
||||
-t gfm \
|
||||
"${filename}" \
|
||||
-o "${filename}"
|
||||
popd &>/dev/null
|
||||
pdf_files+=("${file/%md/pdf}")
|
||||
done
|
||||
unset template
|
||||
|
||||
echo "> converted readme files to github flavoured markdown."
|
||||
|
||||
# generate zip archives of keili projects
|
||||
keili_dirs=($(find . -type d -name "${keili_dir_name}"))
|
||||
for item in "${keili_dirs[@]}"; do
|
||||
pushd "$(dirname "${item}")" &>/dev/null
|
||||
zip -r "${keili_dir_name}.zip" "${keili_dir_name}" &>/dev/null
|
||||
popd &>/dev/null
|
||||
done
|
||||
unset keili_dirs
|
||||
|
||||
keili_archives=($(find "${laboratory_dir}" -name "${keili_dir_name}.zip"))
|
||||
|
||||
# copy modified contents to students repository
|
||||
exclude_patterns=("${exclude_file_name}")
|
||||
exclude_patterns+=("${keili_dir_name}")
|
||||
exclude_patterns+=("*.pptx")
|
||||
exclude_patterns+=("*.docx")
|
||||
|
||||
# collect exclude globs
|
||||
ignore_files=($(find . -type f -iname "${exclude_file_name}"))
|
||||
for file in "${ignore_files[@]}"; do
|
||||
temp_path="$(dirname ${file})/"
|
||||
temp_patterns=($(cat "${file}"))
|
||||
exclude_patterns+=(${temp_patterns[@]/#/${temp_path}})
|
||||
done
|
||||
|
||||
# remove contents of the student repository to avoid
|
||||
# orphaned files/directories
|
||||
find "${student_repo_name}" \
|
||||
-mindepth 1 \
|
||||
-maxdepth 1 \
|
||||
-not -name ".git" \
|
||||
-exec rm -rf {} \;
|
||||
|
||||
# create release using `tar`
|
||||
tar -cf "${archive_name}" \
|
||||
-h \
|
||||
--exclude-vcs \
|
||||
--exclude-vcs-ignore \
|
||||
--exclude="${archive_name}" \
|
||||
"${exclude_patterns[@]/#/--exclude=}" \
|
||||
"${keili_archives[@]/#/--add-file=}" \
|
||||
"${pdf_files[@]/#/--add-file=}" \
|
||||
.
|
||||
tar -xf "${archive_name}" \
|
||||
-C "${student_repo_name}/"
|
||||
|
||||
# reset repository after release creation
|
||||
git reset --hard &>/dev/null
|
||||
git clean -fd &>/dev/null
|
||||
rm "${keili_archives[@]}" "${pdf_files[@]}"
|
||||
|
||||
# print message to report success and a reminder to commit and
|
||||
# push the students repository
|
||||
relative_path="$(dirname "${BASH_SOURCE}")/${student_repo_name}"
|
||||
|
||||
echo ""
|
||||
echo "successfully prepared the release for the students repository."
|
||||
echo "generated release is found at \`${relative_path}\`."
|
||||
echo ""
|
||||
|
||||
print_highlighted "remember to commit and push the generated release!"
|
||||
|
||||
echo ""
|
||||
Reference in New Issue
Block a user