Система контроля исходного кода

Система контроля исходного кода НЕОБХОДИМА для управления изменениями, возникающими в процессе разработки программного обеспечения. Разработчикам нужна полная история изменений для возможности отката к предыдущим версиям в случае возникновения проблем. Поскольку исходный код -- самый основной компонент любого проекта программного обеспечения и разработчики расходуют огромное количество времени и денег, очень важно потратить некоторое время для сопровождения (safe-guarding) исходного кода посредством использования системы контроля исходного кода, подобно CVS и RCS.

CVS (Concurrent Version Control System) -- мощный инструмент, позволяющий одновременную разработку программы несколькими пользователями. Он основан на RCS и имеет интерфейс уровня приложений в виде внешних функций к RCS.

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

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

Эти каталоги и файлы можно затем объединить вместе и сформировать выпуск программного обеспечения.

CVS используется для хранения файлов C, C++, Java, Perl, HTML и других.

Что мне подходит, CVS или RCS?
CVS реально использует RCS и является намного более мощным инструментом, обладая возможностью контроля полного дерева исходного кода. Очень настоятельно рекомендуется использование CVS, поскольку имеется возможность чрезвычайно гибкой настройки CVS с помощью скриптовых языков вроде PERL, оболочек Korn и Bash. Смотрите пример для оболочки Korn в "Разд. Скрипты оболочки".

Преимущества CVS

CVS децентрализован от редактируемых пользователем файлов/каталогов из репозитория и имеет свое собственное отдельное дерево каталогов исходного кода.
CVS может создавать "штампы" деревьев исходного кода проекта.
CVS может обеспечить одновременное редактирование файлов.
CVS можно очень гибко настроить для обеспечения сильного блокирования файлов или для одновременного редактирования файлов с использованием скриптов оболочки или PERL.

Недостатки CVS

Требует чуть больше администрирования, чем RCS.
Является очень сложной составной системой и является практически произведением искусста ("State of the Art"). Программа CVS -- очень продвинутая и хитроумная система, разрабатываемая в течении длительного периода времени (нескольких лет!).
Обладает большим количеством команд и параметров, делая кривую обучения круче для начинающих. Скрипты оболочки в "Разд. Скрипты оболочки" могут упростить использование.

Преимущества RCS

RCS очень прост в установке, требует меньше административной работы.

RCS используется в централизованной области, в которой работает каждый отдельный разработчик.

RCS полезен для простых систем.

Осуществляет очень сильную блокировку файлов -- одновременное редактирование исключено.

Обратная сторона RCS

Одновременная разработка несколькими разработчиками невозможна из-за блокировки файлов и ограничения единственным рабочим каталогом. Единственность рабочего каталога может стать причиной неудачи команды "make" после изменения файлов несколькими разработчиками.

Не умеет делать общие "штампы" проекта программного обеспечения.

Этот документ содержит скрипты оболочки, предоставляющие простые команды для извлечения, загрузки и фиксации файлов. Скрипты оболочки смотрите в "Разд. Скрипты оболочки".

О RCS смотрите "RCS mini-howto" на компакт-диске Linux:

cd /mnt/cdrom/Redhat/RPMS
ls -l howto-6.0-*.noarch.rpm
rpm -qpl howto-6* | grep -i rcs

или посетите http://www.LinuxDoc.org/HOWTO/mini/RCS.html. Можно также посмотреть скрипты оболочки для RCS в "Разд. RCS Скрипты оболочки".

Установка CVS

Сперва необходимо инсталлировать пакет CVS; на Redhat Linux наберите:

cd /mnt/cdrom/Redhat/RPMS
rpm -i rcs*.rpm
rpm -i cvs*.rpm
Для просмотра списка установленных файлов:
rpm -qpl cvs*.rpm | less

полученный вывод пролистывайте с помощью "j", "k", "CTRL+f", "CTRL+D", "CTRL+B", "CTRL+U" или клавиш со стрелками и "Page Up", "Page Down". Посмотрите "man less". На других разновидностях Unix может понадобиться скачать tar-архивы RCS и CVS, а затем прочесть файлы README и INSTALL для установки CVS. Посетите http://www.cyclic.com и http://www.loria.fr/~molli/cvs-index.html.

Переменные окружения

Необходимо установить следующие переменные окружения в файле /etc/profile; для всех пользователей требуются значения по умолчанию. Если они не установлены в /etc/profile, то следует добавить их в Ваш локальный файл профиля =/.bash_profile.

export EDITOR=/bin/vi
export CVSROOT=/home/cvsroot
export CVSREAD=yes

Создайте каталог для хранения репозитория исходного кода и установите права на чтение/запись для группы/пользователя. Проверьте, чтобы имя каталога CVSROOT не содержало пробелов. Пример недопустимого значения CVSROOT: "/home/my rootcvs".

export CVSROOT=/home/cvsroot
mkdir $CVSROOT
chmod o-rwx $CVSROOT
chmod ug+rwx $CVSROOT

Теперь установите группу для $CVSROOT в значение группы пользователей, желающих использовать систему CVS. chgrp users $CVSROOT

Для инициализации CVS и размещения файлов исходного кода: cvs init

# Смена каталога обязательна
cd $HOME/my_source_code_dir

# Необходимо указать поставщика (напр., V1_0) и редакцию (напр., R1_0)
cvs import my_source_code_dir V1_0 R1_0 

Миграция от RCS к CVS

Для переноса файлов из RCS в CVS воспользуйтесь следующим скриптом. Проверьте, установлен ли у Вас пакет оболочки Korn pdksh*.rpm с компакт-диска Linux.

ВНИМАНИЕ: оболочка Korn /bin/ksh устанавливается инсталляцией pdksh*.rpm с компакт-диска дистрибутива Linux

#!/bin/ksh

#############################################################
# Программа для переноса существующего в RCS исходного кода
# в CVS
#
# Нуждается в RPM-пакете pdksh*.rpm оболочки Korn c компакт-
# диска Linux
#############################################################

#
# rcs2cvs - преобразование дерева исходного кода из RCS в CVS
#

# проект для преобразования
PROJECT='project'

# текущий корень RCS
RCSROOT="$HOME/rcs"

if cd "$RCSROOT/$PROJECT"
then
cd "$RCSROOT"
else
echo >&2 "`basename "$0"`: не могу перейти в каталог RCS '$RCSROOT/$PROJECT'."
exit 1
fi

# текущий корень CVS
CVSROOT="$HOME/cvs"

# создание нового каталога CVS для проекта "project"
if mkdir "$CVSROOT/$PROJECT"
then
:
else
echo >&2 "`basename "$0"`: не могу создать CVS-каталог '$CVSROOT/$PROJECT'."
exit 2
fi

# создание дерева CVS-проекта из дерева RCS
find "$PROJECT" -type d -name RCS -print |
while read RCS
do
CVS="`dirname "$RCS"`"
(if cd "$RCS"
then
#                             if find . -type f -name '*,v' -print | cpio -pdmv "$CVSROOT/$CVS"
if find . -type f -print | cpio -pdmv "$CVSROOT/$CVS"
then
:
else
echo >&2 "`basename "$0"`: не могу преобразовать RCS-подкаталог '$RCSROOT/$RCS' в CVS-подкаталог '$CVSROOT/$CVS'."
fi
else
echo >&2 "`basename "$0"`: не могу перейти в RCS-подкаталог '$RCSROOT/$RCS'."
fi)
done

Теперь RCS перенесен в CVS под именем "project". Вы можете начать использование команд CVS применительно к модулю "project".

Введение в команды CVS

CVS предоставляет широкий диапазон команд (cvs_command in the Synopsis), каждая из которых, как правило, имеет богатый набор опций, призванные удовлетворить многие потребности управления исходным кодом в распределенных окружениях. Однако, Вы не обязаны овладеть каждой деталью чтобы делать полезную работу с помощью CVS; на самом деле, достаточно пяти команд для использования репозитория исходного кода. Команды CVS, используемые чаще всего: checkout, update, add, remove, commit и diff.

checkout

cvs checkout модули... Необходимая подготовка для выполнения большинства последующей работы CVS: создает Вашу личную копию исходного кода для "модулей" (именнованного набора исходных кодов; здесь можно также использовать путь относительный к местоположению репозитория). Ваша работа с этой копией никак не будет пересекаться с работой других разработчиков. Всегда создается по меньшей мере один уровень подкаталогов. (Для Вашего удобства вывод программы также переведен на русский язык. -- Прим. перев.)

bash$ cvs --help checkout
Вызов:
cvs checkout [-ANPRcflnps] [-r rev | -D дата] [-d dir]
[-j rev1] [-j rev2] [-k kopt] модули...
-A      Сбросить липкие тэги/дату/kopts.
-N      Если задано -d, не укорачивать пути модулей.
-P      Удалять пустые каталоги.
-R      Обрабатывать каталоги рекурсивно.
-c      "cat" базу данных модулей.
-f      Вынудить совпадение редакции, если тэг/дата не найдена.
-l      Только локальный каталог, не рекурсивно.
-n      Не запускать программу модуля (при ее наличии).
-p      Извлечь файлы и отправить на стандартный вывод (избегает липкость).
-s      Подобен -c, но включает статус модуля.
-r rev  Извлечь редакцию или тэг. (включает -P) (липкий)
-D date Извлечь редакцию указанной даты. (включает -P) (липкий)
-d dir  Извлечь в каталог dir вместо каталога с именем модуля.
-k kopt При извлечении использовать опцию RCS kopt -k.
-j rev  Объединить изменения, сделанные между текущей редакцией и rev.
(Задайте глобально опцию --help для получения списка остальных опций справки)

update

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

bash$ cvs --help checkout
Вызов:
cvs checkout [-ANPRcflnps] [-r rev | -D дата] [-d dir]
[-j rev1] [-j rev2] [-k kopt] модули...
-A      Сбросить липкие тэги/дату/kopts.
-N      Если задано -d, не укорачивать пути модулей.
-P      Удалять пустые каталоги.
-R      Обработать каталоги рекурсивно.
-c      "cat" базу данных модулей.
-f      Вынудить совпадение редакции, если тэг/дата не найдена.
-l      Только локальный каталог, не рекурсивно.
-n      Не запускать программу модуля (при ее наличии).
-p      Извлечь файлы и отправить на стандартный вывод (избегает липкость).
-s      Подобен -c, но включает статус модуля.
-r rev  Извлечь редакцию или тэг. (включает -P) (липкий)
-D date Извлечь редакцию указанной даты. (включает -P) (липкий)
-d dir  Извлечь в каталог dir вместо каталога с именем модуля.
-k kopt При извлечении использовать опцию RCS kopt -k.
-j rev  Объединить изменения, сделанные между текущей редакцией и rev.
(Задайте глобально опцию --help для получения списка остальных опций справки)

bash$ cvs --help update
Вызов: cvs update [-APdflRp] [-k kopt] [-r rev|-D дата] [-j rev]
[-I ign] [-W spec] [файлы...]
-A      Сбросить липкие тэги/дату/kopts.
-P      Удалять пустые каталоги.
-d      Создавать каталоги, как делает checkout.
-f      Вынудить совпадение редакции, если тэг/дата не найдена.
-l      Только локальный каталог, не рекурсивно.
-R      Обработать каталоги рекурсивно.
-p      Отправить обновления на стандартный вывод (избегает липкость).
-k kopt При извлечении использовать опцию RCS kopt -k.
-r rev  Обновить используя указанную редакцию/тэг. (липкий)
-D date Указать дату с которой извлечь обновления. (липкий)
-j rev  Объединить изменения, сделанные между текущей редакцией и rev.
-I ign  Больше файлов для игнорирования (! для сброса).
-W spec Строка задания оберток.
(Задайте глобально опцию --help для получения списка остальных опций справки)

add

cvs add файл... Воспользуйтесь этой командой для внесения новых файлов в CVS-записи Вашего рабочего каталога. Файлы будут добавлены в репозиторий в следующий раз, как Вы запустите "cvs commit". Заметьте, что для занесения новых исходных кодов в репозиторий следует использовать команду "cvs import". "cvs add" используется только для файлов, новых для уже извлеченного (checked-out) модуля.

bash$ cvs --help add
Вызов: cvs add [-k rcs-kflag] [-m сообщение] файлы...
-k      Использовать "rcs-kflag" для добавления файла с указанным kflag.
-m      Использовать "сообщение" для лога о создании.
(Задайте глобально опцию --help для получения списка остальных опций справки)

remove

cvs remove файл... Эта команда (после удаления перечисленных файлов) предназначена для заявления желания уничтожить файлы из репозитария. Для остальных разработчиков удаление возымеет действие после выполнения "cvs commit".

bash$ cvs --help remove
Вызов: cvs remove [-flR] [файлы...]
-f      Удалить файл перед его исключением.
-l      Обработать только этот каталог (не рекурсивно).
-R      Обработать каталоги рекурсивно.
(Задайте глобально опцию --help для получения списка остальных опций справки)

commit

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

bash$ cvs --help commit
Вызов: cvs commit [-nRlf] [-m msg | -F logfile] [-r rev] файлы...
-n      Не запускать программу модуля (при ее наличии).
-R      Обработать каталоги рекурсивно.
-l      Только локальный каталог (не рекурсивно).
-f      Вынудить фиксацию файла; отключает рекурсию.
-F file Читать лог-сообщения из файла.
-m msg  Лог-сообщение.
-r rev  Фиксировать в этой ветке или этом стволе редакции.
(Задайте глобально опцию --help для получения списка остальных опций справки)
diff

cvs diff файл... Показывает различия между файлами в рабочем каталоге и репозитории исходных кодов. (Не изменяет ни репозиторий ни рабочий каталог.)

bash$ cvs --help diff
Usage: cvs diff [-lNR] [rcsdiff-options]
[[-r rev1 | -D date1] [-r rev2 | -D date2]] [файлы...]
-l      Только локальный каталог, не рекурсивно.
-R      Обработать каталоги рекурсивно.
-D d1   Редакция различий между указанной датой и рабочим файлом.
-D d2   Различия между rev1/date1 и date2.
-N      Включить различия между добавленными и исключенными файлами.
-r rev1 Редакция различий между rev1 и рабочим файлом.
-r rev2 Различия между rev1/date1 и rev2.
--ifdef=arg     Вывести различия в формате ifdef.
(обратитесь к документации Вашей программы diff насчет rcsdiff-options.
Самым популярным является -c для получения различий с контекстом, но
существует много других опций).
(Задайте глобально опцию --help для получения списка остальных опций справки)

Редактор Emacs

Emacs -- мощный редактор и поддерживает CVS/RCS, особенно для объединения редакций и поиска различий. Основной сайт Emacs расположен здесь: http://www.emacs.org.

Скрипты оболочки

Ниже приведены внешние скрипты к базовым командам CVS. Они написаны для оболочки Korn, поскольку он всегда доступен на всех разновидностях Unix, но, в случае необходимости, Вы можете перевести их на Bash или PERL. Вы можете настроить скрипты на свой вкус. В основном они представляют собой команды CVS с деталями, добавленными для обеспечения нужд конкретной машины. Например, скрипт sedit осуществляет блокировку, давая пользователям знать, что кто-то уже редактирует файл. Безусловно, пользователи могут использовать непосредственно команды CVS, в обход этих скриптов. Эти скрипты лишь демонстрируют как в большой степени можно настроить CVS.

Заметьте: Скрипты оболочки принимают домашний каталог пользователя как корневой и извлекают дерево CVS внутрь него.

К сведению: В скриптах оболочки каждое целевое имя файла состоит из трех частей -- домашнего каталога, подкаталога и имени файла. Полный путь: $HOME/$subdir/$fname. В CVS сохраняется эта же структура каталогов (с помощью переменной $subdir), поэтому в CVS будет что-то вроде $CVSROOT/$subdir/$fname. Во всех стриптах эти четыре переменные -- $HOME, $CVSROOT, $subdir и $fname играют важную роль. Примерами их значений могут быть: HOME=/home/aldev, subdir=myproject/src, CVSROOT=/home/cvsroot и fname=foo.cpp.

Скопируйте скрипты оболочки в /usr/local/bin, который должен быть среди значений переменной окружения PATH пользователя.

sget [-r номер_редакции] <файл/каталог> Для получения файла или целого каталога из CVS в режиме только для чтения. Скрипт Разд. sget.

sedit [-r номер_редакции] <файл> Для редактирования файла с целью внесения изменений в код. Блокирует файл, так что никто не сможет его извлечь. Конечно, Вы можете изменить скрипт по своему усмотрению -- убрать блокировку, предупредительные сообщения или сильную блокировку. Скрипт Разд. sedit.

scommit [-r номер_редакции] <файл> Для фиксации Ваших изменений файла или целого каталога. Загружает Ваши изменения в CVS. Скрипт Разд. scommit.

supdate <файл/каталог> Для обновления файла или целого каталога, получением новейших файлов из CVS. Скрипт Разд. supdate.

sunlock [-r номер_редакции] <файл> Для разблокирования файла, полученного с помощью sedit. Убирает блокировку. Скрипт Разд. sunlock.

slist Для просмотра списка файлов, редактируемых Вами в настоящий момент. Выполняет команду "ls -l | grep | ...". Скрипт Разд. slist. Заметим, что есть еще другая команда Unix с именем slist (список доступных серверов Netware), следует убедиться, что CVS-скрипт slist встречается раньше другого в переменной окружения PATH.

sinfo <файл/каталог> Для получения информации об изменениях/редакциях файла. Скрипт Разд. sinfo.

slog <файл> Для получения от CVS истории изменений/редакций файла. Скрипт Разд. slog.

sdif <файл>

sdif -r ред1 -r ред2 <файл> Для получения отличий Вашего файла от CVS. Скрипт Разд. sdif.

Заметьте, что в sdif одна "f", потому что есть другая Unix-команда "sdiff".

sadd <файл> Для добавления нового файла в репозиторий CVS. Скрипт Разд. sadd.

sdelete <файл> Для удаления файла из репозитория CVS. Скрипт Разд. sdelete.

sfreeze <редакция> <каталог> Для замораживания кода, то есть выпуска редакции всего дерева исходного кода. Скрипт Разд. sfreeze.

Например:

                cd $HOME;  
sfreeze REVISION_1_0  srctree 

Это замораживает код с меткой "REVISION_1_0", так что позже Вы можете извлечь целое дерево с помощью имени редакции.

Документация по CVS

По приглашению Unix напечатайте:
cvs --help
cvs --help-options
cvs --help-commands
cvs -H checkout
cvs -H commit
man cvs
man tkcvs
info cvs (-- перев.)
Посетите http://www.cyclic.com
Посетите http://www.loria.fr/~molli/cvs-index.html
Посетите http://linux.ru.net/index.php?module=library&action=show&docid=33&part=586 ("CVS -- система управления параллельными версиями" в пер. Алексея Махоткина. -- Прим. перев.)
Tkcvs http://www.tkcvs.org -- Tcl/Tk GUI интерфейс к CVS. Имеется также интерактивная справка.
cd $HOME/src/foo.cpp
tkcvs
Щелкните на "foo.cpp"
Щелкните на "Revision Log Icon", расположенном рядом с изображением "очки".
В окне появится ветка дерева. Теперь щелкните ПРАВОЙ кнопкой мыши на надписи "1.3" и ЛЕВОЙ кнопкой мыши на "1.1". Затем нажмите кнопку "Diff". Появится двухпанельное окно.
Щелкните на кнопке "Next" для просмотра различий. Нажмите "Center" чтобы отцентрировать текст.
Существует также CVS-клиент для Windows 95, он называется WinCVS http://www.wincvs.org. WinCVS можно использовать совместно с Samba -- http://www.samba.org.
Основные команды:
cvs checkout <файл>
cvs update <файл>
cvs add <файл, ..>
cvs remove <файл, ..>
cvs commit <файл>
cvs status <файл>
cvs log <файл>
cvs diff -r1.4 -r1.5 <файл> Дает различия между версиями 1.4 и 1.5 файла.

Системная документация

На Linux-системах Вы можете найти CVS-документацию в формате Postscript по пути /usr/doc/cvs*/*.ps. Имеется также FAQ и другая полезная информация.
bash# cd /usr/doc/cvs*
bash# gv cvs.ps
RCS Скрипты оболочки
Если Вы хотите использовать RCS вместо CVS, то могут пригодиться следующие скрипты оболочки.
cotree.sh
#!/bin/ksh
# cotree.sh (Скрипт оболочки для извлечения дерева каталогов)
# cotree.sh - Извлечение целого RCS-каталога
# Вызов:
# Для получения всех каталогов:
#             unix> cotree.sh
#
# Для получения дерева единственного каталога:
#unix> cotree.sh <имя каталога>
# Смотрите также cofiles.sh

###############################################################
# Установка RCS (Revision Control System)
# Инсталлируйте программы RCS -- появятся команды co, ci, rcslog
# Создайте домашний каталог RCS, куда Вы поместите репозиторий
# исходного кода. Выполните $RCSDIR=/home/rcs_version_control
# Задайте переменную окружения RCSDIR=/home/rcs_version_control
# в файле $HOME/.profile. Так:
#                             export RCSDIR=/home/rcs_version_control
# Создайте структуру каталогов в $RCSDIR и занесите туда все
# ваши файлы с помощью ci. Смотрите "man ci"
# Теперь создайте связь из Вашего домашнего каталога со своим
# проектом в $RCSDIR
#                             cd $HOME
#                             mkdir $HOME/myproject
#                             cd $HOME/myproject
# и запустите следующий скрипт чтобы получить все файлы и дерево
# каталогов:
#                             cotree.sh
# Данный скрипт создаст целое дерево исходного кода в домашнем
# каталоге пользователя и будет иметь мягкую ссылку на каталоги
# RCS. Каждый пользователь запустит этот скрипт в своем домашнем
# каталоге.
###############################################################

check_out_directory()
{
# Корневой каталог RCS (Revision Control System)
# подобно RCSDIR=/home/rcs_version_control
RCSDIR=$1
DIRNAME=$2

                # Заданный каталог должен существовать в корневом каталоге RCS
if [ "$DIRNAME" = "" -o  ! -d $RCSDIR/$DIRNAME ]; then
print "\nКаталог DIRNAME=$DIRNAME не существует!!"
print "\nЗавершение программы... и выход...\n"
exit
fi

mkdir -p $DIRNAME
ln -s $RCSDIR/$DIRNAME/RCS $DIRNAME
(
cd $DIRNAME

                               # Неудача, если имя_файла=sample,vv что в RCS
# будет RCS/sample,vv,v
# ls RCS | cut -d',' -f1 | xargs co
# Используем сопоставление с концом имени $, как ниже
# Используем ls RCS/* во избежание прибавления к
# именам ./ и ../
#ls RCS/* | cut -d'/' -f2 | sed -e's/,v$//g' | xargs co
if [ -d RCS ]; then
ls RCS/* | cut -d'/' -f2 | sed -e's/,v$//g' | \
while read ii
do
#echo "ii is : $ii"
if [ -f "RCS/$ii,v" ]; then
co $ii
fi
done
fi
)
}

# Корневой каталог RCS (Revision Control System)
# подобно RCSDIR=/home/rcs_version_control
if [ "$RCSDIR" = "" -o ! -d $RCSDIR ]; then
print "\nКаталог RCSDIR=$RCSDIR не существует!!"
print "\nЗавершение программы... и выход...\n"
exit
fi
#echo "rcsdir is : $RCSDIR"

# Если передан аргумент-каталог, то извлекаем все файлы
# только для этого каталога и выходим.
if [ "$1" != "" ]; then
(cd $RCSDIR; find $1 -type d -print ) |
while read DIRNAME
do
#echo DIRNAME=$DIRNAME
#DIRNAME=c_src
# Передай корневой каталог RCS и имя каталога относительно
# корневого каталога RCS
tmpaa=` basename $DIRNAME `
if [ "$tmpaa" != "RCS" ]; then
check_out_directory $RCSDIR $DIRNAME
fi
done
else
(cd $RCSDIR; find * -type d -print ) |
while read DIRNAME
do
echo DIRNAME=$DIRNAME
#DIRNAME=c_src
# Передай корневой каталог RCS и имя каталога относительно
# корневового каталога RCS
tmpaa=` basename $DIRNAME `
if [ "$tmpaa" != "RCS" ]; then
check_out_directory $RCSDIR $DIRNAME
fi
done
fi
cofiles.sh
#!/bin/ksh
# cofiles.sh (Скрипт оболочки для извлечения файлов)
# cofiles.sh - Извлечь все файлы из RCS в текущий каталог
# Смотрите также cotree.sh и "man rcsclean"
if [ ! -d RCS ]; then
print "\nКаталог RCS не существует!!"
print "\nЗавершение программы... и выход...\n"
exit
fi
#echo "No. of args = " $# " and all args " $@

while true
do
print -n "\n\nИзвлечь все файлы в режиме чтения-записи? <y/n> [n]: "
read ans
if [ "$ans" = "" -o "$ans" = "n" -o "$ans" = "N" ]; then
ans="N"
break
elif [ "$ans" = "y" -o "$ans" = "Y" ]; then
ans="Y"
break
else
print "\nОшибочный ввод! Попробуйте снова!!"
fi
done
#echo "The ans is : " $ans

if [ $# -eq 0 ]; then
# "ls RCS" терпит неудачу в случае имя_файла=sample,vv в RCS/sample,vv,v
# ls RCS | cut -d',' -f1 | xargs co
# Используем сопоставление с концом имени $, как ниже
if [ "$ans" = "Y" ]; then
ls RCS | sed -e's/,v$//g' | xargs co -l
else
ls RCS | sed -e's/,v$//g' | xargs co
fi
elif [ $# -eq 1 ]; then
if [ -f "RCS/$1,v" ]; then
# Здесь, в этом случае $1 будет подобен dbalter.sql,
# а не db*.sql...
#echo "One arg, no. of args = " $# " and all args " $@
if [ "$ans" = "Y" ]; then
co -l "$1"
else
co "$1"
fi
else
# Для случая, когда $1=db*.sql и нет db*.sql в
# текущем каталоге
#echo "No files... no. of args = " $# " and all args " $@
tmpaa="RCS/$1,v"  # будет вроде RCS/db*.sql,v
ls $tmpaa | \
while read ii
do
#echo "ii is : $ii"
if [ "$ans" = "Y" ]; then
co -l "$ii"
else
co "$ii"
fi
done
fi
else
for ii in $@
do
#echo "ii is : $ii,v"
if [ "$ans" = "Y" ]; then
co -l "$ii"
else
co "$ii"
fi
done
fi
ciall.sh
#!/bin/ksh
# ciall.sh (Скрипт оболочки для фиксации файлов)
# ciall.sh - Загрузка всех файлов текущего каталога в RCS
# Данный скрипт очень полезен для загрузки огромного количества
# новых файлов в RCS. Экономит время, избегая необходимости
# набора "описания" для каждого файла
# Для файлов уже в RCS, выполняет обычную команду check-in

# Чтобы преобразовать имена файлов в нижний регистр,
# воспользуйтесь следующей техникой; используйте "tr",
# смотрите "man tr"
#ls * | \
#while read ii
#do
#             jj=`echo $ii | tr [A-Z] [a-z] `
#             echo "ii is : $ii"
#             echo "jj is : $jj"
#             mv $ii $jj
#done
if [ ! -d RCS ]; then
print "\nКаталог RCS не существует!!"
print "\nСоздаю каталог RCS...\n"
mkdir RCS
fi
print "\n\nВНИМАНИЕ: это не лог-сообщение!"
print "Пожалуйста, введите описание (будет использовано для"
print -n "всех фиксируемых файлов): "
read description

#find * -prune -type f |

# Количество аргументов нулевое или больше....
if  [ $# -eq 0 ]; then
listoffiles="*"
else
listoffiles="$@"
fi

find $listoffiles -prune -type f |
while read ii
do
#echo $ii
if [ -f "RCS/$ii,v" ]; then
#print "The file $ii already in RCS"
ci -m"$description" $ii
else
#print "The file $ii is new file"
ci $ii << EOF
$description
EOF
fi
done

Система сообщений об ошибках

Вместе с CVS Вы можете захотеть использовать "Систему отслеживания проекта" (Project Tracking System) или "Систему сообщений об ошибках" (Problem Reporting System). Каждый проект программного обеспечения нуждается в системе сообщений об ошибках, которая отслеживает ошибки и назначает их разным разработчикам. Посетите сайт http://www.stonekeep.com.

Другие форматы этого документа

Данный документ опубликован в 11 различных форматах: DVI, Postscript, Latex, Adobe Acrobat PDF, LyX, GNU-info, HTML, RTF (Rich Text Format), обычный текст, man-страницы Unix и SGML.

Вы можете получить этот HOWTO-документ как один tar-файл в форматах HTML, DVI, Postscript и SGML с ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO/other-formats/.
В формате обычного текста: ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO.
Переводы на другие языки (французский, немецкий, испанский, китайский, японский) есть на ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. Приветствуется любая Ваша помощь по переводу на другие языки.
Документ написан с использованием инструмента под названием "SGML-Tools", который Вы можете получить с http://www.sgmltools.org. После компиляции исходного кода Вы получите команды подобные следующим:
sgml2html CVS-HOWTO.sgml (для генерации HTML-файла)
sgml2rtf CVS-HOWTO.sgml (для генерации RTF-файла)
sgml2latex CVS-HOWTO.sgml (для генерации Latex-файла)
LaTeX-документы можно преобразовать в PDF-файлы просто созданием Postscript-вывода с помощью sgml2latex (и dvips) и пропуском вывода через Acrobat-команду distill (http://www.adobe.com) как показано ниже:
bash$ man sgml2latex
bash$ sgml2latex filename.sgml
bash$ man dvips
bash$ dvips -o filename.ps filename.dvi
bash$ distill filename.ps
bash$ man ghostscript
bash$ man ps2pdf
bash$ ps2pdf input.ps output.pdf
bash$ acroread output.pdf &
Или можно использовать Ghostscript-команду ps2pdf. ps2pdf почти полностью повторяет функциональность продукта Adobe Acrobat Distiller: он преобразует PostScript-файлы в файлы Portable Document Format (PDF). ps2pdf реализован как очень маленький командный скрипт (пакетный файл), вызывающий Ghostscript и выбирающий специальное "выходное устройство" под именем pdfwrite. Для использования ps2pdf, в make-файл Ghostscript при компиляции необходимо включить устройство "pdfwrite"; чтобы получить более подробную информацию смотрите документацию по компиляции Ghostscript. Этот документ расположен по адресу
http://sunsite.unc.edu/LDP/HOWTO/CVS-HOWTO.html.
На сайте "Russian Linux Documentation Project": http://linux.ru.net/~RLDP (-- перев.).
Его можно найти также на следующих зеркалах:
http://www.caldera.com/LDP/HOWTO/CVS-HOWTO.html
http://www.WGS.com/LDP/HOWTO/CVS-HOWTO.html
http://www.cc.gatech.edu/linux/LDP/HOWTO/CVS-HOWTO.html
http://www.redhat.com/linux-info/ldp/HOWTO/CVS-HOWTO.html

Другие зеркала более близкие к Вам (в смысле сетевого адреса) можно найти на http://sunsite.unc.edu/LDP/hmirrors.html; выберите сайт и зайдите в каталог /LDP/HOWTO/CVS-HOWTO.html.

Файлы формата DVI просматриваются с помощью программы xdvi. Она находится в пакете tetex-xdvi*.rpm на Redhat Linux и может быть доступна через ControlPanel | Applications | Publishing | меню для TeX. Для чтения DVI-документов выполните команду

                xdvi -geometry 80x90 howto.dvi
man xdvi
Затем измените размер окна при помощи мыши. Для навигации используйте клавиши со стрелками, "Page Up", "Page Down", а также клавиши с буквами "f", "d", "u", "c", "l", "r", "p", "n" чтобы сместиться вверх, вниз, к следующей странице, предыдущей странице и т.д. Нажатие "x" убирает экспертное меню. Postscript-файлы можно читать с помощью программы "gv" (ghostview) или "ghostscript". Программа ghostscript содержится в пакете ghostscript*.rpm, а gv -- в gv*.rpm на Redhat Linux; их можно найти в пункте меню ControlPanel | Applications | Graphics. Программа gv более дружественна к пользователю нежели ghostscript. Ghostscript и gv доступны и на других платформах, таких как OS/2, Windows 95 и NT, Вы сможете просмотреть этот документ даже на этих платформах.
Ghostscript для Windows 95, OS/2 и других ОС доступен по адресу http://www.cs.wisc.edu/~ghost.
Чтобы прочесть Postscript-документ наберите команду

                               gv howto.ps
ghostscript howto.ps

Документы в формате HTML можно читать с помощью Netscape Navigator, Microsoft Internet Explorer, Redhat Baron Web или любого из 10 остальных веб-браузеров.

Вывод Latex и LyX можно читать с помощью LyX -- X-Window-надстройки над Latex.
sget

Замечание: оболочка Korn /bin/ksh устанавливается инсталляцией pdksh*.rpm с компакт-диска дистрибутива Linux
Сохраните этот файл как текст и выполните для него "chmod a+rx".
#!/bin/ksh
# CVS-программа sget
# Программа для извлечения файлов из CVS в режиме только для чтения
# Имя каждого файла составляется из 3 частей -- домашнего каталога,
# подкаталога и имени файла. Полный путь -- $HOME/$subdir/$fname
# В CVS сохраняется такая же структура каталогов (с помощью переменной
# $subdir), поэтому в CVS мы будем иметь $CVSROOT/$subdir/$fname
# В данной программе эти 4 переменные $HOME, $CVSROOT, $subdir и $fname
# играют важную роль. Примеры их значений:
# HOME=/home/aldev, subdir=myproject/src CVSROOT=/home/cvsroot
# и fname=foo.cpp
# Предупреждение: заключите значения переменных, содержащих пробелы
# в двойные кавычки: "$HOME/$subdir", если subdir равен "some foo.cpp"

cmdname=`basename $0`

Usage()
{
print "\nВызов: $cmdname [-r номер_редакции/символическое_имя_тэга] <файл/каталог> "
print "Опции -r необязательны "
print "Например: "
print " $cmdname -r 1.1 foo.cpp"
print " $cmdname foo.cpp "
print " $cmdname некий_каталог "
print "Извлечение по символическому тэгу редакции: "
print " $cmdname -r РЕДАКЦИЯ_1 некий_каталог "
print " "
exit
}
# Каманда getopt не будет поддерживаться в следующей версии.
# Вместо нее используем getopts.
while getopts r: ii
do
case $ii in
r) FLAG1=$ii; OARG1="$OPTARG";;
?) Usage; exit 2;;
esac
done
shift ` expr $OPTIND - 1 `
#echo FLAG1 = $FLAG1 , OARG1 = $OARG1
if [ $# -lt 1 ]; then
Usage
fi
bkextn=sget_bak
homedir=` echo $HOME | cut -f1 -d' '  `
if [ "$homedir" = "" ]; then
print "\nОшибка: \$HOME не установлен!!\n"
exit
fi
cur_dir=`pwd`
#echo $cur_dir
len=${#homedir}
len=$(($len + 2))
#echo $len
subdir=` echo $cur_dir | cut -b $len-2000 `
#echo "subdir is : " $subdir
tmpaa=`dirname $1`
if [ "$tmpaa" = "." ]; then
fname=$1
if [ "$subdir" = "" ]; then
subdir=$tmpaa
fi
else
fname=`basename $1`
if [ "$subdir" = "" ]; then
subdir=$tmpaa
else
subdir="$subdir/$tmpaa"
fi
fi
#echo "subdir is : " $subdir
#echo "fname is : " $fname

# Проверка существования файла...
if [ -f "$HOME/$subdir/$fname" ]; then
tmpaa="$HOME/$subdir/$fname"
user_perms=" "
group_perms=" "
other_perms=" "
user_perms=`ls -l $tmpaa | awk '{print $tmpaa }' | cut -b3-3 `
group_perms=`ls -l $tmpaa | awk '{print $tmpaa }' | cut -b6-6 `
other_perms=`ls -l $tmpaa | awk '{print $tmpaa }' | cut -b9-9 `
if [ "$user_perms" = "w" -o "$group_perms" = "w"  \
-o "$other_perms" = "w" ]; then
print "\nОшибка: файл доступен для записи. Завершение $cmdname ......"
print "       Следует либо сделать резервную копию, выполнить scommit"
print "       или удалить файл и запустить $cmdname снова\n"
exit
fi
fi

# Перемещение файла
mkdir -p "$HOME/$subdir"
touch "$HOME/$subdir/$fname" 2>/dev/null
\mv -f "$HOME/$subdir/$fname" "$HOME/$subdir/$fname.$bkextn"

# Создание дочерней оболочки
(
cd $homedir

                # Для очистки всех липких флагов используем опцию -A
if [ "$FLAG1" = "" ]; then
if [ "$subdir" = "." ]; then  # не использовать точку -- это смешает CVS
cvs -r checkout -A $fname
else
cvs -r checkout -A "$subdir/$fname"
fi
else
if [ "$subdir" = "." ]; then  # не использовать точку -- это смешает CVS
cvs -r checkout -A -$FLAG1 $OARG1 $fname
else
cvs -r checkout -A -$FLAG1 $OARG1 "$subdir/$fname"
fi
fi
)
#pwd

if [ -f "$HOME/$subdir/$fname" ]; then
print "\nПолучена копия файла $subdir/$fname только для чтения."
print "$cmdname выполнен."
#print "\nTip (Usage): $cmdname <file/directory name> \n"
fi
sedit

Замечание: оболочка Korn /bin/ksh устанавливается инсталляцией pdksh*.rpm с компакт-диска дистрибутива Linux
Сохраните этот файл как текст и выполните для него "chmod a+rx".
#!/bin/ksh
# CVS-программа sedit
# Программа для извлечения файла из CVS в режиме чтения/записи
# с блокировкой
# Имя каждого файла составляется из 3 частей -- домашнего каталога,
# подкаталога и имени файла. Полный путь -- $HOME/$subdir/$fname
# В CVS сохраняется такая же структура каталогов (с помощью переменной
# $subdir), поэтому в CVS мы будем иметь $CVSROOT/$subdir/$fname
# В данной программе эти 4 переменные $HOME, $CVSROOT, $subdir и $fname
# играют важную роль. Примеры их значений:
# HOME=/home/aldev, subdir=myproject/src CVSROOT=/home/cvsroot
# и fname=foo.cpp

# Предупреждение: заключите значения переменных, содержащих пробелы
# в двойные кавычки: "$HOME/$subdir", если subdir равен "some foo.cpp"

cmdname=`basename $0`

Usage()
{
#       print "\nUsage: $cmdname [-r revision_number] [-F] <filename>"
#       print "The options -r, -F are optional "
#       print "The option -F is FORCE edit even if file is "
#       print "locked by another developer"

        print "\nВызов: $cmdname [-r номер_редакции] <файл>"
print "Опции -r необязательны "

                print "Например: "
print " $cmdname -r 1.1 foo.cpp"
print " $cmdname foo.cpp "
#       print " $cmdname -F foo.cpp "
print " "
}

# Каманда getopt не будет поддерживаться в следующей версии.
# Вместо нее используем getopts.
#while getopts r:F ii
while getopts r: ii
do
case $ii in
r) FLAG1=$ii; OARG1="$OPTARG";;
#       F) FLAG2=$ii; OARG2="$OPTARG";;
?) Usage; exit 2;;
esac
done
shift ` expr $OPTIND - 1 `

#echo FLAG1 = $FLAG1 , OARG1 = $OARG1

if [ $# -lt 1 ]; then
Usage
exit
fi

homedir=` echo $HOME | cut -f1 -d' '  `
if [ "$homedir" = "" ]; then
print "\nОшибка: \$HOME не установлен!!\n"
exit
fi
bkextn=sedit_bak
cur_dir=`pwd`
#echo $cur_dir
len=${#homedir}
len=$(($len + 2))
#echo $len
subdir=` echo $cur_dir | cut -b $len-2000 `
tmpaa=`dirname $1`
if [ "$tmpaa" = "." ]; then
fname=$1
if [ "$subdir" = "" ]; then
subdir=$tmpaa
fi
else
fname=`basename $1`
if [ "$subdir" = "" ]; then
subdir=$tmpaa
else
subdir="$subdir/$tmpaa"
fi
fi
#echo "subdir is : " $subdir
#echo "fname is : " $fname

# Если файл уже извлечен другим разработчиком...
cvs_root=` echo $CVSROOT | cut -f1 -d' '  `
if [ "$cvs_root" = "" ]; then
print "\nОшибка: \$CVSROOT не установлен!!\n"
exit
fi
mkdir -p "$CVSROOT/$subdir/Locks" 2>/dev/null

if [ ! -e "$CVSROOT/$subdir/$fname,v" ]; then
print "\nОшибка: файл $fname не существует в репозитории CVS!!\n"
exit
fi

# Для всех команд требуется каталог CVS в Вашем локальном каталоге...
if [ ! -d  "$homedir/$subdir/CVS" ]; then
tmpaa=` (cd "$CVSROOT/$subdir"; find * -prune -type f -print | head -1 ) `
tmpbb=`basename $tmpaa | cut -d',' -f1 `
if [ "$tmpaa" = "" -o ! -f "$CVSROOT/$subdir/$tmpbb,v" ]; then
print "\nКаталог $homedir/$subdir/CVS не существует"
print "Вы должны выполнить sget в каталоге `basename $subdir`. Наберите"
print "       cd $homedir/`dirname $subdir` "
print "       sget `basename $subdir` "
exit
else
# Теперь попытка создать CVS в локальном каталоге с помощью sget
(
cd "$homedir"
if [ "$subdir" = "." ]; then  # не использовать точку -- это смешает CVS
cvs -r checkout -A $tmpbb
else
cvs -r checkout -A "$subdir/$tmpbb"
fi
)
fi
fi

# Получение старшего номера редакции файла...
# Используем временный файл tmpfile, так как аргумент не может быть задан
# внутри дочерней оболочки
tmpfile=$homedir/sedit-lock.tmp
\rm -f $tmpfile 2>/dev/null
if [ "$FLAG1" = "" ]; then
(
cd $homedir
if [ "$subdir" = "." ]; then  # не использовать точку -- это смешает CVS
cvs log $fname | head -6 | grep head: | awk '{print $2}' > $tmpfile
else
cvs log "$subdir/$fname" | head -6 | grep head: | awk '{print $2}' > $tmpfile
fi
)
OARG1=`cat $tmpfile`
\rm -f $tmpfile 2>/dev/null
fi

lockfile="$CVSROOT/$subdir/Locks/$fname-$OARG1"
#echo "lockfile is : " $lockfile
#if [ -e $lockfile -a "$FLAG2" = "" ]; then
if [ -e $lockfile ]; then
print "\nОшибка: файл $fname версии $OARG1 уже заблокирован другим разработчиком!!"
aa=` ls -l $lockfile | awk '{print "Unix-имя бюджета блокирующего разработчика: " $3}' `
print $aa
print "Этот разработчик должен выполнить scommit или sunlock для разблокировки"
print " "
#       print "Вы можете воспользоваться опцией -F чтобы вынудить редактирование файла даже если"
#       print "файл заблокирован другим разработчиком. Но Вы должны поговорить с"
#       print "остальными разработчиками прежде чем одновременно работать с этим файлом."
#       print "Например, эта возможность полезна, если Вы работаете над отдельной"
#       print "функцией C++ в файле, которая не пересекается с остальными разработчиками."
#       print " "
exit
fi

# Теперь получение копии только для чтения...
if [ ! -e "$HOME/$subdir/$fname" ]; then
(
cd $homedir
if [ "$subdir" = "." ]; then  # не использовать точку -- это смешает CVS
cvs -r checkout $fname 1>/dev/null
else
cvs -r checkout "$subdir/$fname" 1>/dev/null
fi
)
fi

# Проверка существования файла...
tmpaa="$HOME/$subdir/$fname"
if [ -f $tmpaa ]; then
user_perms=" "
group_perms=" "
other_perms=" "
user_perms=`ls -l $tmpaa | awk '{print $tmpaa }' | cut -b3-3 `
group_perms=`ls -l $tmpaa | awk '{print $tmpaa }' | cut -b6-6 `
other_perms=`ls -l $tmpaa | awk '{print $tmpaa }' | cut -b9-9 `
if [ "$user_perms" = "w" -o "$group_perms" = "w"  \
-o "$other_perms" = "w" ]; then
print "\nОшибка: файл доступен для записи. Завершение $cmdname ......"
print "       Следует либо сделать резервную копию, выполнить scommit"
print "       или удалить файл и запустить $cmdname снова\n"
exit
fi
#print "\nNote: The file $tmpaa is read-only."
#print "Hence I am moving it to $tmpaa.$bkextn ....\n"
\mv -f $tmpaa $tmpaa.$bkextn
chmod 444 $tmpaa.$bkextn
elif [ -d $tmpaa ]; then
print "\nОшибка: $tmpaa является каталогом, а НЕ файлом. Завершение $cmdname ....\n"
exit
fi

# Создание дочерней оболочки
print "\nПолучение файла $fname из CVS-репозитория...\n"
(
cd $homedir
# Используем опцию -A для очистки липкого тэга и получения
# номер редакции HEAD
if [ "$FLAG1" = "" ]; then
if [ "$subdir" = "." ]; then  # не использовать точку -- это смешает CVS
cvs -w checkout -A $fname
else
cvs -w checkout -A "$subdir/$fname"
fi
else
if [ "$subdir" = "." ]; then  # не использовать точку -- это смешает CVS
cvs -w checkout -A -$FLAG1 $OARG1 $fname
else
cvs -w checkout -A -$FLAG1 $OARG1 "$subdir/$fname"
fi
fi
)

if [ -e "$HOME/$subdir/$fname" ]; then

# Файл блокировки -- $CVSROOT/$subdir/Locks/$fname-$OARG1
                touch $lockfile
fi

#pwd

print "\n$cmdname выполнен."
#print "\nTip (Usage): $cmdname <filename> \n"

scommit
Замечание: оболочка Korn /bin/ksh устанавливается инсталляцией pdksh*.rpm с компакт-диска дистрибутива Linux

Сохраните этот файл как текст и выполните для него "chmod a+rx".

#!/bin/ksh

# CVS-программа scommit
# Программа для фиксации изменений и загрузки файла в CVS

# Имя каждого файла составляется из 3 частей -- домашнего каталога,
# подкаталога и имени файла. Полный путь -- $HOME/$subdir/$fname
# В CVS сохраняется такая же структура каталогов (с помощью переменной
# $subdir), поэтому в CVS мы будем иметь $CVSROOT/$subdir/$fname
# В данной программе эти 4 переменные $HOME, $CVSROOT, $subdir и $fname
# играют важную роль. Примеры их значений:
# HOME=/home/aldev, subdir=myproject/src CVSROOT=/home/cvsroot
# и fname=foo.cpp

# Предупреждение: заключите значения переменных, содержащих пробелы
# в двойные кавычки: "$HOME/$subdir", если subdir равен "some foo.cpp"

cmdname=`basename $0`

Usage()
{
print "\nВызов: $cmdname [-r номер_редакции] <файл>"
print "Опции -r необязательны "
print "Например: "
print " $cmdname -r 1.1 foo.cpp"
print " $cmdname foo.cpp "
print " "
}

# Каманда getopt не будет поддерживаться в следующей версии.
# Вместо нее используем getopts.
while getopts r: ii
do
case $ii in
r) FLAG1=$ii; OARG1="$OPTARG";;
?) Usage; exit 2;;
esac
done
shift ` expr $OPTIND - 1 `

#echo FLAG1 = $FLAG1 , OARG1 = $OARG1

if [ $# -lt 1 ]; then
Usage
exit 2
fi

if [ -d $1 ]; then
Usage
exit 2
fi

homedir=` echo $HOME | cut -f1 -d' '  `
if [ "$homedir" = "" ]; then
print "\nОшибка: \$HOME не установлен!!\n"
exit
fi

# Определить подкаталог
cur_dir=`pwd`
#echo $cur_dir
len=${#homedir}
len=$(($len + 2))
#echo $len

subdir=` echo $cur_dir | cut -b $len-2000 `
tmpaa=`dirname $1`
if [ "$tmpaa" = "." ]; then
fname=$1
if [ "$subdir" = "" ]; then
subdir=$tmpaa
fi
else
fname=`basename $1`
if [ "$subdir" = "" ]; then
subdir=$tmpaa
else
subdir="$subdir/$tmpaa"
fi
fi
# echo "subdir is : " $subdir
# echo "fname is : " $fname

# Если файл уже извлечен другим разработчиком...
cvs_root=` echo $CVSROOT | cut -f1 -d' '  `
if [ "$cvs_root" = "" ]; then
print "\nОшибка: \$CVSROOT не установлен!!\n"
exit
fi
mkdir -p "$CVSROOT/$subdir/Locks" 2>/dev/null

# Для всех команд требуется каталог CVS в Вашем локальном каталоге...
if [ ! -d  "$homedir/$subdir/CVS" ]; then
tmpaa=` (cd "$CVSROOT/$subdir"; find * -prune -type f -print | head -1 ) `
tmpbb=`basename $tmpaa | cut -d',' -f1 `
if [ "$tmpaa" = "" -o ! -f "$CVSROOT/$subdir/$tmpbb,v" ]; then
print "\nКаталог $homedir/$subdir/CVS не существует"
print "Вы должны выполнить sget в каталоге `basename $subdir`. Наберите"
print "       cd $homedir/`dirname $subdir` "
print "       sget `basename $subdir` "
exit
else
# Теперь попытка создать CVS в локальном каталоге с помощью sget
(
cd "$homedir"
if [ "$subdir" = "." ]; then  # не использовать точку -- это смешает CVS
cvs -r checkout -A $tmpbb
else
cvs -r checkout -A "$subdir/$tmpbb"
fi
)
fi
fi

# Получение рабочего номера версии файла...
# Используем временный файл tmpfile, так как аргумент не может быть задан
# внутри дочерней оболочки
tmpfile=$homedir/sedit-lock.tmp
\rm -f $tmpfile 2>/dev/null
if [ "$FLAG1" = "" ]; then
(
cd $homedir
if [ "$subdir" = "." ]; then  # не использовать точку -- это смешает CVS
cvs status $fname 2>/dev/null | grep "Рабочая версия:" | awk '{print $3}' >$tmpfile
else
cvs status "$subdir/$fname" 2>/dev/null | grep "Рабочая версия:" | awk '{print $3}' >$tmpfile
fi
)
OARG1=`cat $tmpfile`
\rm -f $tmpfile 2>/dev/null
fi

if [ "$OARG1" = "" ]; then
print "Файл $subdir/$fname НОВЫЙ, его нет в CVS-репозитории"
else
lockfile="$CVSROOT/$subdir/Locks/$fname-$OARG1"

                if [ -e $lockfile ]; then
# Проверка владеете ли Вы редакцией...
aa=` ls -l $lockfile | awk '{print $3}' `
userid=`id | cut -d'(' -f2 | cut -d')' -f1 `
if [ "$aa" != "$userid" ]; then
print " "
print "Файл $subdir/$fname заблокирован не Вами!!"
print "А пользователем с именем Unix-бюджета $aa; Ваше имя входа -- $userid"
#                       print "Если Вы работаете одновременно с другим разработчиком"
#                       print "и воспользовались опцией -F команды sedit."
print "Необходимо подождать до выполнения другим разработчиком"
print "команды scommit или sunlock"
print "Завершение $cmdname ...."
print " "
exit 2
fi
else
# Файл должен существовать в CVS
if [ -f "$CVSROOT/$subdir/$fname,v" ]; then
print "Вы не заблокировали файл $subdir/$fname с помощью sedit!!"
print "Завершение $cmdname ...."
exit 2
else
print "\nФайл $subdir/$fname еще не существует CVS-репозитории!!"
print "Следует выполнить sadd для $subdir/$fname ...."
exit 2
fi
fi
fi

# Действуем внутри дочерней оболочки и из корневого каталога
(
cd $homedir

                # Не позволять фиксацию каталогов с этого момента...
#if [ -d "$subdir/$fname" ]; then
#             cvs commit "$subdir/$fname"
#fi

                if [ "$subdir" = "." ]; then  # не использовать точку -- это смешает CVS
cvs commit $fname
else
cvs commit "$subdir/$fname"
fi
exit_status=$?

                if [ $exit_status -eq 0 ]; then
lockfile="$CVSROOT/$subdir/Locks/$fname-$OARG1"
if [ -e $lockfile ]; then
\rm -f $lockfile
fi

                               # В случае отсутствия изменений в файле, нужно
# изменить права доступа к файлу
chmod a-w "$HOME/$subdir/$fname"
print "\n$cmdname удачно выполнен."
#print "\nTip (Usage): $cmdname <filename/directory name>\n"
fi
)

supdate

Замечание: оболочка Korn /bin/ksh устанавливается инсталляцией pdksh*.rpm с компакт-диска дистрибутива Linux

Сохраните этот файл как текст и выполните для него "chmod a+rx".

#!/bin/ksh

# CVS-программа supdate
# Программа для обновления файла из CVS в режиме чтения/записи

# Имя каждого файла составляется из 3 частей -- домашнего каталога,
# подкаталога и имени файла. Полный путь -- $HOME/$subdir/$fname
# В CVS сохраняется такая же структура каталогов (с помощью переменной
# $subdir), поэтому в CVS мы будем иметь $CVSROOT/$subdir/$fname
# В данной программе эти 4 переменные $HOME, $CVSROOT, $subdir и $fname
# играют важную роль. Примеры их значений:
# HOME=/home/aldev, subdir=myproject/src CVSROOT=/home/cvsroot
# и fname=foo.cpp

# Предупреждение: заключите значения переменных, содержащих пробелы
# в двойные кавычки: "$HOME/$subdir", если subdir равен "some foo.cpp"

cmdname=`basename $0`

if [ $# -lt 1 ]; then
print "\nВызов: $cmdname <файл>"
exit
fi

# Двойные кавычки для защиты пробелов в $1
tmpaa="$1"

# Проверка существования файла...
if [ $# -gt 0 -a  -f $tmpaa ]; then
user_perms=" "
group_perms=" "
other_perms=" "
user_perms=`ls -l $tmpaa | awk '{print $tmpaa }' | cut -b3-3 `
group_perms=`ls -l $tmpaa | awk '{print $tmpaa }' | cut -b6-6 `
other_perms=`ls -l $tmpaa | awk '{print $tmpaa }' | cut -b9-9 `
if [ "$user_perms" = "w" -o "$group_perms" = "w"  \
-o "$other_perms" = "w" ]; then
while :
do
print "\n$cmdname сделает резервную копию Вашего рабочего файла "
print "$tmpaa в $tmpaa.supdate_bak перед выполнением слияния."
print "Вы уверены в желании объединения изменений из"
print -n "CVS-репозитория с Вашим рабочим файлом? <y/n> [n]: "
read ans
if [ "$ans" = "y" -o "$ans" = "Y" ]; then
if [ -f $tmpaa.supdate_bak ]; then
print "\nВнимание: файл $tmpaa.supdate_bak уже существует!!"
print "Пожалуйста просмотрите файл $tmpaa.supdate_bak и удалите его,"
print "а затем повторно выполните эту команду $cmdname "
print "Завершение $cmdname ...."
exit
else
cp $tmpaa $tmpaa.supdate_bak
break
fi
elif [ "$ans" = "n" -o "$ans" = "N" -o "$ans" = "" -o "$ans" = " " ]; then
exit
fi
done
fi
fi

if [ -d $tmpaa ]; then
print "\nОбновление каталога недоступно, потому что CVS update"
print "объединяет изменения из репозитория с Вашим рабочим каталогом."
print "Поэтому укажите файл для обновления, как показано ниже: "
print " Вызов: $cmdname <файл>"
exit
#       cvs update
else
cvs update $tmpaa
fi

print "\n$cmdname удачно выполнен."
print "\n\nСделана резервная копия исходного файла как $tmpaa.supdate_bak"
print "\nПоэтому Ваш исходный файл СОХРАНЕН в $tmpaa.supdate_bak"
print "\n\n"
#print "\nTip (Usage): $cmdname <filename/directory name>\n"

sunlock

Замечание: оболочка Korn /bin/ksh устанавливается инсталляцией pdksh*.rpm с компакт-диска дистрибутива Linux

Сохраните этот файл как текст и выполните для него "chmod a+rx".
#!/bin/ksh

# CVS-программа sunlock
# Программа разблокировки файла, заблокированного sedit

# Имя каждого файла составляется из 3 частей -- домашнего каталога,
# подкаталога и имени файла. Полный путь -- $HOME/$subdir/$fname
# В CVS сохраняется такая же структура каталогов (с помощью переменной
# $subdir), поэтому в CVS мы будем иметь $CVSROOT/$subdir/$fname
# В данной программе эти 4 переменные $HOME, $CVSROOT, $subdir и $fname
# играют важную роль. Примеры их значений:
# HOME=/home/aldev, subdir=myproject/src CVSROOT=/home/cvsroot
# и fname=foo.cpp

# Предупреждение: заключите значения переменных, содержащих пробелы
# в двойные кавычки: "$HOME/$subdir", если subdir равен "some foo.cpp"

cmdname=`basename $0`

Usage()
{
print "\nВызов: $cmdname [-r номер_редакции] <файл>"
print "Опции -r необязательны "
print "Например: "
print " $cmdname -r 1.1 foo.cpp"
print " $cmdname foo.cpp "
print " "
}
# Каманда getopt не будет поддерживаться в следующей версии.
# Вместо нее используем getopts.
while getopts r: ii
do
case $ii in
r) FLAG1=$ii; OARG1="$OPTARG";;
?) Usage; exit 2;;
esac
done
shift ` expr $OPTIND - 1 `

if [ $# -lt 1 ]; then
Usage
exit
fi

homedir=` echo $HOME | cut -f1 -d' '  `
if [ "$homedir" = "" ]; then
print "\nОшибка: \$HOME не установлен!!\n"
exit
fi

cur_dir=`pwd`
#echo $cur_dir

len=${#homedir}
len=$(($len + 2))
#echo $len

subdir=` echo $cur_dir | cut -b $len-2000 `
#echo "subdir is : " $subdir
tmpaa=`dirname $1`
if [ "$tmpaa" = "." ]; then
fname=$1
if [ "$subdir" = "" ]; then
subdir=$tmpaa
fi
else
fname=`basename $1`
if [ "$subdir" = "" ]; then
subdir=$tmpaa
else
subdir="$subdir/$tmpaa"
fi
fi
#echo "subdir is : " $subdir
#echo "fname is : " $fname

cvs_root=` echo $CVSROOT | cut -f1 -d' '  `
if [ "$cvs_root" = "" ]; then
print "\nОшибка: \$CVSROOT не установлен!!\n"
exit
fi

if [ ! -e "$CVSROOT/$subdir/$fname,v" ]; then
print "\nОшибка: файл $fname отсутствует в CVS-репозитории!!\n"
exit
fi

# Для всех команд требуется каталог CVS в Вашем локальном каталоге...
if [ ! -d  "$homedir/$subdir/CVS" ]; then
tmpaa=` (cd "$CVSROOT/$subdir"; find * -prune -type f -print | head -1 ) `
tmpbb=`basename $tmpaa | cut -d',' -f1 `
if [ "$tmpaa" = "" -o ! -f "$CVSROOT/$subdir/$tmpbb,v" ]; then
print "\nКаталог $homedir/$subdir/CVS не существует"
print "Вы должны выполнить sget в каталоге `basename $subdir`. Наберите"
print "       cd $homedir/`dirname $subdir` "
print "       sget `basename $subdir` "
exit
else
# Теперь попытка создать CVS в локальном каталоге с помощью sget
(
cd "$homedir"
if [ "$subdir" = "." ]; then  # не использовать точку -- это смешает CVS
cvs -r checkout -A $tmpbb
else
cvs -r checkout -A "$subdir/$tmpbb"
fi
)
fi
fi

# Получение старшего номера редакции файла...
# Используем временный файл tmpfile, так как аргумент не может быть задан
# внутри дочерней оболочки
tmpfile=$homedir/sunlock-lock.tmp
\rm -f $tmpfile 2>/dev/null
if [ "$FLAG1" = "" ]; then
# Действуем внутри дочерней оболочки и из корневого каталога
(
cd $homedir
if [ "$subdir" = "." ]; then  # не использовать точку -- это смешает CVS
cvs log $fname | head -6 | grep head: | awk '{print $2}' > $tmpfile
else
cvs log "$subdir/$fname" | head -6 | grep head: | awk '{print $2}' > $tmpfile
fi
)
OARG1=`cat $tmpfile`
\rm -f $tmpfile 2>/dev/null
fi

lockfile="$CVSROOT/$subdir/Locks/$fname-$OARG1"
#echo lockfile is : $lockfile
if [ ! -e $lockfile ]; then
print "\nФайл $fname редакции $OARG1 НЕ заблокирован никем"
print " "
exit
fi

ans=""
while :
do
print "\n\n***************************************************"
print "ВНИМАНИЕ: $cmdname уберет блокировку и другие разработчики"
print "         смогут редактировать файл. Рекомендуется сохранить"
print "         Ваши изменения командой scommit"
print "***************************************************"
print -n "\nВы действительно хотите разблокировать файл <y/n>? [n]: "
read ans
if [ "$ans" = "" -o "$ans" = " " -o "$ans" = "n" -o "$ans" = "N" ]; then
print "\nЗавершение $cmdname..."
exit
fi
if [ "$ans" = "y" -o "$ans" = "Y" ]; then
print "\n\n\n\n\n "
print "ПРЕДУПРЕЖДЕНИЕ: Вы можете потерять все изменения файла!!"
print -n "Вы уверены? Действительно ли Вы хотите разблокировать файл <y/n>? [n]: "
read ans
if [ "$ans" = "y" -o "$ans" = "Y" ]; then
break
elif [ "$ans" = "" -o "$ans" = " " -o "$ans" = "n" -o "$ans" = "N" ]; then
exit
else
print "\n\nОшибка ввода. Попробуйте снова..."
sleep 1
fi
else
print "\n\nОшибка ввода. Попробуйте снова..."
sleep 1
fi
done

if [ -e $lockfile ]; then
\rm -f $lockfile
print "\n$cmdname выполнен"
else
print "\nФайл $fname больше никем НЕ заблокирован"
print " "
fi
slist

Замечание: оболочка Korn /bin/ksh устанавливается инсталляцией pdksh*.rpm с компакт-диска дистрибутива Linux

Сохраните этот файл как текст и выполните для него "chmod a+rx".

Заметьте, что есть другая Unix-команда с именем slist (список доступных серверов Netware), следует удостовериться, что CVS-скрипт slist встречается раньше другого в Вашей переменной окружения PATH.

#!/bin/ksh

# CVS-программа slist
# Программа перечисления всех отредактированных файлов исходного кода из CVS

# Имя каждого файла составляется из 3 частей -- домашнего каталога,
# подкаталога и имени файла. Полный путь -- $HOME/$subdir/$fname
# В CVS сохраняется такая же структура каталогов (с помощью переменной
# $subdir), поэтому в CVS мы будем иметь $CVSROOT/$subdir/$fname
# В данной программе эти 4 переменные $HOME, $CVSROOT, $subdir и $fname
# играют важную роль. Примеры их значений:
# HOME=/home/aldev, subdir=myproject/src CVSROOT=/home/cvsroot
# и fname=foo.cpp

# Предупреждение: заключите значения переменных, содержащих пробелы
# в двойные кавычки: "$HOME/$subdir", если subdir равен "some foo.cpp"

# Вызов:
#                             $ slist      (Все файлы и подкаталоги)
#                             $ slist *.*      (Все файлы)
#                             $ slist *      (Все файлы и подкаталоги)
#                             $ slist ab*      (Все файлы, начинающиеся на "ab")

homedir=` echo $HOME | cut -f1 -d' '  `
if [ "$homedir" = "" ]; then
print "\nОшибка: \$HOME не установлен!!\n"
exit
fi

cur_dir=`pwd`
#echo $cur_dir

len=${#homedir}
len=$(($len + 2))
#echo $len

subdir=` echo $cur_dir | cut -b $len-2000 `
#echo "subdir is : " $subdir

# Если файл уже извлечен другим разработчиком...
cvs_root=` echo $CVSROOT | cut -f1 -d' '  `
if [ "$cvs_root" = "" ]; then
print "\nОшибка: \$CVSROOT не установлен!!\n"
exit
fi

# Если текущий каталог не находится в корне CVS, то выход
if [ ! -d $CVSROOT/$subdir ]; then
print "\nКаталог $subdir не существует в $CVSROOT"
exit
fi

#echo "no of params : " $#
#echo "The arg $ 1 is : " $1
#echo "all args : " $@

if [ $# -eq 0 ]; then
tmpbb=` find * -prune -type d `
elif [ $# -eq 1 ]; then
if [ "$1" = "." ]; then
tmpbb=` find * -prune -type d `
else
if [ -d $1 -a ! -d $CVSROOT/$subdir/$1 ]; then
print "\nКаталог $subdir/$1 не существует в $CVSROOT"
exit
fi
tmpbb=$@
fi
else
tmpbb=$@
fi

#echo "The tmpbb is : " $tmpbb

# Теперь удалим все имена каталогов, не существующих в корне CVS
dirnames=""
for ii in $tmpbb ; do
if [ -d $CVSROOT/$subdir/$ii ]; then
dirnames="$dirnames $ii "
fi
done
#echo "The dirnames is : " $dirnames

if [ "$dirnames" != "" ]; then
find $dirnames  -type f |
while read ii
do
# Перечислить только те файлы, которые находятся в CVS-системе
if [ -f "$CVSROOT/$subdir/$ii,v" ]; then
#echo "ii is : " $ii
ls -l $ii | grep ^\-rw
fi
done;
fi

# Получить все файлы в текущем каталоге
listfiles=`ls $tmpbb `
find * -prune -type f |
while read ii
do
for jj in $listfiles ; do
if [ "$jj" = "$ii" ]; then
# Перечислить только те файлы, которые находятся в CVS-системе
if [ -f "$CVSROOT/$subdir/$ii,v" ]; then
#echo "ii is : " $ii
ls -l $ii | grep ^\-rw
fi
fi
done
done;
sinfo

Замечание: оболочка Korn /bin/ksh устанавливается инсталляцией pdksh*.rpm с компакт-диска дистрибутива Linux

Сохраните этот файл как текст и выполните для него "chmod a+rx".

#!/bin/ksh

# CVS-программа sinfo
# Программа для получения статуса файлов в рабочем каталоге

# Имя каждого файла составляется из 3 частей -- домашнего каталога,
# подкаталога и имени файла. Полный путь -- $HOME/$subdir/$fname
# В CVS сохраняется такая же структура каталогов (с помощью переменной
# $subdir), поэтому в CVS мы будем иметь $CVSROOT/$subdir/$fname
# В данной программе эти 4 переменные $HOME, $CVSROOT, $subdir и $fname
# играют важную роль. Примеры их значений:
# HOME=/home/aldev, subdir=myproject/src CVSROOT=/home/cvsroot
# и fname=foo.cpp

# Предупреждение: заключите значения переменных, содержащих пробелы
# в двойные кавычки: "$HOME/$subdir", если subdir равен "some foo.cpp"

cmdname=`basename $0`

if [ $# -lt 1 ]; then
print "\nВызов: $cmdname [имя файла/каталога] "
print "Например: "
print " $cmdname foo.cpp"
print " $cmdname some_directory "
print " "
exit
fi

homedir=` echo $HOME | cut -f1 -d' '  `
if [ "$homedir" = "" ]; then
print "\nОшибка: \$HOME не установлен!!\n"
exit
fi

cur_dir=`pwd`
#echo $cur_dir

len=${#homedir}
len=$(($len + 2))
#echo $len

subdir=` echo $cur_dir | cut -b $len-2000 `
#echo "subdir is : " $subdir
tmpaa=`dirname $1`
if [ "$tmpaa" = "." ]; then
fname=$1
if [ "$subdir" = "" ]; then
subdir=$tmpaa
fi
else
fname=`basename $1`
if [ "$subdir" = "" ]; then
subdir=$tmpaa
else
subdir="$subdir/$tmpaa"
fi
fi
#echo "subdir is : " $subdir
#echo "fname is : " $fname

# Для всех команд требуется каталог CVS в Вашем локальном каталоге...
if [ ! -d  "$homedir/$subdir/CVS" ]; then
tmpaa=` (cd "$CVSROOT/$subdir"; find * -prune -type f -print | head -1 ) `
tmpbb=`basename $tmpaa | cut -d',' -f1 `
if [ "$tmpaa" = "" -o ! -f "$CVSROOT/$subdir/$tmpbb,v" ]; then
print "\nКаталог $homedir/$subdir/CVS не существует"
print "Вы должны выполнить sget в каталоге `basename $subdir`. Наберите"
print "       cd $homedir/`dirname $subdir` "
print "       sget `basename $subdir` "
exit
else
# Теперь попытка создать CVS в локальном каталоге с помощью sget
(
cd "$homedir"
if [ "$subdir" = "." ]; then  # не использовать точку -- это смешает CVS
cvs -r checkout -A $tmpbb
else
cvs -r checkout -A "$subdir/$tmpbb"
fi
)
fi
fi

# Создание дочерней оболочки
if [ -f $1 ]; then
(
cd $homedir
clear
print "\nстатус CVS: "
cvs status "$subdir/$fname"
)
elif [ -d $1 ]; then
(
cd $homedir
clear
print "\nстатус CVS: "
tmpfile="$homedir/cvs_sinfo.tmp"
rm -f $tmpfile
echo "  " >> $tmpfile
echo "  ****************************************" >> $tmpfile
echo "        Полный статус каталога" >> $tmpfile
echo "  ****************************************" >> $tmpfile
cvs release "$subdir/$fname" 1>>$tmpfile 2>>$tmpfile << EOF
N
EOF
echo "\n   -------------------------------\n" >> $tmpfile

        aa=`cat $tmpfile | grep ^"M " | awk '{print $2}' `
for ii in $aa
do
jj="(cd $homedir; cvs status \"$subdir/$ii\" );"
echo $jj | /bin/sh  \
| grep -v Sticky | awk '{if (NF != 0) print $0}' \
1>>$tmpfile 2>>$tmpfile
done

        cat $tmpfile | grep -v ^? | grep -v "Are you sure you want to release" \
| less
rm -f $tmpfile
)
else
print "\nАргумент $1 не файл или каталог"
exit
fi

slog

Замечание: оболочка Korn /bin/ksh устанавливается инсталляцией pdksh*.rpm с компакт-диска дистрибутива Linux

Сохраните этот файл как текст и выполните для него "chmod a+rx".

#!/bin/ksh

# CVS-программа slog
# Программа перечисления истории файла в CVS

# Имя каждого файла составляется из 3 частей -- домашнего каталога,
# подкаталога и имени файла. Полный путь -- $HOME/$subdir/$fname
# В CVS сохраняется такая же структура каталогов (с помощью переменной
# $subdir), поэтому в CVS мы будем иметь $CVSROOT/$subdir/$fname
# В данной программе эти 4 переменные $HOME, $CVSROOT, $subdir и $fname
# играют важную роль. Примеры их значений:
# HOME=/home/aldev, subdir=myproject/src CVSROOT=/home/cvsroot
# и fname=foo.cpp

# Предупреждение: заключите значения переменных, содержащих пробелы
# в двойные кавычки: "$HOME/$subdir", если subdir равен "some foo.cpp"

cmdname=`basename $0`

if [ $# -lt 1 ]; then
print "\nВызов: $cmdname <файл> \n"
exit
fi

# Проверка существования файла...
if [ ! -f "$1" ]; then
print "\nОшибка: $1 НЕ файл. Завершение $cmdname ......"
exit
fi

homedir=` echo $HOME | cut -f1 -d' '  `
if [ "$homedir" = "" ]; then
print "\nОшибка: \$HOME не установлен!!\n"
exit
fi

cur_dir=`pwd`
#echo $cur_dir

len=${#homedir}
len=$(($len + 2))
#echo $len

subdir=` echo $cur_dir | cut -b $len-2000 `
#echo "subdir is : " $subdir
tmpaa=`dirname $1`
if [ "$tmpaa" = "." ]; then
fname="$1"
if [ "$subdir" = "" ]; then
subdir=$tmpaa
fi
else
fname=`basename $1`
if [ "$subdir" = "" ]; then
subdir=$tmpaa
else
subdir="$subdir/$tmpaa"
fi
fi
#echo "subdir is : " $subdir
#echo "fname is : " $fname

# Для всех команд требуется каталог CVS в Вашем локальном каталоге...
if [ ! -d  "$homedir/$subdir/CVS" ]; then
tmpaa=` (cd "$CVSROOT/$subdir"; find * -prune -type f -print | head -1 ) `
tmpbb=`basename $tmpaa | cut -d',' -f1 `
if [ "$tmpaa" = "" -o ! -f "$CVSROOT/$subdir/$tmpbb,v" ]; then
print "\nКаталог $homedir/$subdir/CVS не существует"
print "Вы должны выполнить sget в каталоге `basename $subdir`. Наберите"
print "       cd $homedir/`dirname $subdir` "
print "       sget `basename $subdir` "
exit
else
# Теперь попытка создать CVS в локальном каталоге с помощью sget
(
cd "$homedir"
if [ "$subdir" = "." ]; then  # не использовать точку -- это смешает CVS
cvs -r checkout -A $tmpbb
else
cvs -r checkout -A "$subdir/$tmpbb"
fi
)
fi
fi

# Действовать внутри дочерней оболочки
(
cd $homedir
cvs log "$homedir/$subdir/$fname" | less
)

print "\n$cmdname удачно завершен."
#print "\nTip (Usage): $cmdname <filename>\n"
sdif

Замечание: оболочка Korn /bin/ksh устанавливается инсталляцией pdksh*.rpm с компакт-диска дистрибутива Linux

Сохраните этот файл как текст и выполните для него "chmod a+rx".
#!/bin/ksh

# CVS-программа sdif
# Программа просмотра отличий рабочего файла от CVS-копии

# Имя каждого файла составляется из 3 частей -- домашнего каталога,
# подкаталога и имени файла. Полный путь -- $HOME/$subdir/$fname
# В CVS сохраняется такая же структура каталогов (с помощью переменной
# $subdir), поэтому в CVS мы будем иметь $CVSROOT/$subdir/$fname
# В данной программе эти 4 переменные $HOME, $CVSROOT, $subdir и $fname
# играют важную роль. Примеры их значений:
# HOME=/home/aldev, subdir=myproject/src CVSROOT=/home/cvsroot
# и fname=foo.cpp

# Предупреждение: заключите значения переменных, содержащих пробелы
# в двойные кавычки: "$HOME/$subdir", если subdir равен "some foo.cpp"

cmdname=`basename $0`

Usage()
{
print "\nВызов: $cmdname <файл> "
print "$cmdname -r<rev1> -r<rev2> <файл> \n"
exit
}

homedir=` echo $HOME | cut -f1 -d' '  `
if [ "$homedir" = "" ]; then
print "\nОшибка: \$HOME не установлен!!\n"
exit
fi

FLAG1=""
FLAG2=""
OARG1=""
OARG2=""
# Каманда getopt не будет поддерживаться в следующей версии.
# Вместо нее используем getopts.
while getopts r:r: ii
do
case $ii in
r)
if [ "$FLAG1" = "" ]; then
FLAG1=$ii;
OARG1="$OPTARG"
else
FLAG2=$ii;
OARG2="$OPTARG"
fi
;;
?) Usage; exit 2;;
esac
done
shift ` expr $OPTIND - 1 `

if [ "$FLAG2" = "" ]; then
FLAG2=r
OARG2=HEAD
fi

cur_dir=`pwd`
#echo $cur_dir

len=${#homedir}
len=$(($len + 2))
#echo $len

subdir=` echo $cur_dir | cut -b $len-2000 `
#echo "subdir is : " $subdir
tmpaa=`dirname $1`
if [ "$tmpaa" = "." ]; then
fname="$1"
if [ "$subdir" = "" ]; then
subdir=$tmpaa
fi
else
fname=`basename $1`
if [ "$subdir" = "" ]; then
subdir=$tmpaa
else
subdir="$subdir/$tmpaa"
fi
fi
#echo "subdir is : " $subdir
#echo "fname is : " $fname

# Для всех команд требуется каталог CVS в Вашем локальном каталоге...
if [ ! -d  "$homedir/$subdir/CVS" ]; then
tmpaa=` (cd "$CVSROOT/$subdir"; find * -prune -type f -print | head -1 ) `
tmpbb=`basename $tmpaa | cut -d',' -f1 `
if [ "$tmpaa" = "" -o ! -f "$CVSROOT/$subdir/$tmpbb,v" ]; then
print "\nКаталог $homedir/$subdir/CVS не существует"
print "Вы должны выполнить sget в каталоге `basename $subdir`. Наберите"
print "       cd $homedir/`dirname $subdir` "
print "       sget `basename $subdir` "
exit
else
# Теперь попытка создать CVS в локальном каталоге с помощью sget
(
cd "$homedir"
if [ "$subdir" = "." ]; then  # не использовать точку -- это смешает CVS
cvs -r checkout -A $tmpbb
else
cvs -r checkout -A "$subdir/$tmpbb"
fi
)
fi
fi

# Действовать внутри дочерней оболочки
(
cd $homedir
if [ "$FLAG1" = "" ]; then
cvs diff -r HEAD "$homedir/$subdir/$fname" | less
else
cvs diff -$FLAG1 $OARG1 -$FLAG2 $OARG2 "$homedir/$subdir/$fname" | less
fi
)

sadd

Замечание: оболочка Korn /bin/ksh устанавливается инсталляцией pdksh*.rpm с компакт-диска дистрибутива Linux

Сохраните этот файл как текст и выполните для него "chmod a+rx".
#!/bin/ksh

# CVS-программа sadd
# Программа добавления файла в CVS

# Имя каждого файла составляется из 3 частей -- домашнего каталога,
# подкаталога и имени файла. Полный путь -- $HOME/$subdir/$fname
# В CVS сохраняется такая же структура каталогов (с помощью переменной
# $subdir), поэтому в CVS мы будем иметь $CVSROOT/$subdir/$fname
# В данной программе эти 4 переменные $HOME, $CVSROOT, $subdir и $fname
# играют важную роль. Примеры их значений:
# HOME=/home/aldev, subdir=myproject/src CVSROOT=/home/cvsroot
# и fname=foo.cpp

# Предупреждение: заключите значения переменных, содержащих пробелы
# в двойные кавычки: "$HOME/$subdir", если subdir равен "some foo.cpp"

cmdname=`basename $0`
if [ $# -lt 1 ]; then
print "\nВызов: $cmdname <файл/каталог> \n"
exit
fi

onearg="$1"
if [ ! -f "$onearg" -a ! -d "$onearg" ]; then
print "\nАргумент $onearg не файл или каталог!"
print "Вызов: $cmdname <файл/каталог> \n"
exit
fi

# Аргумент имя каталога .....
homedir=` echo $HOME | cut -f1 -d' '  `
if [ "$homedir" = "" ]; then
print "\nОшибка: \$HOME не установлен!!\n"
exit
fi

cvs_root=` echo $CVSROOT | cut -f1 -d' '  `
if [ "$cvs_root" = "" ]; then
print "\nОшибка: \$CVSROOT не установлен!!\n"
exit
fi

cur_dir=`pwd`
len=${#homedir}
len=$(($len + 2))
subdir=` echo $cur_dir | cut -b $len-2000 `
#echo "subdir is : " $subdir
tmpaa=`dirname "$onearg" `
if [ "$tmpaa" = "." ]; then
fname="$onearg"
if [ "$subdir" = "" ]; then
subdir=$tmpaa
fi
else
fname=`basename "$onearg" `
if [ "$subdir" = "" ]; then
subdir=$tmpaa
else
subdir="$subdir/$tmpaa"
fi
fi
#echo "subdir is : " $subdir
#echo "fname is : " $fname

# Для всех команд требуется каталог CVS в Вашем локальном каталоге...
if [ ! -d  "$homedir/$subdir/CVS" ]; then
tmpaa=` (cd "$CVSROOT/$subdir"; find * -prune -type f -print | head -1 ) `
tmpbb=`basename $tmpaa | cut -d',' -f1 `
if [ "$tmpaa" = "" -o ! -f "$CVSROOT/$subdir/$tmpbb,v" ]; then
print "\nКаталог $homedir/$subdir/CVS не существует"
print "Вы должны выполнить sget в каталоге `basename $subdir`. Наберите"
print "       cd $homedir/`dirname $subdir` "
print "       sget `basename $subdir` "
exit
else
# Теперь попытка создать CVS в локальном каталоге с помощью sget
(
cd "$homedir"
if [ "$subdir" = "." ]; then  # не использовать точку -- это смешает CVS
cvs -r checkout -A $tmpbb
else
cvs -r checkout -A "$subdir/$tmpbb"
fi
)
fi
fi

# Проверка существования файла...
if [ $# -eq 1 ]; then
if [ -f "$onearg" ]; then
cvs add "$onearg"
exit
fi
elif [ $# -gt 1 ]; then
print "\n\n\nДобавление всех файлов в текущем каталоге к CVS"
print "Каталоги добавлены не будут"
print -n "Нажмите ВВОД для продолжения или CTRL+C для прервания..."
read ans
for ii in $@
do

                               if [ -f "$ii" ]; then
                                               cvs add "$ii"
                               fi
                done;
                exit
fi

# Когда $subdir равен ".", мы в корневом каталоге
if [ "$subdir" = "." ]; then
# В этом месте $onearg -- каталог, а не файл...
if [ -d "$CVSROOT/$onearg" ]; then
print "\nКаталог $onearg уже существует в CVSROOT"
exit
else
# Добавление в корневой каталог $CVSROOT
if [ "$2" = "" -o "$3" = "" ]; then
print "\nВызов: $cmdname <каталог> <тэг поставщика> <тэг редакции>"
print "Например: "
print " $cmdname foo_directory V_1_0 R_1_0"
exit
else
(
cd "$homedir/$subdir";
cvs import "$onearg" $2 $3
)
fi
fi
else
# Если текущий каталог существует в CVS...
if [ -d "$CVSROOT/$subdir/$onearg" ]; then
print "\nКаталог $onearg уже в CVS-репозитории!"
exit
else
(
if [ -d "$homedir/$subdir/$onearg/CVS" ]; then
print "\nОшибка: Каталог $homedir/$subdir/$onearg/CVS существует!!"
print "\nЗавершение работы..."
exit
fi

                                               # Для импорта мы ДОЛЖНЫ перейти в каталог назначения
# и указать полный путь, начинающийся с $subdir
cd "$homedir/$subdir/$onearg";
cvs import "$subdir/$onearg" Ver_1 Rel_1
)
fi
fi

sdelete

Замечание: оболочка Korn /bin/ksh устанавливается инсталляцией pdksh*.rpm с компакт-диска дистрибутива Linux

Сохраните этот файл как текст и выполните для него "chmod a+rx".

#!/bin/ksh

# CVS-программа sdelete
# Программа удаления файла из CVS

# Имя каждого файла составляется из 3 частей -- домашнего каталога,
# подкаталога и имени файла. Полный путь -- $HOME/$subdir/$fname
# В CVS сохраняется такая же структура каталогов (с помощью переменной
# $subdir), поэтому в CVS мы будем иметь $CVSROOT/$subdir/$fname
# В данной программе эти 4 переменные $HOME, $CVSROOT, $subdir и $fname
# играют важную роль. Примеры их значений:
# HOME=/home/aldev, subdir=myproject/src CVSROOT=/home/cvsroot
# и fname=foo.cpp

# Предупреждение: заключите значения переменных, содержащих пробелы
# в двойные кавычки: "$HOME/$subdir", если subdir равен "some foo.cpp"

cmdname=`basename $0`

if [ $# -lt 1 ]; then
print "\nВызов: $cmdname <файл> \n"
exit
fi

onearg="$1"

homedir=` echo $HOME | cut -f1 -d' '  `
if [ "$homedir" = "" ]; then
print "\nОшибка: \$HOME не установлен!!\n"
exit
fi

cur_dir=`pwd`
len=${#homedir}
len=$(($len + 2))
subdir=` echo $cur_dir | cut -b $len-2000 `
#echo "subdir is : " $subdir
tmpaa=`dirname "$onearg" `
if [ "$tmpaa" = "." ]; then
fname="$onearg"
if [ "$subdir" = "" ]; then
subdir=$tmpaa
fi
else
fname=`basename "$onearg" `
if [ "$subdir" = "" ]; then
subdir=$tmpaa
else
subdir="$subdir/$tmpaa"
fi
fi
#echo "subdir is : " $subdir
#echo "fname is : " $fname

# Для всех команд требуется каталог CVS в Вашем локальном каталоге...
if [ ! -d  "$homedir/$subdir/CVS" ]; then
tmpaa=` (cd "$CVSROOT/$subdir"; find * -prune -type f -print | head -1 ) `
tmpbb=`basename $tmpaa | cut -d',' -f1 `
if [ "$tmpaa" = "" -o ! -f "$CVSROOT/$subdir/$tmpbb,v" ]; then
print "\nКаталог $homedir/$subdir/CVS не существует"
print "Вы должны выполнить sget в каталоге `basename $subdir`. Наберите"
print "       cd $homedir/`dirname $subdir` "
print "       sget `basename $subdir` "
exit
else
# Теперь попытка создать CVS в локальном каталоге с помощью sget
(
cd "$homedir"
if [ "$subdir" = "." ]; then  # не использовать точку -- это смешает CVS
cvs -r checkout -A $tmpbb
else
cvs -r checkout -A "$subdir/$tmpbb"
fi
)
fi
fi

# Действовать внутри дочерней оболочки...
(
cd $homedir

                # Проверка существования файла...
if [ ! -f "$subdir/$fname" ]; then
# Попытка получения файла из CVS
sget "$subdir/$fname"
if [ ! -f "$subdir/$fname" ]; then
print "\nОшибка: $subdir/$fname НЕ существует в CVS-репозитории."
print "\nЗавершение $cmdname ......"
exit
fi
fi

                bkextn=cvs_sdelete_safety_backup
\mv -f "$subdir/$fname" "$subdir/$fname.$bkextn"

                cvs remove "$subdir/$fname"

                print "\nКоманда sdelete удаляет файлы из CVS-репозитория и "
print "складирует их "на чердаке" CVS (каталог Attic). Если этот "
print "файл понадобится Вам, свяжитесь с Вашим администратором CVS"
print " "

                print "\n$cmdname успешно завершен."
print "Чтобы подтвердить сделанные изменения выполните scommit"
print "для $homedir/$subdir/$fname"
\mv -f "$subdir/$fname.$bkextn" "$subdir/$fname"
)

sfreeze

Замечание: оболочка Korn /bin/ksh устанавливается инсталляцией pdksh*.rpm с компакт-диска дистрибутива Linux

Сохраните этот файл как текст и выполните для него "chmod a+rx".
#!/bin/ksh

# CVS-программа sfreeze
# Программа для замораживания и вырезания редакции дерева исходного
# кода из CVS

cmdname=`basename $0`

Usage()
{
clear
print "\nВызов: $cmdname символический_тэг <имя каталога> "

                print "\nНапример: "
print "   cd \$HOME"
print "   $cmdname  REVISION_1   myprojectsource_directory"
print "Для просмотра списка редакций:"
print "slog <файл> посмотрите символическое имя и выполните"
print "cvs history -T"

                print "\nЧтобы создать ветку от основного ствола, используйте"
print "опции -b и -r, что принимает тэг как тэг ветки. Это полезно"
print "для создания \"заплатки\" к предыдущей редакции программного"
print "обеспечения"
print "Например: "
print "   cd \$HOME"
print "   cvs rtag -b -r REVISION_1   REVISION_1_1   myprojectsource_directory"
print " "

#   print "\nИнформация о тэге расположена в \$CVSROOT/CVSROOT/taginfo,v"
#   print "Вы можете просмотреть этот файл так: cd $HOME; sget CVSROOT"
exit
}

# Каманда getopt не будет поддерживаться в следующей версии.
# Вместо нее используем getopts.
#while getopts r: ii
#do
#             case $ii in
#                             r) FLAG1=$ii; OARG1="$OPTARG";;
#                             ?) Usage; exit 2;;
#             esac
#done
#shift ` expr $OPTIND - 1 `

#echo FLAG1 = $FLAG1 , OARG1 = $OARG1

if [ $# -lt 2 ]; then
Usage
fi

if [ ! -d $2 ]; then
print "\nОшибка: второй аргумент $2 не каталог!"
print "       Завершение $cmdname...."
print " "
exit
fi

homedir=` echo $HOME | cut -f1 -d' '  `
if [ "$homedir" = "" ]; then
print "\nОшибка: \$HOME не установлен!!\n"
exit
fi

cur_dir=`pwd`
len=${#homedir}
len=$(($len + 2))
subdir=` echo $cur_dir | cut -b $len-2000 `
#echo "subdir is : " $subdir

# Для всех команд требуется каталог CVS в Вашем локальном каталоге...
if [ ! -d  "$homedir/$subdir/CVS" ]; then
tmpaa=` (cd "$CVSROOT/$subdir"; find * -prune -type f -print | head -1 ) `
tmpbb=`basename $tmpaa | cut -d',' -f1 `
if [ "$tmpaa" = "" -o ! -f "$CVSROOT/$subdir/$tmpbb,v" ]; then
print "\nКаталог $homedir/$subdir/CVS не существует"
print "Вы должны выполнить sget в каталоге `basename $subdir`. Наберите"
print "       cd $homedir/`dirname $subdir` "
print "       sget `basename $subdir` "
exit
else
# Теперь попытка создать CVS в локальном каталоге с помощью sget
(
cd "$homedir"
if [ "$subdir" = "." ]; then  # не использовать точку -- это смешает CVS
cvs -r checkout -A $tmpbb
else
cvs -r checkout -A "$subdir/$tmpbb"
fi
)
fi
fi

if [ "$cur_dir" != "$homedir" ]; then
print "\nВы находитесь не в каталоге $homedir!!"
print "Команду sfreeze необходимо выполнять из"
print "домашнего каталога $homedir"
exit
fi

# cvs rtag symbolic_tag <directory name>
cvs rtag $1 $2

print "\n$cmdname удачно завершен."