Как стать автором
Обновить

Автоматизация создания соответствий исполняемых файлов исходным кодам в GIT

Время на прочтение 2 мин
Количество просмотров 2.9K
Имея программный проект с компилируемым языком программирования возникает задача имея исполняемый файл определить из каких исходных кодов он был собран. В данной статье мы опишем как автоматизировать добавление коммита в исполняемые файлы и как по нему в дальнейшем получить исходный код.

В общем представлении git — это хранилище объектов. Объекты в git бывают 4 типов:
  • blob — для хранения данных.
  • tree — для хранения ссылок на blob и другие tree.
  • commit — для указания на конкретный объект tree, т.е. маркировки снимка проекта в определенный момент времени.
  • tag — для маркировки commit, как некоторой версии проекта.

Любой объект может быть доступен по его “объектному имени” — набор 40 цифр и букв (шестнадцатеричное представление), представляющий собой SHA1 данных этого объекта. Таким образом состояние исходных кодов проекта в GIT может быть описано “объектным именем“ коммита или просто коммитом. Получить текущий коммит одной строкой и с комментарием к нему можно с помощью следующей команды:
git log --pretty=oneline -n1

Теперь нужно лишь добавить его в исполняемые файлы и выводить пользователю, например при запуске программы с параметром --version.

Автоматизировать этот процесс можно с помощью хуков — пользовательских действий, которые будут выполняться при совершении git некоторых операций. Есть различные хуки, но нам потребуются лишь post-commit (вызывается после обработки git commit), post-checkout (вызывается после обработки git checkout) и post-merge (вызывается после обработки git merge, которая вызывается в том числе и при git pull). Хуки это исполняемые файлы, которые находятся в директории $GIT_DIR/hooks.

Для того, чтобы хуки были в git репозитории удобно создать папку git_hooks и сделать симлинк на $GIT_DIR/hooks. Создадим в этой директории 3 файла post-commit, post-checkout, post-merge с одинаковым содержанием. Для примера мы используем С/С++ проект и хотим хранить коммит в виде строки в header файле, тогда эти файлы будут выглядеть следующим образом:

#!/bin/sh
# post-commit
#Файл в который мы будем записывать коммит
file="git_commit.h"
file_def=`echo $file|tr . _`
echo "#ifndef $file_def" > $file
echo "#define $file_def" >> $file
echo "static const char *git_commit_str = \""`git log --pretty=oneline -n1`"\";" >> $file
echo "#endif" >> $file

# Выведем сообщение о том что все успешно
echo "--- Git commit is written to $file ---"
echo "--- !!! NOW PLEASE RECOMPILE YOUR PROJECT TO TAKE EFFECT !!! ---"

Теперь в проекте можно вставить следующий код, который будет выводить версию коммита.
#include git_commit.h
…
printf("Git commit: %s\n", git_commit_str);

При каждом вызове git commit, git checkout, git pull (если локальная версия будет отличаться от удаленной) будет перезаписываться файл git_commit.h и необходимо будет пересобрать проект, для того чтобы отображался нужный коммит. В дальнейшем, имея исполняемый файл, можно получить исходный код этого файла с помощью git checkout COMMIT либо посмотреть исходный код в веб браузере, если используется github по github.com/USER/PROJECT/tree/COMMIT.

Кстати в SVN ту же операцию можно проделать схожим образом. В SVN состояние исходных кодов проекта описывается с помощью глобального номера ревизии, который можно получить с помощью команды svnversion, а хуки могут быть повешены на события post-commit и post-revprop-change.
Теги:
Хабы:
+6
Комментарии 7
Комментарии Комментарии 7

Публикации

Истории

Ближайшие события

Московский туристический хакатон
Дата 23 марта – 7 апреля
Место
Москва Онлайн
Геймтон «DatsEdenSpace» от DatsTeam
Дата 5 – 6 апреля
Время 17:00 – 20:00
Место
Онлайн