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