Проектная лаборатория
Собственный Git
Этап 05 · Основные этапы
Запись объекта-дерева
Русский перевод заданий CodeCrafters. Примеры подготовлены для Go. Выбор языка меняет команды и результаты, но не текст задания.
На этом этапе вы реализуете запись дерева в каталог .git/objects.
Хранение объектов-деревьев: повторение
Напомним: объекты-деревья хранят структуру каталогов и сохраняются в каталоге .git/objects.
Например, если хеш дерева равен e88f7a929cd70b0274c4ea33b209c97fa845fdbc, его путь будет .git/objects/e8/8f7a929cd70b0274c4ea33b209c97fa845fdbc.
Файл объекта-дерева выглядит следующим образом (до сжатия Zlib):
tree <size>\0
<mode> <name>\0<20_byte_sha>
<mode> <name>\0<20_byte_sha>(В блоке выше для удобства чтения добавлены переводы строк, но в настоящем файле их нет.)
- Файл начинается с
tree <size>\0. Это заголовок объекта, устроенный так же, как заголовок blob-объекта. - После заголовка идёт несколько записей. Каждая имеет формат
<mode> <name>\0<sha>:<mode>задаёт тип и права доступа файла или каталога.<name>— имя файла или каталога.\0обозначает нулевой байт.<20_byte_sha>— 20-байтовый хеш SHA-1 файла или каталога.
Поле <mode>
Поле <mode> задаёт тип и права доступа каждой записи. Среди допустимых значений:
100644— обычный файл.100755— исполняемый файл.40000— каталог (объект-дерево).
Обратите внимание: режим каталога — 40000, а не 040000. Хотя команды Git, например git ls-tree, для удобства чтения показывают его как 040000, в объекте-дереве хранится 40000.
Подробнее о внутреннем формате объекта-дерева можно прочитать здесь.
Команда git write-tree
Команда git write-tree создаёт объект-дерево из текущего состояния «области подготовленных изменений» (индекса). В эту область изменения попадают после выполнения git add.
В этом задании вы не будете реализовывать индекс. Вместо этого считайте, что все файлы рабочего каталога уже подготовлены к коммиту.
Пример использования git write-tree:
# Create a file with some content
$ echo "hello world" > test.txt
# Add the file to the staging area (we won't implement a staging area in this challenge)
$ git add test.txt
# Write the tree to .git/objects
$ git write-tree
4b825dc642cb6eb9a060e54bf8d69288fbee4904Команда git write-tree выводит 40-символьный хеш SHA-1 объекта-дерева, записанного в .git/objects.
Для реализации git write-tree нужно:
- Перебрать файлы и каталоги в рабочем каталоге.
- Для файла создать blob-объект и сохранить его хеш SHA-1.
- Для каталога рекурсивно создать объект-дерево и сохранить его хеш SHA-1.
- Отсортировать все записи по имени в алфавитном порядке.
- Собрав все записи и их хеши SHA-1, записать объект-дерево в каталог
.git/objects.
Если вы локально сравниваете результат с git, обязательно выполните git add . перед git write-tree, чтобы подготовить все файлы рабочего каталога.
Тесты
Тестирующая система инициализирует новый репозиторий Git вашей программой:
$ mkdir test_dir && cd test_dir
$ /path/to/your_program.sh initЗатем создаст несколько случайных файлов и каталогов:
$ echo "hello world" > test_file_1.txt
$ mkdir test_dir_1
$ echo "hello world" > test_dir_1/test_file_2.txt
$ mkdir test_dir_2
$ echo "hello world" > test_dir_2/test_file_3.txtПосле этого запустит программу следующим образом:
$ /path/to/your_program.sh write-tree
4b825dc642cb6eb9a060e54bf8d69288fbee4904Вы должны записать весь рабочий каталог в виде объекта-дерева и вывести его 40-символьный хеш SHA-1 в stdout.
Тестирующая система проверит, что вывод совпадает с хешем SHA-1 дерева, которое записала бы официальная реализация git.
Примечания
- Не забудьте исключить каталог
.gitпри создании записей дерева и отсортировать все записи по имени в алфавитном порядке. - Ваша реализация
git write-treeдолжна поддерживать вложенные каталоги. Здесь полезна рекурсия: чтобы создать дерево родительского каталога, нужно создать деревья всех подкаталогов. - Наша реализация
git write-treeнемного отличается от официальной. Официальная реализацияgitопределяет содержимое дерева по индексу. Мы считаем, что все файлы рабочего каталога уже подготовлены.
Проверка в вашей IDE
Нужны Node.js, Git, Go 1.24+ для тестеров и инструменты выбранного языка. Тестеры загружаются и запускаются локально; отдельным проектам нужны дополнительные системные зависимости.
Настройка проекта и IDE
1. Создайте проект один раз
node '/opt/graphlms/tools/project-lab/cli.mjs' init git ./my-git --language go2. Откройте папку в IDE
cd ./my-gitРеализуйте требования этапа в созданном проекте.
Запустите из папки проекта
node '/opt/graphlms/tools/project-lab/cli.mjs' submit --stage fe4Запускайте submit из папки проекта. Это локальные проверки, а не сертификаты или результаты аккаунта CodeCrafters.
Результат проверки
go / ЛОКАЛЬНОПодключение к локальной проверке…
Здесь появится результат
Запустите submit в терминале. Страница обновляет результаты каждые 8 секунд.