1 |
ChangeLog entry: |
ChangeLog entry: |
2 |
|
|
3 |
2005-09-27 Mark D. Baushke <mdb@gnu.org> |
2005-09-28 Mark D. Baushke <mdb@gnu.org> |
4 |
|
|
5 |
* man/rcsfile.5in: Document new commitid delta phrase. |
* man/rcsfile.5in: Document new commitid delta phrase. |
6 |
* man/rcsfile.5: Regenerated. |
* man/rcsfile.5: Regenerated. |
7 |
|
|
8 |
2005-09-26 Mark D. Baushke <mdb@gnu.org> |
* src/ci.c (RANDOM_BYTES, N): New constants. |
9 |
|
(mainProg): Add commitid to delta records. Use |
10 |
* ci.c (mainProg): Add commitid to delta records using the |
random data and represent in base62 or fall back to using the |
11 |
same basic format construction as is used by CVS and CVSNT. |
same basic format construction as is used by CVS and CVSNT. |
12 |
* rcsbase.h (commitidsize): Room for 64bit pid, 32bit time, |
(divide_by): New function used by convert. |
13 |
16bit random rendered as hex plus one NUL byte round up to 32. |
(convert): New fucntion to convert to base62. |
14 |
|
* rcsbase.h (commitidsize): Room for base62 encoded block or |
15 |
|
32bit pid, 32bit time, 16bit random rendered as hex plus one |
16 |
|
NUL byte round up to 64. |
17 |
(struct hshentry): Add new commitid field. |
(struct hshentry): Add new commitid field. |
18 |
* rcsgen.c (putdelta): Preserve old commitid entries. |
* src/rcsgen.c (putdelta): Preserve old commitid entries. |
19 |
* rcssyn.c (Kcommitid): New global constant keyword. |
* src/rcssyn.c (Kcommitid): New global constant keyword. |
20 |
(getdelta): Add optional parsing for it. |
(getdelta): Add optional parsing for it. |
21 |
* rlog.c (putadelta): Print it out. |
* src/rlog.c (putadelta): Print it out. |
22 |
|
|
|
Index:src/ci.c |
|
|
--- src/ci.c~ 1995-06-16 06:19:24.000000000 +0000 |
|
|
+++ src/ci.c 2005-09-26 16:47:38.435505000 +0000 |
|
|
@@ -285,6 +285,7 @@ mainProg(ciId, "ci", " ci.c,v 5.30 1 |
|
|
char olddate[datesize]; |
|
|
char newdatebuf[datesize + zonelenmax]; |
|
|
char targetdatebuf[datesize + zonelenmax]; |
|
|
+ char commitid[commitidsize]; |
|
|
char *a, **newargv, *textfile; |
|
|
char const *author, *krev, *rev, *state; |
|
|
char const *diffname, *expname; |
|
|
@@ -309,6 +310,9 @@ mainProg(ciId, "ci", " ci.c,v 5.30 1 |
|
|
suffixes = X_DEFAULT; |
|
|
nextassoc = &assoclst; |
|
|
|
|
|
+ snprintf(commitid, sizeof(commitid), "%x%08lx%04x", |
|
|
+ (int)getpid(), (long)time (NULL), rand()&0xFFFF); |
|
|
+ |
|
|
argc = getRCSINIT(argc, argv, &newargv); |
|
|
argv = newargv; |
|
|
while (a = *++argv, 0<--argc && *a++=='-') { |
|
|
@@ -532,6 +536,8 @@ mainProg(ciId, "ci", " ci.c,v 5.30 1 |
|
|
newdelta.name = 0; |
|
|
clear_buf(&newdelta.ig); |
|
|
clear_buf(&newdelta.igtext); |
|
|
+ /* set commitid */ |
|
|
+ newdelta.commitid=commitid; |
|
|
/* set author */ |
|
|
if (author) |
|
|
newdelta.author=author; /* set author given by -w */ |
|
|
Index:src/rcsbase.h |
|
|
--- src/rcsbase.h~ 1995-06-16 06:19:24.000000000 +0000 |
|
|
+++ src/rcsbase.h 2005-09-26 16:48:34.726505000 +0000 |
|
|
@@ -222,6 +222,7 @@ Report problems and direct all questions |
|
|
/* 1 sets the default locking to strict; */ |
|
|
/* used in production environments. */ |
|
|
|
|
|
+#define commitidsize 32 /* pid + time + random bits */ |
|
|
#define yearlength 16 /* (good through AD 9,999,999,999,999,999) */ |
|
|
#define datesize (yearlength+16) /* size of output of time2date */ |
|
|
#define RCSTMPPREFIX '_' /* prefix for temp files in working dir */ |
|
|
@@ -358,6 +359,7 @@ struct hshentry { |
|
|
char const * lockedby; /* who locks the revision */ |
|
|
char const * state; /* state of revision (Exp by default) */ |
|
|
char const * name; /* name (if any) by which retrieved */ |
|
|
+ char const * commitid; /* text string to associate commits */ |
|
|
struct cbuf log; /* log message requested at checkin */ |
|
|
struct branchhead * branches; /* list of first revisions on branches*/ |
|
|
struct cbuf ig; /* ignored phrases in admin part */ |
|
|
@@ -662,6 +664,7 @@ extern int TotalDeltas; |
|
|
extern char const *const expand_names[]; |
|
|
extern char const |
|
|
Kaccess[], Kauthor[], Kbranch[], Kcomment[], |
|
|
+ Kcommitid[], |
|
|
Kdate[], Kdesc[], Kexpand[], Khead[], Klocks[], Klog[], |
|
|
Knext[], Kstate[], Kstrict[], Ksymbols[], Ktext[]; |
|
|
void unexpected_EOF P((void)) exiting; |
|
|
Index:src/rcsgen.c |
|
|
--- src/rcsgen.c~ 1995-06-16 06:19:24.000000000 +0000 |
|
|
+++ src/rcsgen.c 2005-09-23 18:09:11.408920000 +0000 |
|
|
@@ -547,6 +547,9 @@ putdelta(node, fout) |
|
|
|
|
|
aprintf(fout, ";\n%s\t%s;\n", Knext, node->next?node->next->num:""); |
|
|
awrite(node->ig.string, node->ig.size, fout); |
|
|
+ |
|
|
+ if (node->commitid) |
|
|
+ aprintf(fout, "%s\t%s;\n", Kcommitid, node->commitid); |
|
|
} |
|
|
|
|
|
|
|
|
Index:src/rcssyn.c |
|
|
--- src/rcssyn.c~ 1995-06-16 06:19:24.000000000 +0000 |
|
|
+++ src/rcssyn.c 2005-09-23 18:01:47.652920000 +0000 |
|
|
@@ -171,6 +171,7 @@ char const |
|
|
Kauthor[] = "author", |
|
|
Kbranch[] = "branch", |
|
|
Kcomment[] = "comment", |
|
|
+ Kcommitid[] = "commitid", |
|
|
Kdate[] = "date", |
|
|
Kdesc[] = "desc", |
|
|
Kexpand[] = "expand", |
|
|
@@ -433,6 +434,13 @@ getdelta() |
|
|
Delta->lockedby = 0; |
|
|
Delta->log.string = 0; |
|
|
Delta->selector = true; |
|
|
+ |
|
|
+ if (getkeyopt(Kcommitid)) { |
|
|
+ Delta->commitid = NextString; |
|
|
+ nextlex(); |
|
|
+ getsemi(Kcommitid); |
|
|
+ } |
|
|
+ |
|
|
Delta->ig = getphrases(Kdesc); |
|
|
TotalDeltas++; |
|
|
return (true); |
|
|
Index:src/rlog.c |
|
|
--- src/rlog.c~ 1995-06-16 06:19:24.000000000 +0000 |
|
|
+++ src/rlog.c 2005-09-26 17:23:55.257504000 +0000 |
|
|
@@ -591,6 +591,10 @@ putadelta(node,editscript,trunk) |
|
|
aprintf(out, insDelFormat, |
|
|
editscript->insertlns, editscript->deletelns); |
|
|
|
|
|
+ if ( node->commitid ) |
|
|
+ aprintf(out, "%s commitid: %s", (editscript) ? ";" : "", |
|
|
+ node->commitid); |
|
|
+ |
|
|
newbranch = node->branches; |
|
|
if ( newbranch ) { |
|
|
bufautobegin(&branchnum); |
|
|
Index:man/rcsfile.5in |
|
|
--- man/rcsfile.5in~ 1995-06-05 08:28:35.000000000 +0000 |
|
|
+++ man/rcsfile.5in 2005-09-27 20:52:46.424504000 +0000 |
|
|
@@ -68,6 +68,7 @@ nonterminal symbols are in |
|
|
\f3state\fP {\f2id\fP}\f3;\fP |
|
|
\f3branches\fP {\f2num\fP}*\f3;\fP |
|
|
\f3next\fP {\f2num\fP}\f3;\fP |
|
|
+ { \f3commitid\fP \f2id\fP\f3;\fP } |
|
|
{ \f2newphrase\fP }* |
|
|
.LP |
|
|
\f2desc\fP ::= \f3desc\fP \f2string\fP |
|
|
@@ -127,6 +128,18 @@ and all the digits of years thereafter. |
|
|
Dates use the Gregorian calendar; times use UTC. |
|
|
.PP |
|
|
The |
|
|
+.I commitid |
|
|
+is followed by an |
|
|
+.I id |
|
|
+token. This token is intended to be unique across |
|
|
+multiple files and is used to help group files as |
|
|
+being a part of the same logical commit. |
|
|
+This token must uniquely identify the commit |
|
|
+operation that was applied to a set of RCS files. |
|
|
+In particular, it must be unique among all the |
|
|
+commitids in this file. |
|
|
+.PP |
|
|
+The |
|
|
.I newphrase |
|
|
productions in the grammar are reserved for future extensions |
|
|
to the format of \*r files. |
|
23 |
Index:man/rcsfile.5 |
Index:man/rcsfile.5 |
24 |
--- man/rcsfile.5~ 1995-06-16 06:58:26.000000000 +0000 |
--- man/rcsfile.5~ 1995-06-15 23:58:26.000000000 -0700 |
25 |
+++ man/rcsfile.5 2005-09-27 20:53:01.023504000 +0000 |
+++ man/rcsfile.5 2005-09-27 13:53:01.023504000 -0700 |
26 |
@@ -1,4 +1,4 @@ |
@@ -1,4 +1,4 @@ |
27 |
-.lf 1 ./rcsfile.5in |
-.lf 1 ./rcsfile.5in |
28 |
+.lf 1 rcsfile.5in |
+.lf 1 rcsfile.5in |
176 |
.\} |
.\} |
177 |
.PP |
.PP |
178 |
.SH IDENTIFICATION |
.SH IDENTIFICATION |
179 |
|
Index:man/rcsfile.5in |
180 |
|
--- man/rcsfile.5in~ 1995-06-05 01:28:35.000000000 -0700 |
181 |
|
+++ man/rcsfile.5in 2005-09-27 13:52:46.424504000 -0700 |
182 |
|
@@ -68,6 +68,7 @@ nonterminal symbols are in |
183 |
|
\f3state\fP {\f2id\fP}\f3;\fP |
184 |
|
\f3branches\fP {\f2num\fP}*\f3;\fP |
185 |
|
\f3next\fP {\f2num\fP}\f3;\fP |
186 |
|
+ { \f3commitid\fP \f2id\fP\f3;\fP } |
187 |
|
{ \f2newphrase\fP }* |
188 |
|
.LP |
189 |
|
\f2desc\fP ::= \f3desc\fP \f2string\fP |
190 |
|
@@ -127,6 +128,18 @@ and all the digits of years thereafter. |
191 |
|
Dates use the Gregorian calendar; times use UTC. |
192 |
|
.PP |
193 |
|
The |
194 |
|
+.I commitid |
195 |
|
+is followed by an |
196 |
|
+.I id |
197 |
|
+token. This token is intended to be unique across |
198 |
|
+multiple files and is used to help group files as |
199 |
|
+being a part of the same logical commit. |
200 |
|
+This token must uniquely identify the commit |
201 |
|
+operation that was applied to a set of RCS files. |
202 |
|
+In particular, it must be unique among all the |
203 |
|
+commitids in this file. |
204 |
|
+.PP |
205 |
|
+The |
206 |
|
.I newphrase |
207 |
|
productions in the grammar are reserved for future extensions |
208 |
|
to the format of \*r files. |
209 |
|
Index:src/rcsbase.h |
210 |
|
--- src/rcsbase.h~ 1995-06-15 23:19:24.000000000 -0700 |
211 |
|
+++ src/rcsbase.h 2005-09-28 14:47:51.490505000 -0700 |
212 |
|
@@ -222,6 +222,11 @@ Report problems and direct all questions |
213 |
|
/* 1 sets the default locking to strict; */ |
214 |
|
/* used in production environments. */ |
215 |
|
|
216 |
|
+/* base64_encode(128 random bits) needs 24 bytes + 1 for NUL */ |
217 |
|
+/* time_t may be 64bits on some machines needs 16 bytes + 1 as hex */ |
218 |
|
+#define commitidsize 64 /* time+1+base64(128bits)+1 | pid+time+rand+1 */ |
219 |
|
+#define urandom_dev "/dev/urandom" |
220 |
|
+ |
221 |
|
#define yearlength 16 /* (good through AD 9,999,999,999,999,999) */ |
222 |
|
#define datesize (yearlength+16) /* size of output of time2date */ |
223 |
|
#define RCSTMPPREFIX '_' /* prefix for temp files in working dir */ |
224 |
|
@@ -358,6 +363,7 @@ struct hshentry { |
225 |
|
char const * lockedby; /* who locks the revision */ |
226 |
|
char const * state; /* state of revision (Exp by default) */ |
227 |
|
char const * name; /* name (if any) by which retrieved */ |
228 |
|
+ char const * commitid; /* text string to associate commits */ |
229 |
|
struct cbuf log; /* log message requested at checkin */ |
230 |
|
struct branchhead * branches; /* list of first revisions on branches*/ |
231 |
|
struct cbuf ig; /* ignored phrases in admin part */ |
232 |
|
@@ -662,6 +668,7 @@ extern int TotalDeltas; |
233 |
|
extern char const *const expand_names[]; |
234 |
|
extern char const |
235 |
|
Kaccess[], Kauthor[], Kbranch[], Kcomment[], |
236 |
|
+ Kcommitid[], |
237 |
|
Kdate[], Kdesc[], Kexpand[], Khead[], Klocks[], Klog[], |
238 |
|
Knext[], Kstate[], Kstrict[], Ksymbols[], Ktext[]; |
239 |
|
void unexpected_EOF P((void)) exiting; |
240 |
|
Index:src/ci.c |
241 |
|
--- src/ci.c~ 1995-06-15 23:19:24.000000000 -0700 |
242 |
|
+++ src/ci.c 2005-09-28 15:01:57.823507000 -0700 |
243 |
|
@@ -262,6 +262,10 @@ static void cleanup P((void)); |
244 |
|
static void incnum P((char const*,struct buf*)); |
245 |
|
static void addassoclst P((int,char const*)); |
246 |
|
|
247 |
|
+enum {RANDOM_BYTES = 8}; |
248 |
|
+enum {N = (sizeof(time_t) + RANDOM_BYTES)}; |
249 |
|
+static void convert P((char const input[N], char *output)); |
250 |
|
+ |
251 |
|
static FILE *exfile; |
252 |
|
static RILE *workptr; /* working file pointer */ |
253 |
|
static struct buf newdelnum; /* new revision number */ |
254 |
|
@@ -285,6 +289,7 @@ mainProg(ciId, "ci", " ci.c,v 5.30 1 |
255 |
|
char olddate[datesize]; |
256 |
|
char newdatebuf[datesize + zonelenmax]; |
257 |
|
char targetdatebuf[datesize + zonelenmax]; |
258 |
|
+ char commitid[commitidsize]; |
259 |
|
char *a, **newargv, *textfile; |
260 |
|
char const *author, *krev, *rev, *state; |
261 |
|
char const *diffname, *expname; |
262 |
|
@@ -309,6 +314,28 @@ mainProg(ciId, "ci", " ci.c,v 5.30 1 |
263 |
|
suffixes = X_DEFAULT; |
264 |
|
nextassoc = &assoclst; |
265 |
|
|
266 |
|
+ { |
267 |
|
+ char buf[N] = { 0, }; |
268 |
|
+ ssize_t len = 0; |
269 |
|
+ time_t rightnow = time (NULL); |
270 |
|
+ unsigned char *p = (unsigned char *) (buf + sizeof(time_t)); |
271 |
|
+ int fd = open (urandom_dev, O_RDONLY, O_NOCTTY); |
272 |
|
+ if (fd >= 0) { |
273 |
|
+ len = read (fd, buf + sizeof(time_t), RANDOM_BYTES); |
274 |
|
+ close (fd); |
275 |
|
+ } |
276 |
|
+ if (len > 0 && rightnow >= 0) { |
277 |
|
+ while (rightnow != 0) { |
278 |
|
+ *--p = rightnow % (UCHAR_MAX + 1); |
279 |
|
+ rightnow /= UCHAR_MAX + 1; |
280 |
|
+ } |
281 |
|
+ convert(buf, commitid); |
282 |
|
+ } else |
283 |
|
+ snprintf(commitid, sizeof(commitid), "%x%08lx%04x", |
284 |
|
+ (int)getpid(), (long int)rightnow, |
285 |
|
+ rand()&0xFFFF); |
286 |
|
+ } |
287 |
|
+ |
288 |
|
argc = getRCSINIT(argc, argv, &newargv); |
289 |
|
argv = newargv; |
290 |
|
while (a = *++argv, 0<--argc && *a++=='-') { |
291 |
|
@@ -532,6 +559,8 @@ mainProg(ciId, "ci", " ci.c,v 5.30 1 |
292 |
|
newdelta.name = 0; |
293 |
|
clear_buf(&newdelta.ig); |
294 |
|
clear_buf(&newdelta.igtext); |
295 |
|
+ /* set commitid */ |
296 |
|
+ newdelta.commitid=commitid; |
297 |
|
/* set author */ |
298 |
|
if (author) |
299 |
|
newdelta.author=author; /* set author given by -w */ |
300 |
|
@@ -1317,3 +1346,38 @@ addassoclst(flag, sp) |
301 |
|
*nextassoc = pt; |
302 |
|
nextassoc = &pt->nextsym; |
303 |
|
} |
304 |
|
+ |
305 |
|
+static char const alphabet[62] = |
306 |
|
+ "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; |
307 |
|
+ |
308 |
|
+/* Divide BUF by D, returning the remainder. Replace BUF by the |
309 |
|
+ quotient. BUF[0] is the most significant part of BUF. |
310 |
|
+ D must not exceed UINT_MAX >> CHAR_BIT. */ |
311 |
|
+static unsigned int |
312 |
|
+divide_by (unsigned char buf[N], unsigned int d) |
313 |
|
+{ |
314 |
|
+ unsigned int carry = 0; |
315 |
|
+ int i; |
316 |
|
+ for (i = 0; i < N; i++) |
317 |
|
+ { |
318 |
|
+ unsigned int byte = buf[i]; |
319 |
|
+ unsigned int dividend = (carry << CHAR_BIT) + byte; |
320 |
|
+ buf[i] = dividend / d; |
321 |
|
+ carry = dividend % d; |
322 |
|
+ } |
323 |
|
+ return carry; |
324 |
|
+} |
325 |
|
+ |
326 |
|
+static void |
327 |
|
+convert (char const input[N], char *output) |
328 |
|
+{ |
329 |
|
+ static char const zero[N] = { 0, }; |
330 |
|
+ unsigned char buf[N]; |
331 |
|
+ size_t o = 0; |
332 |
|
+ memcpy (buf, input, N); |
333 |
|
+ while (memcmp (buf, zero, N) != 0) |
334 |
|
+ output[o++] = alphabet[divide_by (buf, sizeof alphabet)]; |
335 |
|
+ if (! o) |
336 |
|
+ output[o++] = '0'; |
337 |
|
+ output[o] = '\0'; |
338 |
|
+} |
339 |
|
Index:src/rcsgen.c |
340 |
|
--- src/rcsgen.c~ 1995-06-15 23:19:24.000000000 -0700 |
341 |
|
+++ src/rcsgen.c 2005-09-27 15:08:47.421504000 -0700 |
342 |
|
@@ -547,6 +547,9 @@ putdelta(node, fout) |
343 |
|
|
344 |
|
aprintf(fout, ";\n%s\t%s;\n", Knext, node->next?node->next->num:""); |
345 |
|
awrite(node->ig.string, node->ig.size, fout); |
346 |
|
+ |
347 |
|
+ if (node->commitid) |
348 |
|
+ aprintf(fout, "%s\t%s;\n", Kcommitid, node->commitid); |
349 |
|
} |
350 |
|
|
351 |
|
|
352 |
|
Index:src/rcssyn.c |
353 |
|
--- src/rcssyn.c~ 1995-06-15 23:19:24.000000000 -0700 |
354 |
|
+++ src/rcssyn.c 2005-09-27 15:08:47.429504000 -0700 |
355 |
|
@@ -171,6 +171,7 @@ char const |
356 |
|
Kauthor[] = "author", |
357 |
|
Kbranch[] = "branch", |
358 |
|
Kcomment[] = "comment", |
359 |
|
+ Kcommitid[] = "commitid", |
360 |
|
Kdate[] = "date", |
361 |
|
Kdesc[] = "desc", |
362 |
|
Kexpand[] = "expand", |
363 |
|
@@ -433,6 +434,13 @@ getdelta() |
364 |
|
Delta->lockedby = 0; |
365 |
|
Delta->log.string = 0; |
366 |
|
Delta->selector = true; |
367 |
|
+ |
368 |
|
+ if (getkeyopt(Kcommitid)) { |
369 |
|
+ Delta->commitid = NextString; |
370 |
|
+ nextlex(); |
371 |
|
+ getsemi(Kcommitid); |
372 |
|
+ } |
373 |
|
+ |
374 |
|
Delta->ig = getphrases(Kdesc); |
375 |
|
TotalDeltas++; |
376 |
|
return (true); |
377 |
|
Index:src/rlog.c |
378 |
|
--- src/rlog.c~ 1995-06-15 23:19:24.000000000 -0700 |
379 |
|
+++ src/rlog.c 2005-09-26 10:23:55.257504000 -0700 |
380 |
|
@@ -591,6 +591,10 @@ putadelta(node,editscript,trunk) |
381 |
|
aprintf(out, insDelFormat, |
382 |
|
editscript->insertlns, editscript->deletelns); |
383 |
|
|
384 |
|
+ if ( node->commitid ) |
385 |
|
+ aprintf(out, "%s commitid: %s", (editscript) ? ";" : "", |
386 |
|
+ node->commitid); |
387 |
|
+ |
388 |
|
newbranch = node->branches; |
389 |
|
if ( newbranch ) { |
390 |
|
bufautobegin(&branchnum); |