以下提供一組基於 CVS 基本指令的 Korn Shell (ksh) 腳本,放入 /usr/local/bin 並加入 PATH 即可使用。它們展示如何將 CVS 指令封裝為更彈性的操作介面(如檔案鎖定提示),您可依需求移植至 Bash 或 Perl。
| 腳本 | 功能 |
|---|---|
sget [-r rev] <FILE|DIR> | 取出唯讀檔案或目錄 |
sedit [-r rev] <FILE> | 取出可寫入檔案並自動鎖定(防止他人提交) |
scommit [-r rev] <FILE|DIR> | 提交修改 |
supdate <FILE|DIR> | 更新至最新版本 |
sunlock [-r rev] <FILE> | 釋放 sedit 加的鎖 |
slist | 列出正被編輯的檔案 |
sinfo <FILE|DIR> | 顯示版本資訊 |
slog <FILE> | 顯示版本歷史 |
sdif [-r rev1 -r rev2] <FILE> | 比較版本差異(避開系統 sdiff) |
sadd <FILE> | 新增檔案到版本庫 |
sdelete <FILE> | 從版本庫刪除檔案 |
sfreeze <TAG> <DIR> | 凍結原始碼樹並打標籤(發布用) |
saddtree <TAG> <DIR> | 將整個目錄樹納入版控 |
cd $HOME sfreeze REVISION_1_0 srctree # 之後可用標籤名稱 checkout 整個樹
#!/bin/ksh
# CVS program sget - check out read-only
cmdname=$(basename $0)
Usage() {
print "\nUsage: $cmdname [-r revision/tag] "
print "Example: $cmdname -r 1.1 foo.cpp"
print " $cmdname some_dir"
print " $cmdname -r REVISION_1 some_dir"
exit 1
}
while getopts r: opt; do
case $opt in
r) FLAG1=$opt; OARG1=$OPTARG ;;
?) Usage ;;
esac
done
shift $((OPTIND-1))
[ $# -lt 1 ] && Usage
bkextn=sget_bak
hme=$(echo $HOME | cut -f1 -d';')
[ -z "$hme" ] && { print "ERROR: \$HOME not set"; exit 1; }
# 若檔案已存在且可寫,中止
if [ -f "$1" ]; then
perms=$(ls -l "$1" | awk '{print $1}' | cut -b3,6,9)
case $perms in *w*) print "ERROR: File writable. Backup/commit/delete first."; exit ;; esac
fi
cur_dir=$(pwd)
len=${#hme}
len=$((len+2))
subdir=$(echo $cur_dir | cut -b $len-2000)
fdname=${subdir:+$subdir/}$1
touch "$1" 2>/dev/null
mv -f "$1" "$1.$bkextn"
( cd $hme
if [ -z "$FLAG1" ]; then
cvs -r checkout -A "$fdname"
else
cvs -r checkout -A -"$FLAG1" "$OARG1" "$fdname"
fi
)
[ -f "$1" ] && { print "\nREAD-ONLY copy of $fdname obtained."; print "Done $cmdname"; }
#!/bin/ksh
# CVS program sedit - check out read/write with locking
cmdname=$(basename $0)
Usage() {
print "\nUsage: $cmdname [-r revision] "
print "Example: $cmdname -r 1.1 foo.cpp"
exit 1
}
while getopts r: opt; do
case $opt in
r) FLAG1=$opt; OARG1=$OPTARG ;;
?) Usage ;;
esac
done
shift $((OPTIND-1))
[ $# -lt 1 ] && Usage
hme=$(echo $HOME | cut -f1 -d';')
[ -z "$hme" ] && { print "ERROR: \$HOME not set"; exit 1; }
bkextn=sedit_bak
cur_dir=$(pwd)
len=${#hme}
len=$((len+2))
subdir=$(echo $cur_dir | cut -b $len-2000)
fdname=${subdir:+$subdir/}$1
cvs_root=$(echo $CVSROOT | cut -f1 -d';')
[ -z "$cvs_root" ] && { print "ERROR: \$CVSROOT not set"; exit 1; }
cldir=$CVSROOT/$subdir/Locks
mkdir -p "$cldir" 2>/dev/null
rcsfile=$CVSROOT/$subdir/$1,v
[ ! -e "$rcsfile" ] && { print "ERROR: $1 not in CVS repository"; exit 1; }
# 取得最新版本號
tmpfile=$hme/sedit-lock.tmp
rm -f "$tmpfile" 2>/dev/null
if [ -z "$FLAG1" ]; then
( cd $hme; cvs log "$fdname" | head -6 | grep head: | awk '{print $2}' > "$tmpfile" )
OARG1=$(cat "$tmpfile")
rm -f "$tmpfile" 2>/dev/null
fi
lockfile=$cldir/$1-$OARG1
if [ -e "$lockfile" ]; then
print "\nERROR: File $1 Revision $OARG1 already locked."
exit 1
fi
# ...(後續建立鎖定、checkout -r 等邏輯)
完整腳本請參考原始文件;此處節錄核心邏輯。安裝 pdksh*.rpm 即可獲得 /bin/ksh。