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