aboutsummaryrefslogtreecommitdiffstats
path: root/gnu/usr.bin/cvs/cvs/checkin.c
blob: 44b733e970bc3ab9c4c83c8a78515b6f6e67fbcb (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
/*
 * 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.3 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"

#ifndef lint
static char rcsid[] = "@(#)checkin.c 1.40 92/03/31";
#endif

int
Checkin (type, file, repository, rcs, rev, tag, message, entries)
    int type;
    char *file;
    char *repository;
    char *rcs;
    char *rev;
    char *tag;
    char *message;
    List *entries;
{
    char fname[PATH_MAX];
    Vers_TS *vers;

    (void) printf ("Checking in %s;\n", file);
    (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.
     */
    if (!noexec)
	copy_file (file, fname);

    run_setup ("%s%s -f %s%s", Rcsbin, RCS_CI,
	       rev ? "-r" : "", rev ? rev : "");
    run_args ("-m%s", message);
    run_arg (rcs);

    switch (run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL))
    {
	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.
	     */

	    /* XXX - make sure -k options are used on the co; and tag/date? */
#ifdef FREEBSD_DEVELOPER
	    run_setup ("%s%s -q %s%s %s", Rcsbin, RCS_CO,
		       rev ? "-r" : "", rev ? rev : "",
		       freebsd ? "-KeAuthor,Date,Header,Id,Locker,Log,"
		       "RCSfile,Revision,Source,State -KiFreeBSD" : "");
#else
	    run_setup ("%s%s -q %s%s", Rcsbin, RCS_CO,
		       rev ? "-r" : "", rev ? rev : "");
#endif /* FREEBSD_DEVELOPER */
	    run_arg (rcs);
	    (void) run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL);
	    xchmod (file, 1);
	    if (xcmp (file, fname) == 0)
		rename_file (fname, file);
	    else
		(void) unlink_file (fname);

	    /*
	     * If we want read-only files, muck the permissions here, before
	     * getting the file time-stamp.
	     */
	    if (cvswrite == FALSE)
		xchmod (file, 0);

	    /* for added files with symbolic tags, need to add the tag too */
	    if (type == 'A' && tag && !isdigit (*tag))
	    {
		run_setup ("%s%s -q -N%s:%s", Rcsbin, RCS, tag, rev);
		run_arg (rcs);
		(void) run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL);
	    }

	    /* re-register with the new data */
	    vers = Version_TS (repository, (char *) NULL, tag, (char *) NULL,
			       file, 1, 1, entries, (List *) 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);
	    history_write (type, (char *) 0, vers->vn_rcs, file, repository);
	    freevers_ts (&vers);
	    break;

	case -1:			/* fork failed */
	    if (!noexec)
		error (1, errno, "could not check in %s -- fork failed", file);
	    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 (!noexec)
	    {
		rename_file (fname, file);
		error (0, 0, "could not check in %s", file);
	    }
	    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)
    {
	run_setup ("%s%s -q -u", Rcsbin, RCS);
	run_arg (rcs);
	(void) run_exec (RUN_TTY, RUN_TTY, DEVNULL, RUN_NORMAL);
    }
    return (0);
}