[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: patch: new 'cvs import -X' option.
From: |
Chris G. Demetriou |
Subject: |
Re: patch: new 'cvs import -X' option. |
Date: |
24 Jun 2004 15:46:52 +0000 |
User-agent: |
Gnus/5.09 (Gnus v5.9.0) Emacs/21.3 |
At 23 Jun 2004 01:18:14 +0000, Chris G. Demetriou wrote:
> [ bogus comments ]
> Once I get some more feedback, I'll address this.
Well, I know that not much time has passed for feedback, but I'd like
to get this off my plate, so...
Attached find an updated patch, which i believe should address the
comment issues in the way I had intended to.
built/checked again, just to be sure.
chris
--
New-feature entry for the NEWS file:
* `cvs import' now has a new option, `-X', which causes new files to be
imported in a way that they appear only on the vendor branch, and do not
automatically appear on the main trunk.
[ src/ChangeLog ]
2004-06-24 Chris Demetriou <cgd@broadcom.com>
* import.c (import_usage): Add new -X flag.
(import): Handle new -X flag.
(process_import_file): Handle new -X flag.
(killnew): New static flag variable to indicate use of -X flag.
(preserve_initial_permissions): New function, extracted from
add_rcs_file().
(expand_and_copy_contents): Likewise.
(add_rcs_file): New argument, do_killnew, to cause "import -X" flag
processing. Implement -X flag, and use newly abstracted functions.
* rcs.h (add_rcs_file): Update prototype for do_killnew argument.
* commit.c (checkaddfile): Update for add_rcs_file function change.
* mkmodules.c (init): Likewise.
* client.c (handle_mt): Handle an importmergecmd tag without
any conflicts (for 'import -X' support).
* sanity.sh (importX): New test.
[ doc/ChangeLog ]
2004-06-24 Chris Demetriou <cgd@netbsd.org>
* cvs.texinfo (Vendor branch): Document that sometimes
the default branch won't be set to the vendor branch.
(import options): Add -X.
* cvsclient.texi (MT importmergecmd tag): Document that this
can also be used with the 'cvs import -X' command, and
that it can occur when there are no conflicts.
Index: cvs/doc/cvs.texinfo
diff -u cvs/doc/cvs.texinfo:1.1.1.1 cvs/doc/cvs.texinfo:1.4
--- cvs/doc/cvs.texinfo:1.1.1.1 Wed Jun 23 21:34:10 2004
+++ cvs/doc/cvs.texinfo Wed Jun 23 21:39:25 2004
@@ -7418,7 +7418,7 @@
Use the @code{import} command to create and update
the vendor branch. When you import a new file,
-the vendor branch is made the `head' revision, so
+(usually) the vendor branch is made the `head' revision, so
anyone that checks out a copy of the file gets that
revision. When a local modification is committed it is
placed on the main trunk, and made the `head'
@@ -10470,6 +10470,17 @@
@var{spec} can be a file name pattern of the same type
that you can specify in the @file{.cvswrappers}
file. @xref{Wrappers}.
+
+@item -X
+Modify the algorithm used by @sc{cvs} when importing new files
+so that new files do not immediately appear on the main trunk.
+
+Specifically, this flag causes @sc{cvs} to mark new files as
+if they were deleted on the main trunk, by taking the following
+steps for each file in addition to those normally taken on import:
+creating a new revision on the main trunk indicating that
+the new file is @code{dead}, resetting the new file's default branch,
+and placing the file in the Attic (@pxref{Attic}) directory.
@end table
@c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Index: cvs/doc/cvsclient.texi
diff -u cvs/doc/cvsclient.texi:1.1.1.1 cvs/doc/cvsclient.texi:1.4
--- cvs/doc/cvsclient.texi:1.1.1.1 Wed Jun 23 21:34:10 2004
+++ cvs/doc/cvsclient.texi Wed Jun 23 21:39:25 2004
@@ -1823,8 +1823,11 @@
@end example
The @code{importmergecmd} tag is used when doing an import which has
-conflicts. The client can use it to report how to merge in the newly
-imported changes. The @var{count} is the number of conflicts. The
+conflicts, or when doing an import with the @samp{-X} flag.
+The client can use it to report how to merge in the newly
+imported changes. The @var{count} is the number of conflicts, or the
+string @code{No} if no conflicts occurred. (The latter will only be
+sent for imports run with the @samp{-X} flag.) The
newly imported changes can be merged by running the following command:
@smallexample
cvs checkout -j @var{tag1} -j @var{tag2} @var{repository}
Index: cvs/src/client.c
diff -u cvs/src/client.c:1.1.1.1 cvs/src/client.c:1.4
--- cvs/src/client.c:1.1.1.1 Wed Jun 23 21:34:11 2004
+++ cvs/src/client.c Wed Jun 23 21:39:25 2004
@@ -2663,8 +2663,11 @@
break;
}
- sprintf (buf, "\n%d conflicts created by this import.\n",
- importmergecmd.conflicts);
+ if (importmergecmd.conflicts == -1)
+ sprintf (buf, "\nNo conflicts created by this import.\n");
+ else
+ sprintf (buf, "\n%d conflicts created by this import.\n",
+ importmergecmd.conflicts);
cvs_output (buf, 0);
cvs_output ("Use the following command to help the merge:\n\n",
0);
@@ -2720,7 +2723,12 @@
else if (importmergecmd.seen)
{
if (strcmp (tag, "conflicts") == 0)
- importmergecmd.conflicts = atoi (text);
+ {
+ if (strcmp (text, "No") == 0)
+ importmergecmd.conflicts = -1;
+ else
+ importmergecmd.conflicts = atoi (text);
+ }
else if (strcmp (tag, "mergetag1") == 0)
importmergecmd.mergetag1 = xstrdup (text);
else if (strcmp (tag, "mergetag2") == 0)
Index: cvs/src/commit.c
diff -u cvs/src/commit.c:1.1.1.1 cvs/src/commit.c:1.4
--- cvs/src/commit.c:1.1.1.1 Wed Jun 23 21:34:11 2004
+++ cvs/src/commit.c Wed Jun 23 21:39:25 2004
@@ -2000,7 +2000,7 @@
if (add_rcs_file (NULL, rcsname, file, NULL, opt,
NULL, NULL, 0, NULL,
- desc, desclen, NULL) != 0)
+ desc, desclen, NULL, 0) != 0)
{
if (rcsname != NULL)
free (rcsname);
Index: cvs/src/import.c
diff -u cvs/src/import.c:1.1.1.1 cvs/src/import.c:1.5
--- cvs/src/import.c:1.1.1.1 Wed Jun 23 21:34:11 2004
+++ cvs/src/import.c Wed Jun 23 22:16:21 2004
@@ -31,6 +31,12 @@
int targc, char *targv[]);
static int update_rcs_file (char *message, char *vfile, char *vtag, int targc,
char *targv[], int inattic);
+#ifdef PRESERVE_PERMISSIONS_SUPPORT
+static int preserve_initial_permissions (FILE *fprcs, const char *userfile,
+ mode_t file_type, struct stat *sbp);
+#endif
+static int expand_and_copy_contents (FILE *fprcs, mode_t file_type,
+ const char *user, FILE *fpuser);
static void add_log (int ch, char *fname);
static int repos_len;
@@ -41,12 +47,14 @@
static int conflicts;
static int use_file_modtime;
static char *keyword_opt = NULL;
+static int killnew;
static const char *const import_usage[] =
{
- "Usage: %s %s [-d] [-k subst] [-I ign] [-m msg] [-b branch]\n",
+ "Usage: %s %s [-dX] [-k subst] [-I ign] [-m msg] [-b branch]\n",
" [-W spec] repository vendor-tag release-tags...\n",
"\t-d\tUse the file's modification time as the time of import.\n",
+ "\t-X\tWhen importing new files, mark their trunk revisions as dead.\n",
"\t-k sub\tSet default RCS keyword substitution mode.\n",
"\t-I ign\tMore files to ignore (! to reset).\n",
"\t-b bra\tVendor branch id.\n",
@@ -75,7 +83,7 @@
vbranch = xstrdup (CVSBRANCH);
optind = 0;
- while ((c = getopt (argc, argv, "+Qqdb:m:I:k:W:")) != -1)
+ while ((c = getopt (argc, argv, "+Qqdb:m:I:k:W:X")) != -1)
{
switch (c)
{
@@ -129,6 +137,9 @@
case 'W':
wrap_add (optarg, 0);
break;
+ case 'X':
+ killnew = 1;
+ break;
case '?':
default:
usage (import_usage);
@@ -265,6 +276,8 @@
option_with_arg ("-m", message ? message : "");
if (keyword_opt != NULL)
option_with_arg ("-k", keyword_opt);
+ if (killnew)
+ send_arg ("-X");
/* The only ignore processing which takes place on the server side
is the CVSROOT/cvsignore file. But if the user specified -I !,
the documented behavior is to not process said file. */
@@ -324,7 +337,7 @@
/* Just Do It. */
err = import_descend (message, argv[1], argc - 2, argv + 2);
- if (conflicts)
+ if (conflicts || killnew)
{
if (!really_quiet)
{
@@ -332,7 +345,10 @@
cvs_output_tagged ("+importmergecmd", NULL);
cvs_output_tagged ("newline", NULL);
- sprintf (buf, "%d", conflicts);
+ if (conflicts)
+ sprintf (buf, "%d", conflicts);
+ else
+ sprintf (buf, "%s", "No");
cvs_output_tagged ("conflicts", buf);
cvs_output_tagged ("text", " conflicts created by this import.");
cvs_output_tagged ("newline", NULL);
@@ -363,7 +379,11 @@
report any required -d option. There is no particularly
clean way to tell the server about the -d option used by
the client. */
- (void) fprintf (logfp, "\n%d conflicts created by this import.\n",
+ if (conflicts)
+ (void) fprintf (logfp, "\n%d", conflicts);
+ else
+ (void) fprintf (logfp, "\nNo");
+ (void) fprintf (logfp, " conflicts created by this import.\n",
conflicts);
(void) fprintf (logfp,
"Use the following command to help the merge:\n\n");
@@ -550,8 +570,28 @@
int retval;
char *free_opt = NULL;
char *our_opt = keyword_opt;
+
+ /* If marking newly-imported files as dead, they must be
+ created in the attic! */
+ if (! killnew)
+ free (attic_name);
+ else
+ {
+ free (rcs);
+ rcs = attic_name;
+
+ /* Attempt to make the Attic directory, in case it
+ does not exist. */
+ (void) sprintf (rcs, "%s/%s", repository, CVSATTIC);
+ if (CVS_MKDIR (rcs, 0777 ) != 0 && errno != EEXIST)
+ error (1, errno, "cannot make directory `%s'", rcs);
+
+ /* Note that the above clobbered the path name, so we
+ recreate it here. */
+ (void) sprintf (rcs, "%s/%s/%s%s", repository, CVSATTIC,
+ vfile, RCSEXT);
+ }
- free (attic_name);
/*
* A new import source file; it doesn't exist as a ,v within the
* repository nor in the Attic -- create it anew.
@@ -591,7 +631,7 @@
retval = add_rcs_file (message, rcs, vfile, vhead, our_opt,
vbranch, vtag, targc, targv,
- NULL, 0, logfp);
+ NULL, 0, logfp, killnew);
if (free_opt != NULL)
free (free_opt);
free (rcs);
@@ -973,7 +1013,9 @@
*
* INPUTS
* message Log message for the addition. Not used if add_vhead == NULL.
- * rcs Filename of the RCS file to create.
+ * rcs Filename of the RCS file to create. Note that if 'do_killnew'
+ * is set, this file should be in the Attic directory, and the
+ * Attic directory must already exist.
* user Filename of the file to serve as the contents of the initial
* revision. Even if add_vhead is NULL, we use this to determine
* the modes to give the new RCS file.
@@ -994,6 +1036,8 @@
* desclen The number of bytes in desctext.
* add_logfp Write errors to here as well as via error (), or NULL if we
* should use only error ().
+ * do_killnew Mark newly-imported files as being dead on the trunk,
i.e.,
+ * as being imported only to the vendor branch.
*
* RETURNS
* Return value is 0 for success, or nonzero for failure (in which
@@ -1004,7 +1048,7 @@
const char *add_vhead, const char *key_opt,
const char *add_vbranch, const char *vtag, int targc,
char **targv, const char *desctext, size_t desclen,
- FILE *add_logfp)
+ FILE *add_logfp, int do_killnew)
{
FILE *fprcs, *fpuser;
struct stat sb;
@@ -1018,10 +1062,39 @@
const char *userfile;
char *free_opt = NULL;
mode_t file_type;
+ char *dead_revision = NULL;
if (noexec)
return (0);
+ if (do_killnew)
+ {
+ char *last_place;
+ int last_number;
+
+ /* If we are marking the newly imported file as dead, we must
+ have a head revision. */
+ if (add_vhead == NULL)
+ error (1, 0, "killing new file attempted when no head revision is
being added");
+
+ /* One extra byte for NUL, plus one for carry generated by adding
+ one to the last number in the add_vhead revision. */
+ dead_revision = xmalloc (strlen (add_vhead) + 2);
+ strcpy (dead_revision, add_vhead);
+
+ /* Find the loacation of the last number, which we will increment
+ and overwrite. Note that this handles single numbers (w/o
+ dots), which is probably unnecessary. */
+ if ((last_place = strrchr (dead_revision, '.')) != NULL)
+ last_place++;
+ else
+ last_place = dead_revision;
+ last_number = atoi (last_place);
+ if (++last_number <= 0)
+ error (1, 0, "invalid revision number %s", add_vhead);
+ sprintf (last_place, "%d", last_number);
+ }
+
/* Note that as the code stands now, the -k option overrides any
settings in wrappers (whether CVSROOT/cvswrappers, -W, or
whatever). Some have suggested this should be the other way
@@ -1097,7 +1170,8 @@
*/
if (add_vhead != NULL)
{
- if (fprintf (fprcs, "head %s;\012", add_vhead) < 0)
+ if (fprintf (fprcs, "head %s;\012",
+ do_killnew ? dead_revision : add_vhead) < 0)
goto write_error;
}
else
@@ -1106,7 +1180,10 @@
goto write_error;
}
- if (add_vbranch != NULL)
+ /* This sets the default branch. If using the 'do_killnew' functionality,
+ where imports don't show up until merged, no default branch should
+ be set. */
+ if (add_vbranch != NULL && ! do_killnew)
{
if (fprintf (fprcs, "branch %s;\012", add_vbranch) < 0)
goto write_error;
@@ -1153,19 +1230,43 @@
/* Write the revision(s), with the date and author and so on
(that is "delta" rather than "deltatext" from rcsfile(5)). */
+
+ if (use_file_modtime)
+ now = sb.st_mtime;
+ else
+ (void) time (&now);
+ ftm = gmtime (&now);
+ (void) sprintf (altdate1, DATEFORM,
+ ftm->tm_year + (ftm->tm_year < 100 ? 0 : 1900),
+ ftm->tm_mon + 1, ftm->tm_mday, ftm->tm_hour,
+ ftm->tm_min, ftm->tm_sec);
+ author = getcaller ();
+
+ if (do_killnew)
+ {
+ if (fprintf (fprcs, "\012%s\012", dead_revision) < 0 ||
+ fprintf (fprcs, "date %s; author %s; state %s;\012",
+ altdate1, author, RCSDEAD) < 0)
+ goto write_error;
+
+ if (fprintf (fprcs, "branches;\012") < 0)
+ goto write_error;
+ if (fprintf (fprcs, "next %s;\012", add_vhead) < 0)
+ goto write_error;
+
+#ifdef PRESERVE_PERMISSIONS_SUPPORT
+ /* Store initial permissions if necessary. */
+ if (preserve_perms)
+ {
+ if (preserve_initial_permissions (fprcs, userfile,
+ file_type, sbp))
+ goto write_error;
+ }
+#endif
+ }
+
if (add_vhead != NULL)
{
- if (use_file_modtime)
- now = sb.st_mtime;
- else
- (void) time (&now);
- ftm = gmtime (&now);
- (void) sprintf (altdate1, DATEFORM,
- ftm->tm_year + (ftm->tm_year < 100 ? 0 : 1900),
- ftm->tm_mon + 1, ftm->tm_mday, ftm->tm_hour,
- ftm->tm_min, ftm->tm_sec);
- author = getcaller ();
-
if (fprintf (fprcs, "\012%s\012", add_vhead) < 0 ||
fprintf (fprcs, "date %s; author %s; state Exp;\012",
altdate1, author) < 0)
@@ -1188,48 +1289,9 @@
/* Store initial permissions if necessary. */
if (preserve_perms)
{
- if (file_type == S_IFLNK)
- {
- char *link = xreadlink (userfile);
- if (fprintf (fprcs, "symlink\t@") < 0 ||
- expand_at_signs (link, strlen (link), fprcs) < 0 ||
- fprintf (fprcs, "@;\012") < 0)
- goto write_error;
- free (link);
- }
- else
- {
- if (fprintf (fprcs, "owner\t%u;\012", sb.st_uid) < 0)
- goto write_error;
- if (fprintf (fprcs, "group\t%u;\012", sb.st_gid) < 0)
- goto write_error;
- if (fprintf (fprcs, "permissions\t%o;\012",
- sb.st_mode & 07777) < 0)
- goto write_error;
- switch (file_type)
- {
- case S_IFREG: break;
- case S_IFCHR:
- case S_IFBLK:
-#ifdef HAVE_STRUCT_STAT_ST_RDEV
- if (fprintf (fprcs, "special\t%s %lu;\012",
- (file_type == S_IFCHR
- ? "character"
- : "block"),
- (unsigned long) sb.st_rdev) < 0)
- goto write_error;
-#else
- error (0, 0,
-"can't import %s: unable to import device files on this system",
-userfile);
-#endif
- break;
- default:
- error (0, 0,
- "can't import %s: unknown kind of special file",
- userfile);
- }
- }
+ if (preserve_initial_permissions (fprcs, userfile,
+ file_type, sbp))
+ goto write_error;
}
#endif
@@ -1246,47 +1308,9 @@
/* Store initial permissions if necessary. */
if (preserve_perms)
{
- if (file_type == S_IFLNK)
- {
- char *link = xreadlink (userfile);
- if (fprintf (fprcs, "symlink\t@") < 0 ||
- expand_at_signs (link, strlen (link), fprcs) < 0 ||
- fprintf (fprcs, "@;\012") < 0)
- goto write_error;
- free (link);
- }
- else
- {
- if (fprintf (fprcs, "owner\t%u;\012", sb.st_uid) < 0 ||
- fprintf (fprcs, "group\t%u;\012", sb.st_gid) < 0 ||
- fprintf (fprcs, "permissions\t%o;\012",
- sb.st_mode & 07777) < 0)
- goto write_error;
-
- switch (file_type)
- {
- case S_IFREG: break;
- case S_IFCHR:
- case S_IFBLK:
-#ifdef HAVE_STRUCT_STAT_ST_RDEV
- if (fprintf (fprcs, "special\t%s %lu;\012",
- (file_type == S_IFCHR
- ? "character"
- : "block"),
- (unsigned long) sb.st_rdev) < 0)
- goto write_error;
-#else
- error (0, 0,
-"can't import %s: unable to import device files on this system",
-userfile);
-#endif
- break;
- default:
- error (0, 0,
- "cannot import %s: special file of unknown type",
- userfile);
- }
- }
+ if (preserve_initial_permissions (fprcs, userfile,
+ file_type, sbp))
+ goto write_error;
}
#endif
@@ -1312,6 +1336,29 @@
/* Now write the log messages and contents for the revision(s) (that
is, "deltatext" rather than "delta" from rcsfile(5)). */
+
+ if (do_killnew)
+ {
+ if (fprintf (fprcs, "\012%s\012", dead_revision) < 0 ||
+ fprintf (fprcs, "log\012@") < 0)
+ goto write_error;
+ if (fprintf (fprcs, "Revision %s was added on the vendor branch.\012",
+ add_vhead) < 0)
+ goto write_error;
+ if (fprintf (fprcs, "@\012") < 0 ||
+ fprintf (fprcs, "text\012@") < 0)
+ {
+ goto write_error;
+ }
+
+ /* Now copy over the contents of the file, expanding at signs. */
+ if (expand_and_copy_contents (fprcs, file_type, user, fpuser))
+ goto write_error;
+
+ if (fprintf (fprcs, "@\012\012") < 0)
+ goto write_error;
+ }
+
if (add_vhead != NULL)
{
if (fprintf (fprcs, "\012%s\012", add_vhead) < 0 ||
@@ -1338,27 +1385,17 @@
/* Now copy over the contents of the file, expanding at signs.
If preserve_perms is set, do this only for regular files. */
- if (!preserve_perms || file_type == S_IFREG)
+ if (! do_killnew)
{
- char buf[8192];
- unsigned int len;
-
- while (1)
- {
- len = fread (buf, 1, sizeof buf, fpuser);
- if (len == 0)
- {
- if (ferror (fpuser))
- error (1, errno, "cannot read file %s for copying",
- user);
- break;
- }
- if (expand_at_signs (buf, len, fprcs) < 0)
- goto write_error;
- }
+ /* Now copy over the contents of the file, expanding at signs,
+ if not done as part of do_killnew handling above. */
+ if (expand_and_copy_contents (fprcs, file_type, user, fpuser))
+ goto write_error;
}
+
if (fprintf (fprcs, "@\012\012") < 0)
goto write_error;
+
if (add_vbranch != NULL)
{
if (fprintf (fprcs, "\012%s.1\012", add_vbranch) < 0 ||
@@ -1439,7 +1476,127 @@
return (err + 1);
}
+#ifdef PRESERVE_PERMISSIONS_SUPPORT
+/* Write file permissions and symlink information for a file being
+ * added into its RCS file.
+ *
+ * INPUTS
+ * fprcs FILE pointer for the (newly-created) RCS file. Permisisons
+ * and symlink information should be written here.
+ * userfile Filename of the file being added. (Used to read symbolic
+ * link contents, for symlinks.)
+ * file_type File type of userfile, extracted from sbp->st_mode.
+ * sbp 'stat' information for userfile.
+ *
+ * RETURNS
+ * Return value is 0 for success, or nonzero for failure (in which case
+ * no error message has yet been printed).
+ */
+static int
+preserve_initial_permissions (fprcs, userfile, file_type, sbp)
+ FILE *fprcs;
+ const char *userfile;
+ mode_t file_type;
+ struct stat *sbp;
+{
+ if (file_type == S_IFLNK)
+ {
+ char *link = xreadlink (userfile);
+ if (fprintf (fprcs, "symlink\t@") < 0 ||
+ expand_at_signs (link, strlen (link), fprcs) < 0 ||
+ fprintf (fprcs, "@;\012") < 0)
+ goto write_error;
+ free (link);
+ }
+ else
+ {
+ if (fprintf (fprcs, "owner\t%u;\012", sbp->st_uid) < 0)
+ goto write_error;
+ if (fprintf (fprcs, "group\t%u;\012", sbp->st_gid) < 0)
+ goto write_error;
+ if (fprintf (fprcs, "permissions\t%o;\012",
+ sbp->st_mode & 07777) < 0)
+ goto write_error;
+ switch (file_type)
+ {
+ case S_IFREG: break;
+ case S_IFCHR:
+ case S_IFBLK:
+#ifdef HAVE_STRUCT_STAT_ST_RDEV
+ if (fprintf (fprcs, "special\t%s %lu;\012",
+ (file_type == S_IFCHR
+ ? "character"
+ : "block"),
+ (unsigned long) sbp->st_rdev) < 0)
+ goto write_error;
+#else
+ error (0, 0,
+"can't import %s: unable to import device files on this system",
+userfile);
+#endif
+ break;
+ default:
+ error (0, 0,
+ "can't import %s: unknown kind of special file",
+ userfile);
+ }
+ }
+ return 0;
+write_error:
+ return 1;
+}
+#endif /* PRESERVE_PERMISSIONS_SUPPORT */
+
+/* Copy file contents into an RCS file, expanding at signs.
+ *
+ * If preserve_perms is set, nothing is copied if the source is not
+ * a regular file.
+ *
+ * INPUTS
+ * fprcs FILE pointer for the (newly-created) RCS file. The expanded
+ * contents should be written here.
+ * file_type File type of the data source. No data is copied if
+ * preserve_permissions is set and the source is not a
+ * regular file.
+ * user Filename of the data source (used to print error messages).
+ * fpuser FILE pointer for the data source, whose data is being
+ * copied into the RCS file.
+ *
+ * RETURNS
+ * Return value is 0 for success, or nonzero for failure (in which case
+ * no error message has yet been printed).
+ */
+static int
+expand_and_copy_contents (fprcs, file_type, user, fpuser)
+ FILE *fprcs, *fpuser;
+ mode_t file_type;
+ const char *user;
+{
+ if (!preserve_perms || file_type == S_IFREG)
+ {
+ char buf[8192];
+ unsigned int len;
+
+ while (1)
+ {
+ len = fread (buf, 1, sizeof buf, fpuser);
+ if (len == 0)
+ {
+ if (ferror (fpuser))
+ error (1, errno, "cannot read file %s for copying",
+ user);
+ break;
+ }
+ if (expand_at_signs (buf, len, fprcs) < 0)
+ goto write_error;
+ }
+ }
+ return 0;
+
+write_error:
+ return 1;
+}
/*
* Write SIZE bytes at BUF to FP, expanding @ signs into double @
Index: cvs/src/mkmodules.c
diff -u cvs/src/mkmodules.c:1.1.1.1 cvs/src/mkmodules.c:1.4
--- cvs/src/mkmodules.c:1.1.1.1 Wed Jun 23 21:34:12 2004
+++ cvs/src/mkmodules.c Wed Jun 23 21:39:25 2004
@@ -961,7 +961,7 @@
/* No vendor branch. */
NULL, NULL, 0, NULL,
- NULL, 0, NULL);
+ NULL, 0, NULL, 0);
if (retcode != 0)
/* add_rcs_file already printed an error message. */
err = 1;
Index: cvs/src/rcs.h
diff -u cvs/src/rcs.h:1.1.1.1 cvs/src/rcs.h:1.4
--- cvs/src/rcs.h:1.1.1.1 Wed Jun 23 21:34:12 2004
+++ cvs/src/rcs.h Wed Jun 23 21:39:25 2004
@@ -248,4 +248,4 @@
extern int add_rcs_file (const char *, const char *, const char *,
const char *, const char *, const char *,
const char *, int, char **, const char *, size_t,
- FILE *);
+ FILE *, int);
Index: cvs/src/sanity.sh
diff -u cvs/src/sanity.sh:1.1.1.1 cvs/src/sanity.sh:1.4
--- cvs/src/sanity.sh:1.1.1.1 Wed Jun 23 21:34:13 2004
+++ cvs/src/sanity.sh Wed Jun 23 21:39:25 2004
@@ -1061,7 +1061,8 @@
tests="${tests} rm-update-message rmadd rmadd2 rmadd3 resurrection"
tests="${tests} dirs dirs2 branches branches2 branches3"
tests="${tests} branches4 tagc tagf"
- tests="${tests} rcslib multibranch import importb importc import-CVS"
+ tests="${tests} rcslib multibranch import importb importc importX"
+ tests="${tests} import-CVS"
tests="${tests} update-p import-after-initial branch-after-import"
tests="${tests} join join2 join3 join4 join5 join6"
tests="${tests} join-readonly-conflict join-admin join-admin-2"
@@ -7886,6 +7887,7 @@
# import -- more tests of imports with keywords
# importb -- -b option.
# importc -- bunch o' files in bunch o' directories
+ # importX -- -X option.
# modules3
# mflag -- various -m messages
# ignore -- import and cvsignore
@@ -8334,6 +8336,94 @@
TZ=$save_TZ
cd ..
rm -r 1 2
+ rm -rf ${CVSROOT_DIRNAME}/first-dir
+ ;;
+
+
+
+ importX)
+ # More cvs import tests, especially -X option.
+
+ # OK, first we get some sources from the Munger version 1.0,
+ # and import them into the 1.1.1 vendor branch using -X.
+ mkdir imp-dir
+ cd imp-dir
+ echo 'Munger sources' >file1
+ echo 'Munger sources' >file2
+ dotest_sort importX-1 \
+"${testcvs} import -X -m add first-dir munger munger-1_0" \
+"
+
+
+ ${CPROG} checkout -j<prev_rel_tag> -jmunger-1_0 first-dir
+N first-dir/file1
+N first-dir/file2
+No conflicts created by this import.
+Use the following command to help the merge:"
+ cd ..
+ rm -r imp-dir
+
+ # Now we put the sources we get from Munger version 1.1 on
+ # to the 1.1.1 vendor branch using -X.
+ mkdir imp-dir
+ cd imp-dir
+ echo 'Munger sources 1.1' >file1
+ echo 'Munger sources' >file2
+ echo 'Munger sources 1.1' >file3
+ dotest_sort importX-2 \
+"${testcvs} -d ${CVSROOT} import -X -m add first-dir munger munger-1_1" \
+"
+
+
+ ${CPROG} -d ${CVSROOT} checkout -j<prev_rel_tag> -jmunger-1_1 first-dir
+1 conflicts created by this import.
+C first-dir/file1
+N first-dir/file3
+U first-dir/file2
+Use the following command to help the merge:"
+ cd ..
+ rm -r imp-dir
+
+ mkdir 1
+ cd 1
+ # **nothing** should be checked out**
+ dotest importX-3 "${testcvs} -q co first-dir" ""
+ cd first-dir
+ dotest importX-4 "${testcvs} -q log file1" "
+RCS file: ${CVSROOT_DIRNAME}/first-dir/Attic/file1,v
+Working file: file1
+head: 1\.2
+branch:
+locks: strict
+access list:
+symbolic names:
+ munger-1_1: 1\.1\.1\.2
+ munger-1_0: 1\.1\.1\.1
+ munger: 1\.1\.1
+keyword substitution: kv
+total revisions: 4; selected revisions: 4
+description:
+----------------------------
+revision 1\.2
+date: ${ISO8601DATE}; author: ${username}; state: dead; lines: ${PLUS}0 -0
+Revision 1\.1 was added on the vendor branch\.
+----------------------------
+revision 1\.1
+date: ${ISO8601DATE}; author: ${username}; state: Exp;
+branches: 1\.1\.1;
+Initial revision
+----------------------------
+revision 1\.1\.1\.2
+date: ${ISO8601DATE}; author: ${username}; state: Exp; lines: ${PLUS}1 -1
+add
+----------------------------
+revision 1\.1\.1\.1
+date: ${ISO8601DATE}; author: ${username}; state: Exp; lines: ${PLUS}0 -0
+add
+============================================================================="
+
+ cd ../..
+ rm -r 1
rm -rf ${CVSROOT_DIRNAME}/first-dir
;;
- patch: new 'cvs import -X' option., Chris G. Demetriou, 2004/06/22
- Re: patch: new 'cvs import -X' option., Chris G. Demetriou, 2004/06/22
- Re: patch: new 'cvs import -X' option., Mark D. Baushke, 2004/06/22
- Re: patch: new 'cvs import -X' option., Chris G. Demetriou, 2004/06/22
- Re: patch: new 'cvs import -X' option.,
Chris G. Demetriou <=
- Re: patch: new 'cvs import -X' option., Chris G. Demetriou, 2004/06/24
- Re: patch: new 'cvs import -X' option., Mark D. Baushke, 2004/06/26
- Re: patch: new 'cvs import -X' option., cgd, 2004/06/27
- new ForceImportKillNewFiles 'config' option., cgd, 2004/06/27
- Re: new ForceImportKillNewFiles 'config' option., cgd, 2004/06/27
- Re: new ForceImportKillNewFiles 'config' option., Mark D. Baushke, 2004/06/27
- Re: new ForceImportKillNewFiles 'config' option., Larry Jones, 2004/06/27
- Re: new ForceImportKillNewFiles 'config' option., cgd, 2004/06/28