2 * Copyright (C) 1986-2005 The Free Software Foundation, Inc.
4 * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
7 * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk
8 * Portions Copyright (C) 1989-1992, Brian Berliner
10 * You may distribute under the terms of the GNU General Public License as
11 * specified in the README file that comes with the CVS source distribution.
15 * Removes entries from the present version. The entries will be removed from
16 * the RCS repository upon the next "commit".
18 * "remove" accepts no options, only file names that are to be removed. The
19 * file must not exist in the current directory for "remove" to work
26 static int remove_force_fileproc (void *callerdat
,
27 struct file_info
*finfo
);
29 static int remove_fileproc (void *callerdat
, struct file_info
*finfo
);
30 static Dtype
remove_dirproc (void *callerdat
, const char *dir
,
31 const char *repos
, const char *update_dir
,
36 static int removed_files
;
37 static int existing_files
;
39 static const char *const remove_usage
[] =
41 "Usage: %s %s [-flR] [files...]\n",
42 "\t-f\tDelete the file before removing it.\n",
43 "\t-l\tProcess this directory only (not recursive).\n",
44 "\t-R\tProcess directories recursively.\n",
45 "(Specify the --help global option for a list of other help options)\n",
50 cvsremove (int argc
, char **argv
)
58 while ((c
= getopt (argc
, argv
, "+flR")) != -1)
83 if (current_parsed_root
->isremote
) {
84 /* Call expand_wild so that the local removal of files will
85 work. It's ok to do it always because we have to send the
86 file names expanded anyway. */
87 expand_wild (argc
, argv
, &argc
, &argv
);
93 start_recursion (remove_force_fileproc
, NULL
, NULL
, NULL
,
94 NULL
, argc
, argv
, local
, W_LOCAL
,
95 0, CVS_LOCK_NONE
, NULL
, 0, NULL
);
97 /* else FIXME should probably act as if the file doesn't exist
98 in doing the following checks. */
106 /* FIXME: Can't we set SEND_NO_CONTENTS here? Needs investigation. */
107 send_files (argc
, argv
, local
, 0, 0);
108 send_file_names (argc
, argv
, 0);
109 free_names (&argc
, argv
);
110 send_to_server ("remove\012", 0);
111 return get_responses_and_close ();
115 /* start the recursion processor */
116 err
= start_recursion (remove_fileproc
, NULL
, remove_dirproc
, NULL
,
117 NULL
, argc
, argv
, local
, W_LOCAL
, 0,
118 CVS_LOCK_READ
, NULL
, 1, NULL
);
120 if (removed_files
&& !really_quiet
)
121 error (0, 0, "use `%s commit' to remove %s permanently", program_name
,
122 (removed_files
== 1) ? "this file" : "these files");
126 ((existing_files
== 1) ?
127 "%d file exists; remove it first" :
128 "%d files exist; remove them first"),
134 #ifdef CLIENT_SUPPORT
137 * This is called via start_recursion if we are running as the client
138 * and the -f option was used. We just physically remove the file.
143 remove_force_fileproc (void *callerdat
, struct file_info
*finfo
)
145 if (CVS_UNLINK (finfo
->file
) < 0 && ! existence_error (errno
))
146 error (0, errno
, "unable to remove %s", finfo
->fullname
);
153 * remove the file, only if it has already been physically removed
157 remove_fileproc (void *callerdat
, struct file_info
*finfo
)
165 if ( CVS_UNLINK (finfo
->file
) < 0 && ! existence_error (errno
))
167 error (0, errno
, "unable to remove %s", finfo
->fullname
);
170 /* else FIXME should probably act as if the file doesn't exist
171 in doing the following checks. */
174 vers
= Version_TS (finfo
, NULL
, NULL
, NULL
, 0, 0);
176 if (vers
->ts_user
!= NULL
)
180 error (0, 0, "file `%s' still in working directory",
183 else if (vers
->vn_user
== NULL
)
186 error (0, 0, "nothing known about `%s'", finfo
->fullname
);
188 else if (vers
->vn_user
[0] == '0' && vers
->vn_user
[1] == '\0')
193 * It's a file that has been added, but not commited yet. So,
194 * remove the ,t file for it and scratch it from the
196 Scratch_Entry (finfo
->entries
, finfo
->file
);
197 fname
= Xasprintf ("%s/%s%s", CVSADM
, finfo
->file
, CVSEXT_LOG
);
198 if (unlink_file (fname
) < 0
199 && !existence_error (errno
))
200 error (0, errno
, "cannot remove %s", CVSEXT_LOG
);
202 error (0, 0, "removed `%s'", finfo
->fullname
);
204 #ifdef SERVER_SUPPORT
206 server_checked_in (finfo
->file
, finfo
->update_dir
, finfo
->repository
);
210 else if (vers
->vn_user
[0] == '-')
213 error (0, 0, "file `%s' already scheduled for removal",
216 else if (vers
->tag
!= NULL
&& isdigit ((unsigned char) *vers
->tag
))
218 /* Commit will just give an error, and so there seems to be
219 little reason to allow the remove. I mean, conflicts that
220 arise out of parallel development are one thing, but conflicts
221 that arise from sticky tags are quite another.
223 I would have thought that non-branch sticky tags should be the
224 same but at least now, removing a file with a non-branch sticky
225 tag means to delete the tag from the file. I'm not sure that
226 is a good behavior, but until it is changed, we need to allow
229 cannot remove file `%s' which has a numeric sticky tag of `%s'",
230 finfo
->fullname
, vers
->tag
);
232 else if (vers
->date
!= NULL
)
234 /* Commit will just give an error, and so there seems to be
235 little reason to allow the remove. */
237 cannot remove file `%s' which has a sticky date of `%s'",
238 finfo
->fullname
, vers
->date
);
244 /* Re-register it with a negative version number. */
245 fname
= Xasprintf ("-%s", vers
->vn_user
);
246 Register (finfo
->entries
, finfo
->file
, fname
, vers
->ts_rcs
,
247 vers
->options
, vers
->tag
, vers
->date
, vers
->ts_conflict
);
249 error (0, 0, "scheduling `%s' for removal", finfo
->fullname
);
252 #ifdef SERVER_SUPPORT
254 server_checked_in (finfo
->file
, finfo
->update_dir
, finfo
->repository
);
266 * Print a warm fuzzy message
270 remove_dirproc (void *callerdat
, const char *dir
, const char *repos
,
271 const char *update_dir
, List
*entries
)
274 error (0, 0, "Removing %s", update_dir
);