MINDON.NET

CVS: курс молодого бойца

маленьким и глЮпым посвящается…

Вместо вступления

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

Настройка своего рабочего уголка

Данный раздел рассказывает, как настроить свой рабочий закуток на Unix машине (в нашем случае в качестве оной выступает сервер под руководством FreeBSD). Думаю понятно, что неплохо бы сначала попасть в какой-нибудь shell под своим аккаунтом. Здесь я буду приводить все настройки для tcsh, те у кого bash — сами себе злобные буратины (которые идут читать свой man bash).

Итак сделаем следующие допущения:

  • мы работаем на машине, которая по совместительству держит репозиторий (что делать если репозиторий живет в другом месте обсудим ниже)
  • наш репозиторий живет в каталоге /home/special/cvs
  • наш проект называется aovengine

Для удобства можно установить себе переменную окружения CVSROOT в значение /home/special/cvs — да-да, именно туда где живет наш репозиторий. Сделать это можно либо выполнив:

setenv CVSROOT /home/special/cvs

тогда эта переменная умрет мучительной смертью при logout-е, или же поместив эту строчку в файл ~/.tcshrc, чтобы она, как птица Феникс, смогла возродиться, когда мы в следующий раз зайдем на сервер. Заметим, что эта операция не есть обязательной, но если ее пропустить, то в момент, когда мы будем первый раз вытаскивать проект из репозитория, необходимо будет сразу после команды cvs прописать еще такой аргумент -d /home/special/cvs. Но для всех операций, проводимых уже непосредственно внутри рабочего каталога, указывать путь к CVSROOT не требуется (он берется из технического каталога CVS).

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

cvs checkout aovengine

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

Что делать если репозиторий живет в другом месте?

Этот раздел также кратко рассказывает, как работать с CVS находясь на Windows машине. Однако предполагается, что у вас есть shell аккаунт на машине с репозиторием и локальный доступ к последнему. Вариант использования CVS в режиме pserver я не буду рассматривать, так как никогда им не пользуюсь (по соображениям безопасности).

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

setenv CVS_RSH ssh

Таким образом CVS будет самостоятельно ходить по ssh протоколу на удаленный сервер, логиниться там под вашим аккаунтом и тянуть файлы через созданный таким образом канал. Однако вводить пароль придеться все же вам, так что не обольщайтесь, или же протяните себе ключи (man ssh, ssh-keygen). Впрочем одной лишь установкой переменной CVS_RSH дело не обойдется, так как еще необходимо указать, где именно искать репозиторий. Поможет нам в этом (как вы уже наверное догадались) правильная установка переменной CVSROOT, которая в данном случае должна быть прописана как:

setenv CVSROOT :ext:username@mindon.net:/home/special/cvs

где :ext: есть магическое слово, username — имя того аккаунта, который вам милостливо выдали злобные админы, mindon.net в данном случае это имя сервера, ну и наконец, то, что идет после двоеточия в конце — это локальный путь к репозиторию на удаленной машине (см. выше).

Для пользователей операционной системы «всех времен и народов», а именно MS Windows, также есть возможность иметь человеческие (читай Unix-овые) tools-ы, в частности ssh и cvs. Для чего им необходимо сходить на сайтец www.cygwin.com и установить оттуда цяцю, которую там предлагают. Детальный процесс по ее установке, правда, может потянуть на еще один тугумент подобного рода, поэтому оставляю это в качестве домашнего задания всем заинтересовавшимся. Есть еще вариант, вытащить бинарную версию cvs.exe и ssh.exe для Windows, главное чтобы они корректно понимали Unix- и Windows-концы строк, иначе будет полный бардак с переконвертацией.

Базовые команды

На самом деле для начала работы с CVS достаточно всего лишь двух команд: commit и update. Остальные команды (их можно посмотреть выполнив cvs --help-commands) предназначены для получения различного рода информации о файлах и управления ветками и версиями.

Итак, чтобы синхронизировать файлы в своем рабочем каталоге с репозиторием, что нужно делать регулярно перед началом работы если есть подозрение (и даже если его нет), что кто-то успел выложить какую-нибудь новую версию в репозиторий, а это подозрение обычно появляется с получением соответствующего письма с уведомлением, то мы выполняем следующую команду, находясь в рабочем каталоге (в нашем случае, я напоминаю, этот каталог зовется aovengine):

cvs update

В результате на экран будет вывалено некоторое количество строчек, каждая из которых соответствует одному файлу.

Например, можно увидеть нечто подобное:

cvs server: Updating .
P file1.cpp
P file2.cpp
P file3.cpp
RCS file: /home/special/cvs/aovengine/src/bad.cpp,v
retrieving revision 1.24
retrieving revision 1.30
Merging differences between 1.24 and 1.30 into bad.cpp
rcsmerge: warning: conflicts during merge
cvs server: conflicts found in bad.cpp
C bad.cpp
P file4.cpp
P file5.cpp

В данном примере файлы file*.cpp были успешно обновлены, P означает, что был выслан не файл целиком, а лишь patch. Однако для файла bad.cpp обнаружился конфликт — локальная рабочая копия файла (версия 1.24) оказалась измененной и при синхронизации с файлом в репозитории (версия 1.30) изменения не удалось объединить. Это тот случай, который не должен возникать при нормальной работе (если синхронизация делается регулярно), однако если такое случилось, то паниковать не следует. Последовательность действий по выходу из ситуации может быть следующая — открываем файл и пытаемся исправить конфликт руками. Часть файла, вызывающая конфликт, выделена специальным образом:

<<<<<<< bad.cpp
    if (myvariable == 0)
=======
    if (!myvariable || myvariable < 0);
>>>>>>> 1.30

После того как конфликт исправлен, необходимо удалить все маркеры и закачать новую версию файла в репозиторий (см. ниже). Также необходимо помнить, что при возникновении конфликта оригинальная версия файла в рабочем каталоге сохраняется с именем .#file.revision, в нашем случае это будет: .#bad.cpp.1.24. После того как конфликтная ситуация исправлена эти файлы можно (и нужно) удалить.

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

cvs server: Updating .
U bad.cpp

Где U означает, что файл был успешно обновлен (в отличии от P нам прислали файл целиком).

Кроме букв U, P, C можно еще увидеть ряд других кодов, их значение детально описано в документации A.16.2 update output. Я отмечу лишь, что M означает, что файл изменен локально в рабочем каталоге, и либо в репозитории лежит предыдущая версия файла, либо изменения удалось успешно объединить.

Для сохранения результатов локальных работ в репозитории используется команда:

cvs commit

Эта команда говорит CVS фиксировать все изменения, сделанные в локальной версии проекта, в репозитории. В частности для всех измененных файлов происходит создание новых версий и загрузка их в репозиторий, созданные или удаленные файлы, соответственно, создаются или отмечаются как удаленные в репозитории (заметим что файл не удаляется физически из репозитория, он лишь помещается в специальный каталог Attic, и может быть возвращен в любой момент). При выполнении этой команды серверными скриптами проверяется наличие у вас достаточного количества прав для завершения операции, файлы проверяются на возможность возникновения конфликтов (о последних вам сообщается и операция прерывается). Также дополнительные серверные скрипты проверяют файлы на соответствие установленным, администратором репозитория, стандартам. Если все проверки прошли успешно, то операция будет завершена и сервером будет сформировано письмо-отчет, которое будет послано всей группе разработчиков (эта операция выполняется специальными серверными скриптами, и не является базовой возможностью CVS). Помимо списка измененных файлов этот отчет содержит также журнальное сообщение, которое вас попросят ввести во время выполнения операции commit — будет вызван ваш редактор по умолчанию в котором, в специальном шаблоне, вам будет нужно ввести текст сообщения, по закрытию редактора сообщение будет отослано на сервер. Пожалуйста, потратьте несколько минут на вдумчивое и полное описание того, что (и для чего) было сделано, не нужно «растекаться мыслию по древу», однако крайне желательно дать ясное представление о сделанной работе. Это помогает впоследствии находить ошибки и лучше контролировать процесс разработки.

Обязательно к прочтению

Version Management with CVS by Per Cederqvist, а также смотрии разнообразную документацию.

© 2003, Олег Гродзевич