Gracefuly handle spaces around the equal sign in the Authors file.
[parsecvs.git] / cvsutil.c
blob625bdfcd83e75e10d69d5a4a180e39abfbcf5d79
1 /*
2 * Copyright © 2006 Keith Packard <keithp@keithp.com>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or (at
7 * your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
19 #include "cvs.h"
20 #include <assert.h>
22 #define min(a,b) ((a) < (b) ? (a) : (b))
23 #define max(a,b) ((a) > (b) ? (a) : (b))
25 int
26 cvs_is_head (cvs_number *n)
28 assert (n->c <= CVS_MAX_DEPTH);
29 return (n->c > 2 && (n->c & 1) == 0 && n->n[n->c-2] == 0);
32 int
33 cvs_same_branch (cvs_number *a, cvs_number *b)
35 cvs_number t;
36 int i;
37 int n;
38 int an, bn;
40 if (a->c & 1) {
41 t = *a;
42 t.n[t.c++] = 0;
43 return cvs_same_branch (&t, b);
45 if (b->c & 1) {
46 t = *b;
47 t.n[t.c++] = 0;
48 return cvs_same_branch (a, &t);
50 if (a->c != b->c)
51 return 0;
53 * Everything on x.y is trunk
55 if (a->c == 2)
56 return 1;
57 n = a->c;
58 for (i = 0; i < n - 1; i++) {
59 an = a->n[i];
60 bn = b->n[i];
62 * deal with n.m.0.p branch numbering
64 if (i == n - 2) {
65 if (an == 0) an = a->n[i+1];
66 if (bn == 0) bn = b->n[i+1];
68 if (an != bn)
69 return 0;
71 return 1;
74 int
75 cvs_number_compare (cvs_number *a, cvs_number *b)
77 int n = min (a->c, b->c);
78 int i;
80 for (i = 0; i < n; i++) {
81 if (a->n[i] < b->n[i])
82 return -1;
83 if (a->n[i] > b->n[i])
84 return 1;
86 if (a->c < b->c)
87 return -1;
88 if (a->c > b->c)
89 return 1;
90 return 0;
93 int
94 cvs_number_compare_n (cvs_number *a, cvs_number *b, int l)
96 int n = min (l, min (a->c, b->c));
97 int i;
99 for (i = 0; i < n; i++) {
100 if (a->n[i] < b->n[i])
101 return -1;
102 if (a->n[i] > b->n[i])
103 return 1;
105 if (l > a->c)
106 return -1;
107 if (l > b->c)
108 return 1;
109 return 0;
113 cvs_is_branch_of (cvs_number *trunk, cvs_number *branch)
115 cvs_number n;
117 if (branch->c > 2) {
118 n = *branch;
119 n.c -= 2;
120 return cvs_same_branch (trunk, &n);
122 return 0;
126 cvs_number_degree (cvs_number *n)
128 cvs_number four;
130 if (n->c < 4)
131 return n->c;
132 four = *n;
133 four.c = 4;
135 * Place vendor branch between trunk and other branches
137 if (cvs_is_vendor (&four))
138 return n->c - 1;
139 return n->c;
142 cvs_number
143 cvs_previous_rev (cvs_number *n)
145 cvs_number p;
146 int i;
148 p.c = n->c;
149 for (i = 0; i < n->c - 1; i++)
150 p.n[i] = n->n[i];
151 if (n->n[i] == 1) {
152 p.c = 0;
153 return p;
155 p.n[i] = n->n[i] - 1;
156 return p;
159 cvs_number
160 cvs_master_rev (cvs_number *n)
162 cvs_number p;
164 p = *n;
165 p.c -= 2;
166 return p;
170 * Find the newest revision along a specific branch
173 cvs_number
174 cvs_branch_head (cvs_file *f, cvs_number *branch)
176 cvs_number n;
177 cvs_version *v;
179 n = *branch;
180 /* Check for magic branch format */
181 if ((n.c & 1) == 0 && n.n[n.c-2] == 0) {
182 n.n[n.c-2] = n.n[n.c-1];
183 n.c--;
185 for (v = f->versions; v; v = v->next) {
186 if (cvs_same_branch (&n, &v->number) &&
187 cvs_number_compare (&n, &v->number) > 0)
188 n = v->number;
190 return n;
193 cvs_number
194 cvs_branch_parent (cvs_file *f, cvs_number *branch)
196 cvs_number n;
197 cvs_version *v;
199 n = *branch;
200 n.n[n.c-1] = 0;
201 for (v = f->versions; v; v = v->next) {
202 if (cvs_same_branch (&n, &v->number) &&
203 cvs_number_compare (branch, &v->number) < 0 &&
204 cvs_number_compare (&n, &v->number) >= 0)
205 n = v->number;
207 return n;
210 Node *
211 cvs_find_version (cvs_file *cvs, cvs_number *number)
213 cvs_version *cv;
214 cvs_version *nv = NULL;
216 for (cv = cvs->versions; cv; cv = cv->next) {
217 if (cvs_same_branch (number, &cv->number) &&
218 cvs_number_compare (&cv->number, number) > 0 &&
219 (!nv || cvs_number_compare (&nv->number, &cv->number) > 0))
220 nv = cv;
222 return nv ? nv->node : NULL;
226 cvs_is_trunk (cvs_number *number)
228 return number->c == 2;
232 * Import branches are of the form 1.1.x where x is odd
235 cvs_is_vendor (cvs_number *number)
237 if (number->c != 4) return 0;
238 if (number->n[0] != 1)
239 return 0;
240 if (number->n[1] != 1)
241 return 0;
242 if ((number->n[2] & 1) != 1)
243 return 0;
244 return 1;
247 static void
248 cvs_symbol_free (cvs_symbol *symbol)
250 cvs_symbol *s;
252 while ((s = symbol)) {
253 symbol = s->next;
254 free (s);
258 static void
259 cvs_branch_free (cvs_branch *branch)
261 cvs_branch *b;
263 while ((b = branch)) {
264 branch = b->next;
265 free (b);
269 static void
270 cvs_version_free (cvs_version *version)
272 cvs_version *v;
274 while ((v = version)) {
275 version = v->next;
276 cvs_branch_free (v->branches);
277 free (v);
281 static void
282 cvs_patch_free (cvs_patch *patch)
284 cvs_patch *v;
286 while ((v = patch)) {
287 patch = v->next;
288 free (v->text);
289 free (v);
293 void
294 cvs_file_free (cvs_file *cvs)
296 cvs_symbol_free (cvs->symbols);
297 cvs_version_free (cvs->versions);
298 cvs_patch_free (cvs->patches);
299 free (cvs);
300 clean_hash();
303 char *
304 cvs_number_string (cvs_number *n, char *str)
306 char r[11];
307 int i;
309 str[0] = '\0';
310 for (i = 0; i < n->c; i++) {
311 snprintf (r, 10, "%d", n->n[i]);
312 if (i > 0)
313 strcat (str, ".");
314 strcat (str, r);
316 return str;