summaryrefslogtreecommitdiffstats
path: root/contrib/cvs/src
diff options
context:
space:
mode:
authorobrien <obrien@FreeBSD.org>2008-03-19 15:07:28 +0000
committerobrien <obrien@FreeBSD.org>2008-03-19 15:07:28 +0000
commit41abcd97db9740a80b6909fb4eb2f712ca73f6b9 (patch)
treef493337ec40107789125e4ceabb004dd0c2bdb1a /contrib/cvs/src
parent9452bc826ee03da4235ec394e2cff88c33aaa28c (diff)
downloadFreeBSD-src-41abcd97db9740a80b6909fb4eb2f712ca73f6b9.zip
FreeBSD-src-41abcd97db9740a80b6909fb4eb2f712ca73f6b9.tar.gz
Merge rev 1.9 (update "-T" Template support) and rev 1.2 (-D'date'
option with -r'branch' on update) into version 1.11-20080310.
Diffstat (limited to 'contrib/cvs/src')
-rw-r--r--contrib/cvs/src/update.c147
1 files changed, 95 insertions, 52 deletions
diff --git a/contrib/cvs/src/update.c b/contrib/cvs/src/update.c
index 3d82ee4..f2c8087 100644
--- a/contrib/cvs/src/update.c
+++ b/contrib/cvs/src/update.c
@@ -1448,8 +1448,10 @@ VERS: ", 0);
/* fix up the vers structure, in case it is used by join */
if (join_rev1)
{
- /* FIXME: Throwing away the original revision info is almost
- certainly wrong -- what if join_rev1 is "BASE"? */
+ /* FIXME: It seems like we should be preserving ts_user
+ * & ts_rcs here, but setting them causes problems in
+ * join_file().
+ */
if (vers_ts->vn_user != NULL)
free (vers_ts->vn_user);
if (vers_ts->vn_rcs != NULL)
@@ -1658,21 +1660,11 @@ patch_file (finfo, vers_ts, docheckout, file_info, checksum)
data.final_nl = 0;
data.compute_checksum = 0;
- /* FIXME - Passing vers_ts->tag here is wrong in the least number
- * of cases. Since we don't know whether vn_user was checked out
- * using a tag, we pass vers_ts->tag, which, assuming the user did
- * not specify a new TAG to -r, will be the branch we are on.
- *
- * The only thing it is used for is to substitute in for the Name
- * RCS keyword, so in the error case, the patch fails to apply on
- * the client end and we end up resending the whole file.
- *
- * At least, if we are keeping track of the tag vn_user came from,
- * I don't know where yet. -DRP
+ /* Duplicating the client working file, so use the original sticky options.
*/
retcode = RCS_checkout (vers_ts->srcfile, (char *) NULL,
- vers_ts->vn_user, vers_ts->tag,
- vers_ts->options, RUN_TTY,
+ vers_ts->vn_user, vers_ts->entdata->tag,
+ vers_ts->entdata->options, RUN_TTY,
patch_file_write, (void *) &data);
if (fclose (e) < 0)
@@ -2230,6 +2222,7 @@ join_file (finfo, vers)
if (rev2 == NULL || RCS_isdead (vers->srcfile, rev2))
{
char *mrev;
+ short conflict = 0;
if (rev2 != NULL)
free (rev2);
@@ -2280,8 +2273,7 @@ join_file (finfo, vers)
|| vers->vn_user[0] == '-'
|| RCS_isdead (vers->srcfile, vers->vn_user))
{
- if (rev1 != NULL)
- free (rev1);
+ free (rev1);
return;
}
@@ -2290,56 +2282,107 @@ join_file (finfo, vers)
resolve. No_Difference will already have been called in
this case, so comparing the timestamps is sufficient to
determine whether the file is locally modified. */
- if (strcmp (vers->vn_user, "0") == 0
- || (vers->ts_user != NULL
- && strcmp (vers->ts_user, vers->ts_rcs) != 0))
+ if (/* may have changed on destination branch */
+ /* file added locally */
+ !strcmp (vers->vn_user, "0")
+ || /* destination branch modified in repository */
+ strcmp (rev1, vers->vn_user)
+ || /* locally modified */
+ vers->ts_user && strcmp (vers->ts_user, vers->ts_rcs))
{
- if (jdate2 != NULL)
- error (0, 0,
- "file %s is locally modified, but has been removed in revision %s as of %s",
- finfo->fullname, jrev2, jdate2);
- else
- error (0, 0,
- "file %s is locally modified, but has been removed in revision %s",
- finfo->fullname, jrev2);
-
- /* FIXME: Should we arrange to return a non-zero exit
- status? */
-
- if (rev1 != NULL)
- free (rev1);
-
- return;
+ /* The removal should happen if either the file has never changed
+ * on the destination or the file has changed to be identical to
+ * the first join revision.
+ *
+ * ------R-----------D
+ * |
+ * \----J1---J2-----S
+ *
+ * So:
+ *
+ * J2 is dead.
+ * D is destination.
+ * R is source branch root/GCA.
+ * if J1 == D removal should happen
+ * if D == R removal should happen
+ * otherwise, fail.
+ *
+ * (In the source, J2 = REV2, D = user file (potentially VN_USER),
+ * R = GCA computed below)
+ */
+ char *gca_rev1 = gca (rev1, vers->vn_user);
+#ifdef SERVER_SUPPORT
+ if (server_active && !isreadable (finfo->file))
+ {
+ int retcode;
+ /* The file is up to date. Need to check out the current
+ * contents.
+ */
+ /* FIXME - see the FIXME comment above the call to RCS_checkout
+ * in the patch_file function.
+ */
+ retcode = RCS_checkout (vers->srcfile, finfo->file,
+ vers->vn_user, vers->tag,
+ NULL, RUN_TTY, NULL, NULL);
+ if (retcode)
+ error (1, 0,
+ "failed to check out %s file", finfo->fullname);
+ }
+#endif
+ if (/* genuinely changed on destination branch */
+ RCS_cmp_file (vers->srcfile, gca_rev1, NULL,
+ NULL, vers->options, finfo->file)
+ && /* genuinely different from REV1 */
+ RCS_cmp_file (vers->srcfile, rev1, NULL,
+ NULL, vers->options, finfo->file))
+ conflict = 1;
}
- /* If only one join tag was specified, and the user file has
- been changed since the greatest common ancestor (rev1),
- then there is a conflict we can not resolve. See above for
- the rationale. */
- if (join_rev2 == NULL
- && strcmp (rev1, vers->vn_user) != 0)
+ free (rev1);
+
+ if (conflict)
{
- if (jdate2 != NULL)
+ char *cp;
+
+ if (jdate2)
error (0, 0,
- "file %s has been modified, but has been removed in revision %s as of %s",
+ "file %s has been removed in revision %s as of %s, but the destination is incompatibly modified",
finfo->fullname, jrev2, jdate2);
else
error (0, 0,
- "file %s has been modified, but has been removed in revision %s",
+ "file %s has been removed in revision %s, but the destination is incompatibly modified",
finfo->fullname, jrev2);
- /* FIXME: Should we arrange to return a non-zero exit
- status? */
+ /* Register the conflict with the client. */
- if (rev1 != NULL)
- free (rev1);
+ /* FIXME: vers->ts_user should always be set here but sometimes
+ * isn't, namely when checkout_file() has just created the file,
+ * but simply setting it in checkout_file() appears to cause other
+ * problems.
+ */
+ if (isfile (finfo->file))
+ cp = time_stamp (finfo->file);
+ else
+ cp = xstrdup (vers->ts_user);
+
+ Register (finfo->entries, finfo->file, vers->vn_user,
+ "Result of merge", vers->options, vers->tag, vers->date,
+ cp);
+ write_letter (finfo, 'C');
+ free (cp);
+
+#ifdef SERVER_SUPPORT
+ /* Abuse server_checked_in() to send the updated entry without
+ * needing to update the file.
+ */
+ if (server_active)
+ server_checked_in (finfo->file, finfo->update_dir,
+ finfo->repository);
+#endif
return;
}
- if (rev1 != NULL)
- free (rev1);
-
/* The user file exists and has not been modified. Mark it
for removal. FIXME: If we are doing a checkout, this has
the effect of first checking out the file, and then
OpenPOWER on IntegriCloud