head 1.1; branch 1.1.1; access; symbols netbsd-11-0-RC4:1.1.1.1 netbsd-11-0-RC3:1.1.1.1 netbsd-11-0-RC2:1.1.1.1 netbsd-11-0-RC1:1.1.1.1 perseant-exfatfs-base-20250801:1.1.1.1 netbsd-11:1.1.1.1.0.62 netbsd-11-base:1.1.1.1 netbsd-10-1-RELEASE:1.1.1.1 perseant-exfatfs-base-20240630:1.1.1.1 perseant-exfatfs:1.1.1.1.0.60 perseant-exfatfs-base:1.1.1.1 netbsd-8-3-RELEASE:1.1.1.1 netbsd-9-4-RELEASE:1.1.1.1 netbsd-10-0-RELEASE:1.1.1.1 netbsd-10-0-RC6:1.1.1.1 netbsd-10-0-RC5:1.1.1.1 netbsd-10-0-RC4:1.1.1.1 netbsd-10-0-RC3:1.1.1.1 netbsd-10-0-RC2:1.1.1.1 netbsd-10-0-RC1:1.1.1.1 netbsd-10:1.1.1.1.0.58 netbsd-10-base:1.1.1.1 netbsd-9-3-RELEASE:1.1.1.1 cjep_sun2x-base1:1.1.1.1 cjep_sun2x:1.1.1.1.0.56 cjep_sun2x-base:1.1.1.1 cjep_staticlib_x-base1:1.1.1.1 netbsd-9-2-RELEASE:1.1.1.1 cjep_staticlib_x:1.1.1.1.0.54 cjep_staticlib_x-base:1.1.1.1 netbsd-9-1-RELEASE:1.1.1.1 phil-wifi-20200421:1.1.1.1 phil-wifi-20200411:1.1.1.1 is-mlppp:1.1.1.1.0.52 is-mlppp-base:1.1.1.1 phil-wifi-20200406:1.1.1.1 netbsd-8-2-RELEASE:1.1.1.1 netbsd-9-0-RELEASE:1.1.1.1 netbsd-9-0-RC2:1.1.1.1 netbsd-9-0-RC1:1.1.1.1 phil-wifi-20191119:1.1.1.1 netbsd-9:1.1.1.1.0.50 netbsd-9-base:1.1.1.1 phil-wifi-20190609:1.1.1.1 netbsd-8-1-RELEASE:1.1.1.1 netbsd-8-1-RC1:1.1.1.1 pgoyette-compat-merge-20190127:1.1.1.1 pgoyette-compat-20190127:1.1.1.1 pgoyette-compat-20190118:1.1.1.1 pgoyette-compat-1226:1.1.1.1 pgoyette-compat-1126:1.1.1.1 pgoyette-compat-1020:1.1.1.1 pgoyette-compat-0930:1.1.1.1 pgoyette-compat-0906:1.1.1.1 netbsd-7-2-RELEASE:1.1.1.1 pgoyette-compat-0728:1.1.1.1 netbsd-8-0-RELEASE:1.1.1.1 phil-wifi:1.1.1.1.0.48 phil-wifi-base:1.1.1.1 pgoyette-compat-0625:1.1.1.1 netbsd-8-0-RC2:1.1.1.1 pgoyette-compat-0521:1.1.1.1 pgoyette-compat-0502:1.1.1.1 pgoyette-compat-0422:1.1.1.1 netbsd-8-0-RC1:1.1.1.1 pgoyette-compat-0415:1.1.1.1 pgoyette-compat-0407:1.1.1.1 pgoyette-compat-0330:1.1.1.1 pgoyette-compat-0322:1.1.1.1 pgoyette-compat-0315:1.1.1.1 netbsd-7-1-2-RELEASE:1.1.1.1 pgoyette-compat:1.1.1.1.0.46 pgoyette-compat-base:1.1.1.1 netbsd-7-1-1-RELEASE:1.1.1.1 matt-nb8-mediatek:1.1.1.1.0.44 matt-nb8-mediatek-base:1.1.1.1 perseant-stdc-iso10646:1.1.1.1.0.42 perseant-stdc-iso10646-base:1.1.1.1 netbsd-8:1.1.1.1.0.40 netbsd-8-base:1.1.1.1 prg-localcount2-base3:1.1.1.1 prg-localcount2-base2:1.1.1.1 prg-localcount2-base1:1.1.1.1 prg-localcount2:1.1.1.1.0.38 prg-localcount2-base:1.1.1.1 pgoyette-localcount-20170426:1.1.1.1 bouyer-socketcan-base1:1.1.1.1 pgoyette-localcount-20170320:1.1.1.1 netbsd-7-1:1.1.1.1.0.36 netbsd-7-1-RELEASE:1.1.1.1 netbsd-7-1-RC2:1.1.1.1 netbsd-7-nhusb-base-20170116:1.1.1.1 bouyer-socketcan:1.1.1.1.0.34 bouyer-socketcan-base:1.1.1.1 pgoyette-localcount-20170107:1.1.1.1 netbsd-7-1-RC1:1.1.1.1 pgoyette-localcount-20161104:1.1.1.1 netbsd-7-0-2-RELEASE:1.1.1.1 localcount-20160914:1.1.1.1 netbsd-7-nhusb:1.1.1.1.0.32 netbsd-7-nhusb-base:1.1.1.1 pgoyette-localcount-20160806:1.1.1.1 pgoyette-localcount-20160726:1.1.1.1 pgoyette-localcount:1.1.1.1.0.30 pgoyette-localcount-base:1.1.1.1 netbsd-7-0-1-RELEASE:1.1.1.1 netbsd-7-0:1.1.1.1.0.28 netbsd-7-0-RELEASE:1.1.1.1 netbsd-7-0-RC3:1.1.1.1 netbsd-7-0-RC2:1.1.1.1 netbsd-7-0-RC1:1.1.1.1 netbsd-6-0-6-RELEASE:1.1.1.1 netbsd-6-1-5-RELEASE:1.1.1.1 netbsd-7:1.1.1.1.0.26 netbsd-7-base:1.1.1.1 yamt-pagecache-base9:1.1.1.1 yamt-pagecache-tag8:1.1.1.1 netbsd-6-1-4-RELEASE:1.1.1.1 netbsd-6-0-5-RELEASE:1.1.1.1 tls-earlyentropy:1.1.1.1.0.24 tls-earlyentropy-base:1.1.1.1 riastradh-xf86-video-intel-2-7-1-pre-2-21-15:1.1.1.1 riastradh-drm2-base3:1.1.1.1 netbsd-6-1-3-RELEASE:1.1.1.1 netbsd-6-0-4-RELEASE:1.1.1.1 netbsd-6-1-2-RELEASE:1.1.1.1 netbsd-6-0-3-RELEASE:1.1.1.1 netbsd-6-1-1-RELEASE:1.1.1.1 riastradh-drm2-base2:1.1.1.1 riastradh-drm2-base1:1.1.1.1 riastradh-drm2:1.1.1.1.0.18 riastradh-drm2-base:1.1.1.1 netbsd-6-1:1.1.1.1.0.22 netbsd-6-0-2-RELEASE:1.1.1.1 netbsd-6-1-RELEASE:1.1.1.1 netbsd-6-1-RC4:1.1.1.1 netbsd-6-1-RC3:1.1.1.1 agc-symver:1.1.1.1.0.20 agc-symver-base:1.1.1.1 netbsd-6-1-RC2:1.1.1.1 netbsd-6-1-RC1:1.1.1.1 yamt-pagecache-base8:1.1.1.1 netbsd-6-0-1-RELEASE:1.1.1.1 yamt-pagecache-base7:1.1.1.1 matt-nb6-plus-nbase:1.1.1.1 yamt-pagecache-base6:1.1.1.1 netbsd-6-0:1.1.1.1.0.16 netbsd-6-0-RELEASE:1.1.1.1 netbsd-6-0-RC2:1.1.1.1 tls-maxphys:1.1.1.1.0.14 tls-maxphys-base:1.1.1.1 matt-nb6-plus:1.1.1.1.0.12 matt-nb6-plus-base:1.1.1.1 netbsd-6-0-RC1:1.1.1.1 yamt-pagecache-base5:1.1.1.1 yamt-pagecache-base4:1.1.1.1 netbsd-6:1.1.1.1.0.10 netbsd-6-base:1.1.1.1 yamt-pagecache-base3:1.1.1.1 yamt-pagecache-base2:1.1.1.1 yamt-pagecache:1.1.1.1.0.8 yamt-pagecache-base:1.1.1.1 cherry-xenmp:1.1.1.1.0.6 cherry-xenmp-base:1.1.1.1 bouyer-quota2-nbase:1.1.1.1 bouyer-quota2:1.1.1.1.0.4 bouyer-quota2-base:1.1.1.1 matt-mips64-premerge-20101231:1.1.1.1 matt-premerge-20091211:1.1.1.1 jym-xensuspend-base:1.1.1.1 jym-xensuspend:1.1.1.1.0.2 jym-xensuspend-nbase:1.1.1.1 CVS1_12_13:1.1.1.1 NONGNU:1.1.1; locks; strict; comment @# @; 1.1 date 2009.04.07.22.10.10; author christos; state Exp; branches 1.1.1.1; next ; 1.1.1.1 date 2009.04.07.22.10.10; author christos; state Exp; branches 1.1.1.1.2.1; next ; 1.1.1.1.2.1 date 2009.04.07.22.10.10; author jym; state dead; branches; next 1.1.1.1.2.2; 1.1.1.1.2.2 date 2009.05.13.18.52.52; author jym; state Exp; branches; next ; desc @@ 1.1 log @Initial revision @ text @ChangeLog entry: Thanks to Paul Eggert who suggested using better random numbers as well as using the base62 format for compactness and provided the sample divide_by and convert functions used here. 2005-09-29 Mark D. Baushke * man/rcsfile.5in: Document new commitid delta phrase. * man/rcsfile.5: Regenerated. * src/ci.c (RANDOM_BYTES, COMMITID_RAW_SIZE): New constants. (mainProg): Add commitid to delta records. Use random data and represent in base62 or fall back to using the same basic format construction as is used by CVS and CVSNT. (divide_by): New function used by convert. (convert): New fucntion to convert to base62. * rcsbase.h (commitidsize): Room for base62 encoded block or 32bit pid plus a 32bit time rendered as hex plus one NUL byte round up to 64. (struct hshentry): Add new commitid field. * src/rcsgen.c (putdelta): Preserve old commitid entries. * src/rcssyn.c (Kcommitid): New global constant keyword. (getdelta): Add optional parsing for it. * src/rlog.c (putadelta): Print it out. Index:man/rcsfile.5 --- man/rcsfile.5~ 1995-06-16 06:58:26.000000000 +0000 +++ man/rcsfile.5 2005-09-27 20:53:01.023504000 +0000 @@@@ -1,4 +1,4 @@@@ -.lf 1 ./rcsfile.5in +.lf 1 rcsfile.5in .\" Set p to 1 if your formatter can handle pic output. .if t .nr p 1 .de Id @@@@ -69,6 +69,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 @@@@ -128,6 +129,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. @@@@ -230,7 +243,7 @@@@ The following diagram shows an example o .fi .\} .if \np \{\ -.lf 232 +.lf 245 .PS 4.250i 3.812i .\" -2.0625 -4.25 1.75 0 .\" 0.000i 4.250i 3.812i 0.000i @@@@ -239,7 +252,7 @@@@ The following diagram shows an example o .nr 0x 1 \h'3.812i' .sp -1 -.lf 242 +.lf 255 \h'2.062i-(\w'Head'u/2u)'\v'0.125i-(0v/2u)+0v+0.22m'Head .sp -1 \h'2.062i'\v'0.250i'\D'l0.000i 0.500i' @@@@ -256,7 +269,7 @@@@ The following diagram shows an example o .sp -1 \h'1.688i'\v'0.750i'\D'l0.000i 0.500i' .sp -1 -.lf 244 +.lf 257 \h'2.062i-(\w'2.1'u/2u)'\v'1.000i-(0v/2u)+0v+0.22m'2.1 .sp -1 \h'2.062i'\v'1.250i'\D'l0.000i 0.500i' @@@@ -265,7 +278,7 @@@@ The following diagram shows an example o .sp -1 \h'2.062i'\v'1.750i'\D'l-0.025i -0.100i' .sp -1 -.lf 246 +.lf 259 \h'2.062i-(\w'1.3'u/2u)'\v'2.000i-(1v/2u)+0v+0.22m'1.3 .sp -1 \h'2.062i'\v'2.250i'\D'l-0.375i -0.500i' @@@@ -280,7 +293,7 @@@@ The following diagram shows an example o .sp -1 \h'1.375i'\v'1.500i'\D'l0.025i 0.100i' .sp -1 -.lf 249 +.lf 262 \h'1.375i-(\w'1.3.1.1'u/2u)'\v'1.250i-(1v/2u)+1v+0.22m'1.3.1.1 .sp -1 \h'1.375i'\v'1.000i'\D'l-0.375i 0.500i' @@@@ -295,7 +308,7 @@@@ The following diagram shows an example o .sp -1 \h'2.062i'\v'2.750i'\D'l-0.025i -0.100i' .sp -1 -.lf 252 +.lf 265 \h'2.062i-(\w'1.2'u/2u)'\v'3.000i-(1v/2u)+0v+0.22m'1.2 .sp -1 \h'2.062i'\v'3.250i'\D'l-0.375i -0.500i' @@@@ -310,7 +323,7 @@@@ The following diagram shows an example o .sp -1 \h'0.375i'\v'2.500i'\D'l0.025i 0.100i' .sp -1 -.lf 255 +.lf 268 \h'0.375i-(\w'1.2.1.1'u/2u)'\v'2.250i-(1v/2u)+1v+0.22m'1.2.1.1 .sp -1 \h'0.375i'\v'2.000i'\D'l-0.375i 0.500i' @@@@ -325,7 +338,7 @@@@ The following diagram shows an example o .sp -1 \h'0.375i'\v'1.500i'\D'l0.025i 0.100i' .sp -1 -.lf 257 +.lf 270 \h'0.375i-(\w'1.2.1.3'u/2u)'\v'1.250i-(1v/2u)+1v+0.22m'1.2.1.3 .sp -1 \h'0.375i'\v'1.000i'\D'l-0.375i 0.500i' @@@@ -340,7 +353,7 @@@@ The following diagram shows an example o .sp -1 \h'2.750i'\v'2.500i'\D'l0.025i 0.100i' .sp -1 -.lf 261 +.lf 274 \h'2.750i-(\w'1.2.2.1'u/2u)'\v'2.250i-(1v/2u)+1v+0.22m'1.2.2.1 .sp -1 \h'2.750i'\v'2.000i'\D'l-0.375i 0.500i' @@@@ -355,7 +368,7 @@@@ The following diagram shows an example o .sp -1 \h'3.438i'\v'1.250i'\D'l0.025i 0.100i' .sp -1 -.lf 264 +.lf 277 \h'3.438i-(\w'\s-21.2.2.1.1.1\s0'u/2u)'\v'1.000i-(1v/2u)+1v+0.22m'\s-21.2.2.1.1.1\s0 .sp -1 \h'3.438i'\v'0.750i'\D'l-0.375i 0.500i' @@@@ -370,7 +383,7 @@@@ The following diagram shows an example o .sp -1 \h'2.750i'\v'1.500i'\D'l0.025i 0.100i' .sp -1 -.lf 267 +.lf 280 \h'2.750i-(\w'1.2.2.2'u/2u)'\v'1.250i-(1v/2u)+1v+0.22m'1.2.2.2 .sp -1 \h'2.750i'\v'1.000i'\D'l-0.375i 0.500i' @@@@ -385,7 +398,7 @@@@ The following diagram shows an example o .sp -1 \h'2.062i'\v'3.750i'\D'l-0.025i -0.100i' .sp -1 -.lf 270 +.lf 283 \h'2.062i-(\w'1.1'u/2u)'\v'4.000i-(1v/2u)+0v+0.22m'1.1 .sp -1 \h'2.062i'\v'4.250i'\D'l-0.375i -0.500i' @@@@ -398,9 +411,9 @@@@ The following diagram shows an example o .if \n(00 .fi .br .nr 0x 0 -.lf 271 +.lf 284 .PE -.lf 272 +.lf 285 .\} .PP .SH IDENTIFICATION 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. Index:src/rcsbase.h --- src/rcsbase.h~ 1995-06-16 06:19:24.000000000 +0000 +++ src/rcsbase.h 2005-09-28 21:47:51.490505000 +0000 @@@@ -222,6 +222,11 @@@@ Report problems and direct all questions /* 1 sets the default locking to strict; */ /* used in production environments. */ +/* base64_encode(128 random bits) needs 24 bytes + 1 for NUL */ +/* time_t may be 64bits on some machines needs 16 bytes + 1 as hex */ +#define commitidsize 64 /* time+1+base64(128bits)+1 | pid+time+rand+1 */ +#define urandom_dev "/dev/urandom" + #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 +363,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 +668,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/ci.c --- src/ci.c~ 1995-06-16 06:19:24.000000000 +0000 +++ src/ci.c 2005-09-29 21:57:57.814504000 +0000 @@@@ -262,6 +262,10 @@@@ static void cleanup P((void)); static void incnum P((char const*,struct buf*)); static void addassoclst P((int,char const*)); +enum {RANDOM_BYTES = 8}; +enum {COMMITID_RAW_SIZE = (sizeof(time_t) + RANDOM_BYTES)}; +static void convert P((char const input[COMMITID_RAW_SIZE], char *output)); + static FILE *exfile; static RILE *workptr; /* working file pointer */ static struct buf newdelnum; /* new revision number */ @@@@ -285,6 +289,7 @@@@ mainProg(ciId, "ci", "$Id: 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 +314,45 @@@@ mainProg(ciId, "ci", "$Id: ci.c,v 5.30 1 suffixes = X_DEFAULT; nextassoc = &assoclst; + { + char buf[COMMITID_RAW_SIZE] = { 0, }; + ssize_t len = 0; + time_t rightnow = time (NULL); + char *startrand = buf + sizeof (time_t); + unsigned char *p = (unsigned char *) startrand; + size_t randbytes = RANDOM_BYTES; + int flags = O_RDONLY; + int fd; +#ifdef O_NOCTTY + flags |= O_NOCTTY; +#endif + if (rightnow != (time_t)-1) + while (rightnow > 0) { + *--p = rightnow % (UCHAR_MAX + 1); + rightnow /= UCHAR_MAX + 1; + } + else { + /* try to use more random data */ + randbytes = COMMITID_RAW_SIZE; + startrand = buf; + } + fd = open (urandom_dev, flags); + if (fd >= 0) { + len = read (fd, startrand, randbytes); + close (fd); + } + if (len <= 0) { + /* no random data was available so use pid */ + long int pid = (long int)getpid (); + p = (unsigned char *) (startrand + sizeof (pid)); + while (pid > 0) { + *--p = pid % (UCHAR_MAX + 1); + pid /= UCHAR_MAX + 1; + } + } + convert(buf, commitid); + } + argc = getRCSINIT(argc, argv, &newargv); argv = newargv; while (a = *++argv, 0<--argc && *a++=='-') { @@@@ -532,6 +576,8 @@@@ mainProg(ciId, "ci", "$Id: 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 */ @@@@ -1317,3 +1363,38 @@@@ addassoclst(flag, sp) *nextassoc = pt; nextassoc = &pt->nextsym; } + +static char const alphabet[62] = + "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + +/* Divide BUF by D, returning the remainder. Replace BUF by the + quotient. BUF[0] is the most significant part of BUF. + D must not exceed UINT_MAX >> CHAR_BIT. */ +static unsigned int +divide_by (unsigned char buf[COMMITID_RAW_SIZE], unsigned int d) +{ + unsigned int carry = 0; + int i; + for (i = 0; i < COMMITID_RAW_SIZE; i++) + { + unsigned int byte = buf[i]; + unsigned int dividend = (carry << CHAR_BIT) + byte; + buf[i] = dividend / d; + carry = dividend % d; + } + return carry; +} + +static void +convert (char const input[COMMITID_RAW_SIZE], char *output) +{ + static char const zero[COMMITID_RAW_SIZE] = { 0, }; + unsigned char buf[COMMITID_RAW_SIZE]; + size_t o = 0; + memcpy (buf, input, COMMITID_RAW_SIZE); + while (memcmp (buf, zero, COMMITID_RAW_SIZE) != 0) + output[o++] = alphabet[divide_by (buf, sizeof alphabet)]; + if (! o) + output[o++] = '0'; + output[o] = '\0'; +} Index:src/rcsgen.c --- src/rcsgen.c~ 1995-06-16 06:19:24.000000000 +0000 +++ src/rcsgen.c 2005-09-27 22:08:47.421504000 +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-27 22:08:47.429504000 +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); @ 1.1.1.1 log @from ftp.gnu.org @ text @@ 1.1.1.1.2.1 log @file rcs-5.7-commitid.patch was added on branch jym-xensuspend on 2009-05-13 18:52:52 +0000 @ text @d1 411 @ 1.1.1.1.2.2 log @Sync with HEAD. Second commit. See http://mail-index.netbsd.org/source-changes/2009/05/13/msg221222.html @ text @a0 411 ChangeLog entry: Thanks to Paul Eggert who suggested using better random numbers as well as using the base62 format for compactness and provided the sample divide_by and convert functions used here. 2005-09-29 Mark D. Baushke * man/rcsfile.5in: Document new commitid delta phrase. * man/rcsfile.5: Regenerated. * src/ci.c (RANDOM_BYTES, COMMITID_RAW_SIZE): New constants. (mainProg): Add commitid to delta records. Use random data and represent in base62 or fall back to using the same basic format construction as is used by CVS and CVSNT. (divide_by): New function used by convert. (convert): New fucntion to convert to base62. * rcsbase.h (commitidsize): Room for base62 encoded block or 32bit pid plus a 32bit time rendered as hex plus one NUL byte round up to 64. (struct hshentry): Add new commitid field. * src/rcsgen.c (putdelta): Preserve old commitid entries. * src/rcssyn.c (Kcommitid): New global constant keyword. (getdelta): Add optional parsing for it. * src/rlog.c (putadelta): Print it out. Index:man/rcsfile.5 --- man/rcsfile.5~ 1995-06-16 06:58:26.000000000 +0000 +++ man/rcsfile.5 2005-09-27 20:53:01.023504000 +0000 @@@@ -1,4 +1,4 @@@@ -.lf 1 ./rcsfile.5in +.lf 1 rcsfile.5in .\" Set p to 1 if your formatter can handle pic output. .if t .nr p 1 .de Id @@@@ -69,6 +69,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 @@@@ -128,6 +129,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. @@@@ -230,7 +243,7 @@@@ The following diagram shows an example o .fi .\} .if \np \{\ -.lf 232 +.lf 245 .PS 4.250i 3.812i .\" -2.0625 -4.25 1.75 0 .\" 0.000i 4.250i 3.812i 0.000i @@@@ -239,7 +252,7 @@@@ The following diagram shows an example o .nr 0x 1 \h'3.812i' .sp -1 -.lf 242 +.lf 255 \h'2.062i-(\w'Head'u/2u)'\v'0.125i-(0v/2u)+0v+0.22m'Head .sp -1 \h'2.062i'\v'0.250i'\D'l0.000i 0.500i' @@@@ -256,7 +269,7 @@@@ The following diagram shows an example o .sp -1 \h'1.688i'\v'0.750i'\D'l0.000i 0.500i' .sp -1 -.lf 244 +.lf 257 \h'2.062i-(\w'2.1'u/2u)'\v'1.000i-(0v/2u)+0v+0.22m'2.1 .sp -1 \h'2.062i'\v'1.250i'\D'l0.000i 0.500i' @@@@ -265,7 +278,7 @@@@ The following diagram shows an example o .sp -1 \h'2.062i'\v'1.750i'\D'l-0.025i -0.100i' .sp -1 -.lf 246 +.lf 259 \h'2.062i-(\w'1.3'u/2u)'\v'2.000i-(1v/2u)+0v+0.22m'1.3 .sp -1 \h'2.062i'\v'2.250i'\D'l-0.375i -0.500i' @@@@ -280,7 +293,7 @@@@ The following diagram shows an example o .sp -1 \h'1.375i'\v'1.500i'\D'l0.025i 0.100i' .sp -1 -.lf 249 +.lf 262 \h'1.375i-(\w'1.3.1.1'u/2u)'\v'1.250i-(1v/2u)+1v+0.22m'1.3.1.1 .sp -1 \h'1.375i'\v'1.000i'\D'l-0.375i 0.500i' @@@@ -295,7 +308,7 @@@@ The following diagram shows an example o .sp -1 \h'2.062i'\v'2.750i'\D'l-0.025i -0.100i' .sp -1 -.lf 252 +.lf 265 \h'2.062i-(\w'1.2'u/2u)'\v'3.000i-(1v/2u)+0v+0.22m'1.2 .sp -1 \h'2.062i'\v'3.250i'\D'l-0.375i -0.500i' @@@@ -310,7 +323,7 @@@@ The following diagram shows an example o .sp -1 \h'0.375i'\v'2.500i'\D'l0.025i 0.100i' .sp -1 -.lf 255 +.lf 268 \h'0.375i-(\w'1.2.1.1'u/2u)'\v'2.250i-(1v/2u)+1v+0.22m'1.2.1.1 .sp -1 \h'0.375i'\v'2.000i'\D'l-0.375i 0.500i' @@@@ -325,7 +338,7 @@@@ The following diagram shows an example o .sp -1 \h'0.375i'\v'1.500i'\D'l0.025i 0.100i' .sp -1 -.lf 257 +.lf 270 \h'0.375i-(\w'1.2.1.3'u/2u)'\v'1.250i-(1v/2u)+1v+0.22m'1.2.1.3 .sp -1 \h'0.375i'\v'1.000i'\D'l-0.375i 0.500i' @@@@ -340,7 +353,7 @@@@ The following diagram shows an example o .sp -1 \h'2.750i'\v'2.500i'\D'l0.025i 0.100i' .sp -1 -.lf 261 +.lf 274 \h'2.750i-(\w'1.2.2.1'u/2u)'\v'2.250i-(1v/2u)+1v+0.22m'1.2.2.1 .sp -1 \h'2.750i'\v'2.000i'\D'l-0.375i 0.500i' @@@@ -355,7 +368,7 @@@@ The following diagram shows an example o .sp -1 \h'3.438i'\v'1.250i'\D'l0.025i 0.100i' .sp -1 -.lf 264 +.lf 277 \h'3.438i-(\w'\s-21.2.2.1.1.1\s0'u/2u)'\v'1.000i-(1v/2u)+1v+0.22m'\s-21.2.2.1.1.1\s0 .sp -1 \h'3.438i'\v'0.750i'\D'l-0.375i 0.500i' @@@@ -370,7 +383,7 @@@@ The following diagram shows an example o .sp -1 \h'2.750i'\v'1.500i'\D'l0.025i 0.100i' .sp -1 -.lf 267 +.lf 280 \h'2.750i-(\w'1.2.2.2'u/2u)'\v'1.250i-(1v/2u)+1v+0.22m'1.2.2.2 .sp -1 \h'2.750i'\v'1.000i'\D'l-0.375i 0.500i' @@@@ -385,7 +398,7 @@@@ The following diagram shows an example o .sp -1 \h'2.062i'\v'3.750i'\D'l-0.025i -0.100i' .sp -1 -.lf 270 +.lf 283 \h'2.062i-(\w'1.1'u/2u)'\v'4.000i-(1v/2u)+0v+0.22m'1.1 .sp -1 \h'2.062i'\v'4.250i'\D'l-0.375i -0.500i' @@@@ -398,9 +411,9 @@@@ The following diagram shows an example o .if \n(00 .fi .br .nr 0x 0 -.lf 271 +.lf 284 .PE -.lf 272 +.lf 285 .\} .PP .SH IDENTIFICATION 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. Index:src/rcsbase.h --- src/rcsbase.h~ 1995-06-16 06:19:24.000000000 +0000 +++ src/rcsbase.h 2005-09-28 21:47:51.490505000 +0000 @@@@ -222,6 +222,11 @@@@ Report problems and direct all questions /* 1 sets the default locking to strict; */ /* used in production environments. */ +/* base64_encode(128 random bits) needs 24 bytes + 1 for NUL */ +/* time_t may be 64bits on some machines needs 16 bytes + 1 as hex */ +#define commitidsize 64 /* time+1+base64(128bits)+1 | pid+time+rand+1 */ +#define urandom_dev "/dev/urandom" + #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 +363,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 +668,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/ci.c --- src/ci.c~ 1995-06-16 06:19:24.000000000 +0000 +++ src/ci.c 2005-09-29 21:57:57.814504000 +0000 @@@@ -262,6 +262,10 @@@@ static void cleanup P((void)); static void incnum P((char const*,struct buf*)); static void addassoclst P((int,char const*)); +enum {RANDOM_BYTES = 8}; +enum {COMMITID_RAW_SIZE = (sizeof(time_t) + RANDOM_BYTES)}; +static void convert P((char const input[COMMITID_RAW_SIZE], char *output)); + static FILE *exfile; static RILE *workptr; /* working file pointer */ static struct buf newdelnum; /* new revision number */ @@@@ -285,6 +289,7 @@@@ mainProg(ciId, "ci", "$Id: 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 +314,45 @@@@ mainProg(ciId, "ci", "$Id: ci.c,v 5.30 1 suffixes = X_DEFAULT; nextassoc = &assoclst; + { + char buf[COMMITID_RAW_SIZE] = { 0, }; + ssize_t len = 0; + time_t rightnow = time (NULL); + char *startrand = buf + sizeof (time_t); + unsigned char *p = (unsigned char *) startrand; + size_t randbytes = RANDOM_BYTES; + int flags = O_RDONLY; + int fd; +#ifdef O_NOCTTY + flags |= O_NOCTTY; +#endif + if (rightnow != (time_t)-1) + while (rightnow > 0) { + *--p = rightnow % (UCHAR_MAX + 1); + rightnow /= UCHAR_MAX + 1; + } + else { + /* try to use more random data */ + randbytes = COMMITID_RAW_SIZE; + startrand = buf; + } + fd = open (urandom_dev, flags); + if (fd >= 0) { + len = read (fd, startrand, randbytes); + close (fd); + } + if (len <= 0) { + /* no random data was available so use pid */ + long int pid = (long int)getpid (); + p = (unsigned char *) (startrand + sizeof (pid)); + while (pid > 0) { + *--p = pid % (UCHAR_MAX + 1); + pid /= UCHAR_MAX + 1; + } + } + convert(buf, commitid); + } + argc = getRCSINIT(argc, argv, &newargv); argv = newargv; while (a = *++argv, 0<--argc && *a++=='-') { @@@@ -532,6 +576,8 @@@@ mainProg(ciId, "ci", "$Id: 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 */ @@@@ -1317,3 +1363,38 @@@@ addassoclst(flag, sp) *nextassoc = pt; nextassoc = &pt->nextsym; } + +static char const alphabet[62] = + "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + +/* Divide BUF by D, returning the remainder. Replace BUF by the + quotient. BUF[0] is the most significant part of BUF. + D must not exceed UINT_MAX >> CHAR_BIT. */ +static unsigned int +divide_by (unsigned char buf[COMMITID_RAW_SIZE], unsigned int d) +{ + unsigned int carry = 0; + int i; + for (i = 0; i < COMMITID_RAW_SIZE; i++) + { + unsigned int byte = buf[i]; + unsigned int dividend = (carry << CHAR_BIT) + byte; + buf[i] = dividend / d; + carry = dividend % d; + } + return carry; +} + +static void +convert (char const input[COMMITID_RAW_SIZE], char *output) +{ + static char const zero[COMMITID_RAW_SIZE] = { 0, }; + unsigned char buf[COMMITID_RAW_SIZE]; + size_t o = 0; + memcpy (buf, input, COMMITID_RAW_SIZE); + while (memcmp (buf, zero, COMMITID_RAW_SIZE) != 0) + output[o++] = alphabet[divide_by (buf, sizeof alphabet)]; + if (! o) + output[o++] = '0'; + output[o] = '\0'; +} Index:src/rcsgen.c --- src/rcsgen.c~ 1995-06-16 06:19:24.000000000 +0000 +++ src/rcsgen.c 2005-09-27 22:08:47.421504000 +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-27 22:08:47.429504000 +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); @