1 /* $OpenBSD: release.c,v 1.41 2009/03/21 11:18:45 joris Exp $ */ 2 /*- 3 * Copyright (c) 2005-2007 Xavier Santolaria <xsa@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <sys/stat.h> 19 20 #include <string.h> 21 #include <unistd.h> 22 23 #include "cvs.h" 24 #include "remote.h" 25 26 void cvs_release_local(struct cvs_file *); 27 28 static void release_check_files(struct cvs_file *); 29 30 static int dflag = 0; 31 static int files_altered = 0; 32 33 struct cvs_cmd cvs_cmd_release = { 34 CVS_OP_RELEASE, CVS_USE_WDIR, "release", 35 { "re", "rel" }, 36 "Indicate that a Module is no longer in use", 37 "[-d] dir...", 38 "d", 39 NULL, 40 cvs_release 41 }; 42 43 int 44 cvs_release(int argc, char **argv) 45 { 46 int ch; 47 int flags; 48 struct cvs_recursion cr; 49 50 flags = CR_REPO; 51 52 while ((ch = getopt(argc, argv, cvs_cmd_release.cmd_opts)) != -1) { 53 switch (ch) { 54 case 'd': 55 dflag = 1; 56 break; 57 default: 58 fatal("%s", cvs_cmd_release.cmd_synopsis); 59 } 60 } 61 62 argc -= optind; 63 argv += optind; 64 65 if (argc == 0) 66 fatal("%s", cvs_cmd_release.cmd_synopsis); 67 68 cr.enterdir = NULL; 69 cr.leavedir = NULL; 70 71 if (current_cvsroot->cr_method != CVS_METHOD_LOCAL) { 72 cvs_client_connect_to_server(); 73 cr.fileproc = cvs_client_sendfile; 74 75 if (dflag == 1) 76 cvs_client_send_request("Argument -d"); 77 } else 78 cr.fileproc = cvs_release_local; 79 80 cr.flags = flags; 81 82 cvs_file_run(argc, argv, &cr); 83 84 if (current_cvsroot->cr_method != CVS_METHOD_LOCAL) { 85 cvs_client_send_files(argv, argc); 86 cvs_client_senddir("."); 87 cvs_client_send_request("release"); 88 cvs_client_get_responses(); 89 } 90 91 return (0); 92 } 93 94 void 95 cvs_release_local(struct cvs_file *cf) 96 { 97 struct stat st; 98 struct cvs_recursion cr; 99 char *wdir, cwd[MAXPATHLEN]; 100 char *arg = "."; 101 int saved_noexec; 102 103 if (cf->file_type == CVS_FILE) 104 return; 105 106 cvs_log(LP_TRACE, "cvs_release_local(%s)", cf->file_path); 107 108 cvs_file_classify(cf, cvs_directory_tag); 109 110 if (cvs_server_active == 1) { 111 cvs_history_add(CVS_HISTORY_RELEASE, cf, NULL); 112 return; 113 } 114 115 if ((wdir = getcwd(cwd, sizeof(cwd))) == NULL) 116 fatal("getcwd failed"); 117 118 if (cf->file_type == CVS_DIR) { 119 if (!strcmp(cf->file_name, ".")) 120 return; 121 122 /* chdir before updating the directory. */ 123 cvs_chdir(cf->file_path, 0); 124 125 if (stat(CVS_PATH_CVSDIR, &st) == -1 || !S_ISDIR(st.st_mode)) { 126 if (verbosity > 0) 127 cvs_log(LP_ERR, "no repository directory: %s", 128 cf->file_path); 129 return; 130 } 131 } 132 133 /* Skip the interactive part if -Q is specified. */ 134 if (verbosity == 0) 135 goto delete; 136 137 saved_noexec = cvs_noexec; 138 cvs_noexec = 1; 139 140 cr.enterdir = NULL; 141 cr.leavedir = NULL; 142 cr.fileproc = cvs_update_local; 143 cr.flags = CR_REPO | CR_RECURSE_DIRS; 144 145 cvs_file_run(1, &arg, &cr); 146 147 cvs_noexec = saved_noexec; 148 149 cr.enterdir = NULL; 150 cr.leavedir = NULL; 151 cr.fileproc = release_check_files; 152 cr.flags = CR_RECURSE_DIRS; 153 154 cvs_file_run(1, &arg, &cr); 155 156 (void)printf("You have [%d] altered files in this repository.\n", 157 files_altered); 158 (void)printf("Are you sure you want to release %sdirectory `%s': ", 159 (dflag == 1) ? "(and delete) " : "", cf->file_path); 160 161 if (cvs_yesno() == -1) { 162 (void)fprintf(stderr, 163 "** `%s' aborted by user choice.\n", cmdp->cmd_name); 164 165 /* change back to original working dir */ 166 cvs_chdir(wdir, 0); 167 168 return; 169 } 170 171 /* change back to original working dir */ 172 cvs_chdir(wdir, 0); 173 174 delete: 175 if (dflag == 1) { 176 if (cvs_rmdir(cf->file_path) != 0) 177 fatal("cvs_release_local: cvs_rmdir failed"); 178 } 179 } 180 181 static void 182 release_check_files(struct cvs_file *cf) 183 { 184 cvs_log(LP_TRACE, "release_check_files(%s)", cf->file_path); 185 186 cvs_file_classify(cf, cvs_directory_tag); 187 188 if (cf->file_status == FILE_MERGE || 189 cf->file_status == FILE_ADDED || 190 cf->file_status == FILE_PATCH || 191 cf->file_status == FILE_CONFLICT) 192 files_altered++; 193 } 194