Teach rcs utils about commitid phrase.
authorYONETANI Tomokazu <y0netan1@dragonflybsd.org>
Wed, 17 Jan 2007 17:56:24 +0000 (17:56 +0000)
committerYONETANI Tomokazu <y0netan1@dragonflybsd.org>
Wed, 17 Jan 2007 17:56:24 +0000 (17:56 +0000)
NOTE: commands don't emit the phrase into RCS files unless you compile
      them with RCS_EMIT_COMMITID=yes.

Taken-from: contrib/rcs-5.7-commitid.patch which came with cvs-1.12.13

gnu/usr.bin/rcs/Makefile.inc
gnu/usr.bin/rcs/ci/ci.c
gnu/usr.bin/rcs/lib/rcsbase.h
gnu/usr.bin/rcs/lib/rcsgen.c
gnu/usr.bin/rcs/lib/rcssyn.c
gnu/usr.bin/rcs/rcs/rcsfile.5
gnu/usr.bin/rcs/rlog/rlog.c

index 22d60d7..dc2cacb 100644 (file)
@@ -1,3 +1,4 @@
+# $DragonFly: src/gnu/usr.bin/rcs/Makefile.inc,v 1.2 2007/01/17 17:56:23 y0netan1 Exp $
 # Location of librcs
 
 .if exists(${.OBJDIR}/../lib)
@@ -5,3 +6,8 @@ LIBRCS= ${.OBJDIR}/../lib/librcs.a
 .else
 LIBRCS=        ${.CURDIR}/../lib/librcs.a
 .endif
+
+# by default, don't emit commitid phrase into RCS files
+.if RCS_EMIT_COMMITID
+CFLAGS+=       -DRCS_EMIT_COMMITID
+.endif
index ae17c00..db630fe 100644 (file)
@@ -29,7 +29,7 @@ Report problems and direct all questions to:
 
 /*
  * $FreeBSD: src/gnu/usr.bin/rcs/ci/ci.c,v 1.7 1999/08/27 23:36:38 peter Exp $
- * $DragonFly: src/gnu/usr.bin/rcs/ci/ci.c,v 1.2 2003/06/17 04:25:47 dillon Exp $
+ * $DragonFly: src/gnu/usr.bin/rcs/ci/ci.c,v 1.3 2007/01/17 17:56:23 y0netan1 Exp $
  *
  * Revision 5.30  1995/06/16 06:19:24  eggert
  * Update FSF address.
@@ -264,6 +264,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          */
@@ -277,7 +281,7 @@ static struct hshentry newdelta;    /* new delta to be inserted     */
 static struct stat workstat;
 static struct Symrev *assoclst, **nextassoc;
 
-mainProg(ciId, "ci", "$DragonFly: src/gnu/usr.bin/rcs/ci/ci.c,v 1.2 2003/06/17 04:25:47 dillon Exp $")
+mainProg(ciId, "ci", "$DragonFly: src/gnu/usr.bin/rcs/ci/ci.c,v 1.3 2007/01/17 17:56:23 y0netan1 Exp $")
 {
        static char const cmdusage[] =
                "\nci usage: ci -{fIklMqru}[rev] -d[date] -mmsg -{nN}name -sstate -ttext -T -Vn -wwho -xsuff -zzone file ...";
@@ -287,6 +291,7 @@ mainProg(ciId, "ci", "$DragonFly: src/gnu/usr.bin/rcs/ci/ci.c,v 1.2 2003/06/17 0
        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;
@@ -311,6 +316,45 @@ mainProg(ciId, "ci", "$DragonFly: src/gnu/usr.bin/rcs/ci/ci.c,v 1.2 2003/06/17 0
        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++=='-') {
@@ -534,6 +578,8 @@ mainProg(ciId, "ci", "$DragonFly: src/gnu/usr.bin/rcs/ci/ci.c,v 1.2 2003/06/17 0
        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         */
@@ -1319,3 +1365,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 1a1c478..1288615 100644 (file)
@@ -1,6 +1,6 @@
 /* RCS common definitions and data structures */
 
-#define RCSBASE "$DragonFly: src/gnu/usr.bin/rcs/lib/rcsbase.h,v 1.2 2003/06/17 04:25:47 dillon Exp $"
+#define RCSBASE "$DragonFly: src/gnu/usr.bin/rcs/lib/rcsbase.h,v 1.3 2007/01/17 17:56:23 y0netan1 Exp $"
 
 /* Copyright 1982, 1988, 1989 Walter Tichy
    Copyright 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert
@@ -31,7 +31,7 @@ Report problems and direct all questions to:
 
 /*
  * $FreeBSD: src/gnu/usr.bin/rcs/lib/rcsbase.h,v 1.10 1999/08/27 23:36:44 peter Exp $
- * $DragonFly: src/gnu/usr.bin/rcs/lib/rcsbase.h,v 1.2 2003/06/17 04:25:47 dillon Exp $
+ * $DragonFly: src/gnu/usr.bin/rcs/lib/rcsbase.h,v 1.3 2007/01/17 17:56:23 y0netan1 Exp $
  *
  * Revision 5.20  1995/06/16 06:19:24  eggert
  * Update FSF address.
@@ -224,6 +224,11 @@ Report problems and direct all questions to:
                               /* 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  */
@@ -360,6 +365,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      */
@@ -670,6 +676,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 f344191..2b0d115 100644 (file)
@@ -29,7 +29,7 @@ Report problems and direct all questions to:
 
 /*
  * $FreeBSD: src/gnu/usr.bin/rcs/lib/rcsgen.c,v 1.7 1999/08/27 23:36:46 peter Exp $
- * $DragonFly: src/gnu/usr.bin/rcs/lib/rcsgen.c,v 1.2 2003/06/17 04:25:47 dillon Exp $
+ * $DragonFly: src/gnu/usr.bin/rcs/lib/rcsgen.c,v 1.3 2007/01/17 17:56:23 y0netan1 Exp $
  *
  * Revision 5.16  1995/06/16 06:19:24  eggert
  * Update FSF address.
@@ -143,7 +143,7 @@ Report problems and direct all questions to:
 
 #include "rcsbase.h"
 
-libId(genId, "$DragonFly: src/gnu/usr.bin/rcs/lib/rcsgen.c,v 1.2 2003/06/17 04:25:47 dillon Exp $")
+libId(genId, "$DragonFly: src/gnu/usr.bin/rcs/lib/rcsgen.c,v 1.3 2007/01/17 17:56:23 y0netan1 Exp $")
 
 int interactiveflag;  /* Should we act as if stdin is a tty?  */
 struct buf curlogbuf;  /* buffer for current log message */
@@ -549,6 +549,10 @@ putdelta(node, fout)
 
        aprintf(fout, ";\n%s\t%s;\n", Knext, node->next?node->next->num:"");
        awrite(node->ig.string, node->ig.size, fout);
+#ifdef RCS_EMIT_COMMITID
+       if (node->commitid)
+               aprintf(fout, "%s\t%s;\n", Kcommitid, node->commitid);
+#endif
 }
 
 
index d4d943d..f530ee4 100644 (file)
@@ -37,7 +37,7 @@ Report problems and direct all questions to:
 
 /*
  * $FreeBSD: src/gnu/usr.bin/rcs/lib/rcssyn.c,v 1.7 1999/08/27 23:36:48 peter Exp $
- * $DragonFly: src/gnu/usr.bin/rcs/lib/rcssyn.c,v 1.2 2003/06/17 04:25:47 dillon Exp $
+ * $DragonFly: src/gnu/usr.bin/rcs/lib/rcssyn.c,v 1.3 2007/01/17 17:56:23 y0netan1 Exp $
  *
  * Revision 5.15  1995/06/16 06:19:24  eggert
  * Update FSF address.
@@ -156,7 +156,7 @@ Report problems and direct all questions to:
 
 #include "rcsbase.h"
 
-libId(synId, "$DragonFly: src/gnu/usr.bin/rcs/lib/rcssyn.c,v 1.2 2003/06/17 04:25:47 dillon Exp $")
+libId(synId, "$DragonFly: src/gnu/usr.bin/rcs/lib/rcssyn.c,v 1.3 2007/01/17 17:56:23 y0netan1 Exp $")
 
 static char const *getkeyval P((char const*,enum tokens,int));
 static int getdelta P((void));
@@ -173,6 +173,7 @@ char const
        Kauthor[]   = "author",
        Kbranch[]   = "branch",
        Kcomment[]  = "comment",
+       Kcommitid[] = "commitid",
        Kdate[]     = "date",
        Kdesc[]     = "desc",
        Kexpand[]   = "expand",
@@ -435,6 +436,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 595e805..011babc 100644 (file)
@@ -6,7 +6,7 @@
 .ds Dt \\$4
 ..
 .Id $FreeBSD: src/gnu/usr.bin/rcs/rcs/rcsfile.5,v 1.5.2.1 2001/07/22 11:01:34 dd Exp $
-.Id $DragonFly: src/gnu/usr.bin/rcs/rcs/rcsfile.5,v 1.2 2003/06/17 04:25:47 dillon Exp $
+.Id $DragonFly: src/gnu/usr.bin/rcs/rcs/rcsfile.5,v 1.3 2007/01/17 17:56:23 y0netan1 Exp $
 .ds r \s-1RCS\s0
 .if n .ds - \%--
 .if t .ds - \(em
@@ -70,6 +70,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
@@ -129,6 +130,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 4ce5536..a063009 100644 (file)
@@ -29,7 +29,7 @@ Report problems and direct all questions to:
 
 /*
  * $FreeBSD: src/gnu/usr.bin/rcs/rlog/rlog.c,v 1.13 1999/08/27 23:36:59 peter Exp $
- * $DragonFly: src/gnu/usr.bin/rcs/rlog/rlog.c,v 1.2 2003/06/17 04:25:48 dillon Exp $
+ * $DragonFly: src/gnu/usr.bin/rcs/rlog/rlog.c,v 1.3 2007/01/17 17:56:24 y0netan1 Exp $
  *
  * Revision 5.18  1995/06/16 06:19:24  eggert
  * Update FSF address.
@@ -221,7 +221,7 @@ static struct rcslockers *lockerlist;
 static struct stateattri *statelist;
 
 
-mainProg(rlogId, "rlog", "$DragonFly: src/gnu/usr.bin/rcs/rlog/rlog.c,v 1.2 2003/06/17 04:25:48 dillon Exp $")
+mainProg(rlogId, "rlog", "$DragonFly: src/gnu/usr.bin/rcs/rlog/rlog.c,v 1.3 2007/01/17 17:56:24 y0netan1 Exp $")
 {
        static char const cmdusage[] =
                "\nrlog usage: rlog -{bhLNRt} -v[string] -ddates -l[lockers] -r[revs] -sstates -Vn -w[logins] -xsuff -zzone file ...";
@@ -608,6 +608,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);