2 * Copyright (C) 1994-2005 The Free Software Foundation, Inc.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2, or (at your option)
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
16 * Release: "cancel" a checkout in the history log.
18 * - Enter a line in the history log indicating the "release". - If asked to,
19 * delete the local working directory.
27 static const char *const release_usage
[] =
29 "Usage: %s %s [-d] directories...\n",
30 "\t-d\tDelete the given directory.\n",
31 "(Specify the --help global option for a list of other help options)\n",
36 static int release_server (int argc
, char **argv
);
38 /* This is the server side of cvs release. */
40 release_server (int argc
, char **argv
)
44 /* Note that we skip argv[0]. */
45 for (i
= 1; i
< argc
; ++i
)
46 history_write ('F', argv
[i
], "", argv
[i
], "");
50 #endif /* SERVER_SUPPORT */
52 /* Construct an update command. Be sure to add authentication and
53 * encryption if we are using them currently, else our child process may
54 * not be able to communicate with the server.
57 setup_update_command (pid_t
*child_pid
)
61 run_setup (program_path
);
63 #if defined (CLIENT_SUPPORT) || defined (SERVER_SUPPORT)
64 /* Be sure to add authentication and encryption if we are using them
65 * currently, else our child process may not be able to communicate with
68 if (cvsauthenticate
) run_add_arg ("-a");
69 if (cvsencrypt
) run_add_arg ("-x");
72 /* Don't really change anything. */
75 /* Don't need full verbosity. */
78 /* Propogate our CVSROOT. */
80 run_add_arg (original_parsed_root
->original
);
82 run_add_arg ("update");
83 *child_pid
= run_piped (&tofd
, &fromfd
);
85 error (1, 0, "could not fork server process");
89 return fdopen (fromfd
, "r");
95 close_update_command (FILE *fp
, pid_t child_pid
)
101 w
= waitpid (child_pid
, &status
, 0);
102 while (w
== -1 && errno
== EINTR
);
104 error (1, errno
, "waiting for process %d", child_pid
);
111 /* There are various things to improve about this implementation:
113 1. Using run_popen to run "cvs update" could be replaced by a
114 fairly simple start_recursion/classify_file loop--a win for
115 portability, performance, and cleanliness. In particular, there is
116 no particularly good way to find the right "cvs".
118 2. The fact that "cvs update" contacts the server slows things down;
119 it undermines the case for using "cvs release" rather than "rm -rf".
120 However, for correctly printing "? foo" and correctly handling
121 CVSROOTADM_IGNORE, we currently need to contact the server. (One
122 idea for how to fix this is to stash a copy of CVSROOTADM_IGNORE in
123 the working directories; see comment at base_* in entries.c for a
124 few thoughts on that).
126 3. Would be nice to take processing things on the client side one step
127 further, and making it like edit/unedit in terms of working well if
128 disconnected from the network, and then sending a delayed
131 4. Having separate network turnarounds for the "Notify" request
132 which we do as part of unedit, and for the "release" itself, is slow
136 release (int argc
, char **argv
)
141 size_t line_allocated
= 0;
145 short delete_flag
= 0;
146 struct saved_cwd cwd
;
148 #ifdef SERVER_SUPPORT
150 return release_server (argc
, argv
);
153 /* Everything from here on is client or local. */
155 usage (release_usage
);
157 while ((c
= getopt (argc
, argv
, "+Qdq")) != -1)
164 "-q or -Q must be specified before \"%s\"",
172 usage (release_usage
);
179 /* We're going to run "cvs -n -q update" and check its output; if
180 * the output is sufficiently unalarming, then we release with no
181 * questions asked. Else we prompt, then maybe release.
182 * (Well, actually we ask no matter what. Our notion of "sufficiently
183 * unalarming" doesn't take into account "? foo.c" files, so it is
184 * up to the user to take note of them, at least currently
185 * (ignore-193 in testsuite)).
188 #ifdef CLIENT_SUPPORT
189 /* Start the server; we'll close it after looping. */
190 if (current_parsed_root
->isremote
)
195 #endif /* CLIENT_SUPPORT */
197 /* Remember the directory where "cvs release" was invoked because
198 all args are relative to this directory and we chdir around.
201 error (1, errno
, "Failed to save current directory.");
205 for (i
= arg_start_idx
; i
< argc
; i
++)
211 if (CVS_CHDIR (thisarg
) < 0)
214 error (0, errno
, "can't chdir to: %s", thisarg
);
220 error (0, 0, "no repository directory: %s", thisarg
);
221 if (restore_cwd (&cwd
))
223 "Failed to restore current directory, `%s'.",
231 error (0, 0, "no such directory: %s", thisarg
);
237 int line_length
, status
;
240 /* The "release" command piggybacks on "update", which
241 does the real work of finding out if anything is not
242 up-to-date with the repository. Then "release" prompts
243 the user, telling her how many files have been
244 modified, and asking if she still wants to do the
246 fp
= setup_update_command (&child_pid
);
249 error (0, 0, "cannot run command:");
251 error (1, 0, "Exiting due to fatal error referenced above.");
256 while ((line_length
= getline (&line
, &line_allocated
, fp
)) >= 0)
258 if (strchr ("MARCZ", *line
))
260 (void) fputs (line
, stdout
);
262 if (line_length
< 0 && !feof (fp
))
263 error (0, errno
, "cannot read from subprocess");
265 /* If the update exited with an error, then we just want to
266 complain and go on to the next arg. Especially, we do
267 not want to delete the local copy, since it's obviously
268 not what the user thinks it is. */
269 status
= close_update_command (fp
, child_pid
);
272 error (0, 0, "unable to release `%s' (%d)", thisarg
, status
);
273 if (restore_cwd (&cwd
))
275 "Failed to restore current directory, `%s'.",
280 printf ("You have [%d] altered files in this repository.\n",
285 printf ("Are you sure you want to release %sdirectory `%s': ",
286 delete_flag
? "(and delete) " : "", thisarg
);
289 if (!yesno ()) /* "No" */
291 (void) fprintf (stderr
,
292 "** `%s' aborted by user choice.\n",
294 if (restore_cwd (&cwd
))
296 "Failed to restore current directory, `%s'.",
303 if (restore_cwd (&cwd
))
305 "Failed to restore current directory, `%s'.",
311 /* Note: client.c doesn't like to have other code
312 changing the current directory on it. So a fair amount
313 of effort is needed to make sure it doesn't get confused
314 about the directory and (for example) overwrite
315 CVS/Entries file in the wrong directory. See release-17
316 through release-23. */
318 if (restore_cwd (&cwd
))
319 error (1, errno
, "Failed to restore current directory, `%s'.",
322 #ifdef CLIENT_SUPPORT
323 if (!current_parsed_root
->isremote
324 || (supported_request ("noop") && supported_request ("Notify")))
332 err
+= unedit (argc
, argv
);
333 if (restore_cwd (&cwd
))
334 error (1, errno
, "Failed to restore current directory, `%s'.",
338 #ifdef CLIENT_SUPPORT
339 if (current_parsed_root
->isremote
)
341 send_to_server ("Argument ", 0);
342 send_to_server (thisarg
, 0);
343 send_to_server ("\012", 1);
344 send_to_server ("release\012", 0);
347 #endif /* CLIENT_SUPPORT */
349 history_write ('F', thisarg
, "", thisarg
, ""); /* F == Free */
354 /* FIXME? Shouldn't this just delete the CVS-controlled
355 files and, perhaps, the files that would normally be
356 ignored and leave everything else? */
358 if (unlink_file_dir (thisarg
) < 0)
359 error (0, errno
, "deletion of directory %s failed", thisarg
);
362 #ifdef CLIENT_SUPPORT
363 if (current_parsed_root
->isremote
)
366 * Is there a good reason why get_server_responses() isn't
367 * responsible for restoring its initial directory itself when
370 err
+= get_server_responses ();
372 if (restore_cwd (&cwd
))
373 error (1, errno
, "Failed to restore current directory, `%s'.",
376 #endif /* CLIENT_SUPPORT */
379 if (restore_cwd (&cwd
))
380 error (1, errno
, "Failed to restore current directory, `%s'.",
384 #ifdef CLIENT_SUPPORT
385 if (current_parsed_root
->isremote
)
387 /* Unfortunately, client.c doesn't offer a way to close
388 the connection without waiting for responses. The extra
389 network turnaround here is quite unnecessary other than
391 send_to_server ("noop\012", 0);
392 err
+= get_responses_and_close ();
394 #endif /* CLIENT_SUPPORT */