summaryrefslogtreecommitdiff
path: root/contrib/cvs/src/checkin.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/cvs/src/checkin.c')
-rw-r--r--contrib/cvs/src/checkin.c188
1 files changed, 188 insertions, 0 deletions
diff --git a/contrib/cvs/src/checkin.c b/contrib/cvs/src/checkin.c
new file mode 100644
index 0000000000000..e1ce9cbcbde69
--- /dev/null
+++ b/contrib/cvs/src/checkin.c
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 1992, Brian Berliner and Jeff Polk
+ * Copyright (c) 1989-1992, Brian Berliner
+ *
+ * You may distribute under the terms of the GNU General Public License as
+ * specified in the README file that comes with the CVS 1.4 kit.
+ *
+ * Check In
+ *
+ * Does a very careful checkin of the file "user", and tries not to spoil its
+ * modification time (to avoid needless recompilations). When RCS ID keywords
+ * get expanded on checkout, however, the modification time is updated and
+ * there is no good way to get around this.
+ *
+ * Returns non-zero on error.
+ */
+
+#include "cvs.h"
+#include "fileattr.h"
+#include "edit.h"
+
+int
+Checkin (type, file, update_dir, repository,
+ rcs, rev, tag, options, message, entries)
+ int type;
+ char *file;
+ char *update_dir;
+ char *repository;
+ char *rcs;
+ char *rev;
+ char *tag;
+ char *options;
+ char *message;
+ List *entries;
+{
+ char fname[PATH_MAX];
+ Vers_TS *vers;
+ int set_time;
+ char *fullname;
+
+ char *tocvsPath = NULL;
+
+ fullname = xmalloc (strlen (update_dir) + strlen (file) + 10);
+ if (update_dir[0] == '\0')
+ strcpy (fullname, file);
+ else
+ sprintf (fullname, "%s/%s", update_dir, file);
+
+ (void) printf ("Checking in %s;\n", fullname);
+ (void) sprintf (fname, "%s/%s%s", CVSADM, CVSPREFIX, file);
+
+ /*
+ * Move the user file to a backup file, so as to preserve its
+ * modification times, then place a copy back in the original file name
+ * for the checkin and checkout.
+ */
+
+ tocvsPath = wrap_tocvs_process_file (fullname);
+
+ if (!noexec)
+ {
+ if (tocvsPath)
+ {
+ copy_file (tocvsPath, fname);
+ if (unlink_file_dir (file) < 0)
+ if (! existence_error (errno))
+ error (1, errno, "cannot remove %s", file);
+ copy_file (tocvsPath, file);
+ }
+ else
+ {
+ copy_file (file, fname);
+ }
+ }
+
+ switch (RCS_checkin (rcs, NULL, message, rev, 0, 0))
+ {
+ case 0: /* everything normal */
+
+ /*
+ * The checkin succeeded, so now check the new file back out and
+ * see if it matches exactly with the one we checked in. If it
+ * does, just move the original user file back, thus preserving
+ * the modes; otherwise, we have no recourse but to leave the
+ * newly checkout file as the user file and remove the old
+ * original user file.
+ */
+
+ if (strcmp (options, "-V4") == 0) /* upgrade to V5 now */
+ options[0] = '\0';
+
+ /* FIXME: should be checking for errors. */
+ (void) RCS_checkout (rcs, "", rev, options, RUN_TTY, 0, 0);
+
+ xchmod (file, 1);
+ if (xcmp (file, fname) == 0)
+ {
+ rename_file (fname, file);
+ /* the time was correct, so leave it alone */
+ set_time = 0;
+ }
+ else
+ {
+ if (unlink_file (fname) < 0)
+ error (0, errno, "cannot remove %s", fname);
+ /* sync up with the time from the RCS file */
+ set_time = 1;
+ }
+
+ wrap_fromcvs_process_file (file);
+
+ /*
+ * If we want read-only files, muck the permissions here, before
+ * getting the file time-stamp.
+ */
+ if (cvswrite == FALSE || fileattr_get (file, "_watched"))
+ xchmod (file, 0);
+
+ /* re-register with the new data */
+ vers = Version_TS (repository, (char *) NULL, tag, (char *) NULL,
+ file, 1, set_time, entries, (RCSNode *) NULL);
+ if (strcmp (vers->options, "-V4") == 0)
+ vers->options[0] = '\0';
+ Register (entries, file, vers->vn_rcs, vers->ts_user,
+ vers->options, vers->tag, vers->date, (char *) 0);
+ history_write (type, (char *) 0, vers->vn_rcs, file, repository);
+ freevers_ts (&vers);
+
+ if (tocvsPath)
+ if (unlink_file_dir (tocvsPath) < 0)
+ error (0, errno, "cannot remove %s", tocvsPath);
+
+ break;
+
+ case -1: /* fork failed */
+ if (tocvsPath)
+ if (unlink_file_dir (tocvsPath) < 0)
+ error (0, errno, "cannot remove %s", tocvsPath);
+
+ if (!noexec)
+ error (1, errno, "could not check in %s -- fork failed",
+ fullname);
+ return (1);
+
+ default: /* ci failed */
+
+ /*
+ * The checkin failed, for some unknown reason, so we restore the
+ * original user file, print an error, and return an error
+ */
+ if (tocvsPath)
+ if (unlink_file_dir (tocvsPath) < 0)
+ error (0, errno, "cannot remove %s", tocvsPath);
+
+ if (!noexec)
+ {
+ rename_file (fname, file);
+ error (0, 0, "could not check in %s", fullname);
+ }
+ return (1);
+ }
+
+ /*
+ * When checking in a specific revision, we may have locked the wrong
+ * branch, so to be sure, we do an extra unlock here before
+ * returning.
+ */
+ if (rev)
+ {
+ (void) RCS_unlock (rcs, NULL, 1);
+ }
+
+#ifdef SERVER_SUPPORT
+ if (server_active)
+ {
+ if (set_time)
+ /* Need to update the checked out file on the client side. */
+ server_updated (file, update_dir, repository, SERVER_UPDATED,
+ NULL, NULL);
+ else
+ server_checked_in (file, update_dir, repository);
+ }
+ else
+#endif
+ mark_up_to_date (file);
+
+ return (0);
+}