Как контролировать владение файлами, автоматически помещаемыми в репозиторий git target с помощью хуков коммитов?
Я создал голое репо @
/srv/repos/test
я установил право собственности на wwwrun:www с установленными битами SUID+GUID
chown -R wwwrun:www /srv/repos/hub
chmod ug+s /srv/repos/hub
ls -ald /srv/repos/test
drwsrws---+ 10 wwwrun www 4.0K Mar 7 21:28 /srv/repos/hub/
я клонировал репо в webroot и поменял его владельца,
git clone /srv/repos/hub /srv/www/siteA
chown -R wwwrun:www /srv/www/siteA
для удобства определяю пульт
cd /srv/www/siteA
git remote add HUB /srv/repos/hub
затем создайте хуки post-commit и post-update для синхронизации вещей,
vi /srv/www/siteA/.git/hooks/post-commit
#!/bin/sh
git push HUB
vi /srv/repos/hub/hooks/post-update
#!/bin/sh
cd /srv/www/siteA || exit
unset GIT_DIR
git pull HUB master
exec git-update-server-info
как мой обычный пользователь, я проверяю HUB
whoami
locuse
cd ~
git clone /srv/repos/hub WORK
ls -ald WORK
drwxr-xr-x 10 locuse users 4.0K Mar 7 21:44 WORK/
внести изменения, совершить и подтолкнуть,
cd WORK
touch touch_file
ls -al touch_file
-rw-r--r-- 1 locuse users 0 Mar 7 21:44 touch_file
git add -A
git commit -m "add test"
git push
затем проверяя, что хук сработал и обновление было передано в webroot,
ls -al /srv/www/siteA/touch_file
-rw-rw----+ 1 locuse www 0 Mar 7 21:45 /srv/www/siteA/touch_file
файл там - как и ожидалось.
но я хочу не владения пользователем, а именно user='locuse', а не user='wwwrun'.
в этом конкретном случае использования, как правильно убедиться, что я, INSTEAD, всегда автоматически получу,
ls -al /srv/www/siteA/touch_file
-rw-rw----+ 1 wwwrun www 0 Mar 7 21:45 /srv/www/siteA/touch_file
? т.е. все всегда продвигается в /srv/www/siteA только как wwwrun:www .
что-то в крючке, наверное?
я знаю, я мог бы добавить
chown -R wwwrun:www /srv/www/siteA
к ловушке post-commit, которая отлично работает для небольшого дерева, но затормаживается при каждом коммите / обновлении, если оно большое (что будет).
возможно, если бы я мог эффективно отбить только текущий коммит...?
2 ответа
Это работает,
vi /srv/repos/hub/hooks/post-update
#!/bin/sh
cd /srv/www/siteA || exit
unset GIT_DIR
- git pull HUB master
+ git fetch HUB master
+ files=`git diff ..FETCH_HEAD --name-only --diff-filter=ACMRTUXB`
+ git merge FETCH_HEAD
+ for file in $files
+ do
+ sudo chown wwwrun:www $file
+ done
exec git-update-server-info
chown execs только для тех файлов, которые указаны в наборе коммитов - маленький и быстрый.
У меня была примерно такая же проблема, и после некоторого исследования я обнаружил, что нет решения, если вы обновляете пустой (HUB) репозиторий через SSH, потому что перехваты выполняются пользователем, подключенным к репозиторию HUB (в нашем случае git), Если вы хотите не давать разрешение chown / chmod для пользователя git (проблема безопасности), единственное решение - создать задание cron, чтобы постоянно обновлять репозиторий. Я сделал этот скрипт (мой первый скрипт bash), изменив старый и добавив также уведомление по электронной почте об успешном обновлении:
#!/bin/sh
# web repository directory
REPO_DIR="/srv/www/siteA"
# remote repository
REMOTE_REPO="HUB"
# public branch of the remote repository (only this branch well be public accessible trough the web server)
REMOTE_REPO_BRANCH="master"
# email address where receive notification
EMAIL_TO="your@email.com"
# sender email address and name
SENDER_ADDR="sender@email.com"
SENDER_NAME="sender name"
# tmp file that contain email body
TMP_MSG_FILE="emailmessage.txt"
cd $REPO_DIR || exit
unset GIT_DIR
echo "fetching changes..."
git fetch $REMOTE_REPO $REMOTE_REPO_BRANCH
files=`git diff ..FETCH_HEAD --name-only --diff-filter=ACDMRTUXB`
if [[ -n $files ]]; then
echo "changes found for the following file:"
echo ${files[*]}
echo "merging changes"
git merge FETCH_HEAD
echo "sending email"
SUBJECT="GIT: Web Directory Updated"
TMP_MSG_FILE="emailmessage.txt"
echo "following file are been updated/created/deleted: "> $TMP_MSG_FILE
echo ${files[*]} >>$TMP_MSG_FILE
echo "Working directory:" >>$TMP_MSG_FILE
echo "$repo_dir" >>$TMP_MSG_FILE
mutt -e "unmy_hdr from; my_hdr From: $SENDER_ADDR" -e "set realname='$SENDER_NAME' " -s "$SUBJECT" $EMAIL_TO < $TMP_MSG_FILE
else
echo "no changes found"
fi