आइए तुरंत pre-receive
हुक के एक स्क्रैप कि मैं पहले से ही लिखा है के साथ शुरू:Git 'पूर्व प्राप्त' हुक और 'Git-बजना प्रारूप' स्क्रिप्ट मज़बूती से धक्का का उल्लंघन कोड शैली सम्मेलनों को अस्वीकार करने के
#!/bin/sh
##
format_bold='\033[1m'
format_red='\033[31m'
format_yellow='\033[33m'
format_normal='\033[0m'
##
format_error="${format_bold}${format_red}%s${format_normal}"
format_warning="${format_bold}${format_yellow}%s${format_normal}"
##
stdout() {
format="${1}"
shift
printf "${format}" "${@}"
}
##
stderr() {
stdout "${@}" 1>&2
}
##
output() {
format="${1}"
shift
stdout "${format}\n" "${@}"
}
##
error() {
format="${1}"
shift
stderr "${format_error}: ${format}\n" 'error' "${@}"
}
##
warning() {
format="${1}"
shift
stdout "${format_warning}: ${format}\n" 'warning' "${@}"
}
##
die() {
error "${@}"
exit 1
}
##
git() {
command git --no-pager "${@}"
}
##
list() {
git rev-list "${@}"
}
##
clang_format() {
git clang-format --style='file' "${@}"
}
##
while read sha1_old sha1_new ref; do
case "${ref}" in
refs/heads/*)
branch="$(expr "${ref}" : 'refs/heads/\(.*\)')"
if [ "$(expr "${sha1_new}" : '0*$')" -ne 0 ]; then # delete
unset sha1_new
# ...
else # update
if [ "$(expr "${sha1_old}" : '0*$')" -ne 0 ]; then # create
unset sha1_old
sha1_range="${sha1_new}"
else
sha1_range="${sha1_old}..${sha1_new}"
# ...
fi
fi
# ...
GIT_WORK_TREE="$(mktemp --tmpdir -d 'gitXXXXXX')"
export GIT_WORK_TREE
GIT_DIR="${GIT_WORK_TREE}/.git"
export GIT_DIR
mkdir -p "${GIT_DIR}"
cp -a * "${GIT_DIR}/"
ln -s "${PWD}/../.clang-format" "${GIT_WORK_TREE}/"
error=
for sha1 in $(list "${sha1_range}"); do
git checkout --force "${sha1}" > '/dev/null' 2>&1
if [ "$(list --count "${sha1}")" -eq 1 ]; then
# What should I put here?
else
git reset --soft 'HEAD~1' > '/dev/null' 2>&1
fi
diff="$(clang_format --diff)"
if [ "${diff%% *}" = 'diff' ]; then
error=1
error '%s: %s\n%s' \
'Code style issues detected' \
"${sha1}" \
"${diff}" \
1>&2
fi
done
if [ -n "${error}" ]; then
die '%s' 'Code style issues detected'
fi
fi
;;
refs/tags/*)
tag="$(expr "${ref}" : 'refs/tags/\(.*\)')"
# ...
;;
*)
# ...
;;
esac
done
exit 0
नोट:
अप्रासंगिक कोड वाले स्थान # ...
के साथ दबाए गए हैं।
नोट:
आप git-clang-format
से परिचित नहीं हैं, तो एक नजर here ले।
वह हुक अपेक्षित काम करता है, और अब तक, मुझे कोई भी बग नहीं दिखाई देता है, लेकिन यदि आप किसी समस्या को देखते हैं या कोई सुधार सुझाव देते हैं, तो मैं किसी भी रिपोर्ट की सराहना करता हूं। शायद, मुझे इस हुक के पीछे क्या इरादा है इस पर एक टिप्पणी देनी चाहिए। खैर, यह git-clang-format
का उपयोग करके कोड शैली सम्मेलनों के अनुपालन के लिए प्रत्येक धक्का संशोधन की जांच करता है, और यदि उनमें से कोई भी अनुपालन नहीं करता है, तो यह उनमें से प्रत्येक के लिए प्रासंगिक diff (एक डेवलपर्स को क्या तय किया जाना चाहिए) आउटपुट करेगा। असल में, मेरे पास इस हुक के बारे में दो गहन प्रश्न हैं।
सबसे पहले, ध्यान दें कि मैं कुछ अस्थायी निर्देशिका में रिमोट (सर्वर) नंगे भंडार की प्रतिलिपि करता हूं और वहां विश्लेषण के लिए कोड देखता हूं। मुझे इसके इरादे की व्याख्या करने दो। ध्यान दें कि git-clang-format
के साथ व्यक्तिगत रूप से सभी धक्का संशोधनों का विश्लेषण करने के लिए मैं कई git checkout
s और git reset
s (for
लूप के कारण) करता हूं। मैं यहां से बचने की कोशिश कर रहा हूं, रिमोट (सर्वर) नंगे भंडार में पुश पहुंच पर (संभव) समवर्ती मुद्दा है। यही है, मैं इस धारणा के तहत हूं कि यदि एकाधिक डेवलपर्स एक ही समय में इस pre-receive
हुक के साथ रिमोट पर धक्का देने का प्रयास करेंगे, तो इन समस्याओं में से प्रत्येक "सत्र" git checkout
एस और git reset
एस के साथ नहीं होने पर समस्याएं पैदा हो सकती हैं भंडार की इसकी निजी प्रति। तो, इसे सरल रखने के लिए, git-daemon
में समवर्ती धक्का "सत्र" के लिए अंतर्निहित लॉक प्रबंधन है? क्या यह संबंधित pre-receive
हुक उदाहरणों को सख्ती से अनुक्रमिक रूप से निष्पादित करेगा या इंटरलिविंग की संभावना है (जो संभावित रूप से अपरिभाषित व्यवहार का कारण बन सकता है)? कुछ मुझे बताता है कि कंक्रीट गारंटी के साथ इस समस्या के लिए एक अंतर्निहित समाधान होना चाहिए, अन्यथा समवर्ती धक्का के अधीन सामान्य रूप से काम (जटिल हुक के बिना) को कैसे हटाया जाएगा? यदि ऐसा कोई अंतर्निहित समाधान है, तो प्रतिलिपि अनावश्यक है और केवल नंगे भंडार का पुन: उपयोग करने से वास्तव में प्रसंस्करण तेज हो जाएगा। वैसे, इस प्रश्न के बारे में आधिकारिक दस्तावेज का कोई भी संदर्भ बहुत स्वागत है।
दूसरा, git-clang-format
प्रक्रियाओं केवल मंचन (लेकिन प्रतिबद्ध) बनाम विशिष्ट कुछ परिवर्तन के लिए प्रतिबद्ध (HEAD
डिफ़ॉल्ट रूप से)। इस प्रकार, आप आसानी से देख सकते हैं कि एक कोने का मामला कहाँ है। हां, यह रूट के साथ है (संशोधन)। वास्तव में, git reset --soft 'HEAD~1'
रूट प्रतिबद्धताओं पर लागू नहीं किया जा सकता क्योंकि उनके पास रीसेट करने के लिए कोई माता-पिता नहीं हैं। इसलिए, मेरी दूसरी सवाल के साथ निम्नलिखित की जांच होती है:
if [ "$(list --count "${sha1}")" -eq 1 ]; then
# What should I put here?
else
git reset --soft 'HEAD~1' > '/dev/null' 2>&1
fi
मैं git update-ref -d 'HEAD'
की कोशिश की है, लेकिन यह इस तरह से भंडार टूट जाता है कि git-clang-format
इसे अब और प्रोसेस करने में सक्षम नहीं है। मेरा मानना है कि यह इस तथ्य से संबंधित है कि इन सभी ने संशोधित संशोधनों का विश्लेषण किया है (इस रूट सहित) वास्तव में अभी तक किसी भी शाखा से संबंधित नहीं हैं। यही है, वे अलगHEAD
राज्य में हैं।इस कोने के मामले में भी समाधान ढूंढना सही होगा, ताकि प्रारंभिक प्रतिबद्धता कोड शैली सम्मेलनों के अनुपालन के लिए git-clang-format
द्वारा एक ही चेक से गुजर सकती है।
शांति।