751 |
? SERVER_RCS_DIFF |
? SERVER_RCS_DIFF |
752 |
: SERVER_PATCHED), |
: SERVER_PATCHED), |
753 |
file_info.st_mode, checksum, |
file_info.st_mode, checksum, |
754 |
NULL, false); |
NULL); |
755 |
break; |
break; |
756 |
} |
} |
757 |
} |
} |
1176 |
{ |
{ |
1177 |
if (vers->ts_user == NULL) |
if (vers->ts_user == NULL) |
1178 |
server_scratch_entry_only (); |
server_scratch_entry_only (); |
1179 |
server_updated (finfo, vers, SERVER_UPDATED, (mode_t) -1, NULL, NULL, |
server_updated (finfo, vers, SERVER_UPDATED, (mode_t) -1, NULL, NULL); |
|
false); |
|
1180 |
} |
} |
1181 |
#endif |
#endif |
1182 |
if (unlink_file (finfo->file) < 0 && ! existence_error (errno)) |
if (unlink_file (finfo->file) < 0 && ! existence_error (errno)) |
1289 |
*/ |
*/ |
1290 |
status = base_checkout (vers_ts->srcfile, finfo, |
status = base_checkout (vers_ts->srcfile, finfo, |
1291 |
vers_ts->vn_user, vers_ts->vn_rcs, |
vers_ts->vn_user, vers_ts->vn_rcs, |
1292 |
vers_ts->tag, vers_ts->options, |
vers_ts->tag, vers_ts->options); |
|
cvswrite |
|
|
&& !fileattr_get (finfo->file, |
|
|
"_watched")); |
|
1293 |
} |
} |
1294 |
|
|
1295 |
if (file_is_dead || status == 0) |
if (file_is_dead || status == 0) |
1301 |
Vers_TS *xvers_ts; |
Vers_TS *xvers_ts; |
1302 |
|
|
1303 |
if (!file_is_dead) |
if (!file_is_dead) |
1304 |
base_copy (finfo, vers_ts->vn_rcs, "m"); |
base_copy (finfo, vers_ts->vn_rcs, |
1305 |
|
cvswrite && !fileattr_get (finfo->file, "_watched") |
1306 |
|
? "my" : "mn"); |
1307 |
|
|
1308 |
{ |
{ |
1309 |
/* A newly checked out file is never under the spell |
/* A newly checked out file is never under the spell |
1395 |
if (update_server && server_active) |
if (update_server && server_active) |
1396 |
server_updated (finfo, vers_ts, |
server_updated (finfo, vers_ts, |
1397 |
merging ? SERVER_MERGED : SERVER_UPDATED, |
merging ? SERVER_MERGED : SERVER_UPDATED, |
1398 |
mode, NULL, NULL, true); |
mode, NULL, NULL); |
1399 |
#endif |
#endif |
1400 |
} |
} |
1401 |
else |
else |
1808 |
/* Reregister a file after a merge. */ |
/* Reregister a file after a merge. */ |
1809 |
static void |
static void |
1810 |
RegisterMerge (struct file_info *finfo, Vers_TS *vers, |
RegisterMerge (struct file_info *finfo, Vers_TS *vers, |
1811 |
const char *backup, int has_conflicts) |
const char *backup, bool has_conflicts, bool force_addition) |
1812 |
{ |
{ |
1813 |
/* This file is the result of a merge, which means that it has |
/* This file is the result of a merge, which means that it has |
1814 |
been modified. We use a special timestamp string which will |
been modified. We use a special timestamp string which will |
1820 |
time (&last_register_time); |
time (&last_register_time); |
1821 |
cp = time_stamp (finfo->file); |
cp = time_stamp (finfo->file); |
1822 |
} |
} |
1823 |
Register (finfo->entries, finfo->file, vers->vn_rcs ? vers->vn_rcs : "0", |
Register (finfo->entries, finfo->file, |
1824 |
|
vers->vn_rcs && !force_addition ? vers->vn_rcs : "0", |
1825 |
"Result of merge", vers->options, vers->tag, vers->date, cp); |
"Result of merge", vers->options, vers->tag, vers->date, cp); |
1826 |
if (cp) |
if (cp) |
1827 |
free (cp); |
free (cp); |
1832 |
the message only after the file has safely been written. */ |
the message only after the file has safely been written. */ |
1833 |
if (server_active) |
if (server_active) |
1834 |
{ |
{ |
1835 |
server_copy_file (finfo->file, finfo->update_dir, finfo->repository, |
if (vers->ts_user) |
1836 |
backup); |
server_copy_file (finfo->file, finfo->update_dir, |
1837 |
server_updated (finfo, vers, SERVER_MERGED, (mode_t) -1, NULL, NULL, |
finfo->repository, backup); |
1838 |
false); |
server_updated (finfo, vers, SERVER_MERGED, (mode_t) -1, NULL, NULL); |
1839 |
} |
} |
1840 |
#endif |
#endif |
1841 |
} |
} |
1887 |
thought needs to go into this, and in the meantime it is safe |
thought needs to go into this, and in the meantime it is safe |
1888 |
to treat any such mismatch as an automatic conflict. -twp */ |
to treat any such mismatch as an automatic conflict. -twp */ |
1889 |
|
|
1890 |
status = RCS_checkout (finfo->rcs, finfo->file, vers->vn_rcs, |
status = base_checkout (finfo->rcs, finfo, vers->vn_user, vers->vn_rcs, |
1891 |
vers->tag, vers->options, NULL, NULL, NULL); |
vers->tag, vers->options); |
1892 |
|
base_copy (finfo, vers->vn_rcs, "yy"); |
1893 |
|
|
1894 |
if (status) |
if (status) |
1895 |
{ |
{ |
1896 |
error (0, 0, "failed to check out `%s' file", finfo->fullname); |
error (0, 0, "failed to check out `%s' file", finfo->fullname); |
1901 |
goto out; |
goto out; |
1902 |
} |
} |
1903 |
|
|
1904 |
xchmod (finfo->file, 1); |
RegisterMerge (finfo, vers, backup, true, false); |
|
|
|
|
RegisterMerge (finfo, vers, backup, 1); |
|
1905 |
|
|
1906 |
/* Is there a better term than "nonmergeable file"? What we |
/* Is there a better term than "nonmergeable file"? What we |
1907 |
really mean is, not something that CVS cannot or does not |
really mean is, not something that CVS cannot or does not |
1919 |
goto out; |
goto out; |
1920 |
} |
} |
1921 |
|
|
1922 |
status = RCS_merge (finfo->rcs, vers->srcfile->path, finfo->file, |
status = base_merge (finfo->rcs, finfo, vers->options, vers->vn_user, |
1923 |
vers->options, vers->vn_user, vers->vn_rcs); |
vers->vn_user, vers->vn_rcs); |
1924 |
|
|
1925 |
if (status != 0 && status != 1) |
if (status != 0 && status != 1) |
1926 |
{ |
{ |
1927 |
error (0, status == -1 ? errno : 0, |
error (0, status == -1 ? errno : 0, |
1928 |
"could not merge revision %s of %s", vers->vn_user, finfo->fullname); |
"could not merge revision %s of %s", vers->vn_user, |
1929 |
|
finfo->fullname); |
1930 |
error (status == -1 ? 1 : 0, 0, "restoring %s from backup file %s", |
error (status == -1 ? 1 : 0, 0, "restoring %s from backup file %s", |
1931 |
finfo->fullname, backup); |
finfo->fullname, backup); |
1932 |
rename_file (backup, finfo->file); |
rename_file (backup, finfo->file); |
1947 |
vers->vn_user = xstrdup (vers->vn_rcs); |
vers->vn_user = xstrdup (vers->vn_rcs); |
1948 |
} |
} |
1949 |
|
|
1950 |
RegisterMerge (finfo, vers, backup, status); |
RegisterMerge (finfo, vers, backup, status, false); |
1951 |
|
|
1952 |
if (status == 1) |
if (status == 1) |
1953 |
{ |
{ |
1961 |
} |
} |
1962 |
else /* status == 0 */ |
else /* status == 0 */ |
1963 |
{ |
{ |
1964 |
|
/* FIXME: When BASES, a zero status might mean the server didn't |
1965 |
|
* perform the merge. |
1966 |
|
*/ |
1967 |
history_write ('G', finfo->update_dir, vers->vn_rcs, finfo->file, |
history_write ('G', finfo->update_dir, vers->vn_rcs, finfo->file, |
1968 |
finfo->repository); |
finfo->repository); |
1969 |
|
|
1970 |
/* FIXME: the noexec case is broken. RCS_merge could be doing the |
/* FIXME: the noexec case is broken. RCS_merge could be doing the |
1971 |
xcmp on the temporary files without much hassle, I think. */ |
xcmp on the temporary files without much hassle, I think. */ |
1972 |
if (!noexec && !xcmp (backup, finfo->file)) |
if (!noexec && !bases && !xcmp (backup, finfo->file)) |
1973 |
{ |
{ |
1974 |
|
/* The client will handle these messages when BASES. */ |
1975 |
cvs_output (finfo->fullname, 0); |
cvs_output (finfo->fullname, 0); |
1976 |
cvs_output (" already contains the differences between ", 0); |
cvs_output (" already contains the differences between ", 0); |
1977 |
cvs_output (vers->vn_user, 0); |
cvs_output (vers->vn_user, 0); |
2215 |
{ |
{ |
2216 |
server_scratch (finfo->file); |
server_scratch (finfo->file); |
2217 |
server_updated (finfo, vers, SERVER_UPDATED, (mode_t) -1, |
server_updated (finfo, vers, SERVER_UPDATED, (mode_t) -1, |
2218 |
NULL, NULL, false); |
NULL, NULL); |
2219 |
} |
} |
2220 |
#endif |
#endif |
2221 |
Register (finfo->entries, finfo->file, mrev, vers->ts_rcs, |
Register (finfo->entries, finfo->file, mrev, vers->ts_rcs, |
2231 |
server_checked_in (finfo->file, finfo->update_dir, |
server_checked_in (finfo->file, finfo->update_dir, |
2232 |
finfo->repository); |
finfo->repository); |
2233 |
#endif |
#endif |
2234 |
if (! really_quiet) |
if (!really_quiet) |
2235 |
error (0, 0, "scheduling `%s' for removal", finfo->fullname); |
error (0, 0, "scheduling `%s' for removal", finfo->fullname); |
2236 |
|
|
2237 |
return; |
return; |
2300 |
admin `-kk' option for that file in the repository. */ |
admin `-kk' option for that file in the repository. */ |
2301 |
options = NULL; |
options = NULL; |
2302 |
|
|
2303 |
/* FIXME: If checkout_file fails, we should arrange to |
if (!really_quiet) |
2304 |
|
error (0, 0, "scheduling addition from revision %s of `%s'.", |
2305 |
|
xvers->vn_rcs, finfo->fullname); |
2306 |
|
|
2307 |
|
/* FIXME: If base_checkout fails, we should arrange to |
2308 |
return a non-zero exit status. */ |
return a non-zero exit status. */ |
2309 |
status = checkout_file (finfo, xvers, 1, 0, 1); |
status = base_checkout (xvers->srcfile, finfo, |
2310 |
|
NULL, xvers->vn_rcs, |
2311 |
|
xvers->tag, xvers->options); |
2312 |
|
/* Added files are always writable until commit. */ |
2313 |
|
base_copy (finfo, xvers->vn_rcs, "nyd"); |
2314 |
|
|
2315 |
|
backup = Xasprintf ("%s%s.%s", BAKPREFIX, finfo->file, |
2316 |
|
vers->vn_user); |
2317 |
|
RegisterMerge (finfo, vers, backup, false, true); |
2318 |
|
free (backup); |
2319 |
|
|
2320 |
options = saved_options; |
options = saved_options; |
2321 |
|
|
2322 |
freevers_ts (&xvers); |
freevers_ts (&xvers); |
2403 |
as such). In the text file case, this is probably quite |
as such). In the text file case, this is probably quite |
2404 |
similar to the RCS_merge, but in the binary file case, |
similar to the RCS_merge, but in the binary file case, |
2405 |
RCS_merge gives all kinds of trouble. */ |
RCS_merge gives all kinds of trouble. */ |
2406 |
if (vers->vn_user != NULL |
if ((strcmp (t_options, "-kb") == 0 |
2407 |
&& strcmp (rev1, vers->vn_user) == 0 |
|| wrap_merge_is_copy (finfo->file)) |
2408 |
/* See comments above about how No_Difference has already been |
&& ((vers->vn_user != NULL |
2409 |
called. */ |
&& strcmp (rev1, vers->vn_user) == 0 |
2410 |
&& vers->ts_user != NULL |
/* See comments above about how No_Difference has already been |
2411 |
&& strcmp (vers->ts_user, vers->ts_rcs) == 0 |
called. */ |
2412 |
|
&& vers->ts_user != NULL |
2413 |
|
&& strcmp (vers->ts_user, vers->ts_rcs) == 0) |
2414 |
|
|
2415 |
|
|| special_file_mismatch (finfo, rev1, rev2))) |
2416 |
|
{ |
2417 |
|
if (!really_quiet && !special_file_mismatch (finfo, rev1, rev2)) |
2418 |
|
error (0, 0, "Replacing `%s' with contents of revision %s.", |
2419 |
|
finfo->fullname, rev2); |
2420 |
|
|
|
/* Avoid this in the text file case. See below for why. |
|
|
*/ |
|
|
&& (strcmp (t_options, "-kb") == 0 |
|
|
|| wrap_merge_is_copy (finfo->file))) |
|
|
{ |
|
2421 |
/* FIXME: Verify my comment below: |
/* FIXME: Verify my comment below: |
2422 |
* |
* |
2423 |
* RCS_merge does nothing with keywords. It merges the changes between |
* RCS_merge does nothing with keywords. It merges the changes between |
2434 |
* Also, it is safe to pass in NULL for nametag since we know no |
* Also, it is safe to pass in NULL for nametag since we know no |
2435 |
* substitution is happening during the binary mode checkout. |
* substitution is happening during the binary mode checkout. |
2436 |
*/ |
*/ |
2437 |
if (RCS_checkout (finfo->rcs, finfo->file, rev2, NULL, t_options, |
if (base_checkout (finfo->rcs, finfo, vers->vn_user, rev2, vers->tag, |
2438 |
RUN_TTY, NULL, NULL) != 0) |
t_options) != 0) |
|
status = 2; |
|
|
else |
|
|
status = 0; |
|
|
|
|
|
/* OK, this is really stupid. RCS_checkout carefully removes |
|
|
write permissions, and we carefully put them back. But |
|
|
until someone gets around to fixing it, that seems like the |
|
|
easiest way to get what would seem to be the right mode. |
|
|
I don't check CVSWRITE or _watched; I haven't thought about |
|
|
that in great detail, but it seems like a watched file should |
|
|
be checked out (writable) after a merge. */ |
|
|
xchmod (finfo->file, 1); |
|
|
|
|
|
/* Traditionally, the text file case prints a whole bunch of |
|
|
scary looking and verbose output which fails to tell the user |
|
|
what is really going on (it gives them rev1 and rev2 but doesn't |
|
|
indicate in any way that rev1 == vn_user). I think just a |
|
|
simple "U foo" is good here; it seems analogous to the case in |
|
|
which the file was added on the branch in terms of what to |
|
|
print. */ |
|
|
write_letter (finfo, 'U'); |
|
|
} |
|
|
else if (strcmp (t_options, "-kb") == 0 |
|
|
|| wrap_merge_is_copy (finfo->file) |
|
|
|| special_file_mismatch (finfo, rev1, rev2)) |
|
|
{ |
|
|
/* We are dealing with binary files, or files with a |
|
|
permission/linkage mismatch (this second case only occurs when |
|
|
PRESERVE_PERMISSIONS_SUPPORT is enabled), and real merging would |
|
|
need to take place. This is a conflict. We give the user |
|
|
the two files, and let them resolve it. It is possible |
|
|
that we should require a "touch foo" or similar step before |
|
|
we allow a checkin. */ |
|
|
if (RCS_checkout (finfo->rcs, finfo->file, rev2, NULL, |
|
|
t_options, RUN_TTY, NULL, NULL) != 0) |
|
2439 |
status = 2; |
status = 2; |
2440 |
else |
else |
2441 |
status = 0; |
status = 0; |
2442 |
|
|
2443 |
/* OK, this is really stupid. RCS_checkout carefully removes |
base_copy (finfo, rev2, "yy"); |
2444 |
write permissions, and we carefully put them back. But |
if (!really_quiet && special_file_mismatch (finfo, rev1, rev2)) |
2445 |
until someone gets around to fixing it, that seems like the |
{ |
2446 |
easiest way to get what would seem to be the right mode. |
/* Hmm. We don't give them REV1 anywhere. I guess most people |
2447 |
I don't check CVSWRITE or _watched; I haven't thought about |
probably don't have a 3-way merge tool for the file type in |
2448 |
that in great detail, but it seems like a watched file should |
question, and might just get confused if we tried to either |
2449 |
be checked out (writable) after a merge. */ |
provide them with a copy of the file from REV1, or even just |
2450 |
xchmod (finfo->file, 1); |
told them what REV1 is so they can get it themself, but it |
2451 |
|
might be worth thinking about. */ |
2452 |
/* Hmm. We don't give them REV1 anywhere. I guess most people |
/* See comment in merge_file about the "nonmergeable file" |
2453 |
probably don't have a 3-way merge tool for the file type in |
terminology. */ |
2454 |
question, and might just get confused if we tried to either |
error (0, 0, "nonmergeable file needs merge"); |
2455 |
provide them with a copy of the file from REV1, or even just |
error (0, 0, "revision %s from repository is now in %s", |
2456 |
told them what REV1 is so they can get it themself, but it |
rev2, finfo->fullname); |
2457 |
might be worth thinking about. */ |
error (0, 0, "file from working directory is now in %s", backup); |
2458 |
/* See comment in merge_file about the "nonmergeable file" |
write_letter (finfo, 'C'); |
2459 |
terminology. */ |
} |
|
error (0, 0, "nonmergeable file needs merge"); |
|
|
error (0, 0, "revision %s from repository is now in %s", |
|
|
rev2, finfo->fullname); |
|
|
error (0, 0, "file from working directory is now in %s", backup); |
|
|
write_letter (finfo, 'C'); |
|
2460 |
} |
} |
2461 |
else |
else |
2462 |
status = RCS_merge (finfo->rcs, vers->srcfile->path, finfo->file, |
status = base_merge (finfo->rcs, finfo, t_options, |
2463 |
t_options, rev1, rev2); |
vers->vn_user, rev1, rev2); |
2464 |
|
|
2465 |
if (status != 0) |
if (status != 0) |
2466 |
{ |
{ |
2473 |
rename_file (backup, finfo->file); |
rename_file (backup, finfo->file); |
2474 |
} |
} |
2475 |
} |
} |
2476 |
else /* status == 0 */ |
else if (!bases) /* status == 0 */ |
2477 |
{ |
{ |
2478 |
|
/* The client will handle these messages when BASES. */ |
2479 |
|
|
2480 |
/* FIXME: the noexec case is broken. RCS_merge could be doing the |
/* FIXME: the noexec case is broken. RCS_merge could be doing the |
2481 |
xcmp on the temporary files without much hassle, I think. */ |
xcmp on the temporary files without much hassle, I think. */ |
2482 |
if (!noexec && !xcmp (backup, finfo->file)) |
if (!noexec && !xcmp (backup, finfo->file)) |
2483 |
{ |
{ |
2484 |
if (!really_quiet) |
if (!really_quiet) |
2485 |
{ |
{ |
2486 |
|
cvs_output ("`", 1); |
2487 |
cvs_output (finfo->fullname, 0); |
cvs_output (finfo->fullname, 0); |
2488 |
cvs_output (" already contains the differences between ", 0); |
cvs_output ("' already contains the differences between ", 0); |
2489 |
cvs_output (rev1, 0); |
cvs_output (rev1, 0); |
2490 |
cvs_output (" and ", 0); |
cvs_output (" and ", 5); |
2491 |
cvs_output (rev2, 0); |
cvs_output (rev2, 0); |
2492 |
cvs_output ("\n", 1); |
cvs_output ("\n", 1); |
2493 |
} |
} |
2509 |
RCS_checkout above, and we aren't running as the server. |
RCS_checkout above, and we aren't running as the server. |
2510 |
However, that is not the normal case, and calling Register |
However, that is not the normal case, and calling Register |
2511 |
again won't cost much in that case. */ |
again won't cost much in that case. */ |
2512 |
RegisterMerge (finfo, vers, backup, status); |
RegisterMerge (finfo, vers, backup, status, false); |
2513 |
|
|
2514 |
out: |
out: |
2515 |
free (rev1); |
free (rev1); |