#include "cvs.h"
#include "getline.h"
static void release_delete PROTO((char *dir));
static const char *const release_usage[] =
{
"Usage: %s %s [-d] directories...\n",
"\t-d\tDelete the given directory.\n",
"(Specify the --help global option for a list of other help options)\n",
NULL
};
#ifdef SERVER_SUPPORT
static int release_server PROTO ((int argc, char **argv));
static int
release_server (argc, argv)
int argc;
char **argv;
{
int i;
for (i = 1; i < argc; ++i)
history_write ('F', argv[i], "", argv[i], "");
return 0;
}
#endif
int
release (argc, argv)
int argc;
char **argv;
{
FILE *fp;
int i, c;
char *repository;
char *line = NULL;
size_t line_allocated = 0;
char *update_cmd;
char *thisarg;
int arg_start_idx;
int err = 0;
short delete_flag = 0;
#ifdef SERVER_SUPPORT
if (server_active)
return release_server (argc, argv);
#endif
if (argc == -1)
usage (release_usage);
optind = 0;
while ((c = getopt (argc, argv, "+Qdq")) != -1)
{
switch (c)
{
case 'Q':
case 'q':
error (1, 0,
"-q or -Q must be specified before \"%s\"",
command_name);
break;
case 'd':
delete_flag++;
break;
case '?':
default:
usage (release_usage);
break;
}
}
argc -= optind;
argv += optind;
update_cmd = xmalloc (strlen (program_path)
+ strlen (CVSroot_original)
+ 20);
sprintf (update_cmd, "%s -n -q -d %s update",
program_path, CVSroot_original);
#ifdef CLIENT_SUPPORT
if (client_active)
{
start_server ();
ign_setup ();
}
#endif
arg_start_idx = 0;
for (i = arg_start_idx; i < argc; i++)
{
thisarg = argv[i];
if (isdir (thisarg))
{
if (CVS_CHDIR (thisarg) < 0)
{
if (!really_quiet)
error (0, errno, "can't chdir to: %s", thisarg);
continue;
}
if (!isdir (CVSADM))
{
if (!really_quiet)
error (0, 0, "no repository directory: %s", thisarg);
continue;
}
}
else
{
if (!really_quiet)
error (0, 0, "no such directory: %s", thisarg);
continue;
}
repository = Name_Repository ((char *) NULL, (char *) NULL);
if (!really_quiet)
{
int line_length;
fp = run_popen (update_cmd, "r");
if (fp == NULL)
error (1, 0, "cannot run command %s", update_cmd);
c = 0;
while ((line_length = getline (&line, &line_allocated, fp)) >= 0)
{
if (strchr ("MARCZ", *line))
c++;
(void) printf (line);
}
if (line_length < 0 && !feof (fp))
error (0, errno, "cannot read from subprocess");
if ((pclose (fp)) != 0)
{
error (0, 0, "unable to release `%s'", thisarg);
continue;
}
printf ("You have [%d] altered files in this repository.\n",
c);
printf ("Are you sure you want to release %sdirectory `%s': ",
delete_flag ? "(and delete) " : "", thisarg);
c = !yesno ();
if (c)
{
(void) fprintf (stderr, "** `%s' aborted by user choice.\n",
command_name);
free (repository);
continue;
}
}
if (1
#ifdef CLIENT_SUPPORT
&& !(client_active
&& (!supported_request ("noop")
|| !supported_request ("Notify")))
#endif
)
{
int argc = 1;
char *argv[3];
argv[0] = "dummy";
argv[1] = NULL;
err += unedit (argc, argv);
}
#ifdef CLIENT_SUPPORT
if (client_active)
{
send_to_server ("Argument ", 0);
send_to_server (thisarg, 0);
send_to_server ("\012", 1);
send_to_server ("release\012", 0);
}
else
#endif
{
history_write ('F', thisarg, "", thisarg, "");
}
free (repository);
if (delete_flag) release_delete (thisarg);
#ifdef CLIENT_SUPPORT
if (client_active)
err += get_server_responses ();
#endif
}
#ifdef CLIENT_SUPPORT
if (client_active)
{
send_to_server ("noop\012", 0);
err += get_responses_and_close ();
}
#endif
free (update_cmd);
if (line != NULL)
free (line);
return err;
}
static void
release_delete (dir)
char *dir;
{
struct stat st;
ino_t ino;
(void) CVS_STAT (".", &st);
ino = st.st_ino;
(void) CVS_CHDIR ("..");
(void) CVS_STAT (dir, &st);
if (ino != st.st_ino)
{
#ifndef __CYGWIN32__
error (0, 0,
"Parent dir on a different disk, delete of %s aborted", dir);
return;
#endif
}
if (unlink_file_dir (dir) < 0)
error (0, errno, "deletion of directory %s failed", dir);
}