From info-cvs-request@prep.ai.mit.edu Tue May 23 12:24:27 1995
Received: from Sun.COM (Sun.COM [192.9.9.1]) by jupiter.cs.uml.edu (8.6.11/8.6.9) with SMTP id MAA29964 for <lechner@cs.uml.edu>; Tue, 23 May 1995 12:24:17 -0400
Received: from Central.Sun.COM (central.Central.Sun.COM) by Sun.COM (sun-barr.Sun.COM)
	id AA20046; Tue, 23 May 95 09:16:58 PDT
Received: from rmtc.Central.Sun.COM by Central.Sun.COM (5.0/SMI-5.3)
	id AA18589; Tue, 23 May 1995 11:16:46 -0500
Received: by rmtc.Central.Sun.COM (5.x/SMI-SVR4)
	id AA24335; Tue, 23 May 1995 10:05:53 -0600
Received: from Central.Sun.COM by rmtc.Central.Sun.COM (5.x/SMI-SVR4)
	id AA24327; Tue, 23 May 1995 10:05:49 -0600
Received: from Sun.COM (sun-barr.EBay.Sun.COM) by Central.Sun.COM (5.0/SMI-5.3)
	id AA17993; Tue, 23 May 1995 11:05:26 -0500
Received: from life.ai.mit.edu by Sun.COM (sun-barr.Sun.COM)
	id AA17527; Tue, 23 May 95 09:05:17 PDT
Received: from bou.shl.com (merlin.bou.shl.com) by life.ai.mit.edu (4.1/AI-4.10) for info-cvs@rmtc.central.sun.com id AA13524; Tue, 23 May 95 12:05:07 EDT
Received: from whatnow by bou.shl.com (NX5.67d/NX3.0Ma)
	id AA12807; Tue, 23 May 95 10:04:29 -0600
Message-Id: <9505231604.AA12807@bou.shl.com>
Received: by whatnow.bou.shl.com (NX5.67e/NX3.0X)
	id AA12670; Tue, 23 May 95 10:04:23 -0600
Content-Type: text/plain
Mime-Version: 1.0 (NeXT Mail 3.3 v118.2)
Received: by NeXT.Mailer (1.118.2)
From: Vince Demarco <vdemarco@bou.shl.com>
Date: Tue, 23 May 95 10:04:17 -0600
To: zoo@armadillo.com, info-cvs@prep.ai.mit.edu
Subject: cvswrappers
Content-Length: 47596
Status: RO


Here are the patchs that add the notion of wrappers to cvs.

The wrappers package also a form of support for binary files.

The wrappers code that i have integrated into 1.4A2 has the is this file  
mergable flag.

What it does is use a regex to match a file name for example

*.tiff  -m 'COPY'

Which means that all files ending with .tiff should not be merged only  
copyed into the repository.

All of the matching is done using the fnmatch function in cvs (which does  
globing i believe)

hope this helps and becomes part of the standard release.

(Does anyone have any idea when A3 is going to be released???, there have  
been a ton of patches posted to the net in the last little while)

This stuff is still beta.

vince


diff -cNwr cvs-1.4A2/examples/Makefile.in cvs-1.4A2.v/examples/Makefile.in
*** cvs-1.4A2/examples/Makefile.in	Fri Oct 21 19:56:14 1994
--- cvs-1.4A2.v/examples/Makefile.in	Mon May 22 20:03:10 1995
***************
*** 41,49 ****
  INSTALL_DATA = @INSTALL_DATA@
  INSTALL_PROGRAM = @INSTALL_PROGRAM@

! EXAMPLE_FILES = commitinfo editinfo loginfo modules rcsinfo

! DISTFILES = Makefile.in commitinfo loginfo modules rcsinfo

  all: Makefile
  .PHONY: all
--- 41,49 ----
  INSTALL_DATA = @INSTALL_DATA@
  INSTALL_PROGRAM = @INSTALL_PROGRAM@

! EXAMPLE_FILES = commitinfo editinfo loginfo modules rcsinfo cvswrappers  
comb uncom

! DISTFILES = Makefile.in commitinfo loginfo modules rcsinfo cvswrappers comb uncom

  all: Makefile
  .PHONY: all
diff -cNwr cvs-1.4A2/examples/comb cvs-1.4A2.v/examples/comb
*** cvs-1.4A2/examples/comb	Wed Dec 31 17:00:00 1969
--- cvs-1.4A2.v/examples/comb	Mon May 22 20:03:38 1995
***************
*** 0 ****
--- 1,14 ----
+ #!/bin/sh
+ #
+ # Combine a directory into a single tar package.
+ #
+
+ # move the file to a new name with an extension
+ rm -rf $1.cvswrap
+ mv $1 $1.cvswrap
+
+ # untar the file
+ gzcat $1.cvswrap | gnutar --preserve --sparse -x -f -
+
+ # remove the original
+ rm -rf $1.cvswrap
diff -cNwr cvs-1.4A2/examples/cvswrappers cvs-1.4A2.v/examples/cvswrappers
*** cvs-1.4A2/examples/cvswrappers	Wed Dec 31 17:00:00 1969
--- cvs-1.4A2.v/examples/cvswrappers	Mon May 22 20:08:19 1995
***************
*** 0 ****
--- 1,33 ----
+ #
+ # This file describes wrappers and other binary files to CVS
+ # Wrappers are the concept where directories of files are to be treated
+ # as a single file. The intended use is to wrap up a wrapper into a single tar
+ # such that the tar archive can be treated as a single binary file
+ # in CVS.
+ # To solve the problem effectively, it was also necessary to be able to
+ # prevent rcsmerge from merging these files.
+ #  ------------------
+ #  Format of wrapper file ($CVSROOT/CVSROOT/cvswrappers or .cvswrappers)
+ #
+ #  wildcard	[option value][option value]...
+ #
+ #  where option is one of
+ #  -f		from cvs filter		value: path to filter
+ #  -t		to cvs filter		value: path to filter
+ #  -m		update methodology	value: MERGE or COPY
+ #
+ #  and value is a single-quote delimited value.
+ #
+ #
+
+ *.nib    -f '/TestRepository/CVSROOT/comb %s' -t  
'/TestRepository/CVSROOT/uncom %s %s' -m 'COPY'
+ *.rtfd   -f '/TestRepository/CVSROOT/comb %s' -t  
'/TestRepository/CVSROOT/uncom %s %s' -m 'COPY'
+ *.draw   -f '/TestRepository/CVSROOT/comb %s' -t  
'/TestRepository/CVSROOT/uncom %s %s' -m 'COPY'
+ *.Mesa   -f '/TestRepository/CVSROOT/comb %s' -t  
'/TestRepository/CVSROOT/uncom %s %s' -m 'COPY'
+ *.diagram2 -f '/TestRepository/CVSROOT/comb %s' -t  
'/TestRepository/CVSROOT/uncom %s %s' -m 'COPY'
+ *.taskmaster -f '/TestRepository/CVSROOT/comb %s' -t  
'/TestRepository/CVSROOT/uncom %s %s' -m 'COPY'
+ *.concur -f '/TestRepository/CVSROOT/comb %s' -t  
'/TestRepository/CVSROOT/uncom %s %s' -m 'COPY'
+ *.nb     -f '/TestRepository/CVSROOT/comb %s' -t  
'/TestRepository/CVSROOT/uncom %s %s' -m 'COPY'
+ *.wub    -f '/TestRepository/CVSROOT/comb %s' -t  
'/TestRepository/CVSROOT/uncom %s %s' -m 'COPY'
+ *.pub    -f '/TestRepository/CVSROOT/comb %s' -t  
'/TestRepository/CVSROOT/uncom %s %s' -m 'COPY'
+ *.tiff   -m 'COPY'
diff -cNwr cvs-1.4A2/examples/uncom cvs-1.4A2.v/examples/uncom
*** cvs-1.4A2/examples/uncom	Wed Dec 31 17:00:00 1969
--- cvs-1.4A2.v/examples/uncom	Mon May 22 20:04:17 1995
***************
*** 0 ****
--- 1,6 ----
+ #!/bin/sh
+ #
+ # extract the combined package (created with comb)
+ # into the individual components.
+ #
+ gnutar --preserve --sparse -zcf - $1 > $2
diff -cNwr cvs-1.4A2/src/Makefile.in cvs-1.4A2.v/src/Makefile.in
*** cvs-1.4A2/src/Makefile.in	Wed Sep 28 21:53:56 1994
--- cvs-1.4A2.v/src/Makefile.in	Fri May 19 14:09:25 1995
***************
*** 46,59 ****
  create_adm.c cvsrc.c diff.c entries.c find_names.c hash.c history.c ignore.c \
  import.c lock.c log.c logmsg.c main.c myndbm.c rcs.c modules.c \
  no_diff.c parseinfo.c patch.c recurse.c release.c remove.c repos.c rtag.c \
! status.c tag.c update.c vers_ts.c version.c root.c subr.c
  MSOURCES = mkmodules.c

  OBJECTS = add.o admin.o checkin.o checkout.o classify.o commit.o \
  create_adm.o cvsrc.o diff.o entries.o find_names.o hash.o history.o \
  ignore.o import.o lock.o log.o logmsg.o main.o modules.o myndbm.o no_diff.o \
  parseinfo.o patch.o rcs.o recurse.o release.o remove.o repos.o root.o \
! rtag.o status.o tag.o update.o vers_ts.o

  MOBJECTS = hash.o mkmodules.o myndbm.o

--- 46,59 ----
  create_adm.c cvsrc.c diff.c entries.c find_names.c hash.c history.c ignore.c \
  import.c lock.c log.c logmsg.c main.c myndbm.c rcs.c modules.c \
  no_diff.c parseinfo.c patch.c recurse.c release.c remove.c repos.c rtag.c \
! status.c tag.c update.c vers_ts.c version.c root.c subr.c wrapper.c
  MSOURCES = mkmodules.c

  OBJECTS = add.o admin.o checkin.o checkout.o classify.o commit.o \
  create_adm.o cvsrc.o diff.o entries.o find_names.o hash.o history.o \
  ignore.o import.o lock.o log.o logmsg.o main.o modules.o myndbm.o no_diff.o \
  parseinfo.o patch.o rcs.o recurse.o release.o remove.o repos.o root.o \
! rtag.o status.o tag.o update.o wrapper.o vers_ts.o

  MOBJECTS = hash.o mkmodules.o myndbm.o

diff -cNwr cvs-1.4A2/src/add.c cvs-1.4A2.v/src/add.c
*** cvs-1.4A2/src/add.c	Fri Oct 21 20:10:39 1994
--- cvs-1.4A2.v/src/add.c	Fri May 19 14:21:07 1995
***************
*** 62,67 ****
--- 62,69 ----
      if (argc == 1 || argc == -1)
  	usage (add_usage);

+     wrap_setup(); /* CVSWRAPPER */
+
      /* parse args */
      optind = 1;
      while ((c = getopt (argc, argv, "k:m:")) != -1)
***************
*** 122,128 ****
  		    error (0, 0, "nothing known about %s", user);
  		    err++;
  		}
! 		else if (!isdir (user))
  		{
  		    /*
  		     * See if a directory exists in the repository with
--- 124,130 ----
  		    error (0, 0, "nothing known about %s", user);
  		    err++;
  		}
! 		else if (!isdir (user) || wrap_name_has(user,WRAP_TOCVS)) /*  
CVSWRAPPER */
  		{
  		    /*
  		     * See if a directory exists in the repository with
***************
*** 148,154 ****
  		    {
  		      added_files++;
  		      if (!quiet)
! 		        error (0, 0, "scheduling file `%s' for addition", user);
  		    }
  		}
  	    }
--- 150,157 ----
  		    {
  		      added_files++;
  		      if (!quiet)
! 		        error (0, 0, "scheduling file `%s' for addition",
! 			       wrap_name_has(user,WRAP_TOCVS) ?  
"wrapper":"file",user); /* CVSWRAPPER */
  		    }
  		}
  	    }
***************
*** 235,241 ****
  	freevers_ts (&vers);

  	/* passed all the checks.  Go ahead and add it if its a directory */
! 	if (begin_err == err && isdir (user))
  	{
  	    err += add_directory (repository, user);
  	    continue;
--- 238,244 ----
  	freevers_ts (&vers);

  	/* passed all the checks.  Go ahead and add it if its a directory */
! 	if (begin_err == err && isdir (user)&&  
!wrap_name_has(user,WRAP_TOCVS)) /* CVSWRAPPER */
  	{
  	    err += add_directory (repository, user);
  	    continue;
diff -cNwr cvs-1.4A2/src/admin.c cvs-1.4A2.v/src/admin.c
*** cvs-1.4A2/src/admin.c	Fri Sep 30 01:39:21 1994
--- cvs-1.4A2.v/src/admin.c	Fri May 19 16:14:27 1995
***************
*** 42,47 ****
--- 42,49 ----
      if (argc <= 1)
  	usage (admin_usage);

+     wrap_setup(); /* CVSWRAPPER */
+
      /* skip all optional arguments to see if we have any file names */
      for (ac = 1; ac < argc; ac++)
  	if (argv[ac][0] != '-')
***************
*** 56,62 ****
      /* start the recursion processor */
      err = start_recursion (admin_fileproc, (int (*) ()) NULL, admin_dirproc,
  			   (int (*) ()) NULL, argc, argv, 0,
! 			   W_LOCAL, 0, 1, (char *) NULL, 1, 0);
      return (err);
  }

--- 58,64 ----
      /* start the recursion processor */
      err = start_recursion (admin_fileproc, (int (*) ()) NULL, admin_dirproc,
  			   (int (*) ()) NULL, argc, argv, 0,
! 			   W_LOCAL, 0, 1, (char *) NULL, 1, 0,0);
      return (err);
  }

diff -cNwr cvs-1.4A2/src/checkin.c cvs-1.4A2.v/src/checkin.c
*** cvs-1.4A2/src/checkin.c	Fri Oct  7 01:15:32 1994
--- cvs-1.4A2.v/src/checkin.c	Mon May 22 19:32:00 1995
***************
*** 37,42 ****
--- 37,44 ----
      char fname[PATH_MAX];
      Vers_TS *vers;
      int set_time;
+     char    *tocvsPath=NULL; /* CVSWRAPPERS */
+     char    *filePath; /* CVSWRAPPERS */

      (void) printf ("Checking in %s;\n", file);
      (void) sprintf (fname, "%s/%s%s", CVSADM, CVSPREFIX, file);
***************
*** 46,53 ****
       * modification times, then place a copy back in the original file name
       * for the checkin and checkout.
       */
!     if (!noexec)
  	copy_file (file, fname);

      run_setup ("%s%s -f %s%s", Rcsbin, RCS_CI,
  	       rev ? "-r" : "", rev ? rev : "");
--- 48,68 ----
       * modification times, then place a copy back in the original file name
       * for the checkin and checkout.
       */
!
!     tocvsPath = wrap_tocvs_process_file(file);
!     filePath  = (tocvsPath==NULL ? file:tocvsPath);
!
!     if (!noexec){
! 	unlink_file (fname);
!
! 	if (tocvsPath){
! 	    copy_file (tocvsPath, fname);
! 	    unlink_file (file);
! 	    copy_file (tocvsPath, file);
! 	}else{
  	    copy_file (file, fname);
+ 	}
+     }

      run_setup ("%s%s -f %s%s", Rcsbin, RCS_CI,
  	       rev ? "-r" : "", rev ? rev : "");
***************
*** 68,73 ****
--- 83,94 ----
  	     * original user file.
  	     */

+ 		/* CVSWRAPPERS */
+ 	    if (!noexec){
+ 		if (isfile(file) && unlink_file(file))
+ 		    error(0,0, "warning: could not remove %s before 'co'",file);
+ 	    }
+
  	    if (strcmp (options, "-V4") == 0) /* upgrade to V5 now */
  		options[0] = '\0';
  	    run_setup ("%s%s -q %s %s%s", Rcsbin, RCS_CO, options,
***************
*** 77,82 ****
--- 98,104 ----
  	    xchmod (file, 1);
  	    if (xcmp (file, fname) == 0)
  	    {
+ 		unlink_file (file);
  		rename_file (fname, file);
  		/* the time was correct, so leave it alone */
  		set_time = 0;
***************
*** 88,93 ****
--- 110,117 ----
  		set_time = 1;
  	    }

+ 	    wrap_fromcvs_process_file(file); /* CVSWRAPPERS */
+
  	    /*
  	     * If we want read-only files, muck the permissions here, before
  	     * getting the file time-stamp.
***************
*** 112,120 ****
--- 136,148 ----
  		      vers->options, vers->tag, vers->date, (char *) 0);
  	    history_write (type, (char *) 0, vers->vn_rcs, file, repository);
  	    freevers_ts (&vers);
+ 	    if (tocvsPath) /* CVSWRAPPERS */
+ 		unlink_file(tocvsPath);
  	    break;

  	case -1:			/* fork failed */
+ 	    if (tocvsPath) /* CVSWRAPPERS */
+ 		unlink_file(tocvsPath);
  	    if (!noexec)
  		error (1, errno, "could not check in %s -- fork failed", file);
  	    return (1);
***************
*** 125,130 ****
--- 153,160 ----
  	     * The checkin failed, for some unknown reason, so we restore the
  	     * original user file, print an error, and return an error
  	     */
+ 	    if (tocvsPath) /* CVSWRAPPERS */
+ 		unlink_file(tocvsPath);
  	    if (!noexec)
  	    {
  		rename_file (fname, file);
diff -cNwr cvs-1.4A2/src/checkout.c cvs-1.4A2.v/src/checkout.c
*** cvs-1.4A2/src/checkout.c	Fri Oct  7 01:15:33 1994
--- cvs-1.4A2.v/src/checkout.c	Fri May 19 14:35:50 1995
***************
*** 132,137 ****
--- 132,138 ----
  	usage (valid_usage);

      ign_setup ();
+     wrap_setup(); /* CVSWRAPPERS */

      optind = 1;
      while ((c = getopt (argc, argv, valid_options)) != -1)
diff -cNwr cvs-1.4A2/src/commit.c cvs-1.4A2.v/src/commit.c
*** cvs-1.4A2/src/commit.c	Fri Oct  7 01:15:35 1994
--- cvs-1.4A2.v/src/commit.c	Fri May 19 16:20:41 1995
***************
*** 207,212 ****
--- 207,214 ----
      if (argc <= 0)
  	write_dirtag = tag;

+     wrap_setup(); /* CVSWRAPPERS */
+
      /*
       * Run the recursion processor to find all the dirs to lock and lock all
       * the dirs
***************
*** 215,221 ****
      err = start_recursion ((int (*) ()) NULL, lock_filesdoneproc,
  			   (Dtype (*) ()) NULL, (int (*) ()) NULL, argc,
  			   argv, local, W_LOCAL, aflag, 0, (char *) NULL, 0,
! 			   0);
      sortlist (locklist, fsortcmp);
      if (Writer_Lock (locklist) != 0)
  	error (1, 0, "lock failed - giving up");
--- 217,223 ----
      err = start_recursion ((int (*) ()) NULL, lock_filesdoneproc,
  			   (Dtype (*) ()) NULL, (int (*) ()) NULL, argc,
  			   argv, local, W_LOCAL, aflag, 0, (char *) NULL, 0,
! 			   0,0);
      sortlist (locklist, fsortcmp);
      if (Writer_Lock (locklist) != 0)
  	error (1, 0, "lock failed - giving up");
***************
*** 231,237 ****
      err = start_recursion (check_fileproc, check_filesdoneproc,
  			   check_direntproc, (int (*) ()) NULL, argc,
  			   argv, local, W_LOCAL, aflag, 0, (char *) NULL, 1,
! 			   0);
      if (err)
      {
  	Lock_Cleanup ();
--- 233,239 ----
      err = start_recursion (check_fileproc, check_filesdoneproc,
  			   check_direntproc, (int (*) ()) NULL, argc,
  			   argv, local, W_LOCAL, aflag, 0, (char *) NULL, 1,
! 			   0,0);
      if (err)
      {
  	Lock_Cleanup ();
***************
*** 245,251 ****
  	err = start_recursion (commit_fileproc, commit_filesdoneproc,
  			       commit_direntproc, commit_dirleaveproc,
  			       argc, argv, local, W_LOCAL, aflag, 0,
! 			       (char *) NULL, 1, 0);

      /*
       * Unlock all the dirs and clean up
--- 247,253 ----
  	err = start_recursion (commit_fileproc, commit_filesdoneproc,
  			       commit_direntproc, commit_dirleaveproc,
  			       argc, argv, local, W_LOCAL, aflag, 0,
! 			       (char *) NULL, 1, 0, 0);

      /*
       * Unlock all the dirs and clean up
diff -cNwr cvs-1.4A2/src/cvs.h cvs-1.4A2.v/src/cvs.h
*** cvs-1.4A2/src/cvs.h	Fri Oct 21 20:10:40 1994
--- cvs-1.4A2.v/src/cvs.h	Mon May 22 16:22:13 1995
***************
*** 151,156 ****
--- 151,157 ----
  #define	CVSROOTADM_HISTORY	"history"
  #define	CVSROOTADM_IGNORE	"cvsignore"
  #define	CVSROOTADM_CHECKOUTLIST "checkoutlist"
+ #define CVSROOTADM_WRAPPER      "cvswrappers"
  #define CVSNULLREPOS		"Emptydir"	/* an empty directory */

  /* support for the modules file (CVSROOTADM_MODULES) */
***************
*** 174,179 ****
--- 175,181 ----
  #define	CVSEXT_LOG	",t"
  #define	CVSPREFIX	",,"
  #define CVSDOTIGNORE	".cvsignore"
+ #define CVSDOTWRAPPER   ".cvswrappers"

  /* miscellaneous CVS defines */
  #define	CVSEDITPREFIX	"CVS: "
***************
*** 209,214 ****
--- 211,217 ----
  #define	CVSROOT_DFLT	NULL		/* No dflt; must set for  
checkout */

  #define	IGNORE_ENV	"CVSIGNORE"	/* More files to ignore */
+ #define WRAPPER_ENV     "CVSWRAPPERS"	/* name of the wrapper file */

  /*
   * If the beginning of the Repository matches the following string, strip it
***************
*** 441,447 ****
  		     Dtype PROTO((*direntproc)) (), int PROTO((*dirleaveproc)) (),
  		     int argc, char *argv[], int local, int which,
  		     int aflag, int readlock, char *update_preload,
! 		     int dosrcs, int wd_is_repos));
  void SIG_beginCrSect PROTO((void));
  void SIG_endCrSect PROTO((void));
  void read_cvsrc PROTO((int *argc, char ***argv));
--- 444,462 ----
  		     Dtype PROTO((*direntproc)) (), int PROTO((*dirleaveproc)) (),
  		     int argc, char *argv[], int local, int which,
  		     int aflag, int readlock, char *update_preload,
! 		     int dosrcs, int wd_is_repos,int intoWrappers));
  void SIG_beginCrSect PROTO((void));
  void SIG_endCrSect PROTO((void));
  void read_cvsrc PROTO((int *argc, char ***argv));
+
+
+ typedef enum { WRAP_MERGE, WRAP_COPY } WrapMergeMethod;
+ typedef enum { WRAP_TOCVS, WRAP_FROMCVS, WRAP_CONFLICT } WrapMergeHas;
+
+ void  wrap_setup PROTO((void));
+ int   wrap_name_has PROTO((char *name,WrapMergeHas has));
+ char *wrap_tocvs_process_file PROTO((char *fileName));
+ void  wrap_tocvs_cleanup PROTO((char *fileName));
+ int   wrap_merge_is_copy PROTO((char *fileName));
+ char *wrap_fromcvs_process_file PROTO((char *fileName));
+
diff -cNwr cvs-1.4A2/src/diff.c cvs-1.4A2.v/src/diff.c
*** cvs-1.4A2/src/diff.c	Fri Oct 21 18:57:20 1994
--- cvs-1.4A2.v/src/diff.c	Mon May 22 19:32:14 1995
***************
*** 154,163 ****
      if (diff_rev2 != NULL || diff_date2 != NULL)
  	which |= W_REPOS | W_ATTIC;

      /* start the recursion processor */
      err = start_recursion (diff_fileproc, diff_filesdoneproc, diff_dirproc,
  			   diff_dirleaveproc, argc, argv, local,
! 			   which, 0, 1, (char *) NULL, 1, 0);

      /* clean up */
      free (options);
--- 154,165 ----
      if (diff_rev2 != NULL || diff_date2 != NULL)
  	which |= W_REPOS | W_ATTIC;

+     wrap_setup(); /* CVSWRAPPERS */
+
      /* start the recursion processor */
      err = start_recursion (diff_fileproc, diff_filesdoneproc, diff_dirproc,
  			   diff_dirleaveproc, argc, argv, local,
! 			   which, 0, 1, (char *) NULL, 1, 0, 0);

      /* clean up */
      free (options);
***************
*** 185,190 ****
--- 187,194 ----
  	DIFF_NEITHER
      } empty_file = DIFF_NEITHER;
      char tmp[L_tmpnam+1];
+     char *tocvsPath;
+     char  fname[PATH_MAX];

      vers = Version_TS (repository, (char *) NULL, (char *) NULL, (char *) NULL,
  		       file, 1, 0, entries, srcfiles);
***************
*** 260,265 ****
--- 264,281 ----
  	(void) printf ("Index: %s\n", file);
      (void) fflush (stdout);

+ 	/* CVSWRAPPERS */
+     tocvsPath = wrap_tocvs_process_file(file);
+     if (tocvsPath)
+     {
+ 	    /* Backup the current version of the file to CVS/,,filename */
+ 	sprintf(fname,"%s/%s%s",CVSADM, CVSPREFIX, file);
+ 	unlink_file (fname);
+ 	rename_file(file,fname);
+ 	    /* Copy the wrapped file to the current directory then go to work */
+ 	copy_file(tocvsPath,file);
+     }
+
      if (empty_file == DIFF_ADDED || empty_file == DIFF_REMOVED)
      {
  	(void) printf  
("===================================================================\nRCS  
file: %s\n",
***************
*** 318,323 ****
--- 334,345 ----
  	default:			/* other error */
  	    err = status;
  	    break;
+     }
+ 	/* CVSWRAPPERS */
+     if (tocvsPath){
+ 	unlink_file (file);
+ 	rename_file (fname,file);
+ 	unlink_file(tocvsPath);
      }

      if (empty_file == DIFF_REMOVED)
diff -cNwr cvs-1.4A2/src/import.c cvs-1.4A2.v/src/import.c
*** cvs-1.4A2/src/import.c	Fri Sep 30 01:39:29 1994
--- cvs-1.4A2.v/src/import.c	Mon May 22 19:33:09 1995
***************
*** 95,100 ****
--- 95,101 ----
  	usage (import_usage);

      ign_setup ();
+     wrap_setup ();

      (void) strcpy (vbranch, CVSBRANCH);
      optind = 1;
***************
*** 131,136 ****
--- 132,140 ----
  		else
  		  usage (keyword_usage);
  		break;
+             case 'W':		/* CVSWRAPPERS */
+ 		wrap_add (optarg, 0);
+ 		break;
  	    case '?':
  	    default:
  		usage (import_usage);
***************
*** 277,282 ****
--- 281,287 ----

      /* first, load up any per-directory ignore lists */
      ign_add_file (CVSDOTIGNORE, 1);
+     wrap_add_file (CVSDOTWRAPPER, 1);

      if ((dirp = opendir (".")) == NULL)
      {
***************
*** 293,299 ****
  		add_log ('I', dp->d_name);
  		continue;
  	    }
! 	    if (isdir (dp->d_name))
  	    {
  		has_dirs = 1;
  	    }
--- 298,304 ----
  		add_log ('I', dp->d_name);
  		continue;
  	    }
! 	    if (isdir (dp->d_name) && !wrap_name_has(dp->d_name,WRAP_TOCVS))  
/* CVSWRAPPERS */
  	    {
  		has_dirs = 1;
  	    }
***************
*** 323,329 ****
  	    {
  		if (!strcmp(".", dp->d_name) || !strcmp("..", dp->d_name))
  		    continue;
! 		if (!isdir (dp->d_name) || ign_name (dp->d_name))
  		    continue;
  		err += import_descend_dir (message, dp->d_name,
  					   vtag, targc, targv);
--- 328,334 ----
  	    {
  		if (!strcmp(".", dp->d_name) || !strcmp("..", dp->d_name))
  		    continue;
! 		if (!isdir (dp->d_name) || ign_name (dp->d_name) ||  
wrap_name_has(dp->d_name,WRAP_TOCVS))
  		    continue;
  		err += import_descend_dir (message, dp->d_name,
  					   vtag, targc, targv);
***************
*** 392,397 ****
--- 397,403 ----
      int letter;
      int ierrno;
      char *tmpdir;
+     char *tocvsPath;

      vers = Version_TS (repository, (char *) NULL, vbranch, (char *) NULL, vfile,
  		       1, 0, (List *) NULL, (List *) NULL);
***************
*** 435,442 ****
  	    (void) unlink_file (xtmpfile);
  	    return (1);
  	}
! 	different = xcmp (xtmpfile, vfile);
  	(void) unlink_file (xtmpfile);
  	if (!different)
  	{
  	    int retval = 0;
--- 441,454 ----
  	    (void) unlink_file (xtmpfile);
  	    return (1);
  	}
! 	    /* CVSWRAPPERS */
!         tocvsPath=wrap_tocvs_process_file(vfile);
!         different = xcmp (xtmpfile,(tocvsPath==NULL ? vfile:tocvsPath));
! 	if (tocvsPath)
! 	    unlink_file(tocvsPath);
!
  	(void) unlink_file (xtmpfile);
+
  	if (!different)
  	{
  	    int retval = 0;
***************
*** 489,494 ****
--- 501,507 ----
  {
      int locked, status, ierrno;
      int retcode = 0;
+     char *tocvsPath;

      if (noexec)
  	return (0);
***************
*** 506,511 ****
--- 519,526 ----
  	    return (1);
  	}
      }
+     if((tocvsPath=wrap_tocvs_process_file(vfile))==NULL) /* CVSWRAPPERS */
+     {
  	if (link_file (vfile, FILE_HOLDER) < 0)
  	{
  	    if (errno == EEXIST)
***************
*** 521,534 ****
--- 536,558 ----
  		return (1);
  	    }
  	}
+     }
+
      run_setup ("%s%s -q -f -r%s", Rcsbin, RCS_CI, vbranch);
      run_args ("-m%s", message);
      if (use_file_modtime)
  	run_arg ("-d");
+     run_arg ((tocvsPath==NULL ? vfile:tocvsPath)); /* CVSWRAPPERS */
      run_arg (rcs);
      status = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL);
      ierrno = errno;
+
+ 	/* CVSWRAPPERS */
+     if (tocvsPath == NULL)
  	rename_file (FILE_HOLDER, vfile);
+     if (tocvsPath)
+ 	unlink_file(tocvsPath);
+
      if (status)
      {
  	if (!noexec)
***************
*** 628,633 ****
--- 652,658 ----
      "cc", "// ",
      "cpp", "// ",
      "cxx", "// ",
+     "m", " * ",				/* Objective-C   */
      "cl", ";;; ",			/* Common Lisp	 */
      "cmd", ":: ",			/* command (OS/2) */
      "cmf", "c ",			/* CM Fortran	 */
***************
*** 666,671 ****
--- 691,698 ----
      "pas", " * ",
      "pl", "# ",				/* perl	(conflict with Prolog) */
      "ps", "% ",				/* postscript	 */
+     "psw", "% ",			/* postscript wrap */
+     "pswm", "% ",			/* postscript wrap */
      "r", "# ",				/* ratfor	 */
      "red", "% ",			/* psl/rlisp	 */
  #ifdef sparc
***************
*** 748,760 ****
      char altdate2[50];
  #endif
      char *author, *buf;
      int i, mode, ierrno, err = 0;

      if (noexec)
  	return (0);

      fprcs = open_file (rcs, "w+");
!     fpuser = open_file (user, "r");

      /*
       * putadmin()
--- 775,790 ----
      char altdate2[50];
  #endif
      char *author, *buf;
+     char *tocvsPath;
+
      int i, mode, ierrno, err = 0;

      if (noexec)
  	return (0);

      fprcs = open_file (rcs, "w+");
!     tocvsPath = wrap_tocvs_process_file (user); /* CVSWRAPPERS */
!     fpuser = open_file ((tocvsPath==NULL ? user:tocvsPath), "r");

      /*
       * putadmin()
***************
*** 879,884 ****
--- 909,918 ----
      }
      (void) fclose (fpuser);

+ 	/* CVSWRAPPERS */
+     if (tocvsPath)
+ 	unlink_file(tocvsPath);
+
      /*
       * Fix the modes on the RCS files.  They must maintain the same modes as
       * the original user file, except that all write permissions must be
***************
*** 900,905 ****
--- 934,942 ----
      (void) fclose (fprcs);
  write_error_noclose:
      (void) fclose (fpuser);
+ 	/* CVSWRAPPERS */
+     if (tocvsPath)
+ 	unlink_file(tocvsPath);
      fperror (logfp, 0, ierrno, "ERROR: cannot write file %s", rcs);
      error (0, ierrno, "ERROR: cannot write file %s", rcs);
      if (ierrno == ENOSPC)
diff -cNwr cvs-1.4A2/src/log.c cvs-1.4A2.v/src/log.c
*** cvs-1.4A2/src/log.c	Fri Sep 30 01:39:31 1994
--- cvs-1.4A2.v/src/log.c	Fri May 19 16:16:17 1995
***************
*** 69,78 ****
      argc -= numopt;
      argv += numopt;

      err = start_recursion (log_fileproc, (int (*) ()) NULL, log_dirproc,
  			   (int (*) ()) NULL, argc, argv, local,
  			   W_LOCAL | W_REPOS | W_ATTIC, 0, 1,
! 			   (char *) NULL, 1, 0);
      return (err);
  }

--- 69,80 ----
      argc -= numopt;
      argv += numopt;

+     wrap_setup(); /* CVSWRAPPERS */
+
      err = start_recursion (log_fileproc, (int (*) ()) NULL, log_dirproc,
  			   (int (*) ()) NULL, argc, argv, local,
  			   W_LOCAL | W_REPOS | W_ATTIC, 0, 1,
! 			   (char *) NULL, 1, 0, 0);
      return (err);
  }

diff -cNwr cvs-1.4A2/src/no_diff.c cvs-1.4A2.v/src/no_diff.c
*** cvs-1.4A2/src/no_diff.c	Fri Oct  7 01:15:39 1994
--- cvs-1.4A2.v/src/no_diff.c	Mon May 22 19:33:40 1995
***************
*** 33,38 ****
--- 33,39 ----
      char tmp[L_tmpnam+1];
      int ret;
      char *ts, *options;
+     char *tocvsPath;
      int retcode = 0;

      if (!vers->srcfile || !vers->srcfile->path)
***************
*** 51,58 ****
  	if (!iswritable (file))		/* fix the modes as a side effect */
  	    xchmod (file, 1);

  	/* do the byte by byte compare */
! 	if (xcmp (file, tmp) == 0)
  	{
  	    if (cvswrite == FALSE)	/* fix the modes as a side effect */
  		xchmod (file, 0);
--- 52,61 ----
  	if (!iswritable (file))		/* fix the modes as a side effect */
  	    xchmod (file, 1);

+         tocvsPath=wrap_tocvs_process_file(file);
+
  	    /* do the byte by byte compare */
!         if (xcmp ((tocvsPath==NULL ? file:tocvsPath), tmp) == 0) /*  
CVSWRAPPERS */
  	{
  	    if (cvswrite == FALSE)	/* fix the modes as a side effect */
  		xchmod (file, 0);
***************
*** 72,77 ****
--- 75,84 ----
  	}
  	else
  	    ret = 1;			/* files were really different */
+
+ 	    /* CVSWRAPPERS */
+ 	if (tocvsPath)
+ 	    unlink_file(tocvsPath);
      }
      else
      {
diff -cNwr cvs-1.4A2/src/patch.c cvs-1.4A2.v/src/patch.c
*** cvs-1.4A2/src/patch.c	Fri Sep 30 01:39:35 1994
--- cvs-1.4A2.v/src/patch.c	Fri May 19 16:16:39 1995
***************
*** 257,263 ****
      /* start the recursion processor */
      err = start_recursion (patch_fileproc, (int (*) ()) NULL, patch_dirproc,
  			   (int (*) ()) NULL, *pargc - 1, argv + 1, local,
! 			   which, 0, 1, where, 1, 1);

      return (err);
  }
--- 257,263 ----
      /* start the recursion processor */
      err = start_recursion (patch_fileproc, (int (*) ()) NULL, patch_dirproc,
  			   (int (*) ()) NULL, *pargc - 1, argv + 1, local,
! 			   which, 0, 1, where, 1, 1, 0);

      return (err);
  }
diff -cNwr cvs-1.4A2/src/recurse.c cvs-1.4A2.v/src/recurse.c
*** cvs-1.4A2/src/recurse.c	Fri Sep 30 01:39:37 1994
--- cvs-1.4A2.v/src/recurse.c	Fri May 19 16:16:59 1995
***************
*** 66,72 ****
  int
  start_recursion (fileproc, filesdoneproc, direntproc, dirleaveproc,
  		 argc, argv, local, which, aflag, readlock,
! 		 update_preload, dosrcs, wd_is_repos)
      int (*fileproc) ();
      int (*filesdoneproc) ();
      Dtype (*direntproc) ();
--- 66,72 ----
  int
  start_recursion (fileproc, filesdoneproc, direntproc, dirleaveproc,
  		 argc, argv, local, which, aflag, readlock,
! 		 update_preload, dosrcs, wd_is_repos, intoWrappers)
      int (*fileproc) ();
      int (*filesdoneproc) ();
      Dtype (*direntproc) ();
***************
*** 80,85 ****
--- 80,86 ----
      char *update_preload;
      int dosrcs;
      int wd_is_repos;	/* Set if caller has already cd'd to the repository */
+     int intoWrappers;
  {
      int i, err = 0;
      Dtype flags;
***************
*** 151,157 ****
  	/* if this argument is a directory, then add it to the list of
  	   directories. */

! 	if (isdir(argv[i]))
  	    addlist (&dirlist, argv[i]);
  	else
  	{
--- 152,158 ----
  	/* if this argument is a directory, then add it to the list of
  	   directories. */

! 	if ((intoWrappers || !wrap_name_has(argv[i],WRAP_TOCVS)) &&  
isdir(argv[i])) /* CVSWRAPPERS */
  	    addlist (&dirlist, argv[i]);
  	else
  	{
***************
*** 210,216 ****
  		    repos = Name_Repository (dir, update_dir);
  		    (void) sprintf (tmp, "%s/%s", repos, comp);
  		
! 		    if (isdir(tmp))
  			addlist (&dirlist, argv[i]);
  		    else
  			addfile (&files_by_dir, dir, comp);
--- 211,218 ----
  		    repos = Name_Repository (dir, update_dir);
  		    (void) sprintf (tmp, "%s/%s", repos, comp);

! 			/* CVSWRAPPERS */
! 		    if ((intoWrappers || !wrap_name_has(comp,WRAP_TOCVS)) &&  
isdir(comp))
  			addlist (&dirlist, argv[i]);
  		    else
  			addfile (&files_by_dir, dir, comp);
diff -cNwr cvs-1.4A2/src/remove.c cvs-1.4A2.v/src/remove.c
*** cvs-1.4A2/src/remove.c	Fri Oct  7 01:15:40 1994
--- cvs-1.4A2.v/src/remove.c	Fri May 19 16:17:27 1995
***************
*** 74,83 ****
      argc -= optind;
      argv += optind;

      /* start the recursion processor */
      err = start_recursion (remove_fileproc, (int (*) ()) NULL, remove_dirproc,
  			   (int (*) ()) NULL, argc, argv, local,
! 			   W_LOCAL, 0, 1, (char *) NULL, 1, 0);

      if (removed_files)
  	error (0, 0, "use '%s commit' to remove %s permanently", program_name,
--- 74,85 ----
      argc -= optind;
      argv += optind;

+     wrap_setup (); /* CVSWRAPPERS */
+
      /* start the recursion processor */
      err = start_recursion (remove_fileproc, (int (*) ()) NULL, remove_dirproc,
  			   (int (*) ()) NULL, argc, argv, local,
! 			   W_LOCAL, 0, 1, (char *) NULL, 1, 0, 0);

      if (removed_files)
  	error (0, 0, "use '%s commit' to remove %s permanently", program_name,
diff -cNwr cvs-1.4A2/src/rtag.c cvs-1.4A2.v/src/rtag.c
*** cvs-1.4A2/src/rtag.c	Fri Sep 30 01:39:40 1994
--- cvs-1.4A2.v/src/rtag.c	Fri May 19 16:17:46 1995
***************
*** 223,229 ****
      /* start the recursion processor */
      err = start_recursion (rtag_fileproc, (int (*) ()) NULL, rtag_dirproc,
  			   (int (*) ()) NULL, *pargc - 1, argv + 1, local,
! 			   which, 0, 1, where, 1, 1);

      return (err);
  }
--- 223,229 ----
      /* start the recursion processor */
      err = start_recursion (rtag_fileproc, (int (*) ()) NULL, rtag_dirproc,
  			   (int (*) ()) NULL, *pargc - 1, argv + 1, local,
! 			   which, 0, 1, where, 1, 1, 0);

      return (err);
  }
diff -cNwr cvs-1.4A2/src/status.c cvs-1.4A2.v/src/status.c
*** cvs-1.4A2/src/status.c	Fri Oct  7 01:15:41 1994
--- cvs-1.4A2.v/src/status.c	Fri May 19 16:18:06 1995
***************
*** 69,78 ****
      argc -= optind;
      argv += optind;

      /* start the recursion processor */
      err = start_recursion (status_fileproc, (int (*) ()) NULL, status_dirproc,
  			   (int (*) ()) NULL, argc, argv, local,
! 			   W_LOCAL, 0, 1, (char *) NULL, 1, 0);

      return (err);
  }
--- 69,80 ----
      argc -= optind;
      argv += optind;

+     wrap_setup (); /* CVSWRAPPERS */
+
      /* start the recursion processor */
      err = start_recursion (status_fileproc, (int (*) ()) NULL, status_dirproc,
  			   (int (*) ()) NULL, argc, argv, local,
! 			   W_LOCAL, 0, 1, (char *) NULL, 1, 0, 0);

      return (err);
  }
diff -cNwr cvs-1.4A2/src/subr.c cvs-1.4A2.v/src/subr.c
*** cvs-1.4A2/src/subr.c	Mon Oct 24 15:30:59 1994
--- cvs-1.4A2.v/src/subr.c	Mon May 22 16:48:24 1995
***************
*** 380,395 ****
  /*
   * unlink a file, if possible.
   */
  int
! unlink_file (f)
!     char *f;
  {
      if (trace)
! 	(void) fprintf (stderr, "-> unlink(%s)\n", f);
      if (noexec)
! 	return (0);

!     return (unlink (f));
  }

  /*
--- 380,444 ----
  /*
   * unlink a file, if possible.
   */
+
  int
! unlink_file(path)
!      char *path;
  {
+   int oldTrace;
    if (trace)
!     (void) fprintf (stderr, "-> unlink_file(%s)\n",path);
    if (noexec)
!     return 0;
!
!   oldTrace=trace;
!   trace=0;
!   if( isdir(path) ){
!       if(rmdir(path)!=0){
! 	  trace=oldTrace;
!       return
! 	  deep_remove_dir(path);
!       } else {
!       trace=oldTrace;
!       return 0;
!       }
!   } else {
!     trace=oldTrace;
!     return unlink(path);
!   }
! }
!
! int
! deep_remove_dir (path)
!      char *path;
! {
!   DIR *dirp;
!   struct direct *dp;
!   int err = 0;
!   char buf[PATH_MAX];

!   if ((dirp = opendir (path)) == NULL)
!     return 1;
!
!   while ((dp = readdir (dirp)) != NULL){
!     if (strcmp (dp->d_name, ".") == 0 || strcmp (dp->d_name, "..") == 0)
!       continue;
!
!     sprintf(buf,"%s/%s",path,dp->d_name);
!
!     if (isdir (buf)){
! 	if(deep_remove_dir(buf)){
!         closedir(dirp);
!         return 1;
! 	}
!     } else if(unlink(buf)){
!       closedir (dirp);
!       return 1;
!     }
!   }
!   closedir (dirp);
!
!   return rmdir(path);
  }

  /*
***************
*** 1035,1049 ****
  char *tmpnam(char *s)
  {
      static char value[L_tmpnam+1];

      if (s){
!        strcpy(s,"/tmp/cvsXXXXXX");
         mktemp(s);
         return s;
      }else{
!        strcpy(value,"/tmp/cvsXXXXXX");
         mktemp(s);
         return value;
      }
  }
  #endif
--- 1084,1108 ----
  char *tmpnam(char *s)
  {
      static char  value[L_tmpnam+1];
+     char         directory[L_tmpnam+1];
+     char        *tmpdir;
+
+     tmpdir = getenv ("TMPDIR");
+     if (tmpdir == NULL || tmpdir[0] == '\0'){
+ 	sprintf(directory,"/tmp/cvsXXXXXX");
+     }else{
+ 	sprintf(directory,"%s/cvsXXXXXX",tmpdir);
+     }

      if (s){
!        strcpy(s,directory);
         mktemp(s);
         return s;
      }else{
!        strcpy(value,directory);
         mktemp(s);
         return value;
      }
  }
  #endif
+
diff -cNwr cvs-1.4A2/src/tag.c cvs-1.4A2.v/src/tag.c
*** cvs-1.4A2/src/tag.c	Fri Sep 30 01:39:43 1994
--- cvs-1.4A2.v/src/tag.c	Fri May 19 16:18:22 1995
***************
*** 101,107 ****
      /* start the recursion processor */
      err = start_recursion (tag_fileproc, (int (*) ()) NULL, tag_dirproc,
  			   (int (*) ()) NULL, argc, argv, local,
! 			   W_LOCAL, 0, 1, (char *) NULL, 1, 0);
      return (err);
  }

--- 101,107 ----
      /* start the recursion processor */
      err = start_recursion (tag_fileproc, (int (*) ()) NULL, tag_dirproc,
  			   (int (*) ()) NULL, argc, argv, local,
! 			   W_LOCAL, 0, 1, (char *) NULL, 1, 0, 0);
      return (err);
  }

diff -cNwr cvs-1.4A2/src/update.c cvs-1.4A2.v/src/update.c
*** cvs-1.4A2/src/update.c	Fri Oct 21 20:05:36 1994
--- cvs-1.4A2.v/src/update.c	Mon May 22 19:02:34 1995
***************
*** 71,77 ****
  static time_t last_register_time;
  static char *update_usage[] =
  {
!     "Usage:\n %s %s [-APQdflRpq] [-k kopt] [-r rev|-D date] [-j rev] [-I  
ign] [files...]\n",
      "\t-A\tReset any sticky tags/date/kopts.\n",
      "\t-P\tPrune empty directories.\n",
      "\t-Q\tReally quiet.\n",
--- 71,77 ----
  static time_t last_register_time;
  static char *update_usage[] =
  {
!     "Usage:\n %s %s [-APQdflRpq] [-k kopt] [-r rev|-D date] [-j rev] [-I  
ign] [-W spec] [files...]\n",
      "\t-A\tReset any sticky tags/date/kopts.\n",
      "\t-P\tPrune empty directories.\n",
      "\t-Q\tReally quiet.\n",
***************
*** 86,91 ****
--- 86,92 ----
      "\t-D date\tSet date to update from.\n",
      "\t-j rev\tMerge in changes made between current revision and rev.\n",
      "\t-I ign\tMore files to ignore (! to reset).\n",
+     "\t-W spec\tcvswrappers type line.\n",
      NULL
  };

***************
*** 105,114 ****
  	usage (update_usage);

      ign_setup ();

      /* parse the args */
      optind = 1;
!     while ((c = getopt (argc, argv, "ApPflRQqdk:r:D:j:I:")) != -1)
      {
  	switch (c)
  	{
--- 106,116 ----
  	usage (update_usage);

      ign_setup ();
+     wrap_setup (); /* CVSWRAPPERS */

      /* parse the args */
      optind = 1;
!     while ((c = getopt (argc, argv, "ApPflRQqdk:r:D:j:I:W:")) != -1)
      {
  	switch (c)
  	{
***************
*** 118,123 ****
--- 120,128 ----
  	    case 'I':
  		ign_add (optarg, 0);
  		break;
+ 	    case 'W': /* CVSWRAPPERS */
+                 wrap_add (optarg, 0);
+ 		break;
  	    case 'k':
  		if (options)
  		    free (options);
***************
*** 265,271 ****
      err = start_recursion (update_file_proc, update_filesdone_proc,
  			   update_dirent_proc, update_dirleave_proc,
  			   argc, argv, local, which, aflag, 1,
! 			   preload_update_dir, 1, 0);

      /* see if we need to sleep before returning */
      if (last_register_time)
--- 270,276 ----
      err = start_recursion (update_file_proc, update_filesdone_proc,
  			   update_dirent_proc, update_dirleave_proc,
  			   argc, argv, local, which, aflag, 1,
! 			   preload_update_dir, 1, 0, 0);

      /* see if we need to sleep before returning */
      if (last_register_time)
***************
*** 356,364 ****
--- 361,379 ----
  		(void) write_letter (file, 'C', update_dir);
  		break;
  	    case T_NEEDS_MERGE:		/* needs merging */
+ 		    /* CVSWRAPPERS */
+ 		if(!wrap_merge_is_copy(file))
+ 		{
  		    retval = merge_file (file, repository, entries,
  					 vers, update_dir);
  		    break;
+ 		}
+ 		else
+ 		{
+ 		    retval = checkout_file (file, repository, entries, srcfiles,
+ 					    vers, update_dir);
+ 		    break;
+ 		}
  	    case T_MODIFIED:		/* locally modified */
  		retval = 0;
  		if (vers->ts_conflict)
***************
*** 768,773 ****
--- 783,790 ----
  	    else
  		set_time = 0;

+ 	    wrap_fromcvs_process_file(file); /* CVSWRAPPERS */
+
  	    xvers_ts = Version_TS (repository, options, tag, date, file,
  			      force_tag_match, set_time, entries, srcfiles);
  	    if (strcmp (xvers_ts->options, "-V4") == 0)
***************
*** 985,990 ****
--- 1002,1019 ----
      jdate1 = date_rev1;
      jdate2 = date_rev2;

+ 	/* CVSWRAPPERS */
+     if(wrap_merge_is_copy(file))
+     {
+ 	error(0,0,"Cannot merge %s because it is a merge-by-copy file.",file);
+ 	return;
+     } else
+ 	if(isdir(file))
+ 	{
+ 	    error(0,0,"Cannot merge %s because it is a merge-by-copy file.",file);
+ 	    return;
+ 	}
+
      /* determine if we need to do anything at all */
      if (vers->srcfile == NULL ||
  	vers->srcfile->path == NULL)
***************
*** 1260,1265 ****
--- 1289,1296 ----
  	return;

      ign_add_file (CVSDOTIGNORE, 1);
+     wrap_add_file (CVSDOTWRAPPER, 1); /* CVSWRAPPERS */
+
      while ((dp = readdir (dirp)) != NULL)
      {
  	file = dp->d_name;
diff -cNwr cvs-1.4A2/src/wrapper.c cvs-1.4A2.v/src/wrapper.c
*** cvs-1.4A2/src/wrapper.c	Wed Dec 31 17:00:00 1969
--- cvs-1.4A2.v/src/wrapper.c	Tue May 23 09:53:13 1995
***************
*** 0 ****
--- 1,378 ----
+ #import "cvs.h"
+
+ /*
+   Original Author:  athan@object.com <Andrew C. Athan> 2/1/94
+   Modified By:      vdemarco@bou.shl.com
+
+   Look for CVSWRAPPERS comments
+
+   This package was written to support the NeXTSTEP concept of
+   "wrappers."  These are essentially directories that are to be
+   treated as "files."  This package allows such wrappers to be
+   "processed" on the way in and out of CVS.  The intended use is to
+   wrap up a wrapper into a single tar, such that that tar can be
+   treated as a single binary file in CVS.  To solve the problem
+   effectively, it was also necessary to be able to prevent rcsmerge
+   application at appropriate times.
+
+   Changes to much of the distribution was necessary--though in most
+   places, it was minor (i.e., a call to wrap_setup() at the right
+   time).
+
+   Enjoy,
+     aca
+
+   ------------------
+   Format of wrapper file ($CVSROOT/CVSROOT/cvswrappers or .cvswrappers)
+
+   wildcard	[option value][option value]...
+
+   where option is one of
+   -f		from cvs filter		value: path to filter
+   -t		to cvs filter		value: path to filter
+   -m		update methodology	value: MERGE or COPY
+
+   and value is a single-quote delimited value.
+
+   E.g:
+   *.nib		-f 'gunzipuntar' -t 'targzip' -m 'COPY'
+ */
+
+
+ typedef struct {
+     char *wildCard;
+     char *tocvsFilter;
+     char *fromcvsFilter;
+     char *conflictHook;
+     WrapMergeMethod mergeMethod;
+ } WrapperEntry;
+
+ static WrapperEntry **wrap_list=NULL;
+ static WrapperEntry **wrap_saved_list=NULL;
+
+ static int wrap_size=0;
+ static int wrap_count=0;
+ static int wrap_tempcount=0;
+ static int wrap_saved_count=0;
+ static int wrap_saved_tempcount=0;
+
+ #define WRAPPER_GROW	8
+
+ void wrap_add_file PROTO((char *file,int temp));
+ void wrap_add PROTO((char *line,int temp));
+ void wrap_add_entry PROTO((WrapperEntry *e,int temp));
+ void wrap_kill PROTO(());
+ void wrap_kill_temp PROTO(());
+ void wrap_free_entry PROTO((WrapperEntry *e));
+ void wrap_free_entry_internal PROTO((WrapperEntry *e));
+ void wrap_restore_saved PROTO(());
+
+
+ void wrap_setup()
+ {
+     char file[PATH_MAX];
+     struct passwd *pw;
+
+ 	/* Then add entries found in repository, if it exists */
+     (void) sprintf (file, "%s/%s/%s", CVSroot, CVSROOTADM, CVSROOTADM_WRAPPER);
+     if (isfile (file)){
+ 	wrap_add_file(file,0);
+     }
+
+ 	/* Then add entries found in home dir, (if user has one) and file exists */
+     if ((pw = (struct passwd *) getpwuid (getuid ())) && pw->pw_dir){
+ 	(void) sprintf (file, "%s/%s", pw->pw_dir, CVSDOTWRAPPER);
+ 	if (isfile (file)){
+ 	    wrap_add_file (file, 0);
+ 	}
+     }
+
+ 	/* Then add entries found in CVSWRAPPERS environment variable. */
+     wrap_add (getenv (WRAPPER_ENV), 0);
+ }
+
+ /*
+  * Open a file and read lines, feeding each line to a line parser. Arrange
+  * for keeping a temporary list of wrappers at the end, if the "temp"
+  * argument is set.
+  */
+ void
+ wrap_add_file (file, temp)
+     char *file;
+     int temp;
+ {
+     FILE *fp;
+     char line[1024];
+
+     wrap_restore_saved();
+     wrap_kill_temp();
+
+ 	/* load the file */
+     if (!(fp = fopen (file, "r")))
+ 	return;
+     while (fgets (line, sizeof (line), fp))
+ 	wrap_add (line, temp);
+     (void) fclose (fp);
+ }
+
+ void
+ wrap_kill()
+ {
+     wrap_kill_temp();
+     while(wrap_count)
+ 	wrap_free_entry(wrap_list[--wrap_count]);
+ }
+
+ void
+ wrap_kill_temp()
+ {
+     WrapperEntry **temps=wrap_list+wrap_count;
+
+     while(wrap_tempcount)
+ 	wrap_free_entry(temps[--wrap_tempcount]);
+ }
+
+ void
+ wrap_free_entry(e)
+      WrapperEntry *e;
+ {
+     wrap_free_entry_internal(e);
+     free(e);
+ }
+
+ void
+ wrap_free_entry_internal(e)
+     WrapperEntry *e;
+ {
+     free(e->wildCard);
+     if(e->tocvsFilter)
+ 	free(e->tocvsFilter);
+     if(e->fromcvsFilter)
+ 	free(e->fromcvsFilter);
+     if(e->conflictHook)
+ 	free(e->conflictHook);
+ }
+
+ void
+ wrap_restore_saved()
+ {
+     if(!wrap_saved_list)
+ 	return;
+
+     wrap_kill();
+
+     free(wrap_list);
+
+     wrap_list=wrap_saved_list;
+     wrap_count=wrap_saved_count;
+     wrap_tempcount=wrap_saved_tempcount;
+
+     wrap_saved_list=NULL;
+     wrap_saved_count=0;
+     wrap_saved_tempcount=0;
+ }
+
+ void
+ wrap_add (line, isTemp)
+    char *line;
+    int isTemp;
+ {
+     char *temp;
+     char ctemp;
+     WrapperEntry e;
+     char opt;
+
+     if (!line || line[0] == '#')
+ 	return;
+
+     bzero(&e,sizeof(e));
+
+ 	/* Search for the wild card */
+     while(*line && isspace(*line))
+ 	++line;
+     for(temp=line;*line && !isspace(*line);++line)
+ 	;
+     if(temp==line)
+ 	return;
+
+     ctemp=*line;
+     *line='\0';
+
+     e.wildCard=xstrdup(temp);
+     *line=ctemp;
+
+     while(*line){
+ 	    /* Search for the option */
+ 	while(*line && *line!='-')
+ 	    ++line;
+ 	if(!*line)
+ 	    break;
+ 	++line;
+ 	if(!*line)
+ 	    break;
+ 	opt=*line;
+
+ 	    /* Search for the filter commandline */
+ 	for(++line;*line && *line!='\'';++line);
+ 	if(!*line)
+ 	    break;
+
+ 	for(temp=++line;*line && (*line!='\'' || line[-1]=='\\');++line)
+ 	    ;
+
+ 	if(line==temp+1)
+ 	    break;
+
+ 	ctemp=*line;
+ 	*line='\0';
+ 	switch(opt){
+ 	case 'f':
+ 	    if(e.fromcvsFilter)
+ 		free(e.fromcvsFilter);
+ 	    e.fromcvsFilter=xstrdup(temp);
+ 	    break;
+ 	case 't':
+ 	    if(e.tocvsFilter)
+ 		free(e.tocvsFilter);
+ 	    e.tocvsFilter=xstrdup(temp);
+ 	    break;
+ 	case 'c':
+ 	    if(e.conflictHook)
+ 		free(e.conflictHook);
+ 	    e.conflictHook=xstrdup(temp);
+ 	    break;
+ 	case 'm':
+ 	    if(*temp=='C' || *temp=='c')
+ 		e.mergeMethod=WRAP_COPY;
+ 	    else
+ 		e.mergeMethod=WRAP_MERGE;
+ 	    break;
+ 	default:
+ 	    break;
+ 	}
+ 	*line=ctemp;
+ 	if(!*line)break;
+ 	++line;
+     }
+
+     wrap_add_entry(&e, isTemp);
+ }
+
+ void
+ wrap_add_entry(e, temp)
+ WrapperEntry *e;
+ int temp;
+ {
+     int x;
+     if(wrap_count+wrap_tempcount>=wrap_size){
+ 	wrap_size += WRAPPER_GROW;
+ 	wrap_list = (WrapperEntry **) xrealloc ((char *) wrap_list,
+ 						wrap_size *
+ 						sizeof (WrapperEntry *));
+     }
+
+     if(!temp && wrap_tempcount){
+ 	for(x=wrap_count+wrap_tempcount-1;x>=wrap_count;--x)
+ 	    wrap_list[x+1]=wrap_list[x];
+     }
+
+     x=(temp ? wrap_count+(wrap_tempcount++):(wrap_count++));
+     wrap_list[x]=(WrapperEntry *)xmalloc(sizeof(WrapperEntry));
+     wrap_list[x]->wildCard=e->wildCard;
+     wrap_list[x]->fromcvsFilter=e->fromcvsFilter;
+     wrap_list[x]->tocvsFilter=e->tocvsFilter;
+     wrap_list[x]->conflictHook=e->conflictHook;
+     wrap_list[x]->mergeMethod=e->mergeMethod;
+ }
+
+ /* Return 1 if the given filename is a wrapper filename */
+ int
+ wrap_name_has (name,has)
+     char *name;
+     WrapMergeHas has;
+ {
+     int x,count=wrap_count+wrap_saved_count;
+     char *temp;
+
+     for(x=0;x<count;++x)
+ 	if (fnmatch (wrap_list[x]->wildCard, name, 0) == 0){
+ 	    switch(has){
+ 	    case WRAP_TOCVS:
+ 		temp=wrap_list[x]->tocvsFilter;
+ 		break;
+ 	    case WRAP_FROMCVS:
+ 		temp=wrap_list[x]->fromcvsFilter;
+ 		break;
+ 	    case WRAP_CONFLICT:
+ 		temp=wrap_list[x]->conflictHook;
+ 		break;
+ 	    }
+ 	    if(temp==NULL)
+ 		return (0);
+ 	    else
+ 		return (1);
+ 	}
+     return (0);
+ }
+
+ WrapperEntry *
+ wrap_matching_entry (name)
+     char *name;
+ {
+     int x,count=wrap_count+wrap_saved_count;
+     char *temp;
+
+     for(x=0;x<count;++x)
+ 	if (fnmatch (wrap_list[x]->wildCard, name, 0) == 0)
+ 	    return wrap_list[x];
+     return (WrapperEntry *)NULL;
+ }
+
+ char *
+ wrap_tocvs_process_file(fileName)
+     char *fileName;
+ {
+     WrapperEntry *e=wrap_matching_entry(fileName);
+     static char buf[PATH_MAX];
+     int err;
+
+     if(e==NULL || e->tocvsFilter==NULL)
+ 	return NULL;
+
+     tmpnam(buf);
+
+     if(isfile(buf) && unlink_file(buf))
+ 	error(0,0,"Could not remove %s",buf);
+
+     run_setup(e->tocvsFilter,fileName,buf);
+     run_exec(RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL|RUN_REALLY );
+
+     return buf;
+ }
+
+ int
+ wrap_merge_is_copy (fileName)
+ char *fileName;
+ {
+     WrapperEntry *e=wrap_matching_entry(fileName);
+     if(e==NULL || e->mergeMethod==WRAP_MERGE)
+ 	return 0;
+
+     return 1;
+ }
+
+ char *
+ wrap_fromcvs_process_file(fileName)
+ char *fileName;
+ {
+     WrapperEntry *e=wrap_matching_entry(fileName);
+     static char buf[PATH_MAX];
+     int err;
+
+     if(e==NULL || e->fromcvsFilter==NULL)
+ 	return NULL;
+
+     run_setup(e->fromcvsFilter,fileName);
+     run_exec(RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL );
+     return buf;
+ }


