[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Cvs-cvs] Changes to ccvs/src/client.c [signed-commits2]
From: |
Derek Robert Price |
Subject: |
[Cvs-cvs] Changes to ccvs/src/client.c [signed-commits2] |
Date: |
Fri, 18 Nov 2005 15:02:10 -0500 |
Index: ccvs/src/client.c
diff -u ccvs/src/client.c:1.433.4.2 ccvs/src/client.c:1.433.4.3
--- ccvs/src/client.c:1.433.4.2 Thu Nov 17 17:08:07 2005
+++ ccvs/src/client.c Fri Nov 18 20:02:07 2005
@@ -14,12 +14,17 @@
# include "config.h"
#endif /* HAVE_CONFIG_H */
-#include "cvs.h"
+/* GNULIB */
#include "getline.h"
-#include "edit.h"
-#include "buffer.h"
#include "save-cwd.h"
+/* CVS */
+#include "base.h"
+
+#include "cvs.h"
+#include "buffer.h"
+#include "edit.h"
+
#ifdef CLIENT_SUPPORT
# include "log-buffer.h"
@@ -1328,6 +1333,15 @@
char **failed_patches;
int failed_patches_count;
+enum update_existing {
+ /* We are replacing an existing file. */
+ UPDATE_ENTRIES_EXISTING,
+ /* We are creating a new file. */
+ UPDATE_ENTRIES_NEW,
+ /* We don't know whether it is existing or new. */
+ UPDATE_ENTRIES_EXISTING_OR_NEW
+};
+
struct update_entries_data
{
enum {
@@ -1336,6 +1350,10 @@
* correct.
*/
UPDATE_ENTRIES_CHECKIN,
+
+ /* The file content may be in a temp file, waiting to be renamed. */
+ UPDATE_ENTRIES_BASE,
+
/* We are getting the file contents as well. */
UPDATE_ENTRIES_UPDATE,
/*
@@ -1350,14 +1368,7 @@
UPDATE_ENTRIES_RCS_DIFF
} contents;
- enum {
- /* We are replacing an existing file. */
- UPDATE_ENTRIES_EXISTING,
- /* We are creating a new file. */
- UPDATE_ENTRIES_NEW,
- /* We don't know whether it is existing or new. */
- UPDATE_ENTRIES_EXISTING_OR_NEW
- } existp;
+ enum update_existing existp;
/*
* String to put in the timestamp field or NULL to use the timestamp
@@ -1442,8 +1453,7 @@
static char *
-read_file_from_server (const char *filename, const char *fullname,
- char **mode_string, size_t *size)
+read_file_from_server (const char *fullname, char **mode_string, size_t *size)
{
char *size_string;
bool use_gzip;
@@ -1483,6 +1493,61 @@
+/* Returns false on error. */
+static bool
+validate_change (enum update_existing existp, const char *filename,
+ const char *fullname)
+{
+ /* Note that checking this separately from writing the file is
+ a race condition: if the existence or lack thereof of the
+ file changes between now and the actual calls which
+ operate on it, we lose. However (a) there are so many
+ cases, I'm reluctant to try to fix them all, (b) in some
+ cases the system might not even have a system call which
+ does the right thing, and (c) it isn't clear this needs to
+ work. */
+ if (existp == UPDATE_ENTRIES_EXISTING
+ && !isfile (filename))
+ /* Emit a warning and update the file anyway. */
+ error (0, 0, "warning: %s unexpectedly disappeared", fullname);
+ else if (existp == UPDATE_ENTRIES_NEW
+ && isfile (filename))
+ {
+ /* This error might be confusing; it isn't really clear to
+ the user what to do about it. Keep in mind that it has
+ several causes: (1) something/someone creates the file
+ during the time that CVS is running, (2) the repository
+ has two files whose names clash for the client because
+ of case-insensitivity or similar causes, See 3 for
+ additional notes. (3) a special case of this is that a
+ file gets renamed for example from a.c to A.C. A
+ "cvs update" on a case-insensitive client will get this
+ error. In this case and in case 2, the filename
+ (short_pathname) printed in the error message will likely _not_
+ have the same case as seen by the user in a directory listing.
+ (4) the client has a file which the server doesn't know
+ about (e.g. "? foo" file), and that name clashes with a file
+ the server does know about, (5) classify.c will print the same
+ message for other reasons.
+
+ I hope the above paragraph makes it clear that making this
+ clearer is not a one-line fix. */
+ error (0, 0, "move away `%s'; it is in the way", fullname);
+ if (updated_fname)
+ {
+ cvs_output ("C ", 0);
+ cvs_output (updated_fname, 0);
+ cvs_output ("\n", 1);
+ }
+ failure_exit = true;
+ return false;
+ }
+
+ return true;
+}
+
+
+
/* Update the Entries line for this file. */
static void
update_entries (void *data_arg, List *ent_list, const char *short_pathname,
@@ -1501,7 +1566,8 @@
char *date = NULL;
char *tag_or_date;
char *scratch_entries = NULL;
- int bin;
+ bool bin;
+ char *temp_filename;
#ifdef UTIME_EXPECTS_WRITABLE
int change_it_back = 0;
@@ -1546,61 +1612,19 @@
/* Done parsing the entries line. */
+ temp_filename = newfilename (filename);
+
if (data->contents == UPDATE_ENTRIES_UPDATE
|| data->contents == UPDATE_ENTRIES_PATCH
|| data->contents == UPDATE_ENTRIES_RCS_DIFF)
{
char *mode_string;
- char *temp_filename;
size_t size;
char *buf;
bool patch_failed;
- /* Note that checking this separately from writing the file is
- a race condition: if the existence or lack thereof of the
- file changes between now and the actual calls which
- operate on it, we lose. However (a) there are so many
- cases, I'm reluctant to try to fix them all, (b) in some
- cases the system might not even have a system call which
- does the right thing, and (c) it isn't clear this needs to
- work. */
- if (data->existp == UPDATE_ENTRIES_EXISTING
- && !isfile (filename))
- /* Emit a warning and update the file anyway. */
- error (0, 0, "warning: %s unexpectedly disappeared",
- short_pathname);
-
- if (data->existp == UPDATE_ENTRIES_NEW
- && isfile (filename))
- {
- /* This error might be confusing; it isn't really clear to
- the user what to do about it. Keep in mind that it has
- several causes: (1) something/someone creates the file
- during the time that CVS is running, (2) the repository
- has two files whose names clash for the client because
- of case-insensitivity or similar causes, See 3 for
- additional notes. (3) a special case of this is that a
- file gets renamed for example from a.c to A.C. A
- "cvs update" on a case-insensitive client will get this
- error. In this case and in case 2, the filename
- (short_pathname) printed in the error message will likely _not_
- have the same case as seen by the user in a directory listing.
- (4) the client has a file which the server doesn't know
- about (e.g. "? foo" file), and that name clashes with a file
- the server does know about, (5) classify.c will print the same
- message for other reasons.
-
- I hope the above paragraph makes it clear that making this
- clearer is not a one-line fix. */
- error (0, 0, "move away `%s'; it is in the way", short_pathname);
- if (updated_fname)
- {
- cvs_output ("C ", 0);
- cvs_output (updated_fname, 0);
- cvs_output ("\n", 1);
- }
- failure_exit = true;
-
+ if (!validate_change (data->existp, filename, short_pathname))
+ {
discard_file_and_return:
discard_file ();
free (scratch_entries);
@@ -1608,8 +1632,7 @@
return;
}
- buf = read_file_from_server (filename, short_pathname,
- &mode_string, &size);
+ buf = read_file_from_server (short_pathname, &mode_string, &size);
/* Some systems, like OS/2 and Windows NT, end lines with CRLF
instead of just LF. Format translation is done in the C
@@ -1620,9 +1643,7 @@
if (options)
bin = !strcmp (options, "-kb");
else
- bin = 0;
-
- temp_filename = newfilename (filename);
+ bin = false;
if (data->contents != UPDATE_ENTRIES_RCS_DIFF)
{
@@ -1833,6 +1854,10 @@
free (mode_string);
}
+ else if (data->contents == UPDATE_ENTRIES_BASE)
+ {
+ rename_file (temp_filename, filename);
+ }
if (stored_mode)
{
@@ -2024,6 +2049,165 @@
static void
+client_base_checkout (void *data_arg, List *ent_list,
+ const char *short_pathname, const char *filename)
+{
+ char *options, *prev, *rev;
+ char *basefile;
+
+ read_line (&options);
+ read_line (&prev);
+ read_line (&rev);
+
+ basefile = make_base_file_name (filename, rev);
+
+ /* FIXME: Reenable this check once update is working. */
+ //if (isfile (basefile))
+ //error (1, 0, "Server sent base file `%s', which already exists.",
+ // basefile);
+
+ if (*prev && strcmp (prev, rev))
+ {
+ /* FIXME: Handle diff. */
+ }
+ else
+ {
+ int fd;
+ int bin;
+ char *buf;
+ char *mode_string;
+ size_t size;
+ int status;
+
+ mkdir_if_needed (CVSADM_BASE);
+ /* FIXME: Read/write to file is repeated and could be optimized to
+ * write directly to disk without using so much mem.
+ */
+ buf = read_file_from_server (short_pathname, &mode_string, &size);
+ if (options) bin = strcmp (options, "-kb") ? 0 : OPEN_BINARY;
+ else bin = 0;
+
+
+ fd = CVS_OPEN (basefile, (O_WRONLY | O_CREAT | O_TRUNC | bin), 0777);
+
+ if (fd < 0)
+ {
+ /* I can see a case for making this a fatal error; for
+ a condition like disk full or network unreachable
+ (for a file server), carrying on and giving an
+ error on each file seems unnecessary. But if it is
+ a permission problem, or some such, then it is
+ entirely possible that future files will not have
+ the same problem. */
+ error (0, errno, "cannot write %s", short_pathname);
+ free (basefile);
+ free (buf);
+ free (rev);
+ free (prev);
+ return;
+ }
+
+ if (write (fd, buf, size) != size)
+ error (1, errno, "writing %s", short_pathname);
+
+ if (close (fd) < 0)
+ error (1, errno, "writing %s", short_pathname);
+
+ free (buf);
+
+ status = change_mode (basefile, mode_string, 1);
+ if (status != 0)
+ error (0, status, "cannot change mode of %s", short_pathname);
+ }
+
+ /* FIXME: When enabled, verify base file via openpgp signature. */
+
+ free (rev);
+ free (prev);
+ free (basefile);
+}
+
+
+
+static void
+handle_base_checkout (char *args, size_t len)
+{
+ call_in_directory (args, client_base_checkout, NULL);
+}
+
+
+
+static enum update_existing
+translate_exists (const char *exists)
+{
+ if (*exists == 'n') return UPDATE_ENTRIES_NEW;
+ if (*exists == 'y') return UPDATE_ENTRIES_EXISTING;
+ if (*exists == 'm') return UPDATE_ENTRIES_EXISTING_OR_NEW;
+ error (1, 0, "unknown existence code received from server: `%s'",
+ exists);
+ assert (!"Internal error"); /* Placate GCC. */
+}
+
+
+
+/* Create am up-to-date temporary workfile from a base file. */
+static void
+client_base_copy (void *data_arg, List *ent_list, const char *short_pathname,
+ const char *filename)
+{
+ char *rev, *exists;
+ char *basefile;
+ char *temp_filename;
+
+ read_line (&rev);
+
+ read_line (&exists);
+ if (!validate_change (translate_exists (exists), filename, short_pathname))
+ {
+ free (rev);
+ free (exists);
+ return;
+ }
+ free (exists);
+
+ basefile = make_base_file_name (filename, rev);
+ temp_filename = newfilename (filename);
+ copy_file (basefile, temp_filename);
+
+ /* I think it is ok to assume that if the server is sending base_copy,
+ * then it sent the commands necessary to create the required base file.
+ * If not, then it may be necessary to provide a way to request the base
+ * file be sent.
+ */
+
+ free (temp_filename);
+ free (basefile);
+ free (rev);
+}
+
+
+
+static void
+handle_base_copy (char *args, size_t len)
+{
+ call_in_directory (args, client_base_copy, NULL);
+}
+
+
+
+static void
+handle_base_entry (char *args, size_t len)
+{
+ struct update_entries_data dat;
+ dat.contents = UPDATE_ENTRIES_BASE;
+ dat.existp = UPDATE_ENTRIES_EXISTING_OR_NEW;
+ dat.timestamp = NULL;
+ call_in_directory (args, update_entries, &dat);
+}
+
+
+
+static void
remove_entry (void *data, List *ent_list, const char *short_pathname,
const char *filename)
{
@@ -3103,6 +3287,12 @@
RSP_LINE("E", handle_e, response_type_normal, rs_essential),
RSP_LINE("F", handle_f, response_type_normal, rs_optional),
RSP_LINE("MT", handle_mt, response_type_normal, rs_optional),
+ RSP_LINE("Base-checkout", handle_base_checkout, response_type_normal,
+ rs_optional),
+ RSP_LINE("Base-copy", handle_base_copy, response_type_normal,
+ rs_optional),
+ RSP_LINE("Base-entry", handle_base_entry, response_type_normal,
+ rs_optional),
/* Possibly should be response_type_error. */
RSP_LINE(NULL, NULL, response_type_normal, rs_essential)
- [Cvs-cvs] Changes to ccvs/src/client.c [signed-commits2], Derek Robert Price, 2005/11/17
- [Cvs-cvs] Changes to ccvs/src/client.c [signed-commits2],
Derek Robert Price <=
- [Cvs-cvs] Changes to ccvs/src/client.c [signed-commits2], Derek Robert Price, 2005/11/22
- [Cvs-cvs] Changes to ccvs/src/client.c [signed-commits2], Derek Robert Price, 2005/11/22
- [Cvs-cvs] Changes to ccvs/src/client.c [signed-commits2], Derek Robert Price, 2005/11/29
- [Cvs-cvs] Changes to ccvs/src/client.c [signed-commits2], Derek Robert Price, 2005/11/30
- [Cvs-cvs] Changes to ccvs/src/client.c [signed-commits2], Derek Robert Price, 2005/11/30
- [Cvs-cvs] Changes to ccvs/src/client.c [signed-commits2], Derek Robert Price, 2005/11/30
- [Cvs-cvs] Changes to ccvs/src/client.c [signed-commits2], Derek Robert Price, 2005/11/30
- [Cvs-cvs] Changes to ccvs/src/client.c [signed-commits2], Derek Robert Price, 2005/11/30
- [Cvs-cvs] Changes to ccvs/src/client.c [signed-commits2], Derek Robert Price, 2005/11/30