الخطاف الزئبقي لا يتم تنفيذه بشكل صحيح
-
21-08-2019 - |
سؤال
من المفترض أن يكون تشغيل هذا أمرًا بسيطًا للغاية، ولكن لسبب ما لن يعمل مع مستودع Mercurial الخاص بي.كل ما أريده هو أن يتم تشغيل الريبو عن بعد تلقائيًا hg update
كلما دفع شخص ما لذلك.لدي هذا في ملف .hg/hgrc الخاص بي:
[hook]
changegroup = hg update
بسيطة، أليس كذلك؟ولكن لسبب ما، هذا لا ينفذ أبدا.لقد حاولت أيضًا كتابة برنامج نصي لشل قام بذلك.بدا .hg/hgrc هكذا:
[hooks]
changegroup = /home/marc/bin/hg-update
وبدا تحديث hg كما يلي:
#!/bin/sh
hg help >> /home/marc/works.txt;
hg update >> /home/marc/works.txt;
exit 0;
ولكن مرة أخرى، هذا لا يتم تحديثه.محتويات hg help
مكتوبة ل works.txt
, ، ولكن لم يتم كتابة أي شيء من أجله hg update
.هل هناك شيء واضح أفتقده هنا؟لقد كان هذا يضايقني منذ أيام ولا يبدو أنني أستطيع تشغيله.
تحديث
حسنًا، مرة أخرى، باستخدام -v
تشغيل سطر الأوامر من محطة العمل الخاصة بي، والدفع إلى الريبو البعيد لا يطبع أي رسائل مطولة حتى عندما يكون لدي تلك الرسائل echo
خطوط في .hg/hgrc
.ومع ذلك، عندما أقوم بالدفع من نسخة الريبو على نفس نظام الملفات (لقد قمت بتسجيل الدخول عبر SSH)، هذا ما أحصل عليه:
bash-3.00$ hg -v push ../test-repo/ pushing to ../test-repo/ searching for changes 1 changesets found running hook prechangegroup: echo "Remote repo is at `hg tip -q`" echo "Remote repo wdir is at `hg parents -q`" Remote repo is at 821:1f2656753c98 Remote repo wdir is at 821:1f2656753c98 adding changesets adding manifests adding file changes added 1 changesets with 1 changes to 1 files running hook changegroup: echo "Updating.... `hg update -v`" echo "Remote repo is at `hg tip -q`" echo "Remote repo wdir is at `hg parents -q`" Updating.... resolving manifests getting license.txt 1 files updated, 0 files merged, 0 files removed, 0 files unresolved Remote repo is at 822:389a6c7276c6 Remote repo wdir is at 822:389a6c7276c6
لذا فهو يعمل، ولكن مرة أخرى فقط عندما أقوم بالدفع من نفس نظام الملفات.لا يعمل إذا حاولت الدفع إلى الريبو من محطة عمل أخرى عبر الشبكة.
المحلول
قضيت بعض الوقت في البحث عن هذا بنفسي.أعتقد أن الإجابة على المشكلة موصوفة بإيجاز هنا:
يجب إعادة توجيه الإخراج إلى Stderr (أو /dev /null) ، لأنه يتم استخدام stdout لدفق البيانات.
في الأساس، أنت لا تقوم بإعادة التوجيه إلى stderr، وبالتالي تلويث stdout.
نصائح أخرى
حسنًا، بعد المرور بنفس خطوات الإحباط التي مر بها مارك دبليو منذ فترة، وجدت أخيرًا حل المشكلة، على الأقل عند انتهاء الخدمة عن بُعد باستخدام البرنامج النصي hgwebdir WSGI.
لقد اكتشفت أنه عند استخدام هذا النوع من الدفع عن بعد عبر HTTP أو HTTPS، يتجاهل Mercurial ببساطة كل ما تكتبه في ملف .hg/hgrc أو مستودعك.ومع ذلك، دخول هوك في التكوين hgwebdir عمل الحيلة.
لذلك إذا كان المحصلة النهائية في الخاص بك hgwebdir.wsgi البرنامج النصي هو شيء من هذا القبيل
application = hgwebdir('hgweb.config')
يحتاج قسم التكوين [الخطافات] إلى الدخول في ما ذكر hgweb.config.
أحد العيوب هو أن هذه الخطافات يتم تنفيذها من أجلها كل مستودع المدرجة في قسم [المسارات] من هذا التكوين.على الرغم من أن HG تقدم وظيفة أخرى قادرة على WSGI (hgweb بدلاً من hgwebdir) لخدمة مستودع واحد فقط، إلا أنه لا يبدو أن هذه الوظيفة تدعم أي خطافات (كما أنها لا تحتوي على أي تكوين).ومع ذلك، يمكن التحايل على ذلك باستخدام hgwebdir كما هو موضح أعلاه وجعل Apache RewriteRule يرسم كل شيء في الدليل الفرعي المطلوب.هذا واحد يعمل بالنسبة لي:
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/reponame
RewriteRule ^(.*)$ reponame/$2 [QSA]
استمتع باستخدام الخطافات البعيدة عبر HTTP :D
في البداية، أريد تصحيح بعض التعليقات أعلاه.
- يتم استدعاء الخطافات أيضًا عند الضغط على نظام الملفات.
- ليس من الضروري الاحتفاظ بالخطاف في الريبو الذي تريد أن يعملوا عليه.يمكنك أيضًا كتابة نفس الخطاف الموجود في سؤالك من جانب المستخدم.يجب عليك تغيير الحدث من Changegroup إلى Outgoing وأيضًا تحديد عنوان URL لمستودع الريبو البعيد باستخدام مفتاح -R.ثم إذا كان لدى المستخدم الذي يدفع امتيازات كافية في الريبو البعيد، فسيتم تنفيذ الخطاف بنجاح.
.hg/hgrc
[hooks]
outgoing = hg update -R $HG_URL
والآن نحو مشكلتك....أقترح إنشاء خطافات prechangegroup وchangegroup وطباعة بعض مخرجات تصحيح الأخطاء.
.hg/hgrc
[hooks]
prechangegroup = echo "Remote repo is at `hg tip -q`"
echo "Remote repo wdir is at `hg parents -q`"
changegroup = echo "Updating.... `hg update -v`"
echo "Remote repo is at `hg tip -q`"
echo "Remote repo wdir is at `hg parents -q`"
واضغط أيضًا باستخدام المفتاح -v، حتى تتمكن من معرفة الخطاف الذي يعمل.إذا كنت لا تزال غير قادر على معرفة ذلك، قم بنشر النتيجة.كنت قد تكون قادرة على مساعدة.
كانت مشكلتي هي أن تطبيق hgwebdir الخاص بي كان يعمل كمستخدم "hg"، لكن المستودع كان مملوكًا لي، لذلك اضطررت إلى إضافة هذا الجزء من التكوين إلى hgweb.config لتشغيل الخطافات:
[trusted]
users = me
تحتاج إلى الحصول عليه في بعيد hgrc للمستودع.يبدو كما لو كان في الريبو المحلي الخاص بك.
يحرر:يعتمد ذلك أيضًا على كيفية الدفع.بعض الطرق لا تستدعي الخطافات على الجانب الأيمن.(SSH يفعل ذلك، أعتقد أن HTTP يفعل ذلك، ونظام الملفات يفعل ذلك لا)
تحرير 2:ماذا لو قمت بالضغط على "محليًا" على كمبيوتر الريبو البعيد.قد يكون لديك مستخدمين/أذونات مختلفة بين خادم الويب وملف hgrc.(راجع [الخادم] والتوجيهات الموثوقة لـ hgrc.)
واجهت نفس المشكلة في الدفع من Windows Eclipse عبر http، ولكن بعد التقاط stderr، وجدت أن المسار الكامل مطلوب لملف hg.bat.يبدو قسم الخطافات الخاص بي الآن كما يلي:
[hooks]
incoming = c:\Python27\Scripts\hg.bat update > hg_log.txt 2>>hg_err.txt
آمل أن يساعد هذا شخص آخر.ستيف تي
يحاول تشغيل تصحيح أخطاء الخطاف لمعرفة سبب عدم تشغيله.
من المحتمل أن يكون هناك مشكلة في الأذونات أو شيء من هذا القبيل.
استغرق بعض الوقت ولكن حصلت عليه العمل.
لقد بدأت مع
[hooks]
tag=set >&2
commit=set >&2
يقوم >&2 بتوجيهه إلى الخطأ القياسي حتى تظهره وحدات التحكم عن بعد.
عند التحكم عن بعد، يجب أن يتم إخراج ذلك في وحدة التحكم إذا كانت قيد التشغيل
hg push https://host/hg -v
لم يكن كذلك.
كنت أستخدم hgweb.cgi لذلك قمت بالتبديل إلى hgweb.wsgi دون أي فرق.
ما اكتشفته هو أن بعض الخطافات لا يتم استدعاؤها عن بعد.
عندما قمت بالتبديل إليه
[hooks]
incoming= set >&2
يبدو أنه لا يتم استدعاء علامة الخطافات والالتزام ولكن يتم استدعاء مجموعة التغييرات والواردة.ولم أؤكد الآخرين.
الآن بعد أن نجحت في ذلك، عدت مرة أخرى إلى hgweb.cgi وكل شيء يعمل بنفس الطريقة.
السبب الذي وجدته لهذا لا علاقة له بإعادة التوجيه stdout
ل stderr
.وكما ترى في صفحة الويكي، لم يتم تحديدها في الإصدار الحالي للويكيhttps://www.mercurial-scm.org/wiki/FAQ#FAQ.2FCommonProblems.Any_way_to_.27hg_push.27_and_have_an_automatic_.27hg_update.27_on_the_remote_server.3F
المشكلة التي وجدتها موجودة الأذونات.
في الإعداد الأصلي الخاص بي، كان لدي مستخدم، دعنا نقول hguser
مع الريبو في منزله، والنص /etc/init.d/hg.init
للاطلاق hg serve
.المشكلة هي hg serve
كان يدار من قبل root
, ، في حين أن معظم الملفات ضمن الريبو تتعلق بـ hguser
(وقد تحول بعضهم إلى root
في مرحلة ما، لكنه لن يمانع، لأنني سأصححها chown
)
حل:
chown -R hguser:hguser /home/hguser/repo
(لتصحيح كافة الملفات، العودة إلى hguser)- يطلق
su hguser -c "hg serve ..."
(في حالتي من/etc/init.d/hg.init
) changegroup = hg update -C
تحت[hooks]
فيrepo/.hg/hgrc
كل عادة
الآن يجب أن تعمل على push
ملاحظة:في حالتي، أفضل التحديث لرئيس فرع معين، لذلك أستخدمه hg update -C -r staging
, ، لإجراء تحديث الخادم المرحلي فقط على رأس الفرع المقصود، حتى لو كان tip
من فرع آخر (مثل development
على سبيل المثال)
راجع للشغل بلدي hg.init
انتهى البرنامج النصي مثل هذا:(لاحظ ال su hguser
جزء)
#!/bin/sh
#
# Startup script for mercurial server.
#
# @see http://jf.blogs.teximus.com/2011/01/running-mercurial-hg-serve-on-linux.html
HG=/usr/bin/hg
CONF=/etc/mercurial/hgweb.config
# Path to PID file of running mercurial process.
PID_FILE=/etc/mercurial/hg.pid
state=$1
case "$state" in
'start')
echo "Mecurial Server service starting."
(su hguser -c "${HG} serve -d --webdir-conf ${CONF} -p 8000 --pid-file ${PID_FILE}")
;;
'stop')
if [ -f "${PID_FILE}" ]; then
PID=`cat "${PID_FILE}"`
if [ "${PID}" -gt 1 ]; then
kill -TERM ${PID}
echo "Stopping the Mercurial service PID=${PID}."
else
echo Bad PID for Mercurial -- \"${PID}\"
fi
else
echo No PID file recorded for mercurial
fi
;;
*)
echo "$0 {start|stop}"
exit 1
;;
esac
ملاحظة:الائتمان المستحق ل http://jf.blogs.teximus.com/2011/01/running-mercurial-hg-serve-on-linux.html