housel@ea.ecn.purdue.edu (Peter S. Housel) (02/04/88)
The following is my own "poor-man's version control" system, which is usable with Minix or almost any other Unix workalike. This should help keep track of all of those wonderful patches we've been getting in this newsgroup. It is, of course, in the public domain. Do anything you want with it. -Peter S. Housel- housel@ei.ecn.purdue.edu ...!pur-ee!housel ----------------------cut-here------------------------------------------ #!/bin/sh # this is a shell archive. extract with /bin/sh. echo 'x - README' sed 's/^X//' <<'**-README-EOF-**' >README X X SVC is the Shell Version Control system, and is inspired by Walter XTichy's Revision Control System, or RCS. The intention of SVC is to implement Xthe subset of RCS that is commonly used for everyday maintainance. (That is, Xthe part I know how to use.) X X To run SVC on Minix, you need to do three things. First, apply the Xpatches I posted to comp.os.minix to repair the getc() and fseek() Xlibrary routines; otherwise you will get spurious lines inserted into Xthe front of your files when you check them in/out. Similarly, you also need Xto apply my patches to scanf(). Thirdly, you need a version of ctime(). XVersions have been posted by myself and a few other people, or you could Xuse a dummy version (e.g. return "\n";). X X To use SVC on a non-Minix system, you will need to find a copy Xof "fix", or of Larry Wall's "patch" program. To use patch, you need to Xcompile ci.c with "-DPATCH". X XMAN PAGES X XCommand: ci - check in an SVC revision XSyntax: ci [-l] [-u] file XFlags: -l After checking in, check back out again and lock X -u After checking in, do not delete the file XExamples: ci -u Makefile check Makefile back in X ci -l newfile create SVC file for newfile, relock X X Ci checks the specified file into its SVC archive. If an SVC archive file Xdid not exist, one is created with the name "file,S". (If a directory named X"SVC" is present in the same directory as "file", the archive will be placed Xthere instead.) X A log message will be prompted for, and read from standard input; this Xmay be several lines, terminated with "." on a line by itself or EOT. After Xthe file has been checked in, the default action is to remove the source Xfile. If "-u" is specified, the file will not be unlinked, but all write Xpermissions will be removed. If "-l" is specified, a lock is placed on Xthe SVC archive, and the file will remain writable by the owner. SVC archive Xfiles are always read-only. X Version numbers start at "1" and are incremented by one for each revision Xchecked in. X X XCommand: co - check out an SVC revision XSyntax: co [-l] [-r rev] file XFlags: -l Place a lock on the SVC archive after checkout X -r rev Check out revision "rev" instead most recent revision XExamples: co -l Makefile check out and lock Makefile X co -r 4 foo check out version 4 of foo X X Co checks the specified file out of its SVC archive. If the archive X".../file,S" does not exist, it is searched for in ".../SVC/file,S". X The specified revision will be checked out and placed in "file"; by Xdefault it will be non-writable. If "-l" is specified, a lock will be Xplaced on the archive and the file will be writable. X X XCommand: svclog - print log of SVC revisions XSyntax: svclog file XFlags: none XExamples: svclog foo print out revision history for foo X svclog Makefile,S print out revision history for Makefile X X Svclog prints out the revision history of the specified file. This Xinformation includes the revision numbers, dates, and log entries for each Xof the revisions, and indicates whether or not a lock on this file exists. XFor simplicity, the output format is rather raw. X X XINSTALLATION X X Installation of SVC should be rather straightforward. The "ci" and X"co" binaries should be compiled using the supplied makefile, and the "ci", X"co", and "svclog" files should be put in your favorite default path Xdirectory (such as /usr/bin). It may also be helpful to increase the memory Xallocation for /usr/bin/diff and /usr/bin/fix (using chmem) to as high as Xpossible. X XBACKGROUND X X SVC stands for Shell Version Control, and is so named for two Xreasons. The first is that it was originally implemented using Bourne Xshell scripts. (These are included as "ci.sh" and "co.sh"; they serve no Xuseful purpose in the current version but are presented for your amusement Xand/or enlightenment). This implementation gave pretty good performance on Xan 8-MIPS machine running BSD4.3+, but on my AT compatible it was just too Xslow. Also, the scripts make heavy use of "sed," which doesn't _quite_ work Xon Minix yet. For this reason "ci" and "co" were rewritten in C. X X The other reason for the name is that the SVC archives are in the Xform of shell scripts, in the manner of shar-files. The original reason for Xthis was so that the archives could literally extract themselves - by Xexecuting them with "sh". This format is reasonably easy to figure out by Xreading it, and not too difficult for the program to understand. In a pinch, Xyou can do without "co". X X However, there is a problem with this approach. Shell input using X"<<" (a here document in Minix sh source file terminology) is processed Xby the shell, including the expansion of environment variables and such. XThis means that files which contain shell-variable syntax (i.e. makefiles Xand other shell scripts) may be garbled on extraction. This was another Xreason why the programs were translated into C. X X ci.c and co.c were designed to be somewhat bullet-proof, and have Xworked pretty well in the time I have been using them. X XSUGGESTED USE X X The major use for SVC on my system is keeping track of system Xsources. There are "SVC" subdirectories all throughout /usr/src, and Xwhenever a fix is posted to the net I can check out a file, apply the Xpatches, and check it back in. The advantage of this is that if I want Xto refer to an earlier version of the file, or want to apply patches to a Xfile I have changed since the last official version, an older revision can Xbe checked out. X X I suggest experimenting with the system to get a feel for how it Xworks if you are not already familiar with RCS. Do not use it on any Xfiles for which you do not have a backup copy until you are confident Xthat you are doing things correctly. X X-Peter S. Housel- Xhousel@ei.ecn.purdue.edu ...!pur-ee!housel X **-README-EOF-** echo 'x - Makefile' sed 's/^X//' <<'**-Makefile-EOF-**' >Makefile X# X# makefile for SVC X# X XCFLAGS = -F -T/usr/tmp X Xall: ci co X Xci: ci.c X cc $(CFLAGS) -o ci ci.c X chmem =8000 ci X Xco: co.c X cc $(CFLAGS) -o co co.c X chmem =8000 co X Xsvclog: svclog.sh X cp svclog.sh svclog X chmod 755 svclog **-Makefile-EOF-** echo 'x - ci.c' sed 's/^X//' <<'**-ci.c-EOF-**' >ci.c X/* file: ci.c X** author: Peter S. Housel 12/17/87 X*/ X X#include <stdio.h> X#include <strings.h> X#include <stat.h> X#include <pwd.h> X#include <signal.h> X X#define SUFFIX ",S" /* svc indicator */ X#define SVCDIR "SVC" /* svc postfix indicator */ X X#define LINELEN 256 /* maximum line length */ X X#ifndef PATCH X#define FIX "fix $1 Fix.$1 > New.$1; mv New.$1 $1\n" X#else X#define FIX "patch -n -s $1 < Fix.$1; rm -f $1.orig\n" X#endif !PATCH X X#ifdef MAXPATHLEN X#define PATHLEN MAXPATHLEN X#else X#define PATHLEN 80 /* buffer length for filenames */ X#endif X Xint unlocked = 0; /* leave unlocked after checkin */ Xint relock = 0; /* lock next revision after checkin */ Xchar file[PATHLEN]; /* file to be checked in */ Xchar svc[PATHLEN]; /* filename for svc file */ Xchar newsvc[PATHLEN]; /* new copy of SVC file */ Xchar line[LINELEN]; /* temporary line buffer */ Xchar *p; /* scratch character pointer */ X XFILE *svcfp; /* svc file */ XFILE *origfp, *newfp; /* "orig" and "new" temp files */ XFILE *srcfp; /* source file */ Xint rev; /* new revision number */ Xint status; /* wait() buffer */ Xstruct stat stb1, stb2; /* stat buffers for size compare */ Xchar original[] = "/tmp/cioXXXXXX"; /* previous revision */ Xchar diffout[] = "/tmp/cidXXXXXX"; /* diffs */ X Xextern FILE *fopen(); Xextern char *mktemp(), *fgets(), *rindex(), *index(); Xextern char *ctime(); Xextern struct passwd *getpwuid(); Xextern long ftell(); X Xchar *whoami(); Xint onintr(); X Xmain(argc, argv) Xint argc; char **argv; X{ X#ifdef perprintf X char errbuf[BUFSIZ]; X setbuf(stderr, errbuf); X perprintf(stderr); X#endif X X while(++argv, --argc) X { X if('-' == (*argv)[0]) X { X if('u' == (*argv)[1]) X ++unlocked; X else if('l' == (*argv)[1]) X ++relock; X else X {fprintf(stderr, "ci: illegal option -%c\n", (*argv)[1]); X exit(1); X } X } X else X break; X } X X if(1 != argc) X { X fprintf(stderr, "ci: bad number of files arguments\n"); X exit(1); X } X X fname(*argv, file); X svcname(file, svc); X X fprintf(stderr, "%s -> %s\n", file, svc); X X signal(SIGHUP, onintr); X signal(SIGINT, onintr); X signal(SIGTERM, onintr); X X#ifndef BSD X if(NULL == (p = rindex(file, '/'))) X p = file; X else X ++p; X X if(strlen(p) > 13) X { X fprintf(stderr, "ci: filename %s is too long\n"); X exit(1); X } X#endif !BSD X X strcpy(newsvc, svc); X *(rindex(newsvc, ',')) = ';'; /* temporary file will be "file;S" */ X X if(NULL == (newfp = fopen(newsvc, "w"))) X { X perror("ci: can't create SVC temporary"); X exit(1); X } X X (void) mktemp(original); X (void) mktemp(diffout); X X if(NULL != (svcfp = fopen(svc, "r"))) /* does svc-file exist? */ X { X fgets(line, LINELEN, svcfp); X if(1 != sscanf(line, "# %d", &rev)) X { X fprintf(stderr, "ci: %s: illegal SVC file header\n", svc); X exit(1); X } X ++rev; X X if(!lockcheck(svcfp, rev)) X { X fprintf(stderr, "Revision %d not locked\n", rev); X clean(); X exit(1); X } X X if(NULL == (origfp = fopen(original, "w"))) X { X fprintf(stderr, "ci: can't create %s", original); X perror(""); X } X fgets(line, LINELEN, svcfp); /* skip "cat <<***MAIN-eof***" line */ X X while(NULL != fgets(line, LINELEN, svcfp) X && strcmp(line, "***MAIN-eof***\n")) X { X fputs(line, origfp); X if(ferror(origfp)) X { X perror("ci: origfile"); X exit(1); X } X } X fclose(origfp); X X rundiff(); X X if(0 != stat(original, &stb1) || 0 != stat(diffout, &stb2)) X { X perror("ci: can't stat original or diffout"); X clean(); X exit(1); X } X } X else X { /* no - create one */ X rev = 1; X } X X fprintf(newfp, "# %d\n", rev); X fprintf(newfp, "cat <<***MAIN-eof*** >$1\n"); X if(NULL == (srcfp = fopen(file, "r"))) X { X perror("ci: can't read source file"); X clean(); X exit(1); X } X while(NULL != fgets(line, LINELEN, srcfp)) X fputs(line, newfp); X fclo);srcfp); X fputs("***MAIN-eof***\n", newfp); X X if(rev > 1) X { X fprintf(newfp, "if test $2 -ge %d ; then rm -f Fix.$1 ; exit 0 ; fi ; cat <<***%d-eof*** >Fix.$1\n", rev, rev); X p = (stb1.st_size <= stb2.st_size) ? original : diffout; X if(NULL == (origfp = fopen(p, "r"))) X { X perror("can't open diff output file"); X clean(); X exit(1); X } X while(NULL != fgets(line, LINELEN, origfp)) X fputs(line, newfp); X fclose(origfp); X fprintf(newfp, "***%d-eof***\n", rev); X fputs((original == p) ? "mv Fix.$1 $1\n" : FIX, newfp); X logmsg(newfp); X while(NULL != fgets(line, LINELEN, svcfp) && strncmp(line, "#***SVCLOCK***", 14)) X fputs(line, newfp); X } X else X { X logmsg(newfp); X fputs("rm -f Fix.$1\n", newfp); X } X X if(relock) X {fprintf(stderr, "(relocking into revision %d)\n", rev+1); X fprintf(newfp, "#***SVCLOCK*** %s %d\n", whoami(), rev+1); X } X X signal(SIGHUP, SIG_IGN); /* disable during critical section */ X signal(SIGINT, SIG_IGN); X X if(ferror(newfp) || fclose(newfp) || ((rev > 1) && unlink(svc)) X || link(newsvc, svc)) X { X fprintf(stderr, "SVC file write/link error - Checkin aborted\n"); X clean(); X exit(1); X } X else X fprintf(stderr, "Checkin complete.\n"); X X if(stat(svc, &stb1) < 0 || chmod(svc, stb1.st_mode & 0555) < 0) X perror("ci: can't chmod SVC file"); X X if(unlocked) X {if(stat(file, &stb1) < 0 || chmod(file, stb1.st_mode & 0555) < 0) X perror("ci: can't chmod source file"); X } X else if(relock) X {if(stat(file, &stb1) < 0 || chmod(file, stb1.st_mode | 0200) < 0) X perror("ci: can't chmod source file"); X } X else X unlink(file); X X clean(); X exit(0); X} X Xrundiff() X{ /* do "diff file original > diffout" */ X int fd; /* redirected output file */ X X switch(fork()) X { X case -1:perror("ci: fork"); /* error */ X clean(); X exit(1); X X case 0: /* child */ X if((fd = creat(diffout, 0600)) < 0 || -1 == dup2(fd, 1)) X { X perror("ci: diffout"); X clean(); X exit(1); X } X close(fd); X execl("/usr/bin/diff", "diff", file, original, 0); X perror("ci: exec diff failed"); X exit(1); X X default:break; /* parent */ X } X wait(&status); X if(0 != status && 1<<8 != status) X { X fprintf(stderr, "ci: bad return status (0x%x) from diff\n", status); X clean(); X exit(1); X } X} X Xlogmsg(fp) XFILE *fp; X{ X long now; X X time(&now); X fprintf(stderr, "Enter log message for revision %d (end with ^D or '.'):\n", rev); X fprintf(fp, "#***SVC*** revision %d %s %s", rev, file, ctime(&now)); X while(NULL != gets(line) && strcmp(line, ".")) X fprintf(fp, "#***SVC*** %s\n", line); X} X Xfname(src, dst) Xchar *src, *dst; X{ X char *p; X strcpy(dst, src); X p = &dst[strlen(src) - strlen(SUFFIX)]; X if(!strcmp(p, SUFFIX)) X *p = '\0'; X} X Xsvcname(src, dst) Xchar *src, *dst; X{ X extern char *rindex(); X char *p; X X strcpy(dst, src); X strcat(dst, SUFFIX); X X if(0 != access(dst, 4)) X { X char dirname[PATHLEN]; X if(NULL != (p = rindex(src, '/'))) X strncpy(dirname, src, p - src + 1); X else X dirname[0] = '\0'; X strcat(dirname, SVCDIR); X X if(0 == access(dirname, 1)) X { X strcpy(dst, dirname); X if(NULL == p) X {strcat(dst, "/"); X strcat(dst, src); X } X else X strcat(dst, p); X strcat(dst, SUFFIX); X } X } X} X Xlockcheck(fp, rev) XFILE *fp; Xint rev; X{ X char lock[40], check[40]; X long pos; X int ret; X X sprintf(lock, "#***SVCLOCK*** %s %d\n", whoami(), rev); X X pos = ftell(fp); X fseek(fp, -((long)strlen(lock)), 2); X fgets(check, 40, fp); X ret = (0 == strcmp(lock, check)); X fseek(fp, pos, 0); X X return ret; X} X Xonintr() X{ X fprintf(stderr, "Interrupt - Aborting checkin, cleaning up\n"); X clean(); X exit(1); X} X Xclean() X{ X if(strlen(original)) /* if only RCS made this check! */ X unlink(original); X if(strlen(diffout)) X unlink(diffout); X if(strlen(newsvc)) X unlink(newsvc); X} X Xchar *whoami() X{ X struct passwd *pw; X X if(NULL != (pw = getpwuid(getuid()))) X return pw->pw_name; X else X return "nobody"; X} **-ci.c-EOF-** echo 'x - co.c' sed 's/^X//' <<'**-co.c-EOF-**' >co.c X/* file: co.c X** author: Peter S. Housel 12/24/87 X*/ X X#include <stdio.h> X#include <strings.h> X#include <stat.h> X#include <pwd.h> X X#define SUFFIX ",S" /* svc indicator */ X#define SVCDIR "SVC" /* svc postfix indicator */ X X#define LINELEN 256 /* maximum line length */ X X#ifdef MAXPATHLEN X#define PATHLEN MAXPATHLEN X#else X#define PATHLEN 80 /* buffer length for filenames */ X#endif X Xchar file[PATHLEN]; /* file to be checked in */ Xchar svc[PATHLEN]; /* filename for svc file */ Xchar newsvc[PATHLEN]; /* new copy of SVC file */ Xchar line[LINELEN]; /* temporary line buffer */ Xchar *p; /* scratch character pointer */ X XFILE *svcfp; /* svc file */ Xint rev; /* old revision number */ Xint lastrev, lockrev; /* latest file revision, lock into */ Xint status; /* wait() buffer */ Xint lock; /* lock the SVC file */ Xstruct stat stb; /* stat() buffer */ Xchar *base; /* basename of file */ X Xchar difftemp[PATHLEN]; /* extract() fix/patch input */ X Xextern FILE *fopen(); Xextern char *mktemp(), *fgets(), *rindex(), *index(); Xextern struct passwd *getpwuid(); X Xchar *whoami(), *basename(); X Xmain(argc, argv) Xint argc; char **argv; X{ X#ifdef perprintf X char errbuf[BUFSIZ]; X setbuf(stderr, errbuf); X perprintf(stderr); X#endif X X while(++argv, --argc) X { X if('-' == (*argv)[0]) X { X if('r' == (*argv)[1]) X {--argc; X rev = atoi(*++argv); X if(rev < 1) X {fprintf(stderr, "Illegal revision number\n"); X exit(1); X } X } X else if('l' == (*argv)[1]) X ++lock; X else X {fprintf(stderr, "co: illegal option -%c\n", (*argv)[1]); X exit(1); X } X } X else X break; X } X X if(1 != argc) X { X fprintf(stderr, "co: bad number of files arguments\n"); X exit(1); X } X X fname(*argv, file); X svcname(file, svc); X X fprintf(stderr, "%s -> %s\n", svc, base = basename(file)); X X if(NULL == (svcfp = fopen(svc, "r"))) X { X perror("co: can't read SVC file"); X exit(1); X } X X if(1 != fscanf(svcfp, "# %d", &lastrev) || lastrev < 1) X { X fprintf(stderr, "co: illegal SVC file format\n"); X exit(1); X } X X fclose(svcfp); X X if(stat(base, &stb) >= 0 && (stb.st_mode & 0222)) X { X fprintf(stderr, "Writable %s exists - overwrite (n/y)? ", base); X if(!getyn()) X { X fprintf(stderr, "Checkout aborted\n"); X exit(1); X } X } X X if(strlen(base)) X unlink(base); X X if(0 == rev) X rev = lastrev; X X fprintf(stderr, "Checking out revision %d", rev); X X extract(svc, base, rev); X X if(lock) X { X lockrev = lastrev + 1; X fprintf(stderr, "; Locking into revision %d\n", lockrev); X if(stat(svc, &stb) < 0 || chmod(svc, stb.st_mode | 0200) < 0) X perror("co: can't chmod SVC file"); X X if(stat(base, &stb) < 0 || chmod(base, stb.st_mode | 0200) < 0) X perror("co: can't chmod source file"); X X if(NULL == (svcfp = fopen(svc, "a")) X || (fprintf(svcfp, "#***SVCLOCK*** %s %d\n", whoami(), lockrev), ferror(svcfp))) X { X fprintf(stderr, "co: can't lock %s\n", svc); X exit(1); X } X if(stat(svc, &stb) < 0 || chmod(svc, stb.st_mode & 0555)) X perror("co: can't chmod SVC file"); X } X else X { X putchar('\n'); X if(stat(base, &stb) < 0 || chmod(base, stb.st_mode & 0555)) X perror("co: can't chmod source file"); X } X X exit(0); X} X X Xfname(src, dst) Xchar *src, *dst; X{ X char *p; X strcpy(dst, src); X p = &dst[strlen(src) - strlen(SUFFIX)]; X if(!strcmp(p, SUFFIX)) X *p = '\0'; X} X Xsvcname(src, dst) Xchar *src, *dst; X{ X extern char *rindex(); X char *p; X X strcpy(dst, src); X strcat(dst, SUFFIX); X X if(0 != access(dst, 4)) X { X char dirname[PATHLEN]; X if(NULL != (p = rindex(src, '/'))) X strncpy(dirname, src, p - src + 1); X else X dirname[0] = '\0'; X strcat(dirname, SVCDIR); X X if(0 == access(dirname, 1)) X { X strcpy(dst, dirname); X if(NULL == p) X {strcat(dst, "/"); X strcat(dst, src); X } X else X strcat(dst, p); X strcat(dst, SUFFIX); X } X } X} X Xextract(script, out, rev) Xchar *script, *out; int rev; X{ X FILE *outfp; X int testrev; X char buf[80]; X X sprintf(difftemp, "Fix.%s", out); X X svcfp = fopen(script, "r"); X fgets(line, LINELEN, svcfp); /* skip '# rev' line */ X fgets(line, LINELEN, svcfp); /* skip 'cat <***MAIN-eof***' line */ X X if(NULL == (outfp = fopen(out, "w"))) X { X perror("co: can't create output file"); X return; X } X X while(NULL != fgets(line, LINELEN, svcfp) && strcmp(line, "***MAIN-eof***\n")) X fputs(line, outfp); X X fclose(outfp); X X while(NULL != fgets(line, LINELEN, svcfp)) X { X if(!strncmp(line, "if ", 3)) X { X sscanf(line, "if test $2 -ge %d", &testrev); X if(rev >= testrev) X { X unlink(difftemp); X return; X } X if(NULL == (outfp = fopen(difftemp, "w"))) X { X perror("co: can't create output file"); X return; X } X sprintf(buf, "***%d-eof***\n", testrev); X while(NULL != fgets(line, LINELEN, svcfp) && strcmp(line, buf)) X fputs(line, outfp); X fclose(outfp); X } X else if(!strncmp(line, "mv ", 3)) X { X sprintf(buf, "mv Fix.%s %s", out, out); X system(buf); X } X else if(!strncmp(line, "fix ", 4)) X { X sprintf(buf, "fix %s Fix.%s > New.%s; mv New.%s %s", out, out, out, out, out); X system(buf); X } X else if(!strncmp(line, "patch ", 6)) X { X sprintf(buf, "patch -n -s %s < Fix.%s; rm -f %s.orig", out, out, out); X system(buf); X } X else X { /* ignore */ X } X } X X unlink(difftemp); X return; X} X Xchar *basename(name) Xchar *name; X{ X char *p; X X if(NULL == (p = rindex(name, '/'))) X return name; X else X return p + 1; X} X Xchar *whoami() X{ X struct passwd *pw; X X if(NULL != (pw = getpwuid(getuid()))) X return pw->pw_name; X else X return "nobody"; X} X Xint getyn() X{ X char ans[10]; X X return (NULL != fgets(ans, 10, stdin)) && ('y' == ans[0] || 'Y' == ans[0]); X} **-co.c-EOF-** echo 'x - svclog.sh' sed 's/^X//' <<'**-svclog.sh-EOF-**' >svclog.sh X#!/bin/sh X# Xsvc=`basename $1 ,S`,S Xif test \( ! -r $svc \) -a -d "SVC" ; then svc=SVC/$svc ; fi Xgrep '^#\*\*\*SVC' $svc X **-svclog.sh-EOF-** echo 'x - ci.sh' sed 's/^X//' <<'**-ci.sh-EOF-**' >ci.sh X#!/bin/sh X# SVC - the Shell Version Control system X# author: Peter S. Housel 10/24/87 X# Xremove="rm -f" Xlock="false" X# Xwhile :; do X case $1 in X-u ) remove="chmod a-w" X shift;; X-l ) remove="chmod u+w" X lock=":" X shift;; X* ) break X esac Xdone X# Xfile=`basename $1 ,S` Xsvc=$file,S Xif test \( ! -r $svc \) -a -d "SVC" ; then svc=SVC/$svc ; fi Xecho '***MAIN-eof***' >/tmp/cir$$ Xif test -r $svc; then X rev=`sed -n '1s/#.* //p' $svc`; rev=`expr $rev + 1` X if test "#***SVCLOCK*** $USER $rev" != "`tail -1 $svc`" ; then X echo "Revision $rev not locked by $USER" X exit 1 X fi X sed -e '3,/^\*\*\*MAIN-eof\*\*\*/!d' \ X -e '/^\*\*\*MAIN-eof\*\*\*/d' $svc >/tmp/cio$$ X sed -e '/^\*\*\*MAIN-eof\*\*\*/,$!d' \ X -e '/^#\*\*\*SVCLOCK\*\*\*/d' \ X -e '/^\*\*\*MAIN-eof\*\*\*/d' $svc >/tmp/cid$$ X echo 'if test $2 -ge $rev ; then rm -f /tmp/$$ ; exit 0 ; fi ; cat <<***$rev-eof*** >/tmp/$$' >>/tmp/cir$$ X diff $file /tmp/cio$$ >>/tmp/cir$$ X echo "***$rev-eof***" >>/tmp/cir$$ X echo 'fix $1 /tmp/$$ > New.$1; mv New.$1 $1' >>/tmp/cir$$ Xelse X rev=1 X echo 'rm -f /tmp/$$' > /tmp/cid$$ Xfi Xecho "Enter log message for revision $rev (end with ^D or '.'):" Xecho "#***SVC*** revision $rev $file "`date` $USER >>/tmp/cir$$ Xwhile read logline; do X if test x"$logline" = x. ; then break; fi X echo "#***SVC*** $logline" >>/tmp/cir$$ Xdone Xecho "# " $rev >$svc+ Xecho 'cat <<***MAIN-eof*** >$1' >> $svc+ Xif cat $file /tmp/cir$$ /tmp/cid$$ >> $svc+ ; then X rm -f /tmp/ci?$$ X echo "Checkin complete." X mv $svc+ $svc X if $lock; then X rev=`expr $rev + 1` X echo "#***SVCLOCK*** $USER $rev" >>$svc X echo "(Locking into revision $rev.)" X fi X chmod a-w $svc X $remove $file Xelse X echo "Checkout ABORTED!!!" X exit 1 Xfi **-ci.sh-EOF-** echo 'x - co.sh' sed 's/^X//' <<'**-co.sh-EOF-**' >co.sh X#!/bin/sh X# SVC - the Shell Version Control system X# author: Peter S. Housel 10/24/87 X# Xlock="false" X# Xwhile :; do X case $1 in X-l ) lock=":" X shift;; X-r ) rev=$2; X shift; X shift;; X* ) break X esac Xdone X# Xfile=`basename $1 ,S` Xsvc=$file,S Xif test \( ! -r $svc \) -a -d "SVC" ; then svc=SVC/$svc ; fi Xif test ! -r $svc ; then X echo "can't find $file,S or RCS/$file,S" X exit 1 Xfi Xlastrev=`sed -n '1s/#.* //p' $svc` Xif test -w $file; then X echo -n "Writable $file exists; Continue (n/y)? " ; read yn X if test x$yn != xy ; then echo "Checkout aborted" ; exit 1 ; fi Xelif test -f $file; then X chmod u+w $file Xfi Xecho -n "Checking out revision " ${rev=$lastrev} Xsh $svc $file $rev Xif $lock; then X lockrev=`expr $lastrev + 1` X echo "; Locking into revision $lockrev" X chmod u+w $file X chmod u+w $svc; echo "#***SVCLOCK*** $USER $lockrev" >>$svc; chmod u-w $svc Xelse X echo X chmod a-w $file Xfi Xexit 0 X **-co.sh-EOF-**
worsley@ditmela.oz (Andrew Worsley) (02/05/88)
in article <1660@ea.ecn.purdue.edu>, housel@ea.ecn.purdue.edu (Peter S. Housel) says: > > > The following is my own "poor-man's version control" system, > which is usable with Minix or almost any other Unix workalike. This should > help keep track of all of those wonderful patches we've been getting in this > newsgroup. > It is, of course, in the public domain. Do anything you want with it. Why not post the orginal RCS or atleast port it to MINIX. It is public domain and I think available from the source achives. It is distributed in the /usr/src/new part of BSD Unix, which I believe contains the User contributed stuff. The only non public part is diff, but there are PD versions of that around. If someone could volunteer to maintain an RCS tree of all the major versions of MINIX it would help the job of coordinating the work done on it. Otherwise I fear that a lot of effort will be lost as it will not be combinale with other changes. I am not volunteering, at least not until I start using MINIX. Andrew Worsley
ncoverby@ndsuvax.UUCP (Glen Overby) (02/07/88)
In article <285@ditmela.oz> worsley@ditmela.oz (Andrew Worsley) writes: >in article <1660@ea.ecn.purdue.edu>, housel@ea.ecn.purdue.edu (Peter S. Housel) says: > > If someone could volunteer to maintain an RCS tree of all the major versions >of MINIX it would help the job of coordinating the work done on it. Otherwise >I fear that a lot of effort will be lost as it will not be combinale with >other changes. I am not volunteering, at least not until I start using MINIX. I have tried doing exactly this for local use, with some success. The major problem is the time involved. And, as you mention, combinability of changes (figuring out what changes will co-exist). It would help greatly if everybody had a system like RCS set up with identical revision trees. Then new patches could be merged into the tree in their proper place, and co-existing changes would be documented by where in the tree the changes fell. Also, how would changes from this be distributed? Re-posting to Usenet is rather wasteful, and there is no Minix moderated sources group. And who is to determine what goes "in" and what stays "out"? This means somebody will have to determine things like quality of the work (bug free), documentation, etc. We could go the route of the two comp.sources.{unix,misc}, where the really good stuff (documented, passes lint, etc) goes one way, and everything else goes the other way. To date, it's been everybody on their own determining what changes work by trying them out; the only real unifying force has been Andy Tannebaum's "accepting" people's changes. Andy has already said he doesn't have the time required to be a moderator of sorts. I think the way to really make something like RCS-style maintenance benefit us as a whole is to have a standard "tree" (revision) format established, and place $Header lines in every file. Then convice people to USE it. I'm willing to post the non-minix-source part of my RCS files with the header info (stuff like descriptions and "$Header"s if I can figure out a decent way to do this (lateley, I've been moving the $Header lines to the END of the files because they mess me up when applying new patches, but they're a lot nicer at the beginning)). To give credit where credit is due, much of this "grunt work" was done by Freeman Pascal at NDSU, not me (I just badgered him into doing it). I'd also like to mention that without the 'idx' utility from comp.sources.unix I'd surely go crazy working with Minix's internals!
wheels@mks.UUCP (Gerry Wheeler) (02/10/88)
In article <285@ditmela.oz>, worsley@ditmela.oz (Andrew Worsley) writes: > Why not post the orginal RCS or atleast port it to MINIX. It is public > domain, and I think available from the source achives. I think this is incorrect. Although RCS is distributed with some versions of Berkeley Unix, it is not public domain. There was some discussion about this in comp.sys.ibm.pc (I think) recently. MKS has just recently ported a *licensed* copy of Mr. Tichy's source code to MS-DOS, and we don't want people thinking they can make copies of it for their friends. -- Gerry Wheeler Phone: (519)884-2251 Mortice Kern Systems Inc. UUCP: uunet!watmath!mks!wheels 35 King St. North BIX: join mks Waterloo, Ontario N2J 2W9 CompuServe: 73260,1043
aja@i.cc.purdue.edu (Miek Rowan) (02/12/88)
You are right, RCS was developed here, and it is free only to people with a Unix licence. But I do hear that GNU-RCS will be out really soon... has anyone else heard anything about it? miek
callen@ada-uts (02/12/88)
>In article <285@ditmela.oz>, worsley@ditmela.oz (Andrew Worsley) writes: >> Why not post the orginal RCS or atleast port it to MINIX. It is >>public domain, and I think available from the source achives. >I think this is incorrect. Although RCS is distributed with some >versions of Berkeley Unix, it is not public domain. There was some >discussion about this in comp.sys.ibm.pc (I think) recently. >MKS has just recently ported a *licensed* copy of Mr. Tichy's source >code to MS-DOS, and we don't want people thinking they can make copies >of it for their friends. >-- > Gerry Wheeler Phone: (519)884-2251 >Mortice Kern Systems Inc. UUCP: uunet!watmath!mks!wheels > 35 King St. North BIX: join mks >Waterloo, Ontario N2J 2W9 CompuServe: 73260,1043 >---------- Hmmm... I suggest that anyone porting RCS contact Walter Tichy (his address is tichy@pudue) and get the straight poop. I just asked him about doing a port for the Macintosh, and he said fine. My understanding the way this works is: - RCS ports are encouraged. Contact Tichy before you start, though, so he knows what you are up to; he tries to coordinate ports to avoid duplication of effort. He also wants the source code for the port once it's done so that he may furnish it to others. - Anyone can have RCS for FREE; just ask Tichy first. - You may NOT sell a port of RCS. You MAY sell a product that INCLUDES RCS (like, say, a complete compilation/editing/debugging system), but you must furnish the RCS portion for free and supply source upon request. In other words, he wants RCS to see the widest possible distribution but does NOT want to lose control of his work, or see anyone else profit from his work. So MKS CANNOT insist that their port not be copied.
wnp@killer.UUCP (Wolf Paul) (02/19/88)
In article <70900002@ada-uts> callen@ada-uts writes: > >>MKS has just recently ported a *licensed* copy of Mr. Tichy's source >>code to MS-DOS, and we don't want people thinking they can make copies >>of it for their friends. >Hmmm... I suggest that anyone porting RCS contact Walter Tichy (his >address is tichy@pudue) and get the straight poop. I just asked him about >doing a port for the Macintosh, and he said fine. My understanding the >way this works is: > ... >In other words, he wants RCS to see the widest possible distribution but >does NOT want to lose control of his work, or see anyone else profit from >his work. So MKS CANNOT insist that their port not be copied. I would be careful making statements like that. IF MKS has a license contract in writing, with Walter Tichy's signature on it, which allows them to restrict rights to their port of RCS, then anything Walter Tichy tells you or anyone elseis irrelevant, and MKS could go after anyone copying their port. So, unless you have seen a copy of MKS's agreement with Mr Tichy, and KNOW FOR CERTAIN that it does not give MKS exclusive rights to their port, you should not make suggestions which might get those who follow them into serious legal trouble. Wolf Paul wnp@killer wnp@dcs
KLH@sri-nic.arpa (Ken Harrenstien) (02/19/88)
FYI. --------------- Return-Path: <@RELAY.CS.NET,@ira.uka.de,@i41s1.ira.uka.de:tichy@ira.uka.de> Received: from RELAY.CS.NET by SRI-NIC.ARPA with TCP; Thu 18 Feb 88 05:49:58-PST Received: from germany.csnet by RELAY.CS.NET id ai08492; 18 Feb 88 8:09 EST Received: from i41s1 by iraun1.ira.uka.de. id aa06846; 18 Feb 88 9:22 MET Date: Thu, 18 Feb 88 9:21:58 MET From: Walter Tichy <tichy%ira.uka.de@RELAY.CS.NET> To: Ken Harrenstien <KLH%sri-nic.arpa%ira.uka.de@RELAY.CS.NET> cc: tichy%ira.uka.de@RELAY.CS.NET, wheels%mks.uucp%ira.uka.de@RELAY.CS.NET Subject: Re: [callen@ada-uts: Re: SVC - Revision control for Minix] An important correction to your message: MKS can very well insist that their port not be copied. MKS has a licensed version of RCS that is not in the public domain (an enhancement of the one on the Berkeley tape). They have furthermore added their own software, namely diff and diff3. The originals, as you may know, are AT&T's, and have so far hampered porting RCS. MKS has written its own to overcome this. MKS has a license to sell its port of RCS to the IBM PC. The licencse grants them full rights to their port, and all the copyright protection etc. available. You cannot copy the MKS RCS without permission from MKS. -Walter Tichy -------
mitch@Stride.COM (Thomas Mitchell) (02/20/88)
In article <70900002@ada-uts> callen@ada-uts writes: > >>In article <285@ditmela.oz>, worsley@ditmela.oz (Andrew Worsley) writes: >>> Why not post the original RCS or atleast port it to MINIX. It is >>>public domain, and I think available from the source achives. > >address is tichy@pudue) and get the straight poop. Good Idea. When we at MicroSage looked at RCS it contained (used) AT&T pattern matching code. The result was that a source license was required. Our last contact with Walter Tichy was 21 Feb. 1986. so -- in the intervening time RCS may have been recoded without the AT&T code. Remember that one of the goals of Unix was economy of programming. P.S. I think RCS is vastly better than sccs.