home *** CD-ROM | disk | FTP | other *** search
- /*
- * Release: "cancel" a checkout in the history log.
- *
- * - Don't allow release if anything is active - Don't allow release if not
- * above or inside repository. - Don't allow release if ./CVS/Repository is
- * not the same as the directory specified in the module database.
- *
- * - Enter a line in the history log indicating the "release". - If asked to,
- * delete the local working directory.
- */
-
- #include "cvs.h"
-
- #ifndef lint
- static char rcsid[] = "@(#)release.c 1.21 92/02/29";
- #endif
-
- #if __STDC__
- static void release_delete (char *dir);
- #else
- static void release_delete ();
- #endif /* __STDC__ */
-
- static char *release_usage[] =
- {
- "Usage: %s %s [-d] modules...\n",
- "\t-Q\tReally quiet.\n",
- "\t-d\tDelete the given directory.\n",
- "\t-q\tSomewhat quiet.\n",
- NULL
- };
-
- static short delete;
-
- int
- release (argc, argv)
- int argc;
- char **argv;
- {
- FILE *fp;
- register int i, c;
- register char *cp;
- int margc;
- DBM *db;
- datum key, val;
- char *repository, *srepos;
- char **margv, *modargv[MAXFILEPERDIR], line[PATH_MAX];
-
- if (argc == -1)
- usage (release_usage);
- optind = 1;
- while ((c = gnu_getopt (argc, argv, "Qdq")) != -1)
- {
- switch (c)
- {
- case 'Q':
- really_quiet = 1;
- /* FALL THROUGH */
- case 'q':
- quiet = 1;
- break;
- case 'd':
- delete++;
- break;
- case '?':
- default:
- usage (release_usage);
- break;
- }
- }
- argc -= optind;
- argv += optind;
-
- if (!(db = open_module ()))
- return (1);
- for (i = 0; i < argc; i++)
- {
-
- /*
- * If we are in a repository, do it. Else if we are in the parent of
- * a directory with the same name as the module, "cd" into it and
- * look for a repository there.
- */
- if (isdir (argv[i]))
- {
- if (chdir (argv[i]) < 0)
- {
- if (!really_quiet)
- error (0, 0, "can't chdir to: %s", argv[i]);
- continue;
- }
- if (!isdir (CVSADM) && !isdir (OCVSADM))
- {
- if (!really_quiet)
- error (0, 0, "no repository module: %s", argv[i]);
- continue;
- }
- }
- else
- {
- if (!really_quiet)
- error (0, 0, "no such directory/module: %s", argv[i]);
- continue;
- }
-
- repository = Name_Repository ((char *) NULL, (char *) NULL);
- srepos = Short_Repository (repository);
-
- /* grab module entry from database and check against short repos */
- key.dptr = argv[i];
- key.dsize = strlen (key.dptr);
- val = dbm_fetch (db, key);
- if (!val.dptr)
- {
- error (0, 0, "no such module name: %s", argv[i]);
- continue;
- }
- val.dptr[val.dsize] = '\0';
- if ((cp = index (val.dptr, '#')) != NULL) /* Strip out a comment */
- {
- do
- {
- *cp-- = '\0';
- } while (isspace (*cp));
- }
- (void) sprintf (line, "%s %s", key.dptr, val.dptr);
- line2argv (&margc, modargv, line);
- margv = modargv;
-
- optind = 1;
- while (gnu_getopt (margc, margv, CVSMODULE_OPTS) != -1)
- /* do nothing */ ;
- margc -= optind;
- margv += optind;
-
- if (margc < 1)
- {
- error (0, 0, "modules file missing directory for key %s value %s",
- key.dptr, val.dptr);
- continue;
- }
- if (strcmp (*margv, srepos))
- {
- error (0, 0, "repository mismatch: module[%s], here[%s]",
- *margv, srepos);
- free (repository);
- continue;
- }
-
- if (!really_quiet)
- {
-
- /*
- * Now see if there is any reason not to allow a "Release" This
- * is "popen()" instead of "Popen()" since we don't want "-n" to
- * stop it.
- */
- fp = popen ("cvs -n -q update", "r");
- c = 0;
- while (fgets (line, sizeof (line), fp))
- {
- if (index ("MARCZ", *line))
- c++;
- (void) printf (line);
- }
- (void) pclose (fp);
- (void) printf ("You have [%d] altered files in this repository.\n",
- c);
- (void) printf ("Are you sure you want to release %smodule `%s': ",
- delete ? "(and delete) " : "", argv[i]);
- c = !yesno ();
- if (c) /* "No" */
- {
- (void) fprintf (stderr, "** `%s' aborted by user choice.\n",
- command_name);
- free (repository);
- continue;
- }
- }
-
- /*
- * So, we've passed all the tests, go ahead and release it. First,
- * log the release, then attempt to delete it.
- */
- history_write ('F', argv[i], "", argv[i], ""); /* F == Free */
- free (repository);
-
- if (delete)
- release_delete (argv[i]);
- }
- close_module (db);
- return (0);
- }
-
- /* We want to "rm -r" the repository, but let us be a little paranoid. */
- static void
- release_delete (dir)
- char *dir;
- {
- struct stat st;
- ino_t ino;
- int retcode = 0;
-
- (void) stat (".", &st);
- ino = st.st_ino;
- (void) chdir ("..");
- (void) stat (dir, &st);
- if (ino != st.st_ino)
- {
- error (0, 0,
- "Parent dir on a different disk, delete of %s aborted", dir);
- return;
- }
- run_setup ("%s -r", RM);
- run_arg (dir);
- if ((retcode = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL)) != 0)
- error (0, retcode == -1 ? errno : 0,
- "deletion of module %s failed.", dir);
- }
-