Аннотация |
Этот документ является "практическим руководством" для очень быстрой установки системы контроля исходного кода -- CVS/RCS. Также выборочно будут рассмотрены скрипты оболочки, являющихся внешними функциями для CVS. Они предоставляют легкий пользовательский интерфейс к CVS. Излагаемая информация применима к Linux, а так же ко всем остальным разновидностям Unix, подобно Solaris, HPUX, AIX, SCO, Sinix, BSD, SCO, и т.д. |
Система контроля исходного кода НЕОБХОДИМА для управления изменениями, возникающими в процессе разработки программного обеспечения. Разработчикам нужна полная история изменений для возможности отката к предыдущим версиям в случае возникновения проблем. Поскольку исходный код -- самый основной компонент любого проекта программного обеспечения и разработчики расходуют огромное количество времени и денег, очень важно потратить некоторое время для сопровождения (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, поскольку имеется возможность чрезвычайно гибкой настройки 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 |
Можно также посмотреть скрипты оболочки для RCS в "Разд. RCS Скрипты оболочки".
Сперва необходимо инсталлировать пакет CVS; на Redhat Linux наберите:
cd /mnt/cdrom/Redhat/RPMS rpm -i rcs*.rpm rpm -i cvs*.rpm Для просмотра списка установленных файлов: rpm -qpl cvs*.rpm | 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 |
chgrp users $CVSROOT |
cvs init # Смена каталога обязательна cd $HOME/my_source_code_dir # Необходимо указать поставщика (напр., V1_0) и редакцию (напр., R1_0) cvs import my_source_code_dir V1_0 R1_0 |
Для переноса файлов из 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 |
CVS предоставляет широкий диапазон команд (cvs_command in the Synopsis), каждая из которых, как правило, имеет богатый набор опций, призванные удовлетворить многие потребности управления исходным кодом в распределенных окружениях. Однако, Вы не обязаны овладеть каждой деталью чтобы делать полезную работу с помощью CVS; на самом деле, достаточно пяти команд для использования репозитория исходного кода. Команды CVS, используемые чаще всего: checkout, update, add, remove, commit и diff.
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 для получения списка остальных опций справки) |
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 для получения списка остальных опций справки) |
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 для получения списка остальных опций справки) |
cvs remove файл... Эта команда (после удаления перечисленных файлов) предназначена для заявления желания уничтожить файлы из репозитария. Для остальных разработчиков удаление возымеет действие после выполнения "cvs commit".
bash$ cvs --help remove Вызов: cvs remove [-flR] [файлы...] -f Удалить файл перед его исключением. -l Обработать только этот каталог (не рекурсивно). -R Обработать каталоги рекурсивно. (Задайте глобально опцию --help для получения списка остальных опций справки) |
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 для получения списка остальных опций справки) |
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 -- мощный редактор и поддерживает 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 |
****************************************************** |
По приглашению 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 вместо CVS, то могут пригодиться следующие скрипты оболочки.
#!/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 |
#!/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 |
#!/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. Приветствуется любая Ваша помощь по переводу на другие языки.
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 & |
Этот документ расположен по адресу
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 |
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.
Copyright Al Dev (Alavoor Vasudevan) 1998-2000.
Copyright 2000, 2001 Sultanbek Tezadov, translation into Russian.
Под лицезией GNU GPL с дополнительным требованием сохранять имя и e-mail автора во всех копиях.
Замечание: оболочка 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 |
Замечание: оболочка 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" |
Замечание: оболочка 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 ) |
Замечание: оболочка 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" |
Замечание: оболочка 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 |
Замечание: оболочка 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; |
Замечание: оболочка 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 |
Замечание: оболочка 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" |
Замечание: оболочка 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 ) |
Замечание: оболочка 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 |
Замечание: оболочка 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" ) |
Замечание: оболочка 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 удачно завершен." |