Найти тему
Golang

Как я построил систему контроля версий (VCS) на чистом Go 🚀

Каждый отдельный скрипт, связанный с созданием вашего программного обеспечения, должен находиться под контролем версий. [1]

VCS — это система, которая отслеживает версии кода с течением времени. [2]

Демо

https://asciinema.org/a/487303

Исходный код

https://github.com/Абдулсаметилери/vX

Мотивация

Когда я прочитал прекрасную книгу , чтобы лучше понять системы, управляемые версиями при разработке, я нашел в книге очень хороший пример.

«В качестве аналогии представьте, что вы создаете систему контроля версий, такую ​​как SVN или Git. Когда пользователь впервые изменяет файл, система сохраняет весь файл на диск. Последующие коммиты, отражающие изменения в этом файле, могут сохранить только дельту, то есть только те строки, которые были добавлены, изменены или удалены. Затем, когда пользователь извлекает определенную версию, система открывает файл версии 0 и добавляет все последующие дельты, чтобы получить версию, которую запросил пользователь». [3]

Я просто хотел внедрить систему VCS с этой стратегией. Поэтому я начал экспериментальный хобби-проект под названием vX. Все это всего за 4 дня моей кропотливой работы. 😅

Архитектура

Прежде всего, все связанные файлы находятся в папке .vx. ( Go tool игнорирует любые каталоги или файлы, имена которых начинаются с «_» или «.»)

-2

v1, v2, .., vN — версии фиксации.

checkout — папка, содержащая результат слияния всех файлов с указанной версией коммита. Например, checkout/v2 включает в себя комбинацию commit/v1 + commit/v2.

Разумно создать каталог проверки, потому что «хорошая практика в мире UNIX заключается в развертывании каждой версии приложения в новом каталоге и наличии ссылки, указывающей на текущую версию ». В настоящее время я не реализовал это поведение.

Промежуточная область — это файлы, которые станут частью следующего коммита. В этом контексте это обычный текстовый файл с режимом только добавления. Потому что мы делаем обновления после редактирования файла. Например, часть содержимого этого файла отформатирована как путь к файлу | время модификации файла | Статус файла

-3

Например, README.md — это своего рода файл, который создается с разным временем модификации и статусами перед операцией фиксации. Таким образом, последнее состояние этого файла — «Обновлено 14.04.2022 05:49:09».

status — это текстовый файл, который постоянно отслеживает все файлы. Я очищаю содержимое промежуточной области после успешного изменения файла. Поэтому мне нужно постоянно хранить файлы в системе контроля версий.

Структура проекта

Я следовал структуре проекта, рекомендованной для любого приложения на базе Cobra.

Я использовал каталог testdata.

В настоящее время я не знаю, как обнаружить удаленные файлы, поэтому я просто отслеживаю созданные и измененные файлы. Этот статус основан на времени модификации файла, предоставленном файловой системой.

При каждой операции коммита я сохранял файлы в staging area целиком.

Команды

init: создает каталоги и файлы.

status : читает текстовые файлы промежуточной области и анализирует их в соответствующей структуре и использует tablewriter для отображения результатов. Если вы посмотрите внимательно, я создал функции с интерфейсом io.Writer. В модульных тестах я легко передаю bytes.Buffer и Assert. Я рекомендую прочитать эту замечательную статью об интерфейсах в Go.

history: показывает все коммиты. Чтобы реализовать эту функциональность, я сохраняю файл metadata.txt в каждом каталоге В этом каталоге я храню сообщения коммитов и время, разделенные символом |.

-4

add: добавляет указанные файлы и каталоги в status.txt и staging-area.txt. Как упоминалось ранее, чтобы показать обновленный статус для некоторых файлов, я сохраняю последнее состояние файлов status.txt, поэтому каждый раз я записываю новые данные. staging-area.txt — это данные только для добавления, поэтому нет необходимости выполнять какие-либо операции, просто добавляем новые данные. Дублирование данных не проблема. После успешной фиксации я вычисляю последнее состояние.

commit : читает файл staging-area.txt, копирует его в определенный каталог (v1, v2) и после завершения операции запись осуществляется в staging-area.txt.

Например, предположим, что в коммите v1 добавлен пользователем файл README.md testdata/, а в коммите v2 добавлен пользователем Makefile. Итак, папки коммитов будут выглядеть так

-5

checkout : rsync из каталога commit/ в каталог checkout/ с определенным идентификатором. rsync также объединяет для нас два одинаковых файла.

Весь код:

https://github.com/Abdulsametileri/vX

Golang
Go tests