1 //
2 //	aegis - project change supervisor
3 //	Copyright (C) 2001, 2003-2008 Peter Miller
4 //
5 //	This program is free software; you can redistribute it and/or modify
6 //	it under the terms of the GNU General Public License as published by
7 //	the Free Software Foundation; either version 3 of the License, or
8 //	(at your option) any later version.
9 //
10 //	This program is distributed in the hope that it will be useful,
11 //	but WITHOUT ANY WARRANTY; without even the implied warranty of
12 //	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 //	GNU General Public License for more details.
14 //
15 //	You should have received a copy of the GNU General Public License
16 //	along with this program. If not, see
17 //	<http://www.gnu.org/licenses/>.
18 //
19 
20 #include <aeimport/format/private.h>
21 #include <aeimport/format/rcs.h>
22 #include <aeimport/format/rcs/gram.h>
23 #include <aeimport/format/version.h>
24 #include <common/str_list.h>
25 #include <libaegis/os.h>
26 
27 
28 static void
destructor(format_ty *)29 destructor(format_ty *)
30 {
31 }
32 
33 
34 static int
is_a_candidate(format_ty *,string_ty * filename)35 is_a_candidate(format_ty *, string_ty *filename)
36 {
37     return
38 	(
39 	    filename->str_length > 2
40 	&&
41 	    filename->str_text[filename->str_length - 2] == ','
42 	&&
43 	    filename->str_text[filename->str_length - 1] == 'v'
44 	);
45 }
46 
47 
48 static string_ty *
sanitize(format_ty *,string_ty * filename,int last_part)49 sanitize(format_ty *, string_ty *filename, int last_part)
50 {
51     static string_ty *rcs =	    0;
52     static string_ty *cvs =	    0;
53     static string_ty *attic =	    0;
54 
55     if (!rcs)
56     {
57 	rcs = str_from_c("RCS");
58 	cvs = str_from_c("CVS");
59 	attic = str_from_c("Attic");
60     }
61 
62     //
63     // Break the filename into path elements.
64     //
65     string_list_ty sl;
66     sl.split(filename, "/");
67 
68     //
69     // Get rid of path elements named "RCS" or "CVS" or "Attic".
70     //
71     string_list_ty sl2;
72     for (size_t j = 0; j < sl.nstrings; ++j)
73     {
74 	string_ty	*s;
75 
76 	s = sl.string[j];
77 	if (!str_equal(s, rcs) && !str_equal(s, cvs) && !str_equal(s, attic))
78 	    sl2.push_back(s);
79     }
80 
81     if (last_part)
82     {
83         //
84         // Remove the ",v" from the end of the last path element.
85         //
86         if (sl2.nstrings)
87         {
88             string_ty	*s;
89 
90             s = sl2.string[sl2.nstrings - 1];
91             if
92             (
93                 s->str_length >= 2
94             &&
95                 s->str_text[s->str_length - 2] == ','
96             &&
97                 s->str_text[s->str_length - 1] == 'v'
98             )
99             {
100                 sl2.string[sl2.nstrings - 1] =
101                     str_n_from_c(s->str_text, s->str_length - 2);
102                 str_free(s);
103             }
104         }
105     }
106 
107     //
108     // Rebuild the filename from the remaining path elements.
109     //
110     return sl2.unsplit("/");
111 }
112 
113 
114 static format_version_ty *
read_versions(format_ty *,string_ty * physical,string_ty * logical)115 read_versions(format_ty *, string_ty *physical, string_ty *logical)
116 {
117     return rcs_parse(physical, logical);
118 }
119 
120 
121 static string_ty *
history_put(format_ty *)122 history_put(format_ty *)
123 {
124     return
125 	str_from_c
126 	(
127 	    "ci -u -d -M -m${quote ($version) ${change description}} "
128 		"-t/dev/null ${quote $input} ${quote $history,v}; "
129 	    "rcs -U ${quote $history,v}"
130 	);
131 }
132 
133 
134 static string_ty *
history_get(format_ty *)135 history_get(format_ty *)
136 {
137     return
138 	str_from_c
139 	(
140 	    "co -r${quote $edit} -p ${quote $history,v} > ${quote $output}"
141 	);
142 }
143 
144 
145 static string_ty *
history_query(format_ty *)146 history_query(format_ty	*)
147 {
148     return
149 	str_from_c
150 	(
151 	    "rlog -r ${quote $history,v} | awk '/^revision/ {print $$2}'"
152 	);
153 }
154 
155 
156 static string_ty *
diff(format_ty *)157 diff(format_ty *)
158 {
159     //
160     // I'd prefer to say "diff -U10", but we can't rely on GNU
161     // Diff being installed everywhere.	 It's a risk even using
162     // a context diff, because not all non-GNU diff progs have -c.
163     //
164     return
165 	str_from_c
166 	(
167 	    "set +e; "
168 	    CONF_DIFF " "
169 #ifdef HAVE_GNU_DIFF
170 		"-U10 --text "
171 #else
172 		"-c "
173 #endif
174 		"${quote $original} ${quote $input} > ${quote $output}; "
175 	    "test $? -le 1"
176 	);
177 }
178 
179 
180 static string_ty *
merge(format_ty *)181 merge(format_ty *)
182 {
183     return
184 	str_from_c
185 	(
186 	    "set +e; "
187 	    "merge -p -L baseline -L C$c ${quote $mostrecent} "
188 		"${quote $original} ${quote $input} > ${quote $output}; "
189 	    "test $? -le 1"
190 	);
191 }
192 
193 
194 static void
unlock(format_ty *,string_ty * filename)195 unlock(format_ty *, string_ty *filename)
196 {
197     int		    flags;
198     string_ty	    *cmd;
199     string_ty	    *qfn;
200 
201     //
202     // -b   means resume working from the trunk, not a branch
203     // -e   means get rid of any access list
204     // -ko  means no keyword expansion
205     // -M   means do not send mail
206     // -q   means operate quietly
207     // -U   means set locking to non-strict
208     //
209     // There doesn't seem to be an option to get rid of all locks.
210     //
211     qfn = str_quote_shell(filename);
212     cmd = str_format("rcs -b -e -M -q -U %s", qfn->str_text);
213     str_free(qfn);
214     flags = OS_EXEC_FLAG_ERROK;
215     os_execute(cmd, flags, os_curdir());
216     str_free(cmd);
217 }
218 
219 
220 static format_vtable_ty vtbl =
221 {
222     sizeof(format_ty),
223     destructor,
224     is_a_candidate,
225     sanitize,
226     read_versions,
227     history_put,
228     history_get,
229     history_query,
230     diff,
231     merge,
232     unlock,
233 };
234 
235 
236 format_ty *
format_rcs_new()237 format_rcs_new()
238 {
239     return format_new(&vtbl);
240 }
241