Личный опыт разработки ПО

Сборник рецептов

Как хранить проекты в хранилище кода?

1 комментарий

Проект состоит как из своего кода, так и из библиотек сторонних разработчиков. Естественно возникает вопрос как хранить это добро. На этот вопрос я попытаюсь дать рекомендации на основании собственного опыта.

Основные требования:

  • Разработчик должен быстро приступить к работе не забивая голову установкой десятка библиотек.
  • Библиотеки должны быть доступны из разных проектов, при этом необходимо избежать дублирования кода в репозиториях.
  • Должна быть возможность сохранять определенные состояния проекта: новые версии, номерные сборки для тестеров и т.д.

Перед прочтением настоятельно рекомендую ознакомиться с предыдущей заметкой.

Я рекомендую под каждый проект создавать свой репозиторий. Это позволит четко отделить один проект от другого, при необходимости дать права на редактирование конкретных репозиториев только определенным разработчикам, решить вопрос с архивированием. Библиотеки, даже сторонние, следует рассматривать как отдельные проекты и также хранить в отдельных репозиториях. Исключение может быть сделано только для особо крупных библиотек, например Qt или Boost.

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

Папки trunk, tags, branches

Часто в Subversion используют структуру проекта из трех папок: trunk, tags и branches. Для чего они?

  • trunk — это папка для разработки. В ней всегда находится самая свежая версия кода, доступная для разработчиков. Здесь крайне важно всегда поддерживать код в собирабельном состоянии. Любая поломка сборки проекта должна исправляться как можно быстрее, чтобы не создавать сложностей остальным разработчикам.
  • В tags находятся состояния проекта на определенный момент. Например ближе к релизу, разработчики начинают создавать с определенной периодичностью сборки с уникальным номером которые передаются тестерам. Состояние проекта на этот момент можно зафиксировать в папке tag, присвоив ему говорящее название, например build_723. Это позволит в случае внесения дефекта отсутствующего в данной сборке и обнаруженного в следующей сборке, проанализировать причину проблемы и принять соответствующие меры к ее устранению.Также здесь можно отмечать выпущенные версии, например 1.0.5. Таким образом, получив от пользователей жалобу на ошибку в какой-либо версии, можно взять код актуальный для данной версии, для изучения проблемы.
  • branches— временные ветки разработчиков. Что это значит? Разработчик Вася получает задание на добавление некоторой функциональности. Для того чтобы не блокировать работу других членов команды, он создает копию проекта в branches/vasia_task_1234, работает в этой ветке периодически сохраняя код с репозиторий. Выполнив задачу, он проводит слияние с основной веткой разработки (trunk) и удаляет временную ветку. Задача выполнена, при этом он мог фиксировать состояние своей работы во временной ветке, не нарушая работы остальных разработчиков.

Работа с ветками и фиксация состояния проекта в tags будет описана в другой заметке.

Как именовать версии?

Я предлагаю способ нумерации версий состоящий из трех цифр — major.minor.micro, где:

major — цифра обозначающая версию продукта (разные номера версий обозначают существенные отличия между продуктами),
minor — подверсия продукта (разные номера говорят о том, что подверсии обладают разным функционалом),
micro — в рамках подверсии указывает на то, что были исправлены какие либо ошибки.

  1. При выпуске новой версии содержащей только исправления ошибок увеличивается цифра в позиции micro.
  2. При выпуске версии с изменившимся функционалом инкрементируется minor и обнуляется micro.
  3. При выпуске новой версии продукта существенно отличающегося от предыдущего, увеличивается major, а minor и micro обнуляются.

Пример проекта

Рассмотрим простой проект состоящий собственно из кода проекта (project) и двух библиотек (lib1, lib2). Структура из трех репозиториев:

project (Для примера пусть путь к репозиторию будет https://server/project)

branches
tags
trunk

lib1 (https://server/lib1)

branches
tags

1.0
1.5

trunk

lib2 (https://server/lib2)

branches
tags
trunk

Собственно project — это наш проект, который зависит от сторонней библиотеки lib1 версии 1.0 и от библиотеки собственной разработки lib2, которая разрабатывается совместно с самим проектом, поэтому зависимость будет от ее основной ветки разработки (trunk).

Устанавливаем зависимости в Subversion

Для того, чтобы установить зависимости проекта в Subversion используется свойство svn:externals. Для просмотра установленных свойств нужно перейти в папку с проектом (например trunk) и воспользоваться командой

svn proplist .

Обратите внимание на . — это говорит о том, что надо показать свойства установленные для папки (некоторые свойства можно установить только для конкретных файлов).

Для редактирования и добавления свойств существует команда

svn propedit свойство папка_или_файл

Для установки свойства svn:externals (естественно для всей папки) находясь в папке с основной веткой разработки (путь_на_локальной_машине/project/trunk) выполните

svn propedit svn:externals .

После этого Subversion вызовет текстовой редактор где вам надо будет прописать/отредактировать свойства. После сохранения изменений и выхода из редактора, параметры свойства будут изменены. Если изменения не сохранять, свойство изменено не будет. После этого изменения надо закомитить.

В текстовом редакторе свойство svn:externals выглядит как одна или более строк содержащих имя директории для проекта от которого зависит проект и путь к этому проекту (можно указывать разные папки и ревизии). В нашем случае свойство выглядит следующим образом:

lib1 https://server/lib1/tags/1.0
lib2 https://server/lib2/trunk

Возможно, что Subversion не вызовет текстовой редактор, а выдаст ошибку в которой сообщит, что не определена переменная окружения SVN_EDITOR. Это значит, что надо добавить в системное окружение данную переменную, указав путь к текстовому редактору, который будет вызван. Например C:/WINDOWS/system32/notepad.exe для Windows (обратите внимание — слеши надо разворачивать) или /usr/bin/vi для Linux.

Удалить свойство можно командой

svn propdel svn:externals

И все?

Похоже на то. Теперь каждый раз забирая код project из репозитория будет одновременно подгружаться код библиотек. Если в библиотеках были сделаны изменения, то они автоматически обновятся. Таким образом прописав зависимости проекта можно не думать о библиотеках, они будут обновлены и скачаны автоматически, основная ветка разработки будет содержать папки lib1 и lib2 с библиотеками.

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

Один комментарий к 'Как хранить проекты в хранилище кода?'

Подписаться на комментарии по RSS или TrackBack.

  1. Информация, актуальная на любой момент времени:

    ветки trunk, … придумали люди для наглядности и они вовсе не обязательны для получения нужных версий ПО, тем более посредством сервера CI. Есть номер ревизии и комментарий — этого достаточно ( так, можно разбирать комментарии на предмет выявления оговоренных соглашений, если очень нужно ).

    Информация, актуальная на данный момент времени:

    Вместо branch лучше использовать Git и локальные репозитории.

    Iakov Minochkin

    30 марта 11 19:42

Оставить комментарий