/usr/bin/stg-cvs is in stgit-contrib 0.17.1-1.
This file is owned by root:root, with mode 0o755.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 | #!/bin/bash
set -e
# stg-cvs - helper script to manage a mixed cvs/stgit working copy.
# Allows quick synchronization of a cvs mirror branch (does not try to
# reconstruct patchsets, creates "jumbo" commits), and commits stgit
# patches to CVS.
# Copyright (c) 2007 Yann Dirson <ydirson@altern.org>
# Subject to the GNU GPL, version 2.
# NOTES
# - you want to add a "CVS" line to .git/info/exclude
# - you may want to add a ".git" line to the top .cvsignore
# BRANCH INIT
# - ensure the cvs wc is clean (eg. with "cvsco")
# $ git init
# $ echo CVS >> .git/info/exclude
# $ git add .
# $ git commit -m "Initial import."
# $ git branch -m master cvs
# $ stg branch -c master cvs
# $ git config branch.master.stgit.parentbranch cvs (0.12.1 and earlier only)
# $ git config branch.cvs.description "CVS $(cat CVS/Root) $(cat CVS/Repository) $(cat CVS/Tag 2>/dev/null | echo HEAD)"
# $ git config branch.master.description "Changes for $(cat CVS/Repository) $(cat CVS/Tag 2>/dev/null | echo HEAD)"
# LIMITATIONS
# - this is only a proof-of-concept prototype
# - lacks an "init" command (see above)
# - "commit" does not ensure the base is uptodate before trying to
# commit (but hey, it's CVS ;): better "stg-cvs pull" first
# - "commit" can only commit a single patch
# - not much robustness here
# - still no support for files removed in cvs (should catch "no
# longer in the repository" message)
# - this only deals with CVS but could surely be extended to any other
# VCS
# - lacks synchronisation of .cvsignore <-> .gitignore
# - no support for filenames with spaces (stg lacks --zero output format)
# - git commit is too chatty when it finds nothing to commit
# - lacks a "quick cvs commit" feature
# DESIGN FLAWS
# - while fetching, if a file change was not git update-index'd when
# cvs-update'd (eg. because of a stg-cvs bug), it is not seen on further
# fetches until it changes again, since we scan "cvs update" output.
# This yields possible inconsistencies with CVS.
# - similarly, any conflict while cvs-updating (whether due to illegal
# changes to the cvs-mirror-branch, or due to files added to cvs but
# already-existing in working copy, or to directory moves inside the
# cvs repository, or <fill here>) has to be dealt with by hand (although
# the situation is better here: cvs sees the conflict on subsequent tries)
# - bad/no support for cvsutils:
# - stg push/pop operations confuse cvsu because of timestamp changes
# - cvspurge/cvsco would nuke .git => does not make it easy to ensure
# synchronisation
# - should use a separate workspace for cvs branch like tailor does
# - confused by cvs keyword substitution
usage()
{
[ "$#" = 0 ] || echo "ERROR: $*"
echo "Usage: $(basename $0) <command>"
echo " commands: $(do_commands)"
exit 1
}
do_commands()
{
echo $(grep '^[a-z-]*)' $0 | cut -d')' -f1)
}
do_fetch()
{
local return=0
local path
local parent="$1"
local branch="$2"
# record changes from cvs into index
stg branch "$parent" || exit $?
cvs -fq update -dP | grep -v '^\? ' | tee /dev/tty | while read status path; do
if [ -e "$path" ]; then
git update-index --add "$path" || exit $?
else
git update-index --remove "$path" || exit $?
fi
# cvs update: `FELIN1_PEP/src/java/com/sagem/felin/ui/widget/PEPRifStateIcon.java' is no longer in the repository
done
# create commit
if git commit -m "stg-cvs sync"; then
:
else
return=$?
fi
# back to branch
stg branch "$branch" || exit $?
return $return
}
cvs_add_dir()
{
local parent=$(dirname "$1")
if [ ! -e "$parent/CVS" ]; then
cvs_add_dir "$parent"
fi
cvs add "$1"
}
# get context
branch=$(stg branch)
parent=$(git config "branch.${branch}.stgit.parentbranch") ||
usage "no declared parent for '$branch' - set branch.${branch}.stgit.parentbranch"
# extract command
[ "$#" -ge 1 ] || usage
command="$1"
shift
case "$command" in
fetch)
do_fetch "$parent" "$branch"
;;
pull)
if do_fetch "$parent" "$branch"; then
# update
# --merged
stg rebase "$parent"
stg clean --applied
fi
;;
commit)
# sanity asserts
[ $(stg applied | wc -l) = 1 ] ||
usage "you don't have exactly one patch applied"
# context
patch=$(stg top)
# adds
stg files | grep ^A | cut -c3- | while read file; do
parent=$(dirname "$file")
if [ ! -e "$parent/CVS" ]; then
cvs_add_dir "$parent"
fi
cvs -f add "$file"
done
# removes
stg files | grep ^D | cut -c3- | xargs -r cvs -f remove
# commit
stg files --bare | xargs -r cvs -fq commit \
-F ".git/patches/$branch/patches/$patch/description"
# sync the parent branch
stg branch "$parent"
git cherry-pick "patches/${branch}/${patch}"
stg branch "${branch}"
# update
# --merged
stg rebase "$parent"
stg clean --applied
;;
_commands)
# hint for bash-completion people :)
do_commands
;;
*)
usage "unknown command '$command'"
;;
esac
|