svn commit: r184054 - in projects/csup_cvsmode: contrib/csup usr.bin/csup

Ulf Lilleengen lulf at FreeBSD.org
Sun Oct 19 09:09:00 UTC 2008


Author: lulf
Date: Sun Oct 19 09:08:59 2008
New Revision: 184054
URL: http://svn.freebsd.org/changeset/base/184054

Log:
  - Import csup work from p4.

Added:
  projects/csup_cvsmode/contrib/csup/lex.rcs.c   (contents, props changed)
  projects/csup_cvsmode/contrib/csup/rcsfile.c   (contents, props changed)
  projects/csup_cvsmode/contrib/csup/rcsfile.h   (contents, props changed)
  projects/csup_cvsmode/contrib/csup/rcsparse.c   (contents, props changed)
  projects/csup_cvsmode/contrib/csup/rcsparse.h   (contents, props changed)
  projects/csup_cvsmode/contrib/csup/rcstokenizer.h   (contents, props changed)
  projects/csup_cvsmode/contrib/csup/rcstokenizer.l
Modified:
  projects/csup_cvsmode/contrib/csup/Makefile
  projects/csup_cvsmode/contrib/csup/config.c
  projects/csup_cvsmode/contrib/csup/detailer.c
  projects/csup_cvsmode/contrib/csup/diff.c
  projects/csup_cvsmode/contrib/csup/diff.h
  projects/csup_cvsmode/contrib/csup/fattr.c
  projects/csup_cvsmode/contrib/csup/fattr.h
  projects/csup_cvsmode/contrib/csup/keyword.c
  projects/csup_cvsmode/contrib/csup/keyword.h
  projects/csup_cvsmode/contrib/csup/lister.c
  projects/csup_cvsmode/contrib/csup/misc.c
  projects/csup_cvsmode/contrib/csup/misc.h
  projects/csup_cvsmode/contrib/csup/mux.c
  projects/csup_cvsmode/contrib/csup/proto.c
  projects/csup_cvsmode/contrib/csup/status.c
  projects/csup_cvsmode/contrib/csup/stream.c
  projects/csup_cvsmode/contrib/csup/stream.h
  projects/csup_cvsmode/contrib/csup/updater.c
  projects/csup_cvsmode/usr.bin/csup/Makefile

Modified: projects/csup_cvsmode/contrib/csup/Makefile
==============================================================================
--- projects/csup_cvsmode/contrib/csup/Makefile	Sun Oct 19 08:43:16 2008	(r184053)
+++ projects/csup_cvsmode/contrib/csup/Makefile	Sun Oct 19 09:08:59 2008	(r184054)
@@ -9,10 +9,11 @@ UNAME!=		/usr/bin/uname -s
 PROG=	csup
 SRCS=	attrstack.c config.c detailer.c diff.c fattr.c fixups.c fnmatch.c \
 	globtree.c idcache.c keyword.c lister.c main.c misc.c mux.c parse.y \
-	pathcomp.c proto.c status.c stream.c threads.c token.l updater.c
+	pathcomp.c proto.c status.c stream.c threads.c token.l updater.c \
+	rcsfile.c rcsparse.c lex.rcs.c
 
 CFLAGS+=	-I. -I${.CURDIR} -g -pthread -DHAVE_FFLAGS -DNDEBUG
-WARNS?=		6
+WARNS?=		1
 
 # A bit of tweaking is needed to get this Makefile working
 # with the bsd.prog.mk of all the *BSD OSes...

Modified: projects/csup_cvsmode/contrib/csup/config.c
==============================================================================
--- projects/csup_cvsmode/contrib/csup/config.c	Sun Oct 19 08:43:16 2008	(r184053)
+++ projects/csup_cvsmode/contrib/csup/config.c	Sun Oct 19 09:08:59 2008	(r184054)
@@ -444,10 +444,10 @@ coll_add(char *name)
 		    "\"%s\"\n", cur_coll->co_name);
 		exit(1);
 	}
-	if (!(cur_coll->co_options & CO_CHECKOUTMODE)) {
+/*	if (!(cur_coll->co_options & CO_CHECKOUTMODE)) {
 		lprintf(-1, "Client only supports checkout mode\n");
 		exit(1);
-	}
+	}*/
 	if (!STAILQ_EMPTY(&colls)) {
 		coll = STAILQ_LAST(&colls, coll, co_next);
 		if (strcmp(coll->co_host, cur_coll->co_host) != 0) {

Modified: projects/csup_cvsmode/contrib/csup/detailer.c
==============================================================================
--- projects/csup_cvsmode/contrib/csup/detailer.c	Sun Oct 19 08:43:16 2008	(r184053)
+++ projects/csup_cvsmode/contrib/csup/detailer.c	Sun Oct 19 09:08:59 2008	(r184054)
@@ -30,6 +30,11 @@
 #include <errno.h>
 #include <stdlib.h>
 #include <string.h>
+#include <stdio.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
 
 #include "config.h"
 #include "detailer.h"
@@ -37,6 +42,7 @@
 #include "misc.h"
 #include "mux.h"
 #include "proto.h"
+#include "rcsfile.h"
 #include "status.h"
 #include "stream.h"
 
@@ -56,8 +62,15 @@ struct detailer {
 static int	detailer_batch(struct detailer *);
 static int	detailer_coll(struct detailer *, struct coll *,
 		    struct status *);
-static int	detailer_dofile(struct detailer *, struct coll *,
+static int	detailer_dofile_co(struct detailer *, struct coll *,
 		    struct status *, char *);
+static int	detailer_dofile_rcs(struct detailer *, struct coll *, 
+		    char *, char *);
+static int	detailer_dofile_regular(struct detailer *, char *, char *);
+static int	detailer_checkrcsattr(struct detailer *, struct coll *, char *,
+		    struct fattr *, int);
+int		detailer_send_details(struct detailer *, struct coll *, char *,
+		    char *, struct fattr *);
 
 void *
 detailer(void *arg)
@@ -93,6 +106,7 @@ detailer(void *arg)
 			xasprintf(&args->errmsg, "Detailer failed: "
 			    "Network read failure: %s", strerror(errno));
 		}
+		lprintf(-1, "Error is '%s'\n", args->errmsg);
 		args->status = STATUS_TRANSIENTFAILURE;
 		break;
 	case DETAILER_ERR_WRITE:
@@ -131,8 +145,9 @@ detailer_batch(struct detailer *d)
 		error = proto_get_time(&line, &coll->co_scantime);
 		if (error || line != NULL || strcmp(cmd, "COLL") != 0 ||
 		    strcmp(collname, coll->co_name) != 0 ||
-		    strcmp(release, coll->co_release) != 0)
+		    strcmp(release, coll->co_release) != 0){ 
 			return (DETAILER_ERR_PROTO);
+		}
 		error = proto_printf(wr, "COLL %s %s\n", coll->co_name,
 		    coll->co_release);
 		if (error)
@@ -147,8 +162,9 @@ detailer_batch(struct detailer *d)
 			return (DETAILER_ERR_MSG);
 		error = detailer_coll(d, coll, st);
 		status_close(st, NULL);
-		if (error)
+		if (error) {
 			return (error);
+		}
 		if (coll->co_options & CO_COMPRESS) {
 			stream_filter_stop(rd);
 			stream_filter_stop(wr);
@@ -156,10 +172,12 @@ detailer_batch(struct detailer *d)
 		stream_flush(wr);
 	}
 	line = stream_getln(rd, NULL);
-	if (line == NULL)
+	if (line == NULL) {
 		return (DETAILER_ERR_READ);
-	if (strcmp(line, ".") != 0)
+	}
+	if (strcmp(line, ".") != 0) {
 		return (DETAILER_ERR_PROTO);
+	}
 	error = proto_printf(wr, ".\n");
 	if (error)
 		return (DETAILER_ERR_WRITE);
@@ -186,8 +204,13 @@ detailer_batch(struct detailer *d)
 			}
 			if (fixup->f_coll != coll)
 				break;
-			error = proto_printf(wr, "Y %s %s %s\n", fixup->f_name,
-			    coll->co_tag, coll->co_date);
+			if (coll->co_options & CO_CHECKOUTMODE)
+				error = proto_printf(wr, "Y %s %s %s\n",
+				    fixup->f_name, coll->co_tag, coll->co_date);
+			else {
+				error = proto_printf(wr, "A %s\n",
+				    fixup->f_name);
+			}
 			if (error)
 				return (DETAILER_ERR_WRITE);
 			fixup = NULL;
@@ -208,35 +231,107 @@ detailer_batch(struct detailer *d)
 static int
 detailer_coll(struct detailer *d, struct coll *coll, struct status *st)
 {
+	struct fattr *rcsattr;
 	struct stream *rd, *wr;
-	char *cmd, *file, *line, *msg;
-	int error;
+	char *attr, *cmd, *file, *line, *msg, *target, *path;
+	int error, attic;
 
 	rd = d->rd;
 	wr = d->wr;
+	attic = 0;
 	line = stream_getln(rd, NULL);
-	if (line == NULL)
+	if (line == NULL) {
 		return (DETAILER_ERR_READ);
+	}
 	while (strcmp(line, ".") != 0) {
 		cmd = proto_get_ascii(&line);
-		if (cmd == NULL || strlen(cmd) != 1)
+		if (cmd == NULL || strlen(cmd) != 1) {
 			return (DETAILER_ERR_PROTO);
+		}
 		switch (cmd[0]) {
 		case 'D':
 			/* Delete file. */
 			file = proto_get_ascii(&line);
+			if (file == NULL || line != NULL) {
+				return (DETAILER_ERR_PROTO); 
+			}
+			error = proto_printf(wr, "D %s\n", file);
+			if (error)
+				return (DETAILER_ERR_WRITE);
+			break;
+		case 'I':
+		case 'i':
+		case 'j':
+			/* Directory operations. */
+			file = proto_get_ascii(&line);
 			if (file == NULL || line != NULL)
 				return (DETAILER_ERR_PROTO);
-			error = proto_printf(wr, "D %s\n", file);
+			error = proto_printf(wr, "%s %s\n", cmd, file);
+			if (error)
+				return (DETAILER_ERR_WRITE);
+			break;
+		case 'J':
+			/* Set directory attributes. */
+			file = proto_get_ascii(&line);
+			attr = proto_get_ascii(&line);
+			if (file == NULL || line != NULL || attr == NULL)
+				return (DETAILER_ERR_PROTO);
+			error = proto_printf(wr, "%s %s %s\n", cmd, file, attr);
 			if (error)
 				return (DETAILER_ERR_WRITE);
 			break;
+		case 'H':
+		case 'h':
+			/* Create a hard link. */
+			file = proto_get_ascii(&line);
+			target = proto_get_ascii(&line);
+			if (file == NULL || target == NULL)
+				return (DETAILER_ERR_PROTO);
+			error = proto_printf(wr, "%s %s %s\n", cmd, file,
+			    target);
+			break;
+		case 't':
+			file = proto_get_ascii(&line);
+			attr = proto_get_ascii(&line);
+			if (file == NULL || attr == NULL || line != NULL) {
+				return (DETAILER_ERR_PROTO);
+			}
+			rcsattr = fattr_decode(attr);
+			if (rcsattr == NULL) {
+				return (DETAILER_ERR_PROTO);
+			}
+			error = detailer_checkrcsattr(d, coll, file, rcsattr,
+			    1);
+			break;
+
+		case 'T':
+			file = proto_get_ascii(&line);
+			attr = proto_get_ascii(&line);
+			if (file == NULL || attr == NULL || line != NULL)
+				return (DETAILER_ERR_PROTO);
+			rcsattr = fattr_decode(attr);
+			if (rcsattr == NULL)
+				return (DETAILER_ERR_PROTO);
+			error = detailer_checkrcsattr(d, coll, file, rcsattr,
+			    0);
+			break;
+
 		case 'U':
 			/* Add or update file. */
 			file = proto_get_ascii(&line);
 			if (file == NULL || line != NULL)
 				return (DETAILER_ERR_PROTO);
-			error = detailer_dofile(d, coll, st, file);
+			if (coll->co_options & CO_CHECKOUTMODE) {
+				error = detailer_dofile_co(d, coll, st, file);
+			} else {
+				path = cvspath(coll->co_prefix, file, 0);
+				rcsattr = fattr_frompath(path, FATTR_NOFOLLOW);
+				error = detailer_send_details(d, coll, file,
+				    path, rcsattr);
+				if (rcsattr != NULL)
+					fattr_free(rcsattr);
+				free(path);
+			}
 			if (error)
 				return (error);
 			break;
@@ -248,6 +343,7 @@ detailer_coll(struct detailer *d, struct
 			lprintf(-1, "Server warning: %s\n", msg);
 			break;
 		default:
+			lprintf(-1, "Line: %s, cmd %s\n", line, cmd);
 			return (DETAILER_ERR_PROTO);
 		}
 		stream_flush(wr);
@@ -261,8 +357,81 @@ detailer_coll(struct detailer *d, struct
 	return (0);
 }
 
+/*
+ * Tell the server to update a regular file.
+ */
 static int
-detailer_dofile(struct detailer *d, struct coll *coll, struct status *st,
+detailer_dofile_regular(struct detailer *d, char *name, char *path)
+{
+	struct stream *wr;
+	struct stat st;
+	char md5[MD5_DIGEST_SIZE];
+	int error;
+	
+	wr = d->wr;
+
+	error = stat(path, &st);
+	/* If we don't have it or it's unaccessible, we want it again. */
+	if (error) {
+		proto_printf(wr, "A %s\n", name);
+		return (0);
+	}
+
+	/* If not, we want the file to be updated. */
+	error = MD5_File(path, md5);
+	if (error) {
+		lprintf(-1, "Error reading \"%s\"\n", name);
+		return (error);
+	}
+	error = proto_printf(wr, "R %s %O %s\n", name, st.st_size, md5);
+	if (error)
+		return (DETAILER_ERR_WRITE);
+	return (0);
+}
+
+/*
+ * Tell the server to update an RCS file that we have, or send it if we don't.
+ */
+static int
+detailer_dofile_rcs(struct detailer *d, struct coll *coll, char *name,
+    char *path)
+{
+	struct stream *wr;
+	struct fattr *fa;
+	struct rcsfile *rf;
+	int error;
+
+	wr = d->wr;
+
+	path = atticpath(coll->co_prefix, name);
+	fa = fattr_frompath(path, FATTR_NOFOLLOW);
+	if (fa == NULL) {
+		/* We don't have it, so send request to get it. */
+		error = proto_printf(wr, "A %s\n", name);
+		if (error)
+			return (DETAILER_ERR_WRITE);
+		free(path);
+		return (0);
+	}
+
+	rf = rcsfile_frompath(path, name, coll->co_cvsroot, coll->co_tag);
+	free(path);
+	if (rf == NULL) {
+		lprintf(-1, "Error parsing, resend file.\n");
+		error = proto_printf(wr, "A %s\n", name);
+		if (error)
+			return (DETAILER_ERR_WRITE);
+		return (0);
+	}
+	/* Tell to update the RCS file. The client version details follow. */
+	rcsfile_send_details(rf, wr);
+	rcsfile_free(rf);
+	fattr_free(fa);
+	return (0);
+}
+
+static int
+detailer_dofile_co(struct detailer *d, struct coll *coll, struct status *st,
     char *file)
 {
 	char md5[MD5_DIGEST_SIZE];
@@ -274,8 +443,9 @@ detailer_dofile(struct detailer *d, stru
 
 	wr = d->wr;
 	path = checkoutpath(coll->co_prefix, file);
-	if (path == NULL)
+	if (path == NULL) {
 		return (DETAILER_ERR_PROTO);
+	}
 	fa = fattr_frompath(path, FATTR_NOFOLLOW);
 	if (fa == NULL) {
 		/* We don't have the file, so the only option at this
@@ -337,3 +507,78 @@ detailer_dofile(struct detailer *d, stru
 		return (DETAILER_ERR_WRITE);
 	return (0);
 }
+
+int
+detailer_checkrcsattr(struct detailer *d, struct coll *coll, char *name,
+    struct fattr *server_attr, int attic)
+{
+	struct fattr *client_attr;
+	char *attr, *path;
+	int error;
+
+	/* 
+	 * I don't think we can use the status file, since it only records file
+	 * attributes in cvsmode.
+	 */
+	client_attr = NULL;
+	path = cvspath(coll->co_prefix, name, attic);
+	if (path == NULL) {
+		return (DETAILER_ERR_PROTO);
+	}
+
+	if (access(path, F_OK) == 0 && 
+	    ((client_attr = fattr_frompath(path, FATTR_NOFOLLOW)) != NULL) &&
+	    fattr_equal(client_attr, server_attr)) {
+		attr = fattr_encode(client_attr, NULL, 0);
+		if (attic) {
+			error = proto_printf(d->wr, "l %s %s\n", name, attr);
+		} else {
+			error = proto_printf(d->wr, "L %s %s\n", name, attr);
+		}
+		free(attr);
+		free(path);
+		fattr_free(client_attr);
+		if (error)
+			return (DETAILER_ERR_WRITE);
+		return (0);
+	}
+	/* We don't have it, so tell the server to send it. */
+	error = detailer_send_details(d, coll, name, path, client_attr);
+	fattr_free(client_attr);
+	free(path);
+	return (error);
+}
+
+int
+detailer_send_details(struct detailer *d, struct coll *coll, char *name,
+    char *path, struct fattr *fa)
+{
+	int error;
+	size_t len;
+
+       /* 
+        * Try to check if the file exists either live or dead to see if we can
+        * edit it and put it live or dead, rather than receiving the entire
+        * file.
+	*/
+	if (fa == NULL) {
+		path = atticpath(coll->co_prefix, name); 
+		fa = fattr_frompath(path, FATTR_NOFOLLOW);
+	}
+	if (fa == NULL) {
+		error = proto_printf(d->wr, "A %s\n", name);
+		if (error)
+			return (DETAILER_ERR_WRITE);
+	} else if (fattr_type(fa) == FT_FILE) {
+		if (isrcs(name, &len) && !(coll->co_options & CO_NORCS)) {
+			detailer_dofile_rcs(d, coll, name, path);
+		} else {
+			detailer_dofile_regular(d, name, path);
+		}
+	} else {
+		error = proto_printf(d->wr, "N %s\n", name);
+		if (error)
+			return (DETAILER_ERR_WRITE);
+	}
+	return (0);
+}

Modified: projects/csup_cvsmode/contrib/csup/diff.c
==============================================================================
--- projects/csup_cvsmode/contrib/csup/diff.c	Sun Oct 19 08:43:16 2008	(r184053)
+++ projects/csup_cvsmode/contrib/csup/diff.c	Sun Oct 19 09:08:59 2008	(r184054)
@@ -26,25 +26,33 @@
  * $FreeBSD$
  */
 
+#include <sys/limits.h>
+
 #include <assert.h>
 #include <err.h>
 #include <errno.h>
 #include <stdlib.h>
 #include <string.h>
+#include <stdio.h>
 
 #include "diff.h"
 #include "keyword.h"
 #include "misc.h"
 #include "stream.h"
+#include "queue.h"
 
 typedef long lineno_t;
 
 #define	EC_ADD	0
 #define	EC_DEL	1
+#define MAXKEY LONG_MAX
 
 /* Editing command and state. */
 struct editcmd {
 	int cmd;
+	long key;
+	int havetext;
+	int offset;
 	lineno_t where;
 	lineno_t count;
 	lineno_t lasta;
@@ -55,15 +63,23 @@ struct editcmd {
 	struct diffinfo *di;
 	struct stream *orig;
 	struct stream *dest;
+	LIST_ENTRY(editcmd) next;
+};
+
+struct diffstart {
+	LIST_HEAD(, editcmd) dhead;
 };
 
 static int	diff_geteditcmd(struct editcmd *, char *);
 static int	diff_copyln(struct editcmd *, lineno_t);
+static int	diff_ignoreln(struct editcmd *, lineno_t);
 static void	diff_write(struct editcmd *, void *, size_t);
+static int	diff_insert_edit(struct diffstart *, struct editcmd *);
+static int	diff_free(struct diffstart *);
 
 int
 diff_apply(struct stream *rd, struct stream *orig, struct stream *dest,
-    struct keyword *keyword, struct diffinfo *di)
+    struct keyword *keyword, struct diffinfo *di, int comode)
 {
 	struct editcmd ec;
 	lineno_t i;
@@ -104,7 +120,7 @@ diff_apply(struct stream *rd, struct str
 				line = stream_getln(rd, &size);
 				if (line == NULL)
 					return (-1);
-				if (line[0] == '.') {
+				if (comode && line[0] == '.') {
 					line++;
 					size--;
 				}
@@ -143,6 +159,213 @@ diff_apply(struct stream *rd, struct str
 	return (0);
 }
 
+static int
+diff_write_reverse(struct stream *dest, struct diffstart *ds)
+{
+	long firstoutputlinedeleted, endline, startline, editline, num_deleted,
+	    num_added;
+	int num;
+	struct editcmd *ec, *nextec;
+
+	nextec = LIST_FIRST(&ds->dhead);
+	editline = 0;
+	num = 0;
+	while (nextec != NULL) {
+		ec = nextec;
+		nextec = LIST_NEXT(nextec, next);
+		if (nextec == NULL)
+			break;
+		num++;
+		num_deleted = 0;
+		if (ec->havetext)
+			num_deleted = ec->count;
+		num_added = num_deleted + nextec->offset - ec->offset;
+		if (num_deleted > 0) {
+			firstoutputlinedeleted = ec->key - num_deleted + 1;
+			stream_printf(dest, "d%ld %ld\n", firstoutputlinedeleted,
+			    num_deleted);
+			if (num_added <= 0)
+				continue;
+		}
+		if (num_added > 0) {
+			stream_printf(dest, "a%ld %ld\n", ec->key, num_added);
+			startline = ec->key - num_deleted + 1 + ec->offset;
+			endline = startline + num_added - 1;
+
+			/* Copy lines from original file. First ignore some. */
+			ec->editline = editline;
+			diff_ignoreln(ec,  startline - 1);
+			diff_copyln(ec, endline);
+			editline = ec->editline;
+		}
+	}
+	return (0);
+}
+
+/* 
+ * Insert a diff into the list sorted on key. Should perhaps use quicker
+ * algorithms than insertion sort, but do this for now.
+ */
+static int
+diff_insert_edit(struct diffstart *ds, struct editcmd *ec)
+{
+	struct editcmd *curec;
+
+	if (ec == NULL)
+		return (0);
+
+	if (LIST_EMPTY(&ds->dhead)) {
+		LIST_INSERT_HEAD(&ds->dhead, ec, next);
+		return (0);
+	}
+
+	/* Insertion sort based on key. */
+	/* XXX: check if this gets too slow. */
+	LIST_FOREACH(curec, &ds->dhead, next) {
+		if (ec->key < curec->key) {
+			LIST_INSERT_BEFORE(curec, ec, next);
+			return (0);
+		}
+		if (LIST_NEXT(curec, next) == NULL)
+			break;
+	}
+	/* Just insert it after. */
+	LIST_INSERT_AFTER(curec, ec, next);
+	return (0);
+}
+
+static int
+diff_free(struct diffstart *ds)
+{
+	struct editcmd *ec;
+	int freecount = 0;
+
+	while(!LIST_EMPTY(&ds->dhead)) {
+		ec = LIST_FIRST(&ds->dhead);
+		LIST_REMOVE(ec, next);
+		free(ec);
+		freecount++;
+	}
+	return freecount;
+}
+
+/*
+ * Write the reverse diff from the diff in rd, and original file into
+ * destination. This algorithm is the same as used in cvsup.
+ */
+int
+diff_reverse(struct stream *rd, struct stream *orig, struct stream *dest,
+    struct keyword *keyword, struct diffinfo *di)
+{
+	struct diffstart ds;
+	struct editcmd ec, *addec, *delec;
+	lineno_t i;
+	char *line;
+	int error, offset;
+	int malloccount = 0, freecount = 0;
+
+	memset(&ec, 0, sizeof(ec));
+	ec.orig = orig;
+	ec.dest = dest;
+	ec.keyword = keyword;
+	ec.di = di;
+	addec = NULL;
+	delec = NULL;
+	ec.havetext = 0;
+	offset = 0;
+	LIST_INIT(&ds.dhead);
+
+	/* Start with next since we need it. */
+	line = stream_getln(rd, NULL);
+	/* First we build up the list of diffs from input. */
+	while (line != NULL) {
+		error = diff_geteditcmd(&ec, line);
+		/*fprintf(stderr, "Diff line '%s'\n", line);*/
+		if (error)
+			break;
+		if (ec.cmd == EC_ADD) {
+			addec = xmalloc(sizeof(struct editcmd));
+			malloccount++;
+			*addec = ec;
+			addec->havetext = 1;
+			/* Ignore the lines we was supposed to add. */
+			for (i = 0; i < ec.count; i++) {
+				line = stream_getln(rd, NULL);
+				/*fprintf(stderr, "Diff line '%s'\n", line);*/
+				if (line == NULL)
+					return (-1);
+			}
+
+			/* Get the next diff command if we have one. */
+			addec->key = addec->where + addec->count - offset;
+			if (delec != NULL && delec->key == addec->key - addec->count) {
+				delec->key = addec->key;
+				delec->havetext = addec->havetext;
+				delec->count = addec->count;
+
+				diff_insert_edit(&ds, delec);
+				free(addec);
+				freecount++;
+				delec = NULL;
+				addec = NULL;
+			} else {
+				if (delec != NULL) {
+					diff_insert_edit(&ds, delec);
+				}
+				delec = NULL;
+				addec->offset = offset;
+				diff_insert_edit(&ds, addec);
+				addec = NULL;
+			}
+			offset -= ec.count;
+		} else if (ec.cmd == EC_DEL) {
+			if (delec != NULL) {
+				/* Update offset to our next. */
+				diff_insert_edit(&ds, delec);
+				delec = NULL;
+			}
+			delec = xmalloc(sizeof(struct editcmd));
+			malloccount++;
+			*delec = ec;
+			delec->key = delec->where - 1 - offset;
+			delec->offset = offset;
+			delec->count = 0;
+			delec->havetext = 0;
+			/* Important to use the count we had before reset.*/
+			offset += ec.count;
+		}
+		line = stream_getln(rd, NULL);
+	}
+
+	while (line != NULL) {
+		/*fprintf(stderr, "Diff line '%s'\n", line);*/
+		line = stream_getln(rd, NULL);
+	}
+	/*fprintf(stderr, "Done with diff\n");*/
+	if (delec != NULL) {
+		diff_insert_edit(&ds, delec);
+		delec = NULL;
+	}
+
+	addec = xmalloc(sizeof(struct editcmd));
+	malloccount++;
+	/* Should be filesize, but we set it to max value. */
+	addec->key = MAXKEY;
+	addec->offset = offset;
+	addec->havetext = 0;
+	addec->count = 0;
+	diff_insert_edit(&ds, addec);
+	addec = NULL;
+
+	/*fprintf(stderr, "Done with last diff\n");*/
+	diff_write_reverse(dest, &ds);
+	freecount += diff_free(&ds);
+	/*fprintf(stderr, "Diff did a total of %d mallocs\n", malloccount);
+	fprintf(stderr, "Diff did a total of %d frees\n", freecount);*/
+	stream_flush(dest);
+	return (0);
+}
+
 /* Get an editing command from the diff. */
 static int
 diff_geteditcmd(struct editcmd *ec, char *line)
@@ -194,6 +417,22 @@ diff_copyln(struct editcmd *ec, lineno_t
 	return (0);
 }
 
+/* Ignore lines from the original version of the file up to line "to". */
+static int
+diff_ignoreln(struct editcmd *ec, lineno_t to)
+{
+	char *line;
+	size_t size;
+
+	while (ec->editline < to) {
+		line = stream_getln(ec->orig, &size);
+		if (line == NULL)
+			return (-1);
+		ec->editline++;
+	}
+	return (0);
+}
+
 /* Write a new line to the file, expanding RCS keywords appropriately. */
 static void
 diff_write(struct editcmd *ec, void *buf, size_t size)

Modified: projects/csup_cvsmode/contrib/csup/diff.h
==============================================================================
--- projects/csup_cvsmode/contrib/csup/diff.h	Sun Oct 19 08:43:16 2008	(r184053)
+++ projects/csup_cvsmode/contrib/csup/diff.h	Sun Oct 19 09:08:59 2008	(r184054)
@@ -45,6 +45,8 @@ struct diffinfo {
 };
 
 int		 diff_apply(struct stream *, struct stream *, struct stream *,
-		     struct keyword *, struct diffinfo *);
+		     struct keyword *, struct diffinfo *, int);
+int		 diff_reverse(struct stream *, struct stream *,
+		     struct stream *, struct keyword *, struct diffinfo *);
 
 #endif /* !_DIFF_H_ */

Modified: projects/csup_cvsmode/contrib/csup/fattr.c
==============================================================================
--- projects/csup_cvsmode/contrib/csup/fattr.c	Sun Oct 19 08:43:16 2008	(r184053)
+++ projects/csup_cvsmode/contrib/csup/fattr.c	Sun Oct 19 09:08:59 2008	(r184054)
@@ -44,7 +44,7 @@
 /*
  * Include the appropriate definition for the file attributes we support.
  * There are two different files: fattr_bsd.h for BSD-like systems that
- * support the extended file flags à la chflags() and fattr_posix.h for
+ * support the extended file flags ? la chflags() and fattr_posix.h for
  * bare POSIX systems that don't.
  */
 #ifdef HAVE_FFLAGS
@@ -449,7 +449,7 @@ fattr_encode(const struct fattr *fa, fat
 		piece++;
 	}
 	if (mask & FA_DEV) {
-		vallen = snprintf(piece->val, sizeof(piece->val), "%lld",
+		vallen = snprintf(piece->val, sizeof(piece->val), "%llx",
 		    (long long)fa->dev);
 		len += snprintf(piece->len, sizeof(piece->len), "%lld",
 		    (long long)vallen) + vallen + 1;
@@ -534,6 +534,13 @@ fattr_getlinkcount(const struct fattr *f
 	return (fa->linkcount);
 }
 
+char *
+fattr_getlinktarget(const struct fattr *fa)
+{
+
+	return (fa->linktarget);
+}
+
 /*
  * Eat the specified attribute and put it in the file attribute
  * structure.  Returns NULL on error, or a pointer to the next
@@ -732,23 +739,32 @@ fattr_makenode(const struct fattr *fa, c
 	mode_t modemask, mode;
 	int error;
 
+	error = 0;
+
 	if (fa->mask & FA_OWNER && fa->mask & FA_GROUP)
 		modemask = FA_SETIDMASK | FA_PERMMASK;
 	else
 		modemask = FA_PERMMASK;
 
 	/* We only implement fattr_makenode() for dirs for now. */
-	assert(fa->type == FT_DIRECTORY);
 	if (fa->mask & FA_MODE)
 		mode = fa->mode & modemask;
 	else
 		mode = 0700;
-	error = mkdir(path, mode);
+
+	if (fa->type == FT_DIRECTORY)
+		error = mkdir(path, mode);
+	else if (fa->type == FT_SYMLINK) {
+		error = symlink(fa->linktarget, path);
+	} else if (fa->type == FT_CDEV) {
+		lprintf(-1, "Character devices not supported!\n");
+	} else if (fa->type == FT_BDEV) {
+		lprintf(-1, "Block devices not supported!\n");
+	}
 	return (error);
 }
 
-int
-fattr_delete(const char *path)
+int fattr_delete(const char *path)
 {
 	struct fattr *fa;
 	int error;
@@ -830,8 +846,9 @@ fattr_install(struct fattr *fa, const ch
 				error = rmdir(topath);
 			else
 				error = unlink(topath);
-			if (error)
+			if (error) {
 				goto bad;
+			}
 		}
 	}
 
@@ -842,8 +859,9 @@ fattr_install(struct fattr *fa, const ch
 		tv[1].tv_sec = fa->modtime;	/* Modification time. */
 		tv[1].tv_usec = 0;
 		error = utimes(frompath, tv);
-		if (error)
+		if (error) {
 			goto bad;
+		}
 	}
 	if (mask & FA_OWNER || mask & FA_GROUP) {
 		uid = -1;
@@ -853,8 +871,9 @@ fattr_install(struct fattr *fa, const ch
 		if (mask & FA_GROUP)
 			gid = fa->gid;
 		error = chown(frompath, uid, gid);
-		if (error)
+		if (error) {
 			goto bad;
+		}
 	}
 	if (mask & FA_MODE) {
 		newmode = fa->mode & modemask;
@@ -936,3 +955,12 @@ fattr_equal(const struct fattr *fa1, con
 			return (0);
 	return (1);
 }
+
+/*
+ * Must have to get the correct filesize sendt by the server.
+ */
+off_t
+fattr_filesize(const struct fattr *fa)
+{
+	return (fa->size);
+}

Modified: projects/csup_cvsmode/contrib/csup/fattr.h
==============================================================================
--- projects/csup_cvsmode/contrib/csup/fattr.h	Sun Oct 19 08:43:16 2008	(r184053)
+++ projects/csup_cvsmode/contrib/csup/fattr.h	Sun Oct 19 09:08:59 2008	(r184054)
@@ -101,6 +101,7 @@ int		 fattr_type(const struct fattr *);
 void		 fattr_maskout(struct fattr *, int);
 int		 fattr_getmask(const struct fattr *);
 nlink_t		 fattr_getlinkcount(const struct fattr *);
+char		*fattr_getlinktarget(const struct fattr *);
 void		 fattr_umask(struct fattr *, mode_t);
 void		 fattr_merge(struct fattr *, const struct fattr *);
 void		 fattr_mergedefault(struct fattr *);
@@ -111,5 +112,7 @@ int		 fattr_install(struct fattr *, cons
 int		 fattr_equal(const struct fattr *, const struct fattr *);
 void		 fattr_free(struct fattr *);
 int		 fattr_supported(int);
+off_t		 fattr_filesize(const struct fattr *);
+
 
 #endif /* !_FATTR_H_ */

Modified: projects/csup_cvsmode/contrib/csup/keyword.c
==============================================================================
--- projects/csup_cvsmode/contrib/csup/keyword.c	Sun Oct 19 08:43:16 2008	(r184053)
+++ projects/csup_cvsmode/contrib/csup/keyword.c	Sun Oct 19 09:08:59 2008	(r184054)
@@ -152,6 +152,29 @@ keyword_decode_expand(const char *expand
 		return (-1);
 }
 
+const char *
+keyword_encode_expand(int expand)
+{
+
+	switch (expand) {
+		case EXPAND_DEFAULT:
+			return (".");
+		case EXPAND_KEYVALUE:
+			return ("kv");
+		case EXPAND_KEYVALUELOCKER:
+			return ("kvl");
+		case EXPAND_KEY:
+			return ("k");
+		case EXPAND_OLD:
+			return ("o");
+		case EXPAND_BINARY:
+			return ("b");
+		case EXPAND_VALUE:
+			return ("v");
+	}
+	return (NULL);
+}
+
 void
 keyword_free(struct keyword *keyword)
 {

Modified: projects/csup_cvsmode/contrib/csup/keyword.h
==============================================================================
--- projects/csup_cvsmode/contrib/csup/keyword.h	Sun Oct 19 08:43:16 2008	(r184053)
+++ projects/csup_cvsmode/contrib/csup/keyword.h	Sun Oct 19 09:08:59 2008	(r184054)
@@ -42,6 +42,7 @@ struct keyword;
 
 struct keyword	*keyword_new(void);
 int		 keyword_decode_expand(const char *);
+const char	*keyword_encode_expand(int);
 int		 keyword_alias(struct keyword *, const char *, const char *);
 int		 keyword_enable(struct keyword *, const char *);
 int		 keyword_disable(struct keyword *, const char *);

Added: projects/csup_cvsmode/contrib/csup/lex.rcs.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ projects/csup_cvsmode/contrib/csup/lex.rcs.c	Sun Oct 19 09:08:59 2008	(r184054)
@@ -0,0 +1,2094 @@
+
+#line 3 "lex.rcs.c"
+
+#define  YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 35
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* First, we deal with  platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types. 
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t; 
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+#endif /* ! C99 */
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN               (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN              (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN              (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX               (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX              (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX              (2147483647)

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-projects mailing list