home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-09-24 | 154.8 KB | 6,081 lines |
- Newsgroups: comp.sources.unix
- From: pmiller@bmr.gov.au (Peter Miller)
- Subject: v27i044: aegis - project change supervisor (V2.1), Part09/19
- References: <1.748951883.12788@gw.home.vix.com>
- Sender: unix-sources-moderator@gw.home.vix.com
- Approved: vixie@gw.home.vix.com
-
- Submitted-By: pmiller@bmr.gov.au (Peter Miller)
- Posting-Number: Volume 27, Issue 44
- Archive-Name: aegis-2.1/part09
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 9 (of 19)."
- # Contents: aegis/aecpu.c aegis/aedb.c aegis/aenc.c aegis/aenf.c
- # aegis/aenfu.c aegis/aerf.c aegis/aerm.c aegis/aermu.c aegis/lock.c
- # aux/CHANGES.1.1 doc/c6.0.so
- # Wrapped by vixie@gw.home.vix.com on Sat Sep 25 03:00:41 1993
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'aegis/aecpu.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'aegis/aecpu.c'\"
- else
- echo shar: Extracting \"'aegis/aecpu.c'\" \(13200 characters\)
- sed "s/^X//" >'aegis/aecpu.c' <<'END_OF_FILE'
- X/*
- X * aegis - project change supervisor
- X * Copyright (C) 1991, 1992, 1993 Peter Miller.
- X * All rights reserved.
- X *
- X * This program is free software; you can redistribute it and/or modify
- X * it under the terms of the GNU General Public License as published by
- X * the Free Software Foundation; either version 2 of the License, or
- X * (at your option) any later version.
- X *
- X * This program is distributed in the hope that it will be useful,
- X * but WITHOUT ANY WARRANTY; without even the implied warranty of
- X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- X * GNU General Public License for more details.
- X *
- X * You should have received a copy of the GNU General Public License
- X * along with this program; if not, write to the Free Software
- X * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- X *
- X * MANIFEST: copy files into a change, and undo
- X */
- X
- X#include <stdio.h>
- X#include <stdlib.h>
- X#include <unistd.h>
- X
- X#include <aecpu.h>
- X#include <ael.h>
- X#include <arglex2.h>
- X#include <commit.h>
- X#include <change.h>
- X#include <error.h>
- X#include <file.h>
- X#include <help.h>
- X#include <lock.h>
- X#include <log.h>
- X#include <option.h>
- X#include <os.h>
- X#include <project.h>
- X#include <trace.h>
- X#include <undo.h>
- X#include <user.h>
- X#include <word.h>
- X
- X
- Xstatic void copy_file_undo_usage _((void));
- X
- Xstatic void
- Xcopy_file_undo_usage()
- X{
- X char *progname;
- X
- X progname = option_progname_get();
- X fprintf(stderr, "usage: %s -CoPy_file_Undo [ <option>... ] <filename>...\n", progname);
- X fprintf(stderr, " %s -CoPy_file_Undo -List [ <option>... ]\n", progname);
- X fprintf(stderr, " %s -CoPy_file_Undo -Help\n", progname);
- X quit(1);
- X}
- X
- X
- Xstatic void copy_file_undo_help _((void));
- X
- Xstatic void
- Xcopy_file_undo_help()
- X{
- X static char *text[] =
- X {
- X"NAME",
- X" %s -CoPy_file_Undo - reverse action of aecp",
- X"",
- X"SYNOPSIS",
- X" %s -CoPy_file_Undo [ <option>... ] <filename>...",
- X" %s -CoPy_file_Undo -List [ <option>... ]",
- X" %s -CoPy_file_Undo -Help",
- X"",
- X"DESCRIPTION",
- X" The %s -CoPy_file_Undo command is used to remove a",
- X" file previously copied into a change.",
- X"",
- X" The %s program will attempt to intuit the file names",
- X" intended. All file names are stored within %s as",
- X" relative to the root of the baseline directory tree. The",
- X" development directory and the integration directory are",
- X" shadows of the baseline directory, and so these relative",
- X" names aply there, too. Files named on the command line",
- X" are first converted to absolute paths if necessary. They",
- X" are then compared with the baseline path, and the",
- X" development directory path, and the integration directory",
- X" path, to determine a root-relative name. It is an error",
- X" if the file named is outside one of these directory",
- X" trees.",
- X"",
- X" The named files will be removed from the list of files in",
- X" the change. The file is deleted from the development",
- X" directory unless the -Keep option is specified. The -",
- X" Keep option should be used with great care, as you can",
- X" confuse tools such as make(1) by leaving these files in",
- X" place.",
- X"",
- X" This command will cancel any build or test registrations,",
- X" because deleting a file logically invalidates them. If the",
- X" config file was deleted, any diff registration will also be",
- X" cancelled.",
- X"",
- X"OPTIONS",
- X" The following options are understood:",
- X"",
- X" -Change <number>",
- X" This option may be used to specify a particular",
- X" change within a project. When no -Change option is",
- X" specified, the AEGIS_CHANGE environment variable is",
- X" consulted. If that does not exist, the user's",
- X" $HOME/.aegisrc file is examined for a default change",
- X" field (see aeuconf(5) for more information). If",
- X" that does not exist, when the user is only working",
- X" on one change within a project, that is the default",
- X" change number. Otherwise, it is an error.",
- X"",
- X" -Help",
- X" This option may be used to obtain more",
- X" information about how to use the %s program.",
- X"",
- X" -List",
- X" This option may be used to obtain a list of",
- X" suitable subjects for this command. The list may",
- X" be more general than expected.",
- X"",
- X" -Project <name>",
- X" This option may be used to select the project of",
- X" interest. When no -Project option is specified, the",
- X" AEGIS_PROJECT environment variable is consulted. If",
- X" that does not exist, the user's $HOME/.aegisrc file",
- X" is examined for a default project field (see",
- X" aeuconf(5) for more information). If that does not",
- X" exist, when the user is only working on changes",
- X" within a single project, the project name defaults",
- X" to that project. Otherwise, it is an error.",
- X"",
- X" -TERse",
- X" This option may be used to cause listings to",
- X" produce the bare minimum of information. It is",
- X" usually useful for shell scripts.",
- X"",
- X" -Verbose",
- X" This option may be used to cause %s to produce",
- X" more output. By default %s only produces",
- X" output on errors. When used with the -List",
- X" option this option causes column headings to be",
- X" added.",
- X"",
- X" All options may be abbreviated; the abbreviation is",
- X" documented as the upper case letters, all lower case",
- X" letters and underscores (_) are optional. You must use",
- X" consecutive sequences of optional letters.",
- X"",
- X" All options are case insensitive, you may type them in",
- X" upper case or lower case or a combination of both, case",
- X" is not important.",
- X"",
- X" For example: the arguments \"-project, \"-PROJ\" and \"-p\"",
- X" are all interpreted to mean the -Project option. The",
- X" argument \"-prj\" will not be understood, because",
- X" consecutive optional characters were not supplied.",
- X"",
- X" Options and other command line arguments may be mixed",
- X" arbitrarily on the command line, after the function",
- X" selectors.",
- X"",
- X" The GNU long option names are understood. Since all",
- X" option names for aegis are long, this means ignoring the",
- X" extra leading '-'. The \"--option=value\" convention is",
- X" also understood.",
- X"",
- X"RECOMMENDED ALIAS",
- X" The recommended alias for this command is",
- X" csh%% alias aecpu '%s -cpu \\!* -v'",
- X" sh$ aecpu(){%s -cpu $* -v}",
- X"",
- X"ERRORS",
- X" It is an error if the change is not in the",
- X" 'being_developed' state.",
- X" It is an error if the change is not assigned to the",
- X" current user.",
- X"",
- X"EXIT STATUS",
- X" The %s command will exit with a status of 1 on any",
- X" error. The %s command will only exit with a status of",
- X" 0 if there are no errors.",
- X"",
- X"COPYRIGHT",
- X" %C",
- X"",
- X"AUTHOR",
- X" %A",
- X };
- X
- X help(text, SIZEOF(text), copy_file_undo_usage);
- X}
- X
- X
- Xstatic void copy_file_undo_list _((void));
- X
- Xstatic void
- Xcopy_file_undo_list()
- X{
- X string_ty *project_name;
- X long change_number;
- X
- X trace(("copy_file_undo_list()\n{\n"/*}*/));
- X arglex();
- X project_name = 0;
- X change_number = 0;
- X while (arglex_token != arglex_token_eoln)
- X {
- X switch (arglex_token)
- X {
- X default:
- X generic_argument(copy_file_undo_usage);
- X continue;
- X
- X case arglex_token_change:
- X if (arglex() != arglex_token_number)
- X copy_file_undo_usage();
- X /* fall through... */
- X
- X case arglex_token_number:
- X if (change_number)
- X fatal("duplicate -Change option");
- X change_number = arglex_value.alv_number;
- X if (change_number < 1)
- X fatal("change %ld out of range", change_number);
- X break;
- X
- X case arglex_token_project:
- X if (arglex() != arglex_token_string)
- X copy_file_undo_usage();
- X if (project_name)
- X fatal("duplicate -Project option");
- X project_name = str_from_c(arglex_value.alv_string);
- X break;
- X }
- X arglex();
- X }
- X list_change_files(project_name, change_number);
- X if (project_name)
- X str_free(project_name);
- X trace((/*{*/"}\n"));
- X}
- X
- X
- Xstatic void copy_file_undo_main _((void));
- X
- Xstatic void
- Xcopy_file_undo_main()
- X{
- X wlist wl;
- X cstate cstate_data;
- X pstate pstate_data;
- X int j;
- X string_ty *s1;
- X string_ty *s2;
- X int keep;
- X pconf pconf_data;
- X string_ty *project_name;
- X project_ty *pp;
- X long change_number;
- X change_ty *cp;
- X int nolog;
- X user_ty *up;
- X int config_seen;
- X string_ty *config_name;
- X
- X trace(("copy_file_undo_main()\n{\n"/*}*/));
- X wl_zero(&wl);
- X project_name = 0;
- X change_number = 0;
- X keep = 0;
- X nolog = 0;
- X while (arglex_token != arglex_token_eoln)
- X {
- X switch (arglex_token)
- X {
- X default:
- X generic_argument(copy_file_undo_usage);
- X continue;
- X
- X case arglex_token_string:
- X s1 = str_from_c(arglex_value.alv_string);
- X os_become_orig();
- X s2 = os_pathname(s1, 1);
- X os_become_undo();
- X str_free(s1);
- X if (wl_member(&wl, s2))
- X fatal("file \"%s\" named more than once", arglex_value.alv_string);
- X wl_append(&wl, s2);
- X str_free(s2);
- X break;
- X
- X case arglex_token_keep:
- X if (keep)
- X {
- X duplicate:
- X fatal("duplicate %s option", arglex_value.alv_string);
- X }
- X keep = 1;
- X break;
- X
- X case arglex_token_change:
- X if (arglex() != arglex_token_number)
- X copy_file_undo_usage();
- X /* fall through... */
- X
- X case arglex_token_number:
- X if (change_number)
- X fatal("duplicate -Change option");
- X change_number = arglex_value.alv_number;
- X if (change_number < 1)
- X fatal("change %ld out of range", change_number);
- X break;
- X
- X case arglex_token_project:
- X if (arglex() != arglex_token_string)
- X copy_file_undo_usage();
- X if (project_name)
- X fatal("duplicate -Project option");
- X project_name = str_from_c(arglex_value.alv_string);
- X break;
- X
- X case arglex_token_nolog:
- X if (nolog)
- X goto duplicate;
- X nolog = 1;
- X break;
- X }
- X arglex();
- X }
- X if (!wl.wl_nwords)
- X fatal("no files named");
- X
- X /*
- X * locate project data
- X */
- X if (!project_name)
- X project_name = user_default_project();
- X pp = project_alloc(project_name);
- X str_free(project_name);
- X project_bind_existing(pp);
- X
- X /*
- X * locate user data
- X */
- X up = user_executing(pp);
- X
- X /*
- X * locate change data
- X */
- X if (!change_number)
- X change_number = user_default_change(up);
- X cp = change_alloc(pp, change_number);
- X change_bind_existing(cp);
- X
- X /*
- X * lock the change file
- X */
- X change_cstate_lock_prepare(cp);
- X lock_take();
- X cstate_data = change_cstate_get(cp);
- X pstate_data = project_pstate_get(pp);
- X pconf_data = change_pconf_get(cp);
- X
- X /*
- X * It is an error if the change is not in the in_development state.
- X * It is an error if the change is not assigned to the current user.
- X */
- X if (cstate_data->state != cstate_state_being_developed)
- X change_fatal(cp, "not in 'being_developed' state");
- X if (!str_equal(change_developer_name(cp), user_name(up)))
- X {
- X change_fatal
- X (
- X cp,
- X "user \"%S\" is not the developer",
- X user_name(up)
- X );
- X }
- X
- X /*
- X * resolve the path of each file
- X * 1. the absolute path of the file name is obtained
- X * 2. if the file is inside the development directory, ok
- X * 3. if the file is inside the baseline, ok
- X * 4. if neither, error
- X */
- X config_seen = 0;
- X config_name = str_from_c(THE_CONFIG_FILE);
- X for (j = 0; j < wl.wl_nwords; ++j)
- X {
- X s1 = wl.wl_word[j];
- X assert(s1->str_text[0] == '/');
- X s2 = os_below_dir(change_development_directory_get(cp, 1), s1);
- X if (!s2)
- X s2 = os_below_dir(project_baseline_path_get(pp, 1), s1);
- X if (!s2)
- X change_fatal(cp, "path \"%S\" unrelated", s1);
- X str_free(s1);
- X wl.wl_word[j] = s2;
- X if (str_equal(s2, config_name))
- X config_seen++;
- X }
- X str_free(config_name);
- X
- X /*
- X * ensure that each file
- X * 1. is already part of the change
- X * 2. is being modified by this change
- X */
- X for (j = 0; j < wl.wl_nwords; ++j)
- X {
- X cstate_src src_data;
- X
- X s1 = wl.wl_word[j];
- X src_data = change_src_find(cp, s1);
- X if (!src_data)
- X change_fatal(cp, "file \"%S\" not in change", s1);
- X if (src_data->action != file_action_modify)
- X change_fatal(cp, "file \"%S\" is not -CoPy_file", s1);
- X if (config_seen)
- X src_data->diff_time = 0;
- X }
- X
- X /*
- X * Remove each file from the development directory,
- X * if it still exists.
- X * Remove the difference file, too.
- X */
- X if (!keep)
- X {
- X string_ty *dd;
- X
- X dd = change_development_directory_get(cp, 1);
- X user_become(up);
- X for (j = 0; j < wl.wl_nwords; ++j)
- X {
- X s1 = wl.wl_word[j];
- X s2 = str_format("%S/%S", dd, s1);
- X if (os_exists(s2))
- X commit_unlink_errok(s2);
- X str_free(s2);
- X
- X s2 = str_format("%S/%S,D", dd, s1);
- X if (os_exists(s2))
- X commit_unlink_errok(s2);
- X str_free(s2);
- X }
- X user_become_undo();
- X }
- X
- X /*
- X * Remove each file to the change file,
- X * and write it back out.
- X */
- X for (j = 0; j < wl.wl_nwords; ++j)
- X change_src_remove(cp, wl.wl_word[j]);
- X
- X /*
- X * the number of files changed, or the version did,
- X * so stomp on the validation fields.
- X */
- X cstate_data->build_time = 0;
- X cstate_data->test_time = 0;
- X cstate_data->test_baseline_time = 0;
- X cstate_data->regression_test_time = 0;
- X
- X /*
- X * release the locks
- X */
- X change_cstate_write(cp);
- X commit();
- X lock_release();
- X
- X /*
- X * verbose success message
- X */
- X for (j = 0; j < wl.wl_nwords; ++j)
- X change_verbose(cp, "file \"%S\" copy file undo", wl.wl_word[j]);
- X
- X /*
- X * run the change file command
- X */
- X if (!nolog)
- X log_open(change_logfile_get(cp), up);
- X change_run_change_file_command(cp, &wl, up);
- X wl_free(&wl);
- X project_free(pp);
- X change_free(cp);
- X user_free(up);
- X trace((/*{*/"}\n"));
- X}
- X
- X
- Xvoid
- Xcopy_file_undo()
- X{
- X trace(("copy_file_undo()\n{\n"/*}*/));
- X switch (arglex())
- X {
- X default:
- X copy_file_undo_main();
- X break;
- X
- X case arglex_token_help:
- X copy_file_undo_help();
- X break;
- X
- X case arglex_token_list:
- X copy_file_undo_list();
- X break;
- X }
- X trace((/*{*/"}\n"));
- X}
- END_OF_FILE
- if test 13200 -ne `wc -c <'aegis/aecpu.c'`; then
- echo shar: \"'aegis/aecpu.c'\" unpacked with wrong size!
- fi
- # end of 'aegis/aecpu.c'
- fi
- if test -f 'aegis/aedb.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'aegis/aedb.c'\"
- else
- echo shar: Extracting \"'aegis/aedb.c'\" \(12308 characters\)
- sed "s/^X//" >'aegis/aedb.c' <<'END_OF_FILE'
- X/*
- X * aegis - project change supervisor
- X * Copyright (C) 1991, 1992, 1993 Peter Miller.
- X * All rights reserved.
- X *
- X * This program is free software; you can redistribute it and/or modify
- X * it under the terms of the GNU General Public License as published by
- X * the Free Software Foundation; either version 2 of the License, or
- X * (at your option) any later version.
- X *
- X * This program is distributed in the hope that it will be useful,
- X * but WITHOUT ANY WARRANTY; without even the implied warranty of
- X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- X * GNU General Public License for more details.
- X *
- X * You should have received a copy of the GNU General Public License
- X * along with this program; if not, write to the Free Software
- X * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- X *
- X * MANIFEST: functions to implement develop begin
- X */
- X
- X#include <stdio.h>
- X#include <stdlib.h>
- X#include <string.h>
- X#include <time.h>
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X
- X#include <aedb.h>
- X#include <ael.h>
- X#include <arglex2.h>
- X#include <change.h>
- X#include <col.h>
- X#include <commit.h>
- X#include <common.h>
- X#include <dir.h>
- X#include <error.h>
- X#include <help.h>
- X#include <lock.h>
- X#include <option.h>
- X#include <os.h>
- X#include <project.h>
- X#include <sub.h>
- X#include <trace.h>
- X#include <undo.h>
- X#include <user.h>
- X
- X
- Xstatic void develop_begin_usage _((void));
- X
- Xstatic void
- Xdevelop_begin_usage()
- X{
- X char *progname;
- X
- X progname = option_progname_get();
- X fprintf(stderr, "usage: %s -Develop_Begin <change_number> [ <option>... ]\n", progname);
- X fprintf(stderr, " %s -Develop_Begin -List [ <option>... ]\n", progname);
- X fprintf(stderr, " %s -Develop_Begin -Help\n", progname);
- X quit(1);
- X}
- X
- X
- Xstatic void develop_begin_help _((void));
- X
- Xstatic void
- Xdevelop_begin_help()
- X{
- X static char *text[] =
- X {
- X"NAME",
- X" %s -Develop_Begin - begin development of a change",
- X"",
- X"SYNOPSIS",
- X" %s -Develop_Begin <change-number> [ <option>... ]",
- X" %s -Develop_Begin -List [ <option>... ]",
- X" %s -Develop_Begin -Help",
- X"",
- X"DESCRIPTION",
- X" The %s -Develop_Begin command is used to commence",
- X" development of a change.",
- X"",
- X" The development directory for the change will be created",
- X" automatically; below the directory specified in the",
- X" default_development_directory field of aeuconf(5), or if",
- X" not set below the directory specified in the default_-",
- X" development_directory field of aepattr(5), or if not set",
- X" below the current user's home directory. It is rare to",
- X" need to know the exact pathname of the development",
- X" directory, as the aecd(1) command can take you there at",
- X" any time.",
- X"",
- X" Successful execution of this command will move the",
- X" specified change from the awaiting development state to",
- X" the being developed state.",
- X"",
- X"OPTIONS",
- X" The following options are understood:",
- X"",
- X" -Change <number>",
- X" This option may be used to specify a particular",
- X" change within a project. When no -Change option",
- X" is specified, the AEGIS_CHANGE environment",
- X" variable is consulted. If that does not exist,",
- X" the user's $HOME/.%src file is examined for a",
- X" default change field (see aeuconf(5) for more",
- X" information). If that does not exist, when the",
- X" user is only working on one change within a",
- X" project, that is the default change number.",
- X" Otherwise, it is an error.",
- X"",
- X" -DIRectory <path>",
- X" This option may be used to specify which directory",
- X" is to be used. It is an error if the current user",
- X" does not have appropriate permissions to create",
- X" the directory path given. This must be an",
- X" absolute path.",
- X"",
- X" Caution: If you are using an automounter do not",
- X" use `pwd` to make an absolute path, it usually",
- X" gives the wrong answer.",
- X"",
- X" -Help",
- X" This option may be used to obtain more information",
- X" about how to use the %s program.",
- X"",
- X" -List",
- X" This option may be used to obtain a list of",
- X" suitable subjects for this command. The list may",
- X" be more general than expected.",
- X"",
- X" -Project <name>",
- X" This option may be used to select the project of",
- X" interest. When no -Project option is specified,",
- X" the AEGIS_PROJECT environment variable is",
- X" consulted. If that does not exist, the user's",
- X" $HOME/.%src file is examined for a default",
- X" project field (see aeuconf(5) for more",
- X" information). If that does not exist, when the",
- X" user is only working on changes within a single",
- X" project, the project name defaults to that",
- X" project. Otherwise, it is an error.",
- X"",
- X" -TERse",
- X" This option may be used to cause listings to",
- X" produce the bare minimum of information. It is",
- X" usually useful for shell scripts.",
- X"",
- X" -Verbose",
- X" This option may be used to cause %s to produce",
- X" more output. By default %s only produces",
- X" output on errors. When used with the -List option",
- X" this option causes column headings to be added.",
- X"",
- X" All options may be abbreviated; the abbreviation is",
- X" documented as the upper case letters, all lower case",
- X" letters and underscores (_) are optional. You must use",
- X" consecutive sequences of optional letters.",
- X"",
- X" All options are case insensitive, you may type them in",
- X" upper case or lower case or a combination of both, case",
- X" is not important.",
- X"",
- X" For example: the arguments \"-project, \"-PROJ\" and \"-p\"",
- X" are all interpreted to mean the -Project option. The",
- X" argument \"-prj\" will not be understood, because",
- X" consecutive optional characters were not supplied.",
- X"",
- X" Options and other command line arguments may be mixed",
- X" arbitrarily on the command line, after the function",
- X" selectors.",
- X"",
- X" The GNU long option names are understood. Since all",
- X" option names for aegis are long, this means ignoring the",
- X" extra leading '-'. The \"--option=value\" convention is",
- X" also understood.",
- X"",
- X"RECOMMENDED ALIAS",
- X" The recommended alias for this command is",
- X" csh%% alias aedb '%s -db \\!* -v'",
- X" sh$ aedb(){%s -db $* -v}",
- X"",
- X"ERRORS",
- X" It is an error if the change does not exist.",
- X" It is an error if the change is not in the awaiting",
- X" development state.",
- X" It is an error if the current user is not a developer of",
- X" the specified project.",
- X"",
- X"EXIT STATUS",
- X" The %s command will exit with a status of 1 on any",
- X" error. The %s command will only exit with a status of",
- X" 0 if there are no errors.",
- X"",
- X"COPYRIGHT",
- X" %C",
- X"",
- X"AUTHOR",
- X" %A",
- X };
- X
- X help(text, SIZEOF(text), develop_begin_usage);
- X}
- X
- X
- Xstatic void develop_begin_list _((void));
- X
- Xstatic void
- Xdevelop_begin_list()
- X{
- X string_ty *project_name;
- X
- X trace(("develop_begin_list()\n{\n"/*}*/));
- X project_name = 0;
- X arglex();
- X while (arglex_token != arglex_token_eoln)
- X {
- X switch (arglex_token)
- X {
- X default:
- X generic_argument(develop_begin_usage);
- X continue;
- X
- X case arglex_token_project:
- X if (arglex() != arglex_token_string)
- X develop_begin_usage();
- X /* fall through... */
- X
- X case arglex_token_string:
- X if (project_name)
- X fatal("duplicate -Project option");
- X project_name = str_from_c(arglex_value.alv_string);
- X break;
- X }
- X arglex();
- X }
- X list_changes_in_state_mask
- X (
- X project_name,
- X 1 << cstate_state_awaiting_development
- X );
- X if (project_name)
- X str_free(project_name);
- X trace((/*{*/"}\n"));
- X}
- X
- X
- Xstatic void develop_begin_main _((void));
- X
- Xstatic void
- Xdevelop_begin_main()
- X{
- X cstate cstate_data;
- X pstate pstate_data;
- X cstate_history history_data;
- X string_ty *devdir;
- X string_ty *s2;
- X string_ty *project_name;
- X project_ty *pp;
- X long change_number;
- X change_ty *cp;
- X user_ty *up;
- X
- X trace(("develop_begin_main()\n{\n"/*}*/));
- X project_name = 0;
- X change_number = 0;
- X devdir = 0;
- X while (arglex_token != arglex_token_eoln)
- X {
- X switch (arglex_token)
- X {
- X default:
- X generic_argument(develop_begin_usage);
- X continue;
- X
- X case arglex_token_change:
- X if (arglex() != arglex_token_number)
- X develop_begin_usage();
- X /* fall through... */
- X
- X case arglex_token_number:
- X if (change_number)
- X fatal("duplicate -Change option");
- X change_number = arglex_value.alv_number;
- X if (change_number < 1)
- X fatal("change %ld out of range", change_number);
- X break;
- X
- X case arglex_token_directory:
- X if (arglex() != arglex_token_string)
- X develop_begin_usage();
- X if (devdir)
- X fatal("duplicate -DIRectory option");
- X /*
- X * To cope with automounters, directories are stored as
- X * given, or are derived from the home directory in the
- X * passwd file. Within aegis, pathnames have their
- X * symbolic links resolved, and any comparison of paths
- X * is done on this "system idea" of the pathname.
- X */
- X devdir = str_from_c(arglex_value.alv_string);
- X break;
- X
- X case arglex_token_project:
- X if (arglex() != arglex_token_string)
- X develop_begin_usage();
- X /* fall through... */
- X
- X case arglex_token_string:
- X if (project_name)
- X fatal("duplicate -Project option");
- X project_name = str_from_c(arglex_value.alv_string);
- X break;
- X }
- X arglex();
- X }
- X
- X /*
- X * locate project data
- X */
- X if (!project_name)
- X project_name = user_default_project();
- X pp = project_alloc(project_name);
- X str_free(project_name);
- X project_bind_existing(pp);
- X
- X /*
- X * locate user data
- X */
- X up = user_executing(pp);
- X
- X /*
- X * locate change data
- X *
- X * The change number must be given on the command line,
- X * even if there is only one appropriate change.
- X * The is the "least surprizes" principle at work,
- X * even though we could sometimes work this out for ourself.
- X */
- X if (!change_number)
- X fatal("change number must be stated explicitly");
- X cp = change_alloc(pp, change_number);
- X change_bind_existing(cp);
- X
- X /*
- X * Take an advisory write lock on the appropriate row of the change
- X * table. Take an advisory write lock on the appropriate row of the
- X * user table. The user table row may need to be created.
- X * Block while can't get both simultaneously.
- X */
- X user_ustate_lock_prepare(up);
- X change_cstate_lock_prepare(cp);
- X lock_take();
- X cstate_data = change_cstate_get(cp);
- X pstate_data = project_pstate_get(pp);
- X
- X /*
- X * Extract the appropriate row of the change table.
- X * It is an error if the change is not in the
- X * undevelop_begined state.
- X */
- X if (cstate_data->state != cstate_state_awaiting_development)
- X change_fatal(cp, "not in 'awaiting_development' state");
- X if (!project_developer_query(pp, user_name(up)))
- X {
- X project_fatal
- X (
- X pp,
- X "user \"%S\" is not a developer",
- X user_name(up)
- X );
- X }
- X
- X /*
- X * Set the change data to reflect the current user
- X * as developer and move it to the in-development state.
- X * Append another entry to the change history.
- X */
- X cstate_data->state = cstate_state_being_developed;
- X history_data = change_history_new(cp, up);
- X history_data->what = cstate_history_what_develop_begin;
- X
- X /*
- X * Update user change table to include this change in the list of
- X * changes being developed by this user.
- X */
- X user_own_add(up, project_name_get(pp), change_number);
- X
- X /*
- X * Create the change directory.
- X */
- X if (!devdir)
- X {
- X s2 = user_default_development_directory(up);
- X assert(s2);
- X devdir =
- X str_format
- X (
- X "%S/%S.%3.3ld",
- X s2,
- X project_name_get(pp),
- X change_number
- X );
- X str_free(s2);
- X }
- X change_development_directory_set(cp, devdir);
- X
- X /*
- X * Create the development directory.
- X */
- X user_become(up);
- X os_mkdir(devdir, 02755);
- X undo_rmdir_errok(devdir);
- X user_become_undo();
- X change_verbose(cp, "development directory \"%S\"", devdir);
- X
- X /*
- X * Clear the time fields.
- X */
- X cstate_data->build_time = 0;
- X cstate_data->test_time = 0;
- X cstate_data->test_baseline_time = 0;
- X cstate_data->regression_test_time = 0;
- X
- X /*
- X * Update change table row (and change history table).
- X * Update user table row.
- X * Release advisory write locks.
- X */
- X change_cstate_write(cp);
- X user_ustate_write(up);
- X commit();
- X lock_release();
- X
- X /*
- X * run the develop begin command
- X */
- X change_run_develop_begin_command(cp, up);
- X
- X /*
- X * verbose success message
- X */
- X change_verbose
- X (
- X cp,
- X "user \"%S\" has begun development",
- X user_name(up)
- X );
- X change_free(cp);
- X project_free(pp);
- X user_free(up);
- X trace((/*{*/"}\n"));
- X}
- X
- X
- Xvoid
- Xdevelop_begin()
- X{
- X trace(("develop_begin()\n{\n"/*}*/));
- X switch (arglex())
- X {
- X default:
- X develop_begin_main();
- X break;
- X
- X case arglex_token_help:
- X develop_begin_help();
- X break;
- X
- X case arglex_token_list:
- X develop_begin_list();
- X break;
- X }
- X trace((/*{*/"}\n"));
- X}
- END_OF_FILE
- if test 12308 -ne `wc -c <'aegis/aedb.c'`; then
- echo shar: \"'aegis/aedb.c'\" unpacked with wrong size!
- fi
- # end of 'aegis/aedb.c'
- fi
- if test -f 'aegis/aenc.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'aegis/aenc.c'\"
- else
- echo shar: Extracting \"'aegis/aenc.c'\" \(13153 characters\)
- sed "s/^X//" >'aegis/aenc.c' <<'END_OF_FILE'
- X/*
- X * aegis - project change supervisor
- X * Copyright (C) 1991, 1992, 1993 Peter Miller.
- X * All rights reserved.
- X *
- X * This program is free software; you can redistribute it and/or modify
- X * it under the terms of the GNU General Public License as published by
- X * the Free Software Foundation; either version 2 of the License, or
- X * (at your option) any later version.
- X *
- X * This program is distributed in the hope that it will be useful,
- X * but WITHOUT ANY WARRANTY; without even the implied warranty of
- X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- X * GNU General Public License for more details.
- X *
- X * You should have received a copy of the GNU General Public License
- X * along with this program; if not, write to the Free Software
- X * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- X *
- X * MANIFEST: functions to implement new change
- X */
- X
- X#include <stdio.h>
- X#include <stdlib.h>
- X#include <time.h>
- X
- X#include <aeca.h>
- X#include <aenc.h>
- X#include <ael.h>
- X#include <arglex2.h>
- X#include <cattr.h>
- X#include <change.h>
- X#include <col.h>
- X#include <commit.h>
- X#include <common.h>
- X#include <error.h>
- X#include <help.h>
- X#include <lock.h>
- X#include <option.h>
- X#include <os.h>
- X#include <project.h>
- X#include <trace.h>
- X#include <user.h>
- X
- X
- Xstatic void new_change_usage _((void));
- X
- Xstatic void
- Xnew_change_usage()
- X{
- X char *progname;
- X
- X progname = option_progname_get();
- X fprintf(stderr, "usage: %s -New_Change <attr-file> [ <option>... ]\n", progname);
- X fprintf(stderr, " %s -New_Change -Edit [ <option>... ]\n", progname);
- X fprintf(stderr, " %s -New_Change -List [ <option>... ]\n", progname);
- X fprintf(stderr, " %s -New_Change -Help\n", progname);
- X quit(1);
- X}
- X
- X
- Xstatic void new_change_help _((void));
- X
- Xstatic void
- Xnew_change_help()
- X{
- X static char *text[] =
- X {
- X"NAME",
- X" %s -New_Change - add a new change to a project",
- X"",
- X"SYNOPSIS",
- X" %s -New_Change <attr-file> [ <option>... ]",
- X" %s -New_Change -Edit [ <option>... ]",
- X" %s -New_Change -List [ <option>... ]",
- X" %s -New_Change -Help",
- X"",
- X"DESCRIPTION",
- X" The %s -New_Change command is used to add a new change",
- X" to a project. See aecattr(5) for information on the",
- X" format of the attr-file.",
- X"",
- X" The change is created in the 'awaiting_development'",
- X" state. The change is not assigned to any user. The",
- X" change has no development directory.",
- X"",
- X" It is not possible to choose your own change number.",
- X"",
- X"OPTIONS",
- X" The following options are understood:",
- X"",
- X" -Edit",
- X" Edit the attributes with a text editor, this is",
- X" usually more convenient than supplying a text",
- X" file. The EDITOR environment variable will be",
- X" consulted for the name of the editor to use;",
- X" defaults to vi(1) if not set. Warning: not well",
- X" behaved when faced with errors, the temporary",
- X" file is always deleted.",
- X"",
- X" -Help",
- X" This option may be used to obtain more",
- X" information about how to use the %s program.",
- X"",
- X" -List",
- X" This option may be used to obtain a list of",
- X" suitable subjects for this command. The list may",
- X" be more general than expected.",
- X"",
- X" -Project <name>",
- X" This option may be used to select the project of",
- X" interest. When no -Project option is specified, the",
- X" AEGIS_PROJECT environment variable is consulted. If",
- X" that does not exist, the user's $HOME/.aegisrc file",
- X" is examined for a default project field (see",
- X" aeuconf(5) for more information). If that does not",
- X" exist, when the user is only working on changes",
- X" within a single project, the project name defaults",
- X" to that project. Otherwise, it is an error.",
- X"",
- X" -TERse",
- X" This option may be used to cause listings to",
- X" produce the bare minimum of information. It is",
- X" usually useful for shell scripts.",
- X"",
- X" -Verbose",
- X" This option may be used to cause %s to produce",
- X" more output. By default %s only produces",
- X" output on errors. When used with the -List",
- X" option this option causes column headings to be",
- X" added.",
- X"",
- X" All options may be abbreviated; the abbreviation is",
- X" documented as the upper case letters, all lower case",
- X" letters and underscores (_) are optional. You must use",
- X" consecutive sequences of optional letters.",
- X"",
- X" All options are case insensitive, you may type them in",
- X" upper case or lower case or a combination of both, case",
- X" is not important.",
- X"",
- X" For example: the arguments \"-project, \"-PROJ\" and \"-p\"",
- X" are all interpreted to mean the -Project option. The",
- X" argument \"-prj\" will not be understood, because",
- X" consecutive optional characters were not supplied.",
- X"",
- X" Options and other command line arguments may be mixed",
- X" arbitrarily on the command line, after the function",
- X" selectors.",
- X"",
- X" The GNU long option names are understood. Since all",
- X" option names for aegis are long, this means ignoring the",
- X" extra leading '-'. The \"--option=value\" convention is",
- X" also understood.",
- X"",
- X"RECOMMENDED ALIAS",
- X" The recommended alias for this command is",
- X" csh%% alias aenc '%s -nc \\!* -v'",
- X" sh$ aenc(){%s -nc $* -v}",
- X"",
- X"ERRORS",
- X" It is an error if the current user is not an",
- X" administrator of the project. (In some cases it is",
- X" possible for developers of a project to create changes,",
- X" see aepattr(5) for more information.)",
- X"",
- X"EXIT STATUS",
- X" The %s command will exit with a status of 1 on any",
- X" error. The %s command will only exit with a status of",
- X" 0 if there are no errors.",
- X"",
- X"COPYRIGHT",
- X" %C",
- X"",
- X"AUTHOR",
- X" %A",
- X };
- X
- X help(text, SIZEOF(text), new_change_usage);
- X}
- X
- X
- Xstatic void new_change_list _((void));
- X
- Xstatic void
- Xnew_change_list()
- X{
- X string_ty *project_name;
- X
- X trace(("new_chane_list()\n{\n"/*}*/));
- X project_name = 0;
- X arglex();
- X while (arglex_token != arglex_token_eoln)
- X {
- X switch (arglex_token)
- X {
- X default:
- X generic_argument(new_change_usage);
- X continue;
- X
- X case arglex_token_project:
- X if (arglex() != arglex_token_string)
- X new_change_usage();
- X if (project_name)
- X fatal("duplicate -Project option");
- X project_name = str_from_c(arglex_value.alv_string);
- X break;
- X }
- X arglex();
- X }
- X list_changes(project_name, 0);
- X if (project_name)
- X str_free(project_name);
- X trace((/*{*/"}\n"));
- X}
- X
- X
- Xstatic void cattr_defaults _((cattr, pstate));
- X
- Xstatic void
- Xcattr_defaults(a, ps)
- X cattr a;
- X pstate ps;
- X{
- X if
- X (
- X a->cause == change_cause_internal_improvement
- X ||
- X a->cause == change_cause_internal_improvement
- X )
- X {
- X if (!(a->mask & cattr_test_exempt_mask))
- X {
- X a->test_exempt = 1;
- X a->mask |= cattr_test_exempt_mask;
- X }
- X if (!(a->mask & cattr_test_baseline_exempt_mask))
- X {
- X a->test_baseline_exempt = 1;
- X a->mask |= cattr_test_baseline_exempt_mask;
- X }
- X if (!(a->mask & cattr_regression_test_exempt_mask))
- X {
- X a->regression_test_exempt = 0;
- X a->mask |= cattr_regression_test_exempt_mask;
- X }
- X }
- X else
- X {
- X if (!(a->mask & cattr_regression_test_exempt_mask))
- X {
- X a->regression_test_exempt = 1;
- X a->mask |= cattr_regression_test_exempt_mask;
- X }
- X }
- X if (!(a->mask & cattr_test_exempt_mask))
- X {
- X a->test_exempt = ps->default_test_exemption;
- X a->mask |= cattr_test_exempt_mask;
- X }
- X if (!(a->mask & cattr_test_baseline_exempt_mask))
- X {
- X a->test_baseline_exempt = ps->default_test_exemption;
- X a->mask |= cattr_test_baseline_exempt_mask;
- X }
- X}
- X
- X
- Xstatic void new_change_main _((void));
- X
- Xstatic void
- Xnew_change_main()
- X{
- X pstate pstate_data;
- X cstate cstate_data;
- X cstate_history history_data;
- X cattr cattr_data;
- X string_ty *project_name;
- X project_ty *pp;
- X long change_number;
- X change_ty *cp;
- X user_ty *up;
- X int edit;
- X
- X trace(("new_change_main()\n{\n"/*}*/));
- X cattr_data = 0;
- X project_name = 0;
- X edit = 0;
- X while (arglex_token != arglex_token_eoln)
- X {
- X switch (arglex_token)
- X {
- X default:
- X generic_argument(new_change_usage);
- X continue;
- X
- X case arglex_token_string:
- X if (cattr_data)
- X fatal("too many files named");
- X os_become_orig();
- X cattr_data = cattr_read_file(arglex_value.alv_string);
- X os_become_undo();
- X cattr_verify(arglex_value.alv_string, cattr_data);
- X break;
- X
- X case arglex_token_project:
- X if (arglex() != arglex_token_string)
- X new_change_usage();
- X if (project_name)
- X fatal("duplicate -Project option");
- X project_name = str_from_c(arglex_value.alv_string);
- X break;
- X
- X case arglex_token_edit:
- X if (edit)
- X fatal("duplicate \"%s\" option", arglex_value.alv_string);
- X edit++;
- X break;
- X }
- X arglex();
- X }
- X if (!edit && !cattr_data)
- X fatal("no change attributes file named");
- X
- X /*
- X * locate project data
- X */
- X if (!project_name)
- X fatal("project name must be stated explicitly");
- X pp = project_alloc(project_name);
- X str_free(project_name);
- X project_bind_existing(pp);
- X
- X /*
- X * locate user data
- X */
- X up = user_executing(pp);
- X
- X /*
- X * see if must invoke editor
- X */
- X if (edit)
- X {
- X /*
- X * build template cattr
- X */
- X if (!cattr_data)
- X {
- X string_ty *none = str_from_c("none");
- X cattr_data = (cattr)cattr_type.alloc();
- X cattr_data->brief_description = str_copy(none);
- X cattr_data->description = str_copy(none);
- X cattr_data->cause = change_cause_internal_bug;
- X str_free(none);
- X }
- X
- X /*
- X * default a few things
- X */
- X pstate_data = project_pstate_get(pp);
- X cattr_defaults(cattr_data, pstate_data);
- X
- X /*
- X * edit the attributes
- X */
- X cattr_edit(&cattr_data);
- X }
- X
- X /*
- X * Lock the project state file.
- X * Block if necessary.
- X */
- X project_pstate_lock_prepare(pp);
- X lock_take();
- X pstate_data = project_pstate_get(pp);
- X
- X /*
- X * it is an error if
- X * the user is not an administrator for the project.
- X */
- X if
- X (
- X !project_administrator_query(pp, user_name(up))
- X &&
- X (
- X !pstate_data->developers_may_create_changes
- X ||
- X !project_developer_query(pp, user_name(up))
- X )
- X )
- X {
- X project_fatal
- X (
- X pp,
- X "user \"%S\" is not an administrator",
- X user_name(up)
- X );
- X }
- X
- X /*
- X * when developers create changes,
- X * they may not give themselves a testing exemption,
- X * only administrators may do that.
- X */
- X if (!project_administrator_query(pp, user_name(up)))
- X {
- X /*
- X * If they are asking for default behaviour, don't complain.
- X * (e.g. admin may have given general testing exemption)
- X */
- X cattr dflt = cattr_type.alloc();
- X dflt->cause = cattr_data->cause;
- X cattr_defaults(dflt, pstate_data);
- X
- X if
- X (
- X (
- X (cattr_data->mask & cattr_test_exempt_mask)
- X &&
- X cattr_data->test_exempt
- X &&
- X (cattr_data->test_exempt != dflt->test_exempt)
- X )
- X ||
- X (
- X (cattr_data->mask & cattr_test_baseline_exempt_mask)
- X &&
- X cattr_data->test_baseline_exempt
- X &&
- X (cattr_data->test_baseline_exempt != dflt->test_baseline_exempt)
- X )
- X ||
- X (
- X (cattr_data->mask & cattr_regression_test_exempt_mask)
- X &&
- X cattr_data->regression_test_exempt
- X &&
- X (cattr_data->regression_test_exempt != dflt->regression_test_exempt)
- X )
- X )
- X fatal("developers may not grant testing exemptions");
- X cattr_type.free(dflt);
- X }
- X
- X /*
- X * Add another row to the change table.
- X * Create the change history.
- X */
- X assert(pstate_data->next_change_number >= 1);
- X change_number = pstate_data->next_change_number++;
- X cp = change_alloc(pp, change_number);
- X change_bind_new(cp);
- X
- X cstate_data = change_cstate_get(cp);
- X cstate_data->state = cstate_state_awaiting_development;
- X history_data = change_history_new(cp, up);
- X history_data->what = cstate_history_what_new_change;
- X if (cattr_data->description)
- X cstate_data->description = str_copy(cattr_data->description);
- X assert(cattr_data->brief_description);
- X cstate_data->brief_description = str_copy(cattr_data->brief_description);
- X assert(cattr_data->mask & cattr_cause_mask);
- X if (change_number == 1)
- X {
- X cattr_data->cause = change_cause_internal_enhancement;
- X cattr_data->test_baseline_exempt = 1;
- X cattr_data->mask |= cattr_test_baseline_exempt_mask;
- X cattr_data->regression_test_exempt = 1;
- X cattr_data->mask |= cattr_regression_test_exempt_mask;
- X }
- X cattr_defaults(cattr_data, pstate_data);
- X cstate_data->cause = cattr_data->cause;
- X assert(cattr_data->mask & cattr_test_exempt_mask);
- X cstate_data->test_exempt = cattr_data->test_exempt;
- X assert(cattr_data->mask & cattr_test_baseline_exempt_mask);
- X cstate_data->test_baseline_exempt =
- X cattr_data->test_baseline_exempt;
- X assert(cattr_data->mask & cattr_regression_test_exempt_mask);
- X cstate_data->regression_test_exempt =
- X cattr_data->regression_test_exempt;
- X cattr_type.free(cattr_data);
- X
- X /*
- X * Write out the change file.
- X * There is no need to lock this file
- X * as it does not exist yet;
- X * the project state file, with the number in it, is locked.
- X */
- X change_cstate_write(cp);
- X
- X /*
- X * Add the change to the list of existing changes.
- X * Incriment the next_change_number.
- X * and write pstate back out.
- X */
- X project_change_append(pp, change_number);
- X
- X /*
- X * Unlock the pstate file.
- X */
- X project_pstate_write(pp);
- X commit();
- X lock_release();
- X
- X /*
- X * verbose success message
- X */
- X change_verbose(cp, "created");
- X project_free(pp);
- X change_free(cp);
- X user_free(up);
- X trace((/*{*/"}\n"));
- X}
- X
- X
- Xvoid
- Xnew_change()
- X{
- X trace(("new_change()\n{\n"/*}*/));
- X switch (arglex())
- X {
- X default:
- X new_change_main();
- X break;
- X
- X case arglex_token_help:
- X new_change_help();
- X break;
- X
- X case arglex_token_list:
- X new_change_list();
- X break;
- X }
- X trace((/*{*/"}\n"));
- X}
- END_OF_FILE
- if test 13153 -ne `wc -c <'aegis/aenc.c'`; then
- echo shar: \"'aegis/aenc.c'\" unpacked with wrong size!
- fi
- # end of 'aegis/aenc.c'
- fi
- if test -f 'aegis/aenf.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'aegis/aenf.c'\"
- else
- echo shar: Extracting \"'aegis/aenf.c'\" \(14176 characters\)
- sed "s/^X//" >'aegis/aenf.c' <<'END_OF_FILE'
- X/*
- X * aegis - project change supervisor
- X * Copyright (C) 1991, 1992, 1993 Peter Miller.
- X * All rights reserved.
- X *
- X * This program is free software; you can redistribute it and/or modify
- X * it under the terms of the GNU General Public License as published by
- X * the Free Software Foundation; either version 2 of the License, or
- X * (at your option) any later version.
- X *
- X * This program is distributed in the hope that it will be useful,
- X * but WITHOUT ANY WARRANTY; without even the implied warranty of
- X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- X * GNU General Public License for more details.
- X *
- X * You should have received a copy of the GNU General Public License
- X * along with this program; if not, write to the Free Software
- X * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- X *
- X * MANIFEST: functions to add or remove a new file to a change
- X */
- X
- X#include <stdio.h>
- X#include <stdlib.h>
- X#include <unistd.h>
- X
- X#include <ael.h>
- X#include <aenf.h>
- X#include <arglex2.h>
- X#include <change.h>
- X#include <col.h>
- X#include <commit.h>
- X#include <error.h>
- X#include <glue.h>
- X#include <help.h>
- X#include <lock.h>
- X#include <log.h>
- X#include <option.h>
- X#include <os.h>
- X#include <project.h>
- X#include <trace.h>
- X#include <user.h>
- X#include <word.h>
- X
- X
- Xstatic void new_file_usage _((void));
- X
- Xstatic void
- Xnew_file_usage()
- X{
- X char *progname;
- X
- X progname = option_progname_get();
- X fprintf(stderr, "usage: %s -New_File <filename>... [ <option>... ]\n", progname);
- X fprintf(stderr, " %s -New_File -List [ <option>... ]\n", progname);
- X fprintf(stderr, " %s -New_File -Help\n", progname);
- X quit(1);
- X}
- X
- X
- Xstatic void new_file_help _((void));
- X
- Xstatic void
- Xnew_file_help()
- X{
- X static char *text[] =
- X {
- X"NAME",
- X" %s -New_File - add new files to a change",
- X"",
- X"SYNOPSIS",
- X" %s -New_File <file-name>... [ <option>... ]",
- X" %s -New_File -List [ <option>... ]",
- X" %s -New_File -Help",
- X"",
- X"DESCRIPTION",
- X" The %s -New_File command is used to add new files to a",
- X" change.",
- X"",
- X" The %s program will attempt to intuit the file names",
- X" intended. All file names are stored within %s as",
- X" relative to the root of the baseline directory tree. The",
- X" development directory and the integration directory are",
- X" shadows of the baseline directory, and so these relative",
- X" names aply there, too. Files named on the command line",
- X" are first converted to absolute paths if necessary. They",
- X" are then compared with the baseline path, and the",
- X" development directory path, and the integration directory",
- X" path, to determine a root-relative name. It is an error",
- X" if the file named is outside one of these directory",
- X" trees.",
- X"",
- X" The named files will be added to the list of files in the",
- X" change. For each file named, a new file is created in the",
- X" development directory, if it does not exist already. The",
- X" config file will be searched for a template for the new",
- X" file. If a template is found, the new file will be",
- X" initialized to the template, otherwise it will be created",
- X" empty. If the file already exists, it will not be altered.",
- X" See aepconf(5) for more information.",
- X"",
- X"OPTIONS",
- X" The following options are understood",
- X"",
- X" -Build",
- X" This option may be used to specify that the file",
- X" is constructed during a build (often only an",
- X" integrate build), so that history of it may be",
- X" kept. This is useful for generating patch files,",
- X" where a history of generated files is important.",
- X" Files created in this way may not be copied into",
- X" a change, though they may be deleted. Avoid",
- X" using files of this type, if at all possible.",
- X"",
- X" -Change <number>",
- X" This option may be used to specify a particular",
- X" change within a project. When no -Change option is",
- X" specified, the AEGIS_CHANGE environment variable is",
- X" consulted. If that does not exist, the user's",
- X" $HOME/.aegisrc file is examined for a default change",
- X" field (see aeuconf(5) for more information). If",
- X" that does not exist, when the user is only working",
- X" on one change within a project, that is the default",
- X" change number. Otherwise, it is an error.",
- X"",
- X" -Help",
- X" This option may be used to obtain more",
- X" information about how to use the %s program.",
- X"",
- X" -List",
- X" This option may be used to obtain a list of",
- X" suitable subjects for this command. The list may",
- X" be more general than expected.",
- X"",
- X" -Project <name>",
- X" This option may be used to select the project of",
- X" interest. When no -Project option is specified, the",
- X" AEGIS_PROJECT environment variable is consulted. If",
- X" that does not exist, the user's $HOME/.aegisrc file",
- X" is examined for a default project field (see",
- X" aeuconf(5) for more information). If that does not",
- X" exist, when the user is only working on changes",
- X" within a single project, the project name defaults",
- X" to that project. Otherwise, it is an error.",
- X"",
- X" -TERse",
- X" This option may be used to cause listings to",
- X" produce the bare minimum of information. It is",
- X" usually useful for shell scripts.",
- X"",
- X" -Verbose",
- X" This option may be used to cause %s to produce",
- X" more output. By default %s only produces",
- X" output on errors. When used with the -List",
- X" option this option causes column headings to be",
- X" added.",
- X"",
- X" All options may be abbreviated; the abbreviation is",
- X" documented as the upper case letters, all lower case",
- X" letters and underscores (_) are optional. You must use",
- X" consecutive sequences of optional letters.",
- X"",
- X" All options are case insensitive, you may type them in",
- X" upper case or lower case or a combination of both, case",
- X" is not important.",
- X"",
- X" For example: the arguments \"-project, \"-PROJ\" and \"-p\"",
- X" are all interpreted to mean the -Project option. The",
- X" argument \"-prj\" will not be understood, because",
- X" consecutive optional characters were not supplied.",
- X"",
- X" Options and other command line arguments may be mixed",
- X" arbitrarily on the command line, after the function",
- X" selectors.",
- X"",
- X" The GNU long option names are understood. Since all",
- X" option names for aegis are long, this means ignoring the",
- X" extra leading '-'. The \"--option=value\" convention is",
- X" also understood.",
- X"",
- X"RECOMMENDED ALIAS",
- X" The recommended alias for this command is",
- X" csh%% alias aenf '%s -nf \\!* -v'",
- X" sh$ aenf(){%s -nf $* -v}",
- X"",
- X"ERRORS",
- X" It is an error if the change is not in the",
- X" 'being_developed' state.",
- X" It is an error if the change is not assigned to the",
- X" current user.",
- X" It is an error if the file is already part of the change.",
- X" It is an error if the file is already part of the",
- X" baseline.",
- X"",
- X"EXIT STATUS",
- X" The %s command will exit with a status of 1 on any",
- X" error. The %s command will only exit with a status of",
- X" 0 if there are no errors.",
- X"",
- X"COPYRIGHT",
- X" %C",
- X"",
- X"AUTHOR",
- X" %A",
- X };
- X
- X help(text, SIZEOF(text), new_file_usage);
- X}
- X
- X
- Xstatic void new_file_list _((void));
- X
- Xstatic void
- Xnew_file_list()
- X{
- X string_ty *project_name;
- X long change_number;
- X
- X trace(("new_file_list()\n{\n"/*}*/));
- X project_name = 0;
- X change_number = 0;
- X arglex();
- X while (arglex_token != arglex_token_eoln)
- X {
- X switch (arglex_token)
- X {
- X default:
- X generic_argument(new_file_usage);
- X continue;
- X
- X case arglex_token_change:
- X if (arglex() != arglex_token_number)
- X new_file_usage();
- X /* fall through... */
- X
- X case arglex_token_number:
- X if (change_number)
- X fatal("duplicate -Change option");
- X change_number = arglex_value.alv_number;
- X if (change_number < 1)
- X fatal("change %ld out of range", change_number);
- X break;
- X
- X case arglex_token_project:
- X if (arglex() != arglex_token_string)
- X new_file_usage();
- X if (project_name)
- X fatal("duplicate -Project option");
- X project_name = str_from_c(arglex_value.alv_string);
- X break;
- X }
- X arglex();
- X }
- X list_project_files(project_name, change_number);
- X if (project_name)
- X str_free(project_name);
- X trace((/*{*/"}\n"));
- X}
- X
- X
- Xstatic void new_file_main _((void));
- X
- Xstatic void
- Xnew_file_main()
- X{
- X string_ty *bl;
- X string_ty *dd;
- X wlist wl;
- X cstate cstate_data;
- X pstate pstate_data;
- X int j;
- X string_ty *s1;
- X string_ty *s2;
- X pconf pconf_data;
- X string_ty *project_name;
- X project_ty *pp;
- X long change_number;
- X change_ty *cp;
- X int nolog;
- X user_ty *up;
- X int generated;
- X
- X trace(("new_file_main()\n{\n"/*}*/));
- X project_name = 0;
- X change_number = 0;
- X generated = 0;
- X wl_zero(&wl);
- X nolog = 0;
- X while (arglex_token != arglex_token_eoln)
- X {
- X switch (arglex_token)
- X {
- X default:
- X generic_argument(new_file_usage);
- X continue;
- X
- X case arglex_token_string:
- X s1 = str_from_c(arglex_value.alv_string);
- X os_become_orig();
- X s2 = os_pathname(s1, 1);
- X str_free(s1);
- X if (wl_member(&wl, s2))
- X fatal("file \"%s\" named more than once", arglex_value.alv_string);
- X s1 = os_entryname(s2);
- X os_become_undo();
- X if (s1->str_length > PATH_ELEMENT_MAX - 2)
- X {
- X fatal
- X (
- X "file \"%s\" basename too long (by %ld)",
- X arglex_value.alv_string,
- X s1->str_length - (PATH_ELEMENT_MAX - 2)
- X );
- X }
- X str_free(s1);
- X wl_append(&wl, s2);
- X str_free(s2);
- X break;
- X
- X case arglex_token_change:
- X if (arglex() != arglex_token_number)
- X new_file_usage();
- X /* fall through... */
- X
- X case arglex_token_number:
- X if (change_number)
- X fatal("duplicate -Change option");
- X change_number = arglex_value.alv_number;
- X if (change_number < 1)
- X fatal("change %ld out of range", change_number);
- X break;
- X
- X case arglex_token_project:
- X if (arglex() != arglex_token_string)
- X new_file_usage();
- X if (project_name)
- X fatal("duplicate -Project option");
- X project_name = str_from_c(arglex_value.alv_string);
- X break;
- X
- X case arglex_token_nolog:
- X if (nolog)
- X {
- X duplicate:
- X fatal
- X (
- X "duplicate %s option",
- X arglex_value.alv_string
- X );
- X }
- X nolog = 1;
- X break;
- X
- X case arglex_token_build:
- X if (generated)
- X goto duplicate;
- X generated = 1;
- X break;
- X }
- X arglex();
- X }
- X if (!wl.wl_nwords)
- X fatal("no files named");
- X
- X /*
- X * locate project data
- X */
- X if (!project_name)
- X project_name = user_default_project();
- X pp = project_alloc(project_name);
- X str_free(project_name);
- X project_bind_existing(pp);
- X
- X /*
- X * locate user data
- X */
- X up = user_executing(pp);
- X
- X /*
- X * locate change data
- X */
- X if (!change_number)
- X change_number = user_default_change(up);
- X cp = change_alloc(pp, change_number);
- X change_bind_existing(cp);
- X
- X /*
- X * lock the change file
- X */
- X change_cstate_lock_prepare(cp);
- X lock_take();
- X cstate_data = change_cstate_get(cp);
- X pstate_data = project_pstate_get(pp);
- X pconf_data = change_pconf_get(cp);
- X
- X /*
- X * It is an error if the change is not in the in_development state.
- X * It is an error if the change is not assigned to the current user.
- X */
- X if (cstate_data->state != cstate_state_being_developed)
- X change_fatal(cp, "not in 'being_developed' state");
- X if (!str_equal(change_developer_name(cp), user_name(up)))
- X {
- X change_fatal
- X (
- X cp,
- X "user \"%S\" is not the developer",
- X user_name(up)
- X );
- X }
- X
- X /*
- X * resolve the path of each file
- X * 1. the absolute path of the file name is obtained
- X * 2. if the file is inside the development directory, ok
- X * 3. if the file is inside the baseline, ok
- X * 4. if neither, error
- X */
- X dd = change_development_directory_get(cp, 1);
- X bl = project_baseline_path_get(pp, 1);
- X for (j = 0; j < wl.wl_nwords; ++j)
- X {
- X s1 = wl.wl_word[j];
- X assert(s1->str_text[0] == '/');
- X s2 = os_below_dir(dd, s1);
- X if (!s2)
- X s2 = os_below_dir(bl, s1);
- X if (!s2)
- X change_fatal(cp, "path \"%S\" unrelated", s1);
- X str_free(s1);
- X wl.wl_word[j] = s2;
- X }
- X
- X /*
- X * ensure that each file
- X * 1. is not already part of the change
- X * 2. is not already part of the baseline
- X */
- X for (j = 0; j < wl.wl_nwords; ++j)
- X {
- X pstate_src src_data;
- X
- X s1 = wl.wl_word[j];
- X if (change_src_find(cp, s1))
- X change_fatal(cp, "file \"%S\" already exists", s1);
- X src_data = project_src_find(pp, s1);
- X if
- X (
- X src_data
- X &&
- X !src_data->about_to_be_created_by
- X &&
- X !src_data->deleted_by
- X )
- X project_fatal(pp, "file \"%S\" already exists", s1);
- X }
- X
- X /*
- X * Create each file in the development directory,
- X * if it does not already exist.
- X * Create any necessary directories along the way.
- X */
- X user_become(up);
- X for (j = 0; j < wl.wl_nwords; ++j)
- X {
- X s1 = wl.wl_word[j];
- X os_mkdir_between(dd, s1, 02755);
- X s2 = str_format("%S/%S", dd, s1);
- X if (!os_exists(s2))
- X {
- X int fd;
- X string_ty *template;
- X
- X user_become_undo();
- X template = change_file_template(cp, s1);
- X user_become(up);
- X fd = glue_creat(s2->str_text, 0666);
- X if (fd < 0)
- X nfatal("create(\"%s\")", s2->str_text);
- X if (template)
- X {
- X glue_write
- X (
- X fd,
- X template->str_text,
- X template->str_length
- X );
- X str_free(template);
- X }
- X glue_close(fd);
- X os_chmod(s2, 0644 & ~change_umask(cp));
- X }
- X str_free(s2);
- X }
- X user_become_undo();
- X
- X /*
- X * Add each file to the change file,
- X * and write it back out.
- X */
- X for (j = 0; j < wl.wl_nwords; ++j)
- X {
- X cstate_src src_data;
- X
- X src_data = change_src_new(cp);
- X src_data->file_name = str_copy(wl.wl_word[j]);
- X src_data->action = file_action_create;
- X if (generated)
- X src_data->usage = file_usage_build;
- X else
- X src_data->usage = file_usage_source;
- X }
- X
- X /*
- X * the number of files changed, or the version did,
- X * so stomp on the validation fields.
- X */
- X cstate_data->build_time = 0;
- X cstate_data->test_time = 0;
- X cstate_data->test_baseline_time = 0;
- X cstate_data->regression_test_time = 0;
- X
- X /*
- X * release the locks
- X */
- X change_cstate_write(cp);
- X commit();
- X lock_release();
- X
- X /*
- X * run the change file command
- X */
- X if (!nolog)
- X log_open(change_logfile_get(cp), up);
- X change_run_change_file_command(cp, &wl, up);
- X
- X /*
- X * verbose success message
- X */
- X for (j = 0; j < wl.wl_nwords; ++j)
- X change_verbose(cp, "file \"%S\" added", wl.wl_word[j]);
- X wl_free(&wl);
- X change_free(cp);
- X project_free(pp);
- X user_free(up);
- X trace((/*{*/"}\n"));
- X}
- X
- X
- Xvoid
- Xnew_file()
- X{
- X trace(("new_file()\n{\n"/*}*/));
- X switch (arglex())
- X {
- X default:
- X new_file_main();
- X break;
- X
- X case arglex_token_help:
- X new_file_help();
- X break;
- X
- X case arglex_token_list:
- X new_file_list();
- X break;
- X }
- X trace((/*{*/"}\n"));
- X}
- END_OF_FILE
- if test 14176 -ne `wc -c <'aegis/aenf.c'`; then
- echo shar: \"'aegis/aenf.c'\" unpacked with wrong size!
- fi
- # end of 'aegis/aenf.c'
- fi
- if test -f 'aegis/aenfu.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'aegis/aenfu.c'\"
- else
- echo shar: Extracting \"'aegis/aenfu.c'\" \(12929 characters\)
- sed "s/^X//" >'aegis/aenfu.c' <<'END_OF_FILE'
- X/*
- X * aegis - project change supervisor
- X * Copyright (C) 1991, 1992, 1993 Peter Miller.
- X * All rights reserved.
- X *
- X * This program is free software; you can redistribute it and/or modify
- X * it under the terms of the GNU General Public License as published by
- X * the Free Software Foundation; either version 2 of the License, or
- X * (at your option) any later version.
- X *
- X * This program is distributed in the hope that it will be useful,
- X * but WITHOUT ANY WARRANTY; without even the implied warranty of
- X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- X * GNU General Public License for more details.
- X *
- X * You should have received a copy of the GNU General Public License
- X * along with this program; if not, write to the Free Software
- X * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- X *
- X * MANIFEST: functions to add or remove a new file to a change
- X */
- X
- X#include <stdio.h>
- X#include <stdlib.h>
- X#include <unistd.h>
- X
- X#include <ael.h>
- X#include <aenfu.h>
- X#include <arglex2.h>
- X#include <change.h>
- X#include <col.h>
- X#include <commit.h>
- X#include <error.h>
- X#include <glue.h>
- X#include <help.h>
- X#include <lock.h>
- X#include <log.h>
- X#include <option.h>
- X#include <os.h>
- X#include <project.h>
- X#include <trace.h>
- X#include <user.h>
- X#include <word.h>
- X
- X
- Xstatic void new_file_undo_usage _((void));
- X
- Xstatic void
- Xnew_file_undo_usage()
- X{
- X char *progname;
- X
- X progname = option_progname_get();
- X fprintf(stderr, "usage: %s -New_File_Undo <filename>... [ <option>... ]\n", progname);
- X fprintf(stderr, " %s -New_File_Undo -List [ <option>... ]\n", progname);
- X fprintf(stderr, " %s -New_File_Undo -Help\n", progname);
- X quit(1);
- X}
- X
- X
- Xstatic void new_file_undo_help _((void));
- X
- Xstatic void
- Xnew_file_undo_help()
- X{
- X static char *text[] =
- X {
- X"NAME",
- X" %s -New_File_Undo - remove new files form a change",
- X"",
- X"SYNOPSIS",
- X" %s -New_File_Undo <file-name>... [ <option>... ]",
- X" %s -New_File_Undo -List [ <option>... ]",
- X" %s -New_File_Undo -Help",
- X"",
- X"DESCRIPTION",
- X" The %s -New_File_Undo command is used to remove new",
- X" files from a change (reverse the actions of the '%s",
- X" -New_File' command).",
- X"",
- X" The %s program will attempt to intuit the file names",
- X" intended. All file names are stored within %s as",
- X" relative to the root of the baseline directory tree. The",
- X" development directory and the integration directory are",
- X" shadows of the baseline dirdctory, and so these relative",
- X" names aply there, too. Files named on the command line",
- X" are first converted to absolute paths if necessary. They",
- X" are then compared with the baseline path, and the",
- X" development directory path, and the integration directory",
- X" path, to determine a root-relative name. It is an error",
- X" if the file named is outside one of these directory",
- X" trees.",
- X"",
- X" The file is removed from the list of files in the change.",
- X" The file is deleted from the development directory,",
- X" unless the -Keep option is used.",
- X"",
- X"OPTIONS",
- X" The following options are understood:",
- X"",
- X" -Change <number>",
- X" This option may be used to specify a particular",
- X" change within a project. When no -Change option is",
- X" specified, the AEGIS_CHANGE environment variable is",
- X" consulted. If that does not exist, the user's",
- X" $HOME/.aegisrc file is examined for a default change",
- X" field (see aeuconf(5) for more information). If",
- X" that does not exist, when the user is only working",
- X" on one change within a project, that is the default",
- X" change number. Otherwise, it is an error.",
- X"",
- X" -Help",
- X" This option may be used to obtain more",
- X" information about how to use the %s program.",
- X"",
- X" -Keep",
- X" This option may be used to retain files and/or",
- X" directories usually deleted by the command.",
- X"",
- X" -List",
- X" This option may be used to obtain a list of",
- X" suitable subjects for this command. The list may",
- X" be more general than expected.",
- X"",
- X" -Project <name>",
- X" This option may be used to select the project of",
- X" interest. When no -Project option is specified, the",
- X" AEGIS_PROJECT environment variable is consulted. If",
- X" that does not exist, the user's $HOME/.aegisrc file",
- X" is examined for a default project field (see",
- X" aeuconf(5) for more information). If that does not",
- X" exist, when the user is only working on changes",
- X" within a single project, the project name defaults",
- X" to that project. Otherwise, it is an error.",
- X"",
- X" -TERse",
- X" This option may be used to cause listings to",
- X" produce the bare minimum of information. It is",
- X" usually useful for shell scripts.",
- X"",
- X" -Verbose",
- X" This option may be used to cause %s to produce",
- X" more output. By default %s only produces",
- X" output on errors. When used with the -List",
- X" option this option causes column headings to be",
- X" added.",
- X"",
- X" All options may be abbreviated; the abbreviation is",
- X" documented as the upper case letters, all lower case",
- X" letters and underscores (_) are optional. You must use",
- X" consecutive sequences of optional letters.",
- X"",
- X" All options are case insensitive, you may type them in",
- X" upper case or lower case or a combination of both, case",
- X" is not important.",
- X"",
- X" For example: the arguments \"-project, \"-PROJ\" and \"-p\"",
- X" are all interpreted to mean the -Project option. The",
- X" argument \"-prj\" will not be understood, because",
- X" consecutive optional characters were not supplied.",
- X"",
- X" Options and other command line arguments may be mixed",
- X" arbitrarily on the command line, after the function",
- X" selectors.",
- X"",
- X" The GNU long option names are understood. Since all",
- X" option names for aegis are long, this means ignoring the",
- X" extra leading '-'. The \"--option=value\" convention is",
- X" also understood.",
- X"",
- X"RECOMMENDED ALIAS",
- X" The recommended alias for this command is",
- X" csh%% alias aenfu '%s -nfu \\!$ -v'",
- X" sh$ aenfu(){%s -nfu $* -v}",
- X"",
- X"ERRORS",
- X" It is an error if the change is not in the",
- X" 'being_developed' state.",
- X" It is an error if the change is not assigned to the",
- X" current user.",
- X" It is an error if the file is not in the change.",
- X" It is an error if the file was not added to the change",
- X" with the '%s -New_File' command.",
- X"",
- X"EXIT STATUS",
- X" The %s command will exit with a status of 1 on any",
- X" error. The %s command will only exit with a status of",
- X" 0 if there are no errors.",
- X"",
- X"COPYRIGHT",
- X" %C",
- X"",
- X"AUTHOR",
- X" %A",
- X };
- X
- X help(text, SIZEOF(text), new_file_undo_usage);
- X}
- X
- X
- Xstatic void new_file_undo_list _((void));
- X
- Xstatic void
- Xnew_file_undo_list()
- X{
- X string_ty *project_name;
- X long change_number;
- X
- X trace(("new_file_undo_list()\n{\n"/*}*/));
- X project_name = 0;
- X change_number = 0;
- X arglex();
- X while (arglex_token != arglex_token_eoln)
- X {
- X switch (arglex_token)
- X {
- X default:
- X generic_argument(new_file_undo_usage);
- X continue;
- X
- X case arglex_token_change:
- X if (arglex() != arglex_token_number)
- X new_file_undo_usage();
- X /* fall through... */
- X
- X case arglex_token_number:
- X if (change_number)
- X fatal("duplicate -Change option");
- X change_number = arglex_value.alv_number;
- X if (change_number < 1)
- X fatal("change %ld out of range", change_number);
- X break;
- X
- X case arglex_token_project:
- X if (arglex() != arglex_token_string)
- X new_file_undo_usage();
- X if (project_name)
- X fatal("duplicate -Project option");
- X project_name = str_from_c(arglex_value.alv_string);
- X break;
- X }
- X arglex();
- X }
- X list_change_files(project_name, change_number);
- X if (project_name)
- X str_free(project_name);
- X trace((/*{*/"}\n"));
- X}
- X
- X
- Xstatic void new_file_undo_main _((void));
- X
- Xstatic void
- Xnew_file_undo_main()
- X{
- X wlist wl;
- X cstate cstate_data;
- X pstate pstate_data;
- X int j;
- X string_ty *s1;
- X string_ty *s2;
- X int keep;
- X pconf pconf_data;
- X string_ty *project_name;
- X project_ty *pp;
- X long change_number;
- X change_ty *cp;
- X int nolog;
- X user_ty *up;
- X string_ty *dd;
- X string_ty *bl;
- X
- X trace(("new_file_undo_main()\n{\n"/*}*/));
- X project_name = 0;
- X change_number = 0;
- X wl_zero(&wl);
- X keep = 0;
- X nolog = 0;
- X while (arglex_token != arglex_token_eoln)
- X {
- X switch (arglex_token)
- X {
- X default:
- X generic_argument(new_file_undo_usage);
- X continue;
- X
- X case arglex_token_string:
- X s1 = str_from_c(arglex_value.alv_string);
- X os_become_orig();
- X s2 = os_pathname(s1, 1);
- X os_become_undo();
- X str_free(s1);
- X if (wl_member(&wl, s2))
- X fatal("file \"%s\" named more than once", arglex_value.alv_string);
- X wl_append(&wl, s2);
- X str_free(s2);
- X break;
- X
- X case arglex_token_keep:
- X if (keep)
- X {
- X duplicate:
- X fatal("duplicate %s option", arglex_value.alv_string);
- X }
- X keep = 1;
- X break;
- X
- X case arglex_token_change:
- X if (arglex() != arglex_token_number)
- X new_file_undo_usage();
- X /* fall through... */
- X
- X case arglex_token_number:
- X if (change_number)
- X fatal("duplicate -Change option");
- X change_number = arglex_value.alv_number;
- X if (change_number < 1)
- X fatal("change %ld out of range", change_number);
- X break;
- X
- X case arglex_token_project:
- X if (arglex() != arglex_token_string)
- X new_file_undo_usage();
- X if (project_name)
- X fatal("duplicate -Project option");
- X project_name = str_from_c(arglex_value.alv_string);
- X break;
- X
- X case arglex_token_nolog:
- X if (nolog)
- X goto duplicate;
- X nolog = 1;
- X break;
- X }
- X arglex();
- X }
- X if (!wl.wl_nwords)
- X fatal("no files named");
- X
- X /*
- X * locate project data
- X */
- X if (!project_name)
- X project_name = user_default_project();
- X pp = project_alloc(project_name);
- X str_free(project_name);
- X project_bind_existing(pp);
- X
- X /*
- X * locate user data
- X */
- X up = user_executing(pp);
- X
- X /*
- X * locate change data
- X */
- X if (!change_number)
- X change_number = user_default_change(up);
- X cp = change_alloc(pp, change_number);
- X change_bind_existing(cp);
- X
- X /*
- X * lock the change file
- X */
- X change_cstate_lock_prepare(cp);
- X lock_take();
- X cstate_data = change_cstate_get(cp);
- X pstate_data = project_pstate_get(pp);
- X pconf_data = change_pconf_get(cp);
- X
- X /*
- X * It is an error if the change is not in the in_development state.
- X * It is an error if the change is not assigned to the current user.
- X */
- X if (cstate_data->state != cstate_state_being_developed)
- X change_fatal(cp, "not in 'being_developed' state");
- X if (!str_equal(change_developer_name(cp), user_name(up)))
- X {
- X change_fatal
- X (
- X cp,
- X "user \"%S\" is not the developer",
- X user_name(up)
- X );
- X }
- X
- X /*
- X * resolve the path of each file
- X * 1. the absolute path of the file name is obtained
- X * 2. if the file is inside the development directory, ok
- X * 3. if the file is inside the baseline, ok
- X * 4. if neither, error
- X */
- X dd = change_development_directory_get(cp, 1);
- X bl = project_baseline_path_get(pp, 1);
- X for (j = 0; j < wl.wl_nwords; ++j)
- X {
- X s1 = wl.wl_word[j];
- X assert(s1->str_text[0] == '/');
- X s2 = os_below_dir(dd, s1);
- X if (!s2)
- X s2 = os_below_dir(bl, s1);
- X if (!s2)
- X change_fatal(cp, "path \"%S\" unrelated", s1);
- X str_free(s1);
- X wl.wl_word[j] = s2;
- X }
- X
- X /*
- X * ensure that each file
- X * 1. is already part of the change
- X * 2. is being created by this change
- X */
- X for (j = 0; j < wl.wl_nwords; ++j)
- X {
- X cstate_src src_data;
- X
- X s1 = wl.wl_word[j];
- X src_data = change_src_find(cp, s1);
- X if (!src_data)
- X change_fatal(cp, "file \"%S\" not in change", s1);
- X if
- X (
- X src_data->action != file_action_create
- X ||
- X src_data->usage != file_usage_source
- X )
- X change_fatal(cp, "file \"%S\" is not -New_File", s1);
- X }
- X
- X /*
- X * Remove each file from the development directory,
- X * if it still exists.
- X */
- X if (!keep)
- X {
- X user_become(up);
- X for (j = 0; j < wl.wl_nwords; ++j)
- X {
- X s1 = wl.wl_word[j];
- X s2 = str_format("%S/%S", dd, s1);
- X if (os_exists(s2))
- X commit_unlink_errok(s2);
- X str_free(s2);
- X
- X s2 = str_format("%S/%S,D", dd, s1);
- X if (os_exists(s2))
- X commit_unlink_errok(s2);
- X str_free(s2);
- X }
- X os_become_undo();
- X }
- X
- X /*
- X * Remove each file to the change file,
- X * and write it back out.
- X */
- X for (j = 0; j < wl.wl_nwords; ++j)
- X change_src_remove(cp, wl.wl_word[j]);
- X
- X /*
- X * the number of files changed, or the version did,
- X * so stomp on the validation fields.
- X */
- X cstate_data->build_time = 0;
- X cstate_data->test_time = 0;
- X cstate_data->test_baseline_time = 0;
- X cstate_data->regression_test_time = 0;
- X
- X /*
- X * release the locks
- X */
- X change_cstate_write(cp);
- X commit();
- X lock_release();
- X
- X /*
- X * run the change file command
- X */
- X if (!nolog)
- X log_open(change_logfile_get(cp), up);
- X change_run_change_file_command(cp, &wl, up);
- X
- X /*
- X * verbose success message
- X */
- X for (j = 0; j < wl.wl_nwords; ++j)
- X {
- X change_verbose
- X (
- X cp,
- X "file \"%S\" new file removed",
- X wl.wl_word[j]
- X );
- X }
- X wl_free(&wl);
- X project_free(pp);
- X change_free(cp);
- X user_free(up);
- X trace((/*{*/"}\n"));
- X}
- X
- X
- Xvoid
- Xnew_file_undo()
- X{
- X trace(("new_file_undo()\n{\n"/*}*/));
- X switch (arglex())
- X {
- X default:
- X new_file_undo_main();
- X break;
- X
- X case arglex_token_help:
- X new_file_undo_help();
- X break;
- X
- X case arglex_token_list:
- X new_file_undo_list();
- X break;
- X }
- X trace((/*{*/"}\n"));
- X}
- END_OF_FILE
- if test 12929 -ne `wc -c <'aegis/aenfu.c'`; then
- echo shar: \"'aegis/aenfu.c'\" unpacked with wrong size!
- fi
- # end of 'aegis/aenfu.c'
- fi
- if test -f 'aegis/aerf.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'aegis/aerf.c'\"
- else
- echo shar: Extracting \"'aegis/aerf.c'\" \(13632 characters\)
- sed "s/^X//" >'aegis/aerf.c' <<'END_OF_FILE'
- X/*
- X * aegis - project change supervisor
- X * Copyright (C) 1991, 1992, 1993 Peter Miller.
- X * All rights reserved.
- X *
- X * This program is free software; you can redistribute it and/or modify
- X * it under the terms of the GNU General Public License as published by
- X * the Free Software Foundation; either version 2 of the License, or
- X * (at your option) any later version.
- X *
- X * This program is distributed in the hope that it will be useful,
- X * but WITHOUT ANY WARRANTY; without even the implied warranty of
- X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- X * GNU General Public License for more details.
- X *
- X * You should have received a copy of the GNU General Public License
- X * along with this program; if not, write to the Free Software
- X * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- X *
- X * MANIFEST: functions to impliment review fail
- X */
- X
- X#include <stdio.h>
- X#include <stdlib.h>
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X
- X#include <ael.h>
- X#include <aerf.h>
- X#include <arglex2.h>
- X#include <change.h>
- X#include <commit.h>
- X#include <dir.h>
- X#include <error.h>
- X#include <file.h>
- X#include <help.h>
- X#include <lock.h>
- X#include <mem.h>
- X#include <option.h>
- X#include <os.h>
- X#include <project.h>
- X#include <sub.h>
- X#include <trace.h>
- X#include <undo.h>
- X#include <user.h>
- X
- X
- Xstatic void review_fail_usage _((void));
- X
- Xstatic void
- Xreview_fail_usage()
- X{
- X char *progname;
- X
- X progname = option_progname_get();
- X fprintf(stderr, "usage: %s -Review_FAIL <reason-file> [ <option>... ]\n", progname);
- X fprintf(stderr, " %s -Review_FAIL -Edit [ <option>... ]\n", progname);
- X fprintf(stderr, " %s -Review_FAIL -List [ <option>... ]\n", progname);
- X fprintf(stderr, " %s -Review_FAIL -Help\n", progname);
- X quit(1);
- X}
- X
- X
- Xstatic void review_fail_help _((void));
- X
- Xstatic void
- Xreview_fail_help()
- X{
- X static char *text[] =
- X {
- X"NAME",
- X" %s -Review_FAIL - fail a change review",
- X"",
- X"SYNOPSIS",
- X" %s -Review_FAIL <reason-file> [ <option>... ]",
- X" %s -Review_FAIL -Edit [ <option>... ]",
- X" %s -Review_FAIL -List [ <option>... ]",
- X" %s -Review_FAIL -Help",
- X"",
- X"DESCRIPTION",
- X" The %s -Review_FAIL command is used to inform",
- X" %s that a change has failed review.",
- X"",
- X" The change will be returned from the 'being_reviewed'",
- X" state to the 'being_developed' state. The change will",
- X" cease to be assigned to the current user, and will be",
- X" reassigned to the originating developer.",
- X"",
- X" The developer will be notified by mail. See the",
- X" integrate_fail_notify_command in aepconf(5) for more",
- X" information.",
- X"",
- X" The reason-file will contain a description of why the",
- X" change was failed. The file is in plain text. It is",
- X" recommened that you only use newline to terminate",
- X" paragraphs, as with will result in better formatting in",
- X" the various listings.",
- X"",
- X"OPTIONS",
- X" The following options are understood:",
- X"",
- X" -Change <number>",
- X" This option may be used to specify a particular",
- X" change within a project. When no -Change option is",
- X" specified, the AEGIS_CHANGE environment variable is",
- X" consulted. If that does not exist, the user's",
- X" $HOME/.aegisrc file is examined for a default change",
- X" field (see aeuconf(5) for more information). If",
- X" that does not exist, when the user is only working",
- X" on one change within a project, that is the default",
- X" change number. Otherwise, it is an error.",
- X"",
- X" -Edit",
- X" Edit the attributes with a text editor, this is",
- X" usually more convenient than supplying a text",
- X" file. The EDITOR environment variable will be",
- X" consulted for the name of the editor to use;",
- X" defaults to vi(1) if not set. Warning: not well",
- X" behaved when faced with errors, the temporary",
- X" file is always deleted.",
- X"",
- X" -Help",
- X" This option may be used to obtain more",
- X" information about how to use the %s program.",
- X"",
- X" -List",
- X" This option may be used to obtain a list of",
- X" suitable subjects for this command. The list may",
- X" be more general than expected.",
- X"",
- X" -Project <name>",
- X" This option may be used to select the project of",
- X" interest. When no -Project option is specified, the",
- X" AEGIS_PROJECT environment variable is consulted. If",
- X" that does not exist, the user's $HOME/.aegisrc file",
- X" is examined for a default project field (see",
- X" aeuconf(5) for more information). If that does not",
- X" exist, when the user is only working on changes",
- X" within a single project, the project name defaults",
- X" to that project. Otherwise, it is an error.",
- X"",
- X" -TERse",
- X" This option may be used to cause listings to",
- X" produce the bare minimum of information. It is",
- X" usually useful for shell scripts.",
- X"",
- X" -Verbose",
- X" This option may be used to cause %s to produce",
- X" more output. By default %s only produces",
- X" output on errors. When used with the -List",
- X" option this option causes column headings to be",
- X" added.",
- X"",
- X" All options may be abbreviated; the abbreviation is",
- X" documented as the upper case letters, all lower case",
- X" letters and underscores (_) are optional. You must use",
- X" consecutive sequences of optional letters.",
- X"",
- X" All options are case insensitive, you may type them in",
- X" upper case or lower case or a combination of both, case",
- X" is not important.",
- X"",
- X" For example: the arguments \"-project, \"-PROJ\" and \"-p\"",
- X" are all interpreted to mean the -Project option. The",
- X" argument \"-prj\" will not be understood, because",
- X" consecutive optional characters were not supplied.",
- X"",
- X" Options and other command line arguments may be mixed",
- X" arbitrarily on the command line, after the function",
- X" selectors.",
- X"",
- X" The GNU long option names are understood. Since all",
- X" option names for aegis are long, this means ignoring the",
- X" extra leading '-'. The \"--option=value\" convention is",
- X" also understood.",
- X"",
- X"RECOMMENDED ALIAS",
- X" The recommended alias for this command is",
- X" csh%% alias aerf '%s -rf \\!* -v'",
- X" sh$ aerf(){%s -rf $* -v}",
- X"",
- X"ERRORS",
- X" It is an error if the change is not in the",
- X" 'being_reviewed' state.",
- X" It is an error if the current user is not a reviewer for",
- X" the project.",
- X" It is an error if the current user developed the change",
- X" and the project is configured to disallow developers to",
- X" review their own changes (default).",
- X"",
- X"EXIT STATUS",
- X" The %s command will exit with a status of 1 on any",
- X" error. The %s command will only exit with a status of",
- X" 0 if there are no errors.",
- X"",
- X"COPYRIGHT",
- X" %C",
- X"",
- X"AUTHOR",
- X" %A",
- X };
- X
- X help(text, SIZEOF(text), review_fail_usage);
- X}
- X
- X
- Xstatic void review_fail_list _((void (*usage)(void)));
- X
- Xstatic void
- Xreview_fail_list(usage)
- X void (*usage)_((void));
- X{
- X string_ty *project_name;
- X
- X trace(("review_fail_list()\n{\n"/*}*/));
- X project_name = 0;
- X arglex();
- X while (arglex_token != arglex_token_eoln)
- X {
- X switch (arglex_token)
- X {
- X default:
- X generic_argument(usage);
- X continue;
- X
- X case arglex_token_project:
- X if (arglex() != arglex_token_string)
- X usage();
- X /* fall through... */
- X
- X case arglex_token_string:
- X if (project_name)
- X fatal("duplicate -Project option");
- X project_name = str_from_c(arglex_value.alv_string);
- X break;
- X }
- X arglex();
- X }
- X list_changes_in_state_mask
- X (
- X project_name,
- X 1 << cstate_state_being_reviewed
- X );
- X if (project_name)
- X str_free(project_name);
- X trace((/*{*/"}\n"));
- X}
- X
- X
- Xstatic void repair_diff_time _((change_ty *, string_ty *));
- X
- Xstatic void
- Xrepair_diff_time(cp, path)
- X change_ty *cp;
- X string_ty *path;
- X{
- X string_ty *s;
- X cstate_src src_data;
- X string_ty *s2;
- X
- X s = os_below_dir(change_development_directory_get(cp, 1), path);
- X src_data = change_src_find(cp, s);
- X if (src_data)
- X src_data->diff_time = os_mtime(path);
- X else
- X {
- X if
- X (
- X s->str_length > 2
- X &&
- X !strcmp(s->str_text + s->str_length - 2, ",D")
- X )
- X {
- X s2 = str_n_from_c(s->str_text, s->str_length - 2);
- X src_data = change_src_find(cp, s2);
- X if (src_data)
- X src_data->diff_file_time = os_mtime(path);
- X str_free(s2);
- X }
- X }
- X str_free(s);
- X}
- X
- X
- Xstatic void rf_func _((void *, dir_walk_message_ty, string_ty *, struct stat *));
- X
- Xstatic void
- Xrf_func(arg, message, path, st)
- X void *arg;
- X dir_walk_message_ty message;
- X string_ty *path;
- X struct stat *st;
- X{
- X change_ty *cp;
- X int uid;
- X
- X trace(("rf_func(message = %d, path = %08lX, st = %08lX)\n{\n"/*}*/,
- X message, path, st));
- X cp = (change_ty *)arg;
- X trace_string(path->str_text);
- X switch (message)
- X {
- X case dir_walk_file:
- X case dir_walk_dir_before:
- X os_become_query(&uid, (int *)0, (int *)0);
- X if (st->st_uid == uid)
- X {
- X os_chmod(path, st->st_mode | 0200);
- X undo_chmod(path, st->st_mode);
- X }
- X repair_diff_time(cp, path);
- X break;
- X
- X case dir_walk_dir_after:
- X case dir_walk_special:
- X case dir_walk_symlink:
- X break;
- X }
- X trace((/*{*/"}\n"));
- X}
- X
- X
- Xstatic void review_fail_main _((void));
- X
- Xstatic void
- Xreview_fail_main()
- X{
- X string_ty *dd;
- X cstate cstate_data;
- X pstate pstate_data;
- X cstate_history history_data;
- X string_ty *comment = 0;
- X int j;
- X string_ty *project_name;
- X project_ty *pp;
- X long change_number;
- X change_ty *cp;
- X user_ty *up;
- X user_ty *devup;
- X int edit;
- X
- X trace(("review_fail_main()\n{\n"/*}*/));
- X project_name = 0;
- X change_number = 0;
- X edit = 0;
- X while (arglex_token != arglex_token_eoln)
- X {
- X switch (arglex_token)
- X {
- X default:
- X generic_argument(review_fail_usage);
- X continue;
- X
- X case arglex_token_string:
- X if (comment)
- X fatal("too many files named");
- X os_become_orig();
- X comment = read_whole_file(arglex_value.alv_string);
- X os_become_undo();
- X break;
- X
- X case arglex_token_change:
- X if (arglex() != arglex_token_number)
- X review_fail_usage();
- X /* fall through... */
- X
- X case arglex_token_number:
- X if (change_number)
- X fatal("duplicate -Change option");
- X change_number = arglex_value.alv_number;
- X if (change_number < 1)
- X fatal("change %ld out of range", change_number);
- X break;
- X
- X case arglex_token_project:
- X if (arglex() != arglex_token_string)
- X review_fail_usage();
- X if (project_name)
- X fatal("duplicate -Project option");
- X project_name = str_from_c(arglex_value.alv_string);
- X break;
- X
- X case arglex_token_edit:
- X if (edit)
- X fatal("duplicate %s option", arglex_value.alv_string);
- X edit++;
- X break;
- X }
- X arglex();
- X }
- X if (edit)
- X {
- X if (comment)
- X fatal("may not use -Edit and also name a comment file");
- X comment = os_edit_new();
- X }
- X if (!comment)
- X fatal("no comment file supplied");
- X
- X /*
- X * locate project data
- X */
- X if (!project_name)
- X project_name = user_default_project();
- X pp = project_alloc(project_name);
- X str_free(project_name);
- X project_bind_existing(pp);
- X
- X /*
- X * locate user data
- X */
- X up = user_executing(pp);
- X
- X /*
- X * locate change data
- X */
- X if (!change_number)
- X change_number = user_default_change(up);
- X cp = change_alloc(pp, change_number);
- X change_bind_existing(cp);
- X
- X /*
- X * lock the change for writing
- X */
- X project_pstate_lock_prepare(pp);
- X change_cstate_lock_prepare(cp);
- X lock_prepare_ustate_all(); /* we don't know which user until later */
- X lock_take();
- X cstate_data = change_cstate_get(cp);
- X pstate_data = project_pstate_get(pp);
- X
- X /*
- X * it is an error if the change is not in the 'being_reviewed' state.
- X */
- X if (cstate_data->state != cstate_state_being_reviewed)
- X change_fatal(cp, "not in 'being_reviewed' state");
- X if (!project_reviewer_query(pp, user_name(up)))
- X {
- X project_fatal
- X (
- X pp,
- X "user \"%S\" is not a reviewer",
- X user_name(up)
- X );
- X }
- X if
- X (
- X !pstate_data->developer_may_review
- X &&
- X str_equal(change_developer_name(cp), user_name(up))
- X )
- X change_fatal(cp, "developer may not review");
- X
- X /*
- X * change the state
- X * remember who reviewed it
- X * add to the change's history
- X */
- X cstate_data->state = cstate_state_being_developed;
- X history_data = change_history_new(cp, up);
- X history_data->what = cstate_history_what_review_fail;
- X history_data->why = comment;
- X cstate_data->build_time = 0;
- X cstate_data->test_time = 0;
- X cstate_data->test_baseline_time = 0;
- X cstate_data->regression_test_time = 0;
- X
- X /*
- X * add it back into the user's change list
- X */
- X devup = user_symbolic(pp, change_developer_name(cp));
- X user_own_add(devup, project_name_get(pp), change_number);
- X
- X /*
- X * Restore write permission to the change files
- X * and repair the diff time fields.
- X */
- X dd = change_development_directory_get(cp, 1);
- X user_become(devup);
- X dir_walk(dd, rf_func, cp);
- X os_become_undo();
- X
- X /*
- X * go through the files in the change and unlock them
- X * in the baseline
- X */
- X for (j = 0; j < cstate_data->src->length; ++j)
- X {
- X cstate_src c_src_data;
- X pstate_src p_src_data;
- X
- X c_src_data = cstate_data->src->list[j];
- X p_src_data = project_src_find(pp, c_src_data->file_name);
- X if (!p_src_data)
- X continue;
- X p_src_data->locked_by = 0;
- X
- X /*
- X * Remove the file if it is about_to_be_created
- X * by the change we are rescinding.
- X */
- X if (p_src_data->about_to_be_created_by)
- X {
- X assert(p_src_data->about_to_be_created_by == change_number);
- X project_src_remove(pp, c_src_data->file_name);
- X }
- X }
- X
- X /*
- X * write out the data and release the locks
- X */
- X project_pstate_write(pp);
- X change_cstate_write(cp);
- X user_ustate_write(devup);
- X commit();
- X lock_release();
- X
- X /*
- X * run the notify command
- X */
- X change_run_review_fail_notify_command(cp);
- X
- X /*
- X * verbose success message
- X */
- X change_verbose(cp, "failed review, returned to developer");
- X change_free(cp);
- X project_free(pp);
- X user_free(up);
- X user_free(devup);
- X trace((/*{*/"}\n"));
- X}
- X
- X
- Xvoid
- Xreview_fail()
- X{
- X trace(("review_fail()\n{\n"/*}*/));
- X switch (arglex())
- X {
- X default:
- X review_fail_main();
- X break;
- X
- X case arglex_token_help:
- X review_fail_help();
- X break;
- X
- X case arglex_token_list:
- X review_fail_list(review_fail_usage);
- X break;
- X }
- X trace((/*{*/"}\n"));
- X}
- END_OF_FILE
- if test 13632 -ne `wc -c <'aegis/aerf.c'`; then
- echo shar: \"'aegis/aerf.c'\" unpacked with wrong size!
- fi
- # end of 'aegis/aerf.c'
- fi
- if test -f 'aegis/aerm.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'aegis/aerm.c'\"
- else
- echo shar: Extracting \"'aegis/aerm.c'\" \(13356 characters\)
- sed "s/^X//" >'aegis/aerm.c' <<'END_OF_FILE'
- X/*
- X * aegis - project change supervisor
- X * Copyright (C) 1991, 1992, 1993 Peter Miller.
- X * All rights reserved.
- X *
- X * This program is free software; you can redistribute it and/or modify
- X * it under the terms of the GNU General Public License as published by
- X * the Free Software Foundation; either version 2 of the License, or
- X * (at your option) any later version.
- X *
- X * This program is distributed in the hope that it will be useful,
- X * but WITHOUT ANY WARRANTY; without even the implied warranty of
- X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- X * GNU General Public License for more details.
- X *
- X * You should have received a copy of the GNU General Public License
- X * along with this program; if not, write to the Free Software
- X * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- X *
- X * MANIFEST: functions to implement remove file
- X */
- X
- X#include <stdio.h>
- X#include <stdlib.h>
- X
- X#include <ael.h>
- X#include <aerm.h>
- X#include <arglex2.h>
- X#include <change.h>
- X#include <commit.h>
- X#include <error.h>
- X#include <help.h>
- X#include <lock.h>
- X#include <log.h>
- X#include <option.h>
- X#include <os.h>
- X#include <project.h>
- X#include <trace.h>
- X#include <user.h>
- X#include <word.h>
- X
- X
- X/*
- X * NAME
- X * remove_file_usage
- X *
- X * SYNOPSIS
- X * void remove_file_usage(void);
- X *
- X * DESCRIPTION
- X * The remove_file_usage function is used to
- X * tell the user how to use the 'aegis -ReMove_file' command.
- X */
- X
- Xstatic void remove_file_usage _((void));
- X
- Xstatic void
- Xremove_file_usage()
- X{
- X char *progname;
- X
- X progname = option_progname_get();
- X fprintf(stderr, "usage: %s -ReMove_file <filename>... [ <option>... ]\n", progname);
- X fprintf(stderr, " %s -ReMove_file -List [ <option>... ]\n", progname);
- X fprintf(stderr, " %s -ReMove_file -Help\n", progname);
- X quit(1);
- X}
- X
- X
- X/*
- X * NAME
- X * remove_file_help
- X *
- X * SYNOPSIS
- X * void remove_file_help(void);
- X *
- X * DESCRIPTION
- X * The remove_file_help function is used to
- X * describe the 'aegis -ReMove_file' command to the user.
- X */
- X
- Xstatic void remove_file_help _((void));
- X
- Xstatic void
- Xremove_file_help()
- X{
- X static char *text[] =
- X {
- X"NAME",
- X" %s -ReMove_file - add files to be deleted to a chasnge",
- X"",
- X"SYNOPSIS",
- X" %s -ReMove_file <filename>... [ <option>... ]",
- X" %s -ReMove_file -List [ <option>... ]",
- X" %s -ReMove_file -Help",
- X"",
- X"DESCRIPTION",
- X" The %s -ReMove_file command is used to add files to be",
- X" deleted to a change.",
- X"",
- X" The %s program will attempt to intuit the file names",
- X" intended. All file names are stored within %s as",
- X" relative to the root of the baseline directory tree. The",
- X" development directory and the integration directory are",
- X" shadows of the baseline dirdctory, and so these relative",
- X" names aply there, too. Files named on the command line",
- X" are first converted to absolute paths if necessary. They",
- X" are then compared with the baseline path, and the",
- X" development directory path, and the integration directory",
- X" path, to determine a root-relative name. It is an error",
- X" if the file named is outside one of these directory",
- X" trees.",
- X"",
- X" The file will be added to the list of files in the",
- X" change, and will be remoed from the baseline at",
- X" integration time.",
- X"",
- X"OPTIONS",
- X" The following options are understood:",
- X"",
- X" -Change <number>",
- X" This option may be used to specify a particular",
- X" change within a project. When no -Change option is",
- X" specified, the AEGIS_CHANGE environment variable is",
- X" consulted. If that does not exist, the user's",
- X" $HOME/.aegisrc file is examined for a default change",
- X" field (see aeuconf(5) for more information). If",
- X" that does not exist, when the user is only working",
- X" on one change within a project, that is the default",
- X" change number. Otherwise, it is an error.",
- X"",
- X" -Help",
- X" This option may be used to obtain more",
- X" information about how to use the %s program.",
- X"",
- X" -List",
- X" This option may be used to obtain a list of",
- X" suitable subjects for this command. The list may",
- X" be more general than expected.",
- X"",
- X" -Project <name>",
- X" This option may be used to select the project of",
- X" interest. When no -Project option is specified, the",
- X" AEGIS_PROJECT environment variable is consulted. If",
- X" that does not exist, the user's $HOME/.aegisrc file",
- X" is examined for a default project field (see",
- X" aeuconf(5) for more information). If that does not",
- X" exist, when the user is only working on changes",
- X" within a single project, the project name defaults",
- X" to that project. Otherwise, it is an error.",
- X"",
- X" -TERse",
- X" This option may be used to cause listings to",
- X" produce the bare minimum of information. It is",
- X" usually useful for shell scripts.",
- X"",
- X" -Verbose",
- X" This option may be used to cause %s to produce",
- X" more output. By default %s only produces",
- X" output on errors. When used with the -List",
- X" option this option causes column headings to be",
- X" added.",
- X"",
- X" All options may be abbreviated; the abbreviation is",
- X" documented as the upper case letters, all lower case",
- X" letters and underscores (_) are optional. You must use",
- X" consecutive sequences of optional letters.",
- X"",
- X" All options are case insensitive, you may type them in",
- X" upper case or lower case or a combination of both, case",
- X" is not important.",
- X"",
- X" For example: the arguments \"-project, \"-PROJ\" and \"-p\"",
- X" are all interpreted to mean the -Project option. The",
- X" argument \"-prj\" will not be understood, because",
- X" consecutive optional characters were not supplied.",
- X"",
- X" Options and other command line arguments may be mixed",
- X" arbitrarily on the command line, after the function",
- X" selectors.",
- X"",
- X" The GNU long option names are understood. Since all",
- X" option names for aegis are long, this means ignoring the",
- X" extra leading '-'. The \"--option=value\" convention is",
- X" also understood.",
- X"",
- X"RECOMMENDED ALIAS",
- X" The recommended alias for this command is",
- X" csh%% alias aerm '%s -rm \\!* -v'",
- X" sh$ aerm(){%s -rm $* -v}",
- X"",
- X"ERRORS",
- X" It is an error if the change is not in the",
- X" 'being_developed' state.",
- X" It is an error if the change is not assigned to the",
- X" current user.",
- X" It is an error if the filesa does not exist in the",
- X" baseline.",
- X" It is an error if the file is already part of the change.",
- X"",
- X"EXIT STATUS",
- X" The %s command will exit with a status of 1 on any",
- X" error. The %s command will only exit with a status of",
- X" 0 if there are no errors.",
- X"",
- X"COPYRIGHT",
- X" %C",
- X"",
- X"AUTHOR",
- X" %A",
- X };
- X
- X help(text, SIZEOF(text), remove_file_usage);
- X}
- X
- X
- X/*
- X * NAME
- X * remove_file_list
- X *
- X * SYNOPSIS
- X * void remove_file_list(void);
- X *
- X * DESCRIPTION
- X * The remove_file_list function is used to
- X * list the file the user may wish to add to the change
- X * as a deletion. All project files are listed.
- X */
- X
- Xstatic void remove_file_list _((void));
- X
- Xstatic void
- Xremove_file_list()
- X{
- X string_ty *project_name;
- X long change_number;
- X
- X trace(("remove_file_list()\n{\n"/*}*/));
- X project_name = 0;
- X change_number = 0;
- X arglex();
- X while (arglex_token != arglex_token_eoln)
- X {
- X switch (arglex_token)
- X {
- X default:
- X generic_argument(remove_file_usage);
- X continue;
- X
- X case arglex_token_change:
- X if (arglex() != arglex_token_number)
- X remove_file_usage();
- X /* fall through... */
- X
- X case arglex_token_number:
- X if (change_number)
- X fatal("duplicate -Change option");
- X change_number = arglex_value.alv_number;
- X if (change_number < 1)
- X fatal("change %ld out of range", change_number);
- X break;
- X
- X case arglex_token_project:
- X if (arglex() != arglex_token_string)
- X remove_file_usage();
- X if (project_name)
- X fatal("duplicate -Project option");
- X project_name = str_from_c(arglex_value.alv_string);
- X break;
- X }
- X arglex();
- X }
- X list_project_files(project_name, change_number);
- X if (project_name)
- X str_free(project_name);
- X trace((/*{*/"}\n"));
- X}
- X
- X
- X/*
- X * NAME
- X * remove_file_main
- X *
- X * SYNOPSIS
- X * void remove_file_main(void);
- X *
- X * DESCRIPTION
- X * The remove_file_main function is used to
- X * add a file to a change as a deletion.
- X * The file will be deleted from the baseline on successful
- X * integration of the change.
- X *
- X * The names of the relevant files are gleaned from the command line.
- X */
- X
- Xstatic void remove_file_main _((void));
- X
- Xstatic void
- Xremove_file_main()
- X{
- X wlist wl;
- X string_ty *s1;
- X string_ty *s2;
- X cstate cstate_data;
- X cstate_src c_src_data;
- X pstate_src p_src_data;
- X int j;
- X pconf pconf_data;
- X pstate pstate_data;
- X string_ty *project_name;
- X project_ty *pp;
- X long change_number;
- X change_ty *cp;
- X int nolog;
- X user_ty *up;
- X string_ty *dd;
- X string_ty *bl;
- X
- X trace(("remove_file_main()\n{\n"/*}*/));
- X project_name = 0;
- X change_number = 0;
- X wl_zero(&wl);
- X nolog = 0;
- X while (arglex_token != arglex_token_eoln)
- X {
- X switch (arglex_token)
- X {
- X default:
- X generic_argument(remove_file_usage);
- X continue;
- X
- X case arglex_token_string:
- X s1 = str_from_c(arglex_value.alv_string);
- X os_become_orig();
- X s2 = os_pathname(s1, 1);
- X os_become_undo();
- X if (wl_member(&wl, s2))
- X fatal("file \"%s\" named more than once", arglex_value.alv_string);
- X wl_append(&wl, s2);
- X str_free(s2);
- X str_free(s1);
- X break;
- X
- X case arglex_token_change:
- X if (arglex() != arglex_token_number)
- X remove_file_usage();
- X /* fall through... */
- X
- X case arglex_token_number:
- X if (change_number)
- X fatal("duplicate -Change option");
- X change_number = arglex_value.alv_number;
- X if (change_number < 1)
- X fatal("change %ld out of range", change_number);
- X break;
- X
- X case arglex_token_project:
- X if (arglex() != arglex_token_string)
- X remove_file_usage();
- X if (project_name)
- X fatal("duplicate -Project option");
- X project_name = str_from_c(arglex_value.alv_string);
- X break;
- X
- X case arglex_token_nolog:
- X if (nolog)
- X fatal("duplicate %s option", arglex_value.alv_string);
- X nolog = 1;
- X break;
- X }
- X arglex();
- X }
- X if (!wl.wl_nwords)
- X fatal("no files specified");
- X
- X /*
- X * locate project data
- X */
- X if (!project_name)
- X project_name = user_default_project();
- X pp = project_alloc(project_name);
- X str_free(project_name);
- X project_bind_existing(pp);
- X
- X /*
- X * locate user data
- X */
- X up = user_executing(pp);
- X
- X /*
- X * locate change data
- X */
- X if (!change_number)
- X change_number = user_default_change(up);
- X cp = change_alloc(pp, change_number);
- X change_bind_existing(cp);
- X
- X /*
- X * take the locks and read the change state
- X */
- X change_cstate_lock_prepare(cp);
- X lock_take();
- X cstate_data = change_cstate_get(cp);
- X pconf_data = change_pconf_get(cp);
- X pstate_data = project_pstate_get(pp);
- X
- X /*
- X * It is an error if the change is not in the in_development state.
- X * It is an error if the change is not assigned to the current user.
- X */
- X if (cstate_data->state != cstate_state_being_developed)
- X change_fatal(cp, "not in 'being_developed' state");
- X if (!str_equal(change_developer_name(cp), user_name(up)))
- X {
- X change_fatal
- X (
- X cp,
- X "user \"%S\" is not the developer",
- X user_name(up)
- X );
- X }
- X
- X /*
- X * resolve the path of each file
- X * 1. the absolute path of the file name is obtained
- X * 2. if the file is inside the development directory, ok
- X * 3. if the file is inside the baseline, ok
- X * 4. if neither, error
- X */
- X dd = change_development_directory_get(cp, 1);
- X bl = project_baseline_path_get(pp, 1);
- X for (j = 0; j < wl.wl_nwords; ++j)
- X {
- X s1 = wl.wl_word[j];
- X assert(s1->str_text[0] == '/');
- X s2 = os_below_dir(dd, s1);
- X if (!s2)
- X s2 = os_below_dir(bl, s1);
- X if (!s2)
- X change_fatal(cp, "path \"%S\" unrelated", s1);
- X str_free(s1);
- X wl.wl_word[j] = s2;
- X }
- X
- X /*
- X * ensure that each file
- X * 1. is not already part of the change
- X * 2. is in the baseline
- X * add it to the change
- X */
- X for (j = 0; j < wl.wl_nwords; ++j)
- X {
- X s1 = wl.wl_word[j];
- X if (change_src_find(cp, s1))
- X change_fatal(cp, "file \"%S\" already in change", s1);
- X p_src_data = project_src_find(pp, s1);
- X if (!p_src_data || p_src_data->deleted_by)
- X project_fatal(pp, "file \"%S\" does not exist", s1);
- X c_src_data = change_src_new(cp);
- X c_src_data->file_name = str_copy(s1);
- X c_src_data->action = file_action_remove;
- X c_src_data->usage = p_src_data->usage;
- X c_src_data->edit_number = str_copy(p_src_data->edit_number);
- X }
- X
- X /*
- X * the number of files changed, or the version did,
- X * so stomp on the validation fields.
- X */
- X cstate_data->build_time = 0;
- X cstate_data->test_time = 0;
- X cstate_data->test_baseline_time = 0;
- X cstate_data->regression_test_time = 0;
- X
- X /*
- X * write the data and release the lock
- X */
- X change_cstate_write(cp);
- X commit();
- X lock_release();
- X
- X /*
- X * run the change file command
- X */
- X if (!nolog)
- X log_open(change_logfile_get(cp), up);
- X change_run_change_file_command(cp, &wl, up);
- X
- X /*
- X * verbose success message
- X */
- X for (j = 0; j < wl.wl_nwords; ++j)
- X change_verbose(cp, "file \"%S\" remove file", wl.wl_word[j]);
- X wl_free(&wl);
- X change_free(cp);
- X project_free(pp);
- X user_free(up);
- X trace((/*{*/"}\n"));
- X}
- X
- X
- X/*
- X * NAME
- X * remove_file
- X *
- X * SYNOPSIS
- X * void remove_file(void);
- X *
- X * DESCRIPTION
- X * The remove_file function is used to
- X * dispatch the 'aegis -ReMove_file' command to the relevant
- X * function to do it's work.
- X */
- X
- Xvoid
- Xremove_file()
- X{
- X trace(("remove_file()\n{\n"/*}*/));
- X switch (arglex())
- X {
- X default:
- X remove_file_main();
- X break;
- X
- X case arglex_token_help:
- X remove_file_help();
- X break;
- X
- X case arglex_token_list:
- X remove_file_list();
- X break;
- X }
- X trace((/*{*/"}\n"));
- X}
- END_OF_FILE
- if test 13356 -ne `wc -c <'aegis/aerm.c'`; then
- echo shar: \"'aegis/aerm.c'\" unpacked with wrong size!
- fi
- # end of 'aegis/aerm.c'
- fi
- if test -f 'aegis/aermu.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'aegis/aermu.c'\"
- else
- echo shar: Extracting \"'aegis/aermu.c'\" \(13459 characters\)
- sed "s/^X//" >'aegis/aermu.c' <<'END_OF_FILE'
- X/*
- X * aegis - project change supervisor
- X * Copyright (C) 1991, 1992, 1993 Peter Miller.
- X * All rights reserved.
- X *
- X * This program is free software; you can redistribute it and/or modify
- X * it under the terms of the GNU General Public License as published by
- X * the Free Software Foundation; either version 2 of the License, or
- X * (at your option) any later version.
- X *
- X * This program is distributed in the hope that it will be useful,
- X * but WITHOUT ANY WARRANTY; without even the implied warranty of
- X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- X * GNU General Public License for more details.
- X *
- X * You should have received a copy of the GNU General Public License
- X * along with this program; if not, write to the Free Software
- X * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- X *
- X * MANIFEST: functions to implement remove file undo
- X */
- X
- X#include <stdio.h>
- X#include <stdlib.h>
- X
- X#include <ael.h>
- X#include <aermu.h>
- X#include <arglex2.h>
- X#include <change.h>
- X#include <commit.h>
- X#include <error.h>
- X#include <help.h>
- X#include <lock.h>
- X#include <log.h>
- X#include <option.h>
- X#include <os.h>
- X#include <project.h>
- X#include <trace.h>
- X#include <user.h>
- X#include <word.h>
- X
- X
- X/*
- X * NAME
- X * remove_file_undo_usage
- X *
- X * SYNOPSIS
- X * void remove_file_undo_usage(void);
- X *
- X * DESCRIPTION
- X * The remove_file_undo_usage function is used to
- X * tell the user how to use the 'aegis -ReMove_file_Undo' command.
- X */
- X
- Xstatic void remove_file_undo_usage _((void));
- X
- Xstatic void
- Xremove_file_undo_usage()
- X{
- X char *progname;
- X
- X progname = option_progname_get();
- X fprintf(stderr, "usage: %s -ReMove_file_Undo <filename>... [ <option>... ]\n", progname);
- X fprintf(stderr, " %s -ReMove_file_Undo -List [ <option>... ]\n", progname);
- X fprintf(stderr, " %s -ReMove_file_Undo -Help\n", progname);
- X quit(1);
- X}
- X
- X
- X/*
- X * NAME
- X * remove_file_undo_help
- X *
- X * SYNOPSIS
- X * void remove_file_undo_help(void);
- X *
- X * DESCRIPTION
- X * The remove_file_undo_help function is used to
- X * describe the 'aegis -ReMove_file_undo' command to the user.
- X */
- X
- Xstatic void remove_file_undo_help _((void));
- X
- Xstatic void
- Xremove_file_undo_help()
- X{
- X static char *text[] =
- X {
- X"NAME",
- X" %s -ReMove_file_Undo - remove files to be deleted from",
- X" a change.",
- X"",
- X"SYNOPSIS",
- X" %s -ReMove_file_Undo <filename>... [ <option>... ]",
- X" %s -ReMove_file_Undo -List [ <option>... ]",
- X" %s -ReMove_file_Undo -Help",
- X"",
- X"DESCRIPTION",
- X" The %s -ReMove_file_Undo command is used to remove",
- X" filesa to be deleted from a change.",
- X"",
- X" The %s program will attempt to intuit the file names",
- X" intended. All file names are stored within %s as",
- X" relative to the root of the baseline directory tree. The",
- X" development directory and the integration directory are",
- X" shadows of the baseline dirdctory, and so these relative",
- X" names aply there, too. Files named on the command line",
- X" are first converted to absolute paths if necessary. They",
- X" are then compared with the baseline path, and the",
- X" development directory path, and the integration directory",
- X" path, to determine a root-relative name. It is an error",
- X" if the file named is outside one of these directory",
- X" trees.",
- X"",
- X" The files is removed from the list of files in the",
- X" change.",
- X"",
- X"OPTIONS",
- X" The following options are understood:",
- X"",
- X" -Change <number>",
- X" This option may be used to specify a particular",
- X" change within a project. When no -Change option is",
- X" specified, the AEGIS_CHANGE environment variable is",
- X" consulted. If that does not exist, the user's",
- X" $HOME/.aegisrc file is examined for a default change",
- X" field (see aeuconf(5) for more information). If",
- X" that does not exist, when the user is only working",
- X" on one change within a project, that is the default",
- X" change number. Otherwise, it is an error.",
- X"",
- X" -Help",
- X" This option may be used to obtain more",
- X" information about how to use the %s program.",
- X"",
- X" -List",
- X" This option may be used to obtain a list of",
- X" suitable subjects for this command. The list may",
- X" be more general than expected.",
- X"",
- X" -Project <name>",
- X" This option may be used to select the project of",
- X" interest. When no -Project option is specified, the",
- X" AEGIS_PROJECT environment variable is consulted. If",
- X" that does not exist, the user's $HOME/.aegisrc file",
- X" is examined for a default project field (see",
- X" aeuconf(5) for more information). If that does not",
- X" exist, when the user is only working on changes",
- X" within a single project, the project name defaults",
- X" to that project. Otherwise, it is an error.",
- X"",
- X" -TERse",
- X" This option may be used to cause listings to",
- X" produce the bare minimum of information. It is",
- X" usually useful for shell scripts.",
- X"",
- X" -Verbose",
- X" This option may be used to cause %s to produce",
- X" more output. By default %s only produces",
- X" output on errors. When used with the -List",
- X" option this option causes column headings to be",
- X" added.",
- X"",
- X" All options may be abbreviated; the abbreviation is",
- X" documented as the upper case letters, all lower case",
- X" letters and underscores (_) are optional. You must use",
- X" consecutive sequences of optional letters.",
- X"",
- X" All options are case insensitive, you may type them in",
- X" upper case or lower case or a combination of both, case",
- X" is not important.",
- X"",
- X" For example: the arguments \"-project, \"-PROJ\" and \"-p\"",
- X" are all interpreted to mean the -Project option. The",
- X" argument \"-prj\" will not be understood, because",
- X" consecutive optional characters were not supplied.",
- X"",
- X" Options and other command line arguments may be mixed",
- X" arbitrarily on the command line, after the function",
- X" selectors.",
- X"",
- X" The GNU long option names are understood. Since all",
- X" option names for aegis are long, this means ignoring the",
- X" extra leading '-'. The \"--option=value\" convention is",
- X" also understood.",
- X"",
- X"RECOMMENDED ALIAS",
- X" The recommended alias for this command is",
- X" csh%% alias aermu '%s -rmu \\!* -v'",
- X" sh$ aermu(){%s -rmu $* -v}",
- X"",
- X"ERRORS",
- X" It is an error if the change is not in the",
- X" 'being_developed' state.",
- X" It is an error if the change is not assigned to the",
- X" current user.",
- X" It is an error if the file is not in the change.",
- X" It is an error if the was not added to the change using",
- X" the %s -ReMove_file command.",
- X"",
- X"EXIT STATUS",
- X" The %s command will exit with a status of 1 on any",
- X" error. The %s command will only exit with a status of",
- X" 0 if there are no errors.",
- X"",
- X"COPYRIGHT",
- X" %C",
- X"",
- X"AUTHOR",
- X" %A",
- X };
- X
- X help(text, SIZEOF(text), remove_file_undo_usage);
- X}
- X
- X
- X/*
- X * NAME
- X * remove_file_undo_list
- X *
- X * SYNOPSIS
- X * void remove_file_undo_list(void);
- X *
- X * DESCRIPTION
- X * The remove_file_undo_list function is used to
- X * list the file the user may wish to remove from the change
- X * as a deletion. All relevant change files are listed.
- X */
- X
- Xstatic void remove_file_undo_list _((void));
- X
- Xstatic void
- Xremove_file_undo_list()
- X{
- X string_ty *project_name;
- X long change_number;
- X
- X trace(("remove_file_undo_list()\n{\n"/*}*/));
- X project_name = 0;
- X change_number = 0;
- X arglex();
- X while (arglex_token != arglex_token_eoln)
- X {
- X switch (arglex_token)
- X {
- X default:
- X generic_argument(remove_file_undo_usage);
- X continue;
- X
- X case arglex_token_change:
- X if (arglex() != arglex_token_number)
- X remove_file_undo_usage();
- X /* fall through... */
- X
- X case arglex_token_number:
- X if (change_number)
- X fatal("duplicate -Change option");
- X change_number = arglex_value.alv_number;
- X if (change_number < 1)
- X fatal("change %ld out of range", change_number);
- X break;
- X
- X case arglex_token_project:
- X if (arglex() != arglex_token_string)
- X remove_file_undo_usage();
- X if (project_name)
- X fatal("duplicate -Project option");
- X project_name = str_from_c(arglex_value.alv_string);
- X break;
- X }
- X arglex();
- X }
- X list_change_files(project_name, change_number);
- X if (project_name)
- X str_free(project_name);
- X trace((/*{*/"}\n"));
- X}
- X
- X
- X/*
- X * NAME
- X * remove_undo_main
- X *
- X * SYNOPSIS
- X * void remove_undo_main(void);
- X *
- X * DESCRIPTION
- X * The remove_undo_main function is used to
- X * remove a file from a change as a deletion.
- X *
- X * The names of the relevant files are gleaned from the command line.
- X */
- X
- Xstatic void remove_file_undo_main _((void));
- X
- Xstatic void
- Xremove_file_undo_main()
- X{
- X wlist wl;
- X string_ty *s1;
- X string_ty *s2;
- X int j;
- X cstate cstate_data;
- X pconf pconf_data;
- X pstate pstate_data;
- X string_ty *project_name;
- X project_ty *pp;
- X long change_number;
- X change_ty *cp;
- X int nolog;
- X user_ty *up;
- X string_ty *dd;
- X string_ty *bl;
- X
- X trace(("remove_file_undo_main()\n{\n"/*}*/));
- X project_name = 0;
- X change_number = 0;
- X wl_zero(&wl);
- X nolog = 0;
- X while (arglex_token != arglex_token_eoln)
- X {
- X switch (arglex_token)
- X {
- X default:
- X generic_argument(remove_file_undo_usage);
- X continue;
- X
- X case arglex_token_string:
- X s1 = str_from_c(arglex_value.alv_string);
- X os_become_orig();
- X s2 = os_pathname(s1, 1);
- X os_become_undo();
- X if (wl_member(&wl, s2))
- X fatal("file \"%s\" named more than once", arglex_value.alv_string);
- X wl_append(&wl, s2);
- X str_free(s2);
- X str_free(s1);
- X break;
- X
- X case arglex_token_change:
- X if (arglex() != arglex_token_number)
- X remove_file_undo_usage();
- X /* fall through... */
- X
- X case arglex_token_number:
- X if (change_number)
- X fatal("duplicate -Change option");
- X change_number = arglex_value.alv_number;
- X if (change_number < 1)
- X fatal("change %ld out of range", change_number);
- X break;
- X
- X case arglex_token_project:
- X if (arglex() != arglex_token_string)
- X remove_file_undo_usage();
- X if (project_name)
- X fatal("duplicate -Project option");
- X project_name = str_from_c(arglex_value.alv_string);
- X break;
- X
- X case arglex_token_nolog:
- X if (nolog)
- X fatal("duplicate %s option", arglex_value.alv_string);
- X nolog = 1;
- X break;
- X }
- X arglex();
- X }
- X if (!wl.wl_nwords)
- X fatal("no files specified");
- X
- X /*
- X * locate project data
- X */
- X if (!project_name)
- X project_name = user_default_project();
- X pp = project_alloc(project_name);
- X str_free(project_name);
- X project_bind_existing(pp);
- X
- X /*
- X * locate user data
- X */
- X up = user_executing(pp);
- X
- X /*
- X * locate change data
- X */
- X if (!change_number)
- X change_number = user_default_change(up);
- X cp = change_alloc(pp, change_number);
- X change_bind_existing(cp);
- X
- X /*
- X * take the locks and read the change state
- X */
- X change_cstate_lock_prepare(cp);
- X lock_take();
- X pstate_data = project_pstate_get(pp);
- X cstate_data = change_cstate_get(cp);
- X pconf_data = change_pconf_get(cp);
- X
- X /*
- X * It is an error if the change is not in the in_development state.
- X * It is an error if the change is not assigned to the current user.
- X */
- X if (cstate_data->state != cstate_state_being_developed)
- X change_fatal(cp, "not in 'being_developed' state");
- X if (!str_equal(change_developer_name(cp), user_name(up)))
- X {
- X change_fatal
- X (
- X cp,
- X "user \"%S\" is not the developer",
- X user_name(up)
- X );
- X }
- X
- X /*
- X * resolve the path of each file
- X * 1. the absolute path of the file name is obtained
- X * 2. if the file is inside the development directory, ok
- X * 3. if the file is inside the baseline, ok
- X * 4. if neither, error
- X */
- X dd = change_development_directory_get(cp, 1);
- X bl = project_baseline_path_get(pp, 1);
- X for (j = 0; j < wl.wl_nwords; ++j)
- X {
- X s1 = wl.wl_word[j];
- X assert(s1->str_text[0] == '/');
- X s2 = os_below_dir(dd, s1);
- X if (!s2)
- X s2 = os_below_dir(bl, s1);
- X if (!s2)
- X change_fatal(cp, "path \"%S\" unrelated", s1);
- X str_free(s1);
- X wl.wl_word[j] = s2;
- X }
- X
- X /*
- X * ensure that each file is part of the change
- X */
- X for (j = 0; j < wl.wl_nwords; ++j)
- X {
- X cstate_src c_src_data;
- X
- X s1 = wl.wl_word[j];
- X c_src_data = change_src_find(cp, s1);
- X if (!c_src_data)
- X change_fatal(cp, "file \"%S\" not in change", s1);
- X if (c_src_data->action != file_action_remove)
- X change_fatal(cp, "file \"%S\" not -ReMove_file", s1);
- X change_src_remove(cp, s1);
- X }
- X
- X /*
- X * Remove the difference files,
- X * if they exist.
- X */
- X user_become(up);
- X for (j = 0; j < wl.wl_nwords; ++j)
- X {
- X s1 = wl.wl_word[j];
- X s2 = str_format("%S/%S,D", dd, s1);
- X if (os_exists(s2))
- X commit_unlink_errok(s2);
- X str_free(s2);
- X }
- X os_become_undo();
- X
- X /*
- X * the number of files changed, or the version did,
- X * so stomp on the validation fields.
- X */
- X cstate_data->build_time = 0;
- X cstate_data->test_time = 0;
- X cstate_data->test_baseline_time = 0;
- X cstate_data->regression_test_time = 0;
- X
- X /*
- X * write the data and release the lock
- X */
- X change_cstate_write(cp);
- X commit();
- X lock_release();
- X
- X /*
- X * run the change file command
- X */
- X if (!nolog)
- X log_open(change_logfile_get(cp), up);
- X change_run_change_file_command(cp, &wl, up);
- X
- X /*
- X * verbose success message
- X */
- X for (j = 0; j < wl.wl_nwords; ++j)
- X change_verbose(cp, "file \"%S\" remove file undo", wl.wl_word[j]);
- X wl_free(&wl);
- X change_free(cp);
- X project_free(pp);
- X user_free(up);
- X trace((/*{*/"}\n"));
- X}
- X
- X
- X/*
- X * NAME
- X * remove_file_undo
- X *
- X * SYNOPSIS
- X * void remove_file_undo(void);
- X *
- X * DESCRIPTION
- X * The remove_file_undo function is used to
- X * dispatch the 'aegis -ReMove_file_Undo' command to the relevant
- X * function to do it's work.
- X */
- X
- Xvoid
- Xremove_file_undo()
- X{
- X trace(("remove_file_undo()\n{\n"/*}*/));
- X switch (arglex())
- X {
- X default:
- X remove_file_undo_main();
- X break;
- X
- X case arglex_token_help:
- X remove_file_undo_help();
- X break;
- X
- X case arglex_token_list:
- X remove_file_undo_list();
- X break;
- X }
- X trace((/*{*/"}\n"));
- X}
- END_OF_FILE
- if test 13459 -ne `wc -c <'aegis/aermu.c'`; then
- echo shar: \"'aegis/aermu.c'\" unpacked with wrong size!
- fi
- # end of 'aegis/aermu.c'
- fi
- if test -f 'aegis/lock.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'aegis/lock.c'\"
- else
- echo shar: Extracting \"'aegis/lock.c'\" \(14304 characters\)
- sed "s/^X//" >'aegis/lock.c' <<'END_OF_FILE'
- X/*
- X * aegis - project change supervisor
- X * Copyright (C) 1991, 1992, 1993 Peter Miller.
- X * All rights reserved.
- X *
- X * This program is free software; you can redistribute it and/or modify
- X * it under the terms of the GNU General Public License as published by
- X * the Free Software Foundation; either version 2 of the License, or
- X * (at your option) any later version.
- X *
- X * This program is distributed in the hope that it will be useful,
- X * but WITHOUT ANY WARRANTY; without even the implied warranty of
- X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- X * GNU General Public License for more details.
- X *
- X * You should have received a copy of the GNU General Public License
- X * along with this program; if not, write to the Free Software
- X * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- X *
- X * MANIFEST: functions to lock aegis' data
- X */
- X
- X#include <errno.h>
- X#include <fcntl.h>
- X#include <stdio.h>
- X#include <unistd.h>
- X#include <string.h>
- X#include <signal.h>
- X
- X#include <error.h>
- X#include <glue.h>
- X#include <gonzo.h>
- X#include <lock.h>
- X#include <mem.h>
- X#include <os.h>
- X#include <trace.h>
- X
- X
- X/*
- X * how many bits of the hash to use in the mux
- X */
- X#define BITS 16
- X#define BITS_SIZE (1L << BITS)
- X#define BITS_MASK (BITS_SIZE - 1)
- X
- Xenum lock_ty
- X{
- X lock_master,
- X lock_gstate,
- X lock_MAX
- X};
- Xtypedef enum lock_ty lock_ty;
- X
- Xenum lock_mux_ty
- X{
- X lock_mux_ustate,
- X lock_mux_pstate,
- X lock_mux_cstate,
- X lock_mux_build,
- X lock_mux_MAX
- X};
- Xtypedef enum lock_mux_ty lock_mux_ty;
- X
- X
- Xstatic string_ty *path;
- Xstatic size_t nplaces;
- Xstatic struct flock *place;
- Xstatic int fd = -1;
- Xstatic long magic;
- Xstatic int quitregd;
- X
- X
- Xstatic void flock_construct _((struct flock *, int type, long start,
- X long length));
- X
- Xstatic void
- Xflock_construct(p, type, start, length)
- X struct flock *p;
- X int type;
- X long start;
- X long length;
- X{
- X /*
- X * the memset is here because some systems have
- X * extra fields in the flock structure.
- X * These fields are frequently undocumented,
- X * and yet these systems give "EINVAL" if the
- X * undocumented fields are not zero!
- X */
- X memset(p, 0, sizeof(*p));
- X
- X assert(start >= 0);
- X assert(length > 0);
- X p->l_type = type;
- X p->l_whence = SEEK_SET;
- X p->l_start = start;
- X p->l_len = length;
- X p->l_pid = 0;
- X}
- X
- X
- Xstatic void lock_prepare _((long, long, int));
- X
- Xstatic void
- Xlock_prepare(start, length, exclusive)
- X long start;
- X long length;
- X int exclusive;
- X{
- X struct flock p;
- X
- X trace(("lock_prepare(start = %ld, length = %ld, excl = %d)\n{\n"/*}*/,
- X start, length, exclusive));
- X assert(start > lock_master);
- X assert(length > 0);
- X flock_construct(&p, (exclusive ? F_WRLCK : F_RDLCK), start, length);
- X *(struct flock *)
- X enlarge(&nplaces, (char **)&place, sizeof(struct flock)) =
- X p;
- X trace((/*{*/"}\n"));
- X}
- X
- X
- Xvoid
- Xlock_prepare_gstate()
- X{
- X trace(("lock_prepare_gstate()\n{\n"/*}*/));
- X lock_prepare((long)lock_gstate, 1L, 1);
- X trace((/*{*/"}\n"));
- X}
- X
- X
- Xstatic void lock_prepare_mux _((lock_mux_ty, long, int));
- X
- Xstatic void
- Xlock_prepare_mux(lock_mux, n, exclusive)
- X lock_mux_ty lock_mux;
- X long n;
- X int exclusive;
- X{
- X trace(("lock_prepare_mux(lock_mux = %d, n = %ld, excl = %d)\n{\n"/*}*/,
- X lock_mux, n, exclusive));
- X lock_prepare
- X (
- X ((lock_mux + 1L) << BITS) + (n & BITS_MASK),
- X 1L,
- X exclusive
- X );
- X trace((/*{*/"}\n"));
- X}
- X
- X
- Xstatic void lock_prepare_mux_all _((lock_mux_ty, int));
- X
- Xstatic void
- Xlock_prepare_mux_all(lock_mux, exclusive)
- X lock_mux_ty lock_mux;
- X int exclusive;
- X{
- X trace(("lock_prepare_mux_all(lock_mux = %d)\n{\n"/*}*/, lock_mux));
- X lock_prepare(((lock_mux + 1L) << BITS), BITS_SIZE, exclusive);
- X trace((/*{*/"}\n"));
- X}
- X
- X
- Xvoid
- Xlock_prepare_pstate(s)
- X string_ty *s;
- X{
- X trace(("lock_prepare_pstate(s = \"%s\")\n{\n"/*}*/, s->str_text));
- X lock_prepare_mux(lock_mux_pstate, (long)s->str_hash, 1);
- X trace((/*{*/"}\n"));
- X}
- X
- X
- Xvoid
- Xlock_prepare_build_read(s)
- X string_ty *s;
- X{
- X trace(("lock_prepare_pstate(s = \"%s\")\n{\n"/*}*/, s->str_text));
- X lock_prepare_mux(lock_mux_build, (long)s->str_hash, 0);
- X trace((/*{*/"}\n"));
- X}
- X
- X
- Xvoid
- Xlock_prepare_build_write(s)
- X string_ty *s;
- X{
- X trace(("lock_prepare_pstate(s = \"%s\")\n{\n"/*}*/, s->str_text));
- X lock_prepare_mux(lock_mux_build, (long)s->str_hash, 1);
- X trace((/*{*/"}\n"));
- X}
- X
- X
- Xvoid
- Xlock_prepare_ustate(uid)
- X int uid;
- X{
- X trace(("lock_prepare_ustate()\n{\n"/*}*/));
- X lock_prepare_mux(lock_mux_ustate, (long)uid, 1);
- X trace((/*{*/"}\n"));
- X}
- X
- X
- Xvoid
- Xlock_prepare_ustate_all()
- X{
- X trace(("lock_prepare_ustate_all()\n{\n"/*}*/));
- X lock_prepare_mux_all(lock_mux_ustate, 1);
- X trace((/*{*/"}\n"));
- X}
- X
- X
- Xvoid
- Xlock_prepare_cstate(project_name, change_number)
- X string_ty *project_name;
- X long change_number;
- X{
- X trace(("lock_prepare_cstate(project_name = \"%s\", change_number = \
- X%ld)\n{\n"/*}*/, project_name->str_text, change_number));
- X lock_prepare_mux
- X (
- X lock_mux_cstate,
- X change_number + project_name->str_hash,
- X 1
- X );
- X trace((/*{*/"}\n"));
- X}
- X
- X
- Xstatic char *flock_type_string _((int));
- X
- Xstatic char *
- Xflock_type_string(n)
- X int n;
- X{
- X switch (n)
- X {
- X case F_RDLCK:
- X return "F_RDLCK";
- X
- X case F_WRLCK:
- X return "F_WRLCK";
- X
- X case F_UNLCK:
- X return "F_UNLCK";
- X }
- X return "unknown";
- X}
- X
- X
- Xstatic char *flock_whence_string _((int));
- X
- Xstatic char *
- Xflock_whence_string(n)
- X int n;
- X{
- X switch (n)
- X {
- X case SEEK_SET:
- X return "SEEK_SET";
- X
- X case SEEK_CUR:
- X return "SEEK_CUR";
- X
- X case SEEK_END:
- X return "SEEK_END";
- X }
- X return "unknown";
- X}
- X
- X
- Xstatic char *flock_string _((struct flock *));
- X
- Xstatic char *
- Xflock_string(p)
- X struct flock *p;
- X{
- X static char buffer[120];
- X
- X sprintf
- X (
- X buffer,
- X "&{type = %s, whence = %s, start = %ld, len = %ld, pid = %d}",
- X flock_type_string(p->l_type),
- X flock_whence_string(p->l_whence),
- X p->l_start,
- X p->l_len,
- X p->l_pid
- X );
- X return buffer;
- X}
- X
- X
- Xstatic char *lock_description _((struct flock *));
- X
- Xstatic char *
- Xlock_description(p)
- X struct flock *p;
- X{
- X switch (p->l_start)
- X {
- X case lock_master:
- X return "master";
- X
- X case lock_gstate:
- X return "global state";
- X }
- X switch ((p->l_start >> BITS) - 1)
- X {
- X case lock_mux_ustate:
- X return "user";
- X
- X case lock_mux_cstate:
- X return "change";
- X
- X case lock_mux_pstate:
- X return "project";
- X
- X case lock_mux_build:
- X return "build";
- X }
- X return "unknown";
- X}
- X
- X
- Xstatic void quitter _((int));
- X
- Xstatic void
- Xquitter(n)
- X int n;
- X{
- X if (fd >= 0)
- X {
- X while (os_become_active())
- X os_become_undo();
- X lock_release();
- X }
- X}
- X
- X
- Xvoid
- Xlock_take()
- X{
- X int flags;
- X struct flock p;
- X int j, k;
- X
- X /*
- X * get the file descriptor of the lock file
- X *
- X * If it isn't there, create it. If it is there, truncate it (prevent
- X * abuse of universally writable file).
- X */
- X trace(("lock_take()\n{\n"/*}*/));
- X assert(fd < 0);
- X assert(nplaces);
- X if (!quitregd)
- X {
- X quitregd = 1;
- X quit_register(quitter);
- X }
- X if (!path)
- X path = gonzo_lockpath_get();
- X gonzo_become();
- X fd = glue_open(path->str_text, O_RDWR | O_CREAT | O_TRUNC, 0600);
- X if (fd < 0)
- X nfatal("open(\"%s\")", path->str_text);
- X trace_int(fd);
- X
- X /*
- X * make sure the file is closed when a child exec's
- X */
- X#ifndef CONF_NO_seteuid
- X if (fcntl(fd, F_GETFD, &flags))
- X nfatal("fcntl(\"%s\", F_GETFD)", path->str_text);
- X flags |= 1;
- X if (fcntl(fd, F_SETFD, flags))
- X nfatal("fcntl(\"%s\", F_SETFD, %d)", path->str_text, flags);
- X trace(("mark\n"));
- X#endif
- X
- X /*
- X * Block for the master lock.
- X * Take the locks we really want.
- X * If we got them, release master and return.
- X * If did not get all of the locks,
- X * release the locks we could get and then the master.
- X * Block on the lock we could not get,
- X * release that lock and start again.
- X *
- X * Unfortunately, this scheme isn't fair
- X * (i.e. no guarantee of success in finite time)
- X * it would be nice if I could atomically lock (and block)
- X * an entire vector of locks. (vfcntl like berkeley's vwrite?)
- X */
- X for (;;)
- X {
- X /*
- X * get the master lock
- X * (block if necessary,
- X * it should never be held for long)
- X */
- X trace(("mark\n"));
- X flock_construct(&p, F_WRLCK, (long)lock_master, 1L);
- X if (glue_fcntl(fd, F_SETLKW, &p))
- X {
- X nfatal
- X (
- X "fcntl(\"%s\", F_SETLKW, %s)",
- X path->str_text,
- X flock_string(&p)
- X );
- X }
- X
- X /*
- X * get each of the locks we really wanted
- X */
- X for (j = 0; j < nplaces; ++j)
- X {
- X trace(("mark\n"));
- X p = place[j];
- X if (glue_fcntl(fd, F_SETLK, &p))
- X {
- X if (errno != EACCES && errno != EAGAIN)
- X {
- X nfatal
- X (
- X "fcntl(\"%s\", F_SETLK, %s)",
- X path->str_text,
- X flock_string(&p)
- X );
- X }
- X break;
- X }
- X }
- X
- X /*
- X * return if were successful.
- X */
- X if (j >= nplaces)
- X {
- X trace(("mark\n"));
- X flock_construct(&p, F_UNLCK, (long)lock_master, 1L);
- X if (glue_fcntl(fd, F_SETLKW, &p))
- X {
- X nfatal
- X (
- X "fcntl(\"%s\", F_SETLKW, %s)",
- X path->str_text,
- X flock_string(&p)
- X );
- X }
- X break;
- X }
- X
- X /*
- X * give all the locks back
- X * that we got so far
- X */
- X for (k = 0; k < j; ++k)
- X {
- X trace(("mark\n"));
- X p = place[k];
- X p.l_type = F_UNLCK;
- X if (glue_fcntl(fd, F_SETLKW, &p))
- X {
- X nfatal
- X (
- X "fcntl(\"%s\", F_SETLKW, %s)",
- X path->str_text,
- X flock_string(&p)
- X );
- X }
- X }
- X
- X /*
- X * release the master lock
- X */
- X flock_construct(&p, F_UNLCK, (long)lock_master, 1L);
- X if (glue_fcntl(fd, F_SETLKW, &p))
- X {
- X nfatal
- X (
- X "fcntl(\"%s\", F_SETLKW, %s)",
- X path->str_text,
- X flock_string(&p)
- X );
- X }
- X trace(("mark\n"));
- X
- X /*
- X * verbose message about why we are blocking
- X */
- X p = place[j];
- X verbose("waiting for %s lock", lock_description(&p));
- X
- X /*
- X * block on the lock that stopped us before
- X */
- X if (glue_fcntl(fd, F_SETLKW, &p))
- X {
- X nfatal
- X (
- X "fcntl(\"%s\", F_SETLKW, %s)",
- X path->str_text,
- X flock_string(&p)
- X );
- X }
- X
- X /*
- X * and then release it,
- X * before trying all over again.
- X */
- X p = place[j];
- X p.l_type = F_UNLCK;
- X if (glue_fcntl(fd, F_SETLKW, &p))
- X {
- X nfatal
- X (
- X "fcntl(\"%s\", F_SETLKW, %s)",
- X path->str_text,
- X flock_string(&p)
- X );
- X }
- X trace(("mark\n"));
- X }
- X gonzo_become_undo();
- X magic++;
- X trace((/*{*/"}\n"));
- X}
- X
- X
- Xvoid
- Xlock_release()
- X{
- X struct flock p;
- X int j;
- X int fildes;
- X
- X /*
- X * set the file descriptor to -1
- X * so that we will not be invoked again should
- X * a fatal error happen here.
- X */
- X trace(("lock_release()\n{\n"/*}*/));
- X trace_int(fd);
- X assert(fd >= 0);
- X assert(nplaces);
- X assert(place);
- X assert(path);
- X gonzo_become();
- X fildes = fd;
- X fd = -1;
- X
- X /*
- X * Release each of the locks.
- X * This should be unnecessary, because we then close the file,
- X * but SunOS hangs onto some of them, even after the process dies.
- X */
- X for (j = 0; j < nplaces; ++j)
- X {
- X p = place[j];
- X p.l_type = F_UNLCK;
- X if (glue_fcntl(fildes, F_SETLKW, &p))
- X {
- X nfatal
- X (
- X "fcntl(\"%s\", F_SETLKW, %s)",
- X path->str_text,
- X flock_string(&p)
- X );
- X }
- X }
- X
- X /*
- X * close the file
- X * (this *should* have been enough)
- X */
- X glue_close(fildes);
- X gonzo_become_undo();
- X nplaces = 0;
- X mem_free((char *)place);
- X place = 0;
- X trace((/*{*/"}\n"));
- X}
- X
- X
- Xlong
- Xlock_magic()
- X{
- X return magic;
- X}
- X
- X
- Xstatic void lock_walk_hunt _((long, long, lock_walk_callback));
- X
- Xstatic void
- Xlock_walk_hunt(min, max, callback)
- X long min;
- X long max;
- X lock_walk_callback callback;
- X{
- X struct flock flock;
- X int j;
- X lock_walk_found found;
- X
- X /*
- X * look for a lock in the given range
- X */
- X flock.l_type = F_WRLCK;
- X flock.l_whence = SEEK_SET;
- X flock.l_start = min;
- X flock.l_len = max - min;
- X flock.l_pid = 0;
- X gonzo_become();
- X if (glue_fcntl(fd, F_GETLK, &flock))
- X nfatal("getlock \"%s\"", path->str_text);
- X gonzo_become_undo();
- X if (flock.l_type == F_UNLCK)
- X return;
- X
- X /*
- X * aegis only uses byte locks,
- X * so multi-byte ranges are separate locks
- X */
- X for (j = 0; j < flock.l_len; ++j)
- X {
- X /*
- X * figure the name and address
- X */
- X found.address = flock.l_start + j;
- X found.subset = 0;
- X switch (found.address)
- X {
- X case lock_master:
- X found.name = lock_walk_name_master;
- X break;
- X
- X case lock_gstate:
- X found.name = lock_walk_name_gstate;
- X break;
- X
- X default:
- X switch ((found.address >> BITS) - 1)
- X {
- X case lock_mux_ustate:
- X found.name = lock_walk_name_ustate;
- X found.subset = found.address & BITS_MASK;
- X break;
- X
- X case lock_mux_pstate:
- X found.name = lock_walk_name_ustate;
- X found.subset = found.address & BITS_MASK;
- X break;
- X
- X case lock_mux_cstate:
- X found.name = lock_walk_name_cstate;
- X found.subset = found.address & BITS_MASK;
- X break;
- X
- X case lock_mux_build:
- X found.name = lock_walk_name_build;
- X found.subset = found.address & BITS_MASK;
- X break;
- X
- X default:
- X found.name = lock_walk_name_unknown;
- X break;
- X }
- X }
- X
- X /*
- X * figure the type
- X */
- X switch (flock.l_type)
- X {
- X case F_RDLCK:
- X found.type = lock_walk_type_shared;
- X break;
- X
- X case F_WRLCK:
- X found.type = lock_walk_type_exclusive;
- X break;
- X
- X default:
- X found.type = lock_walk_type_unknown;
- X break;
- X }
- X
- X /*
- X * Process holding the lock.
- X * Workout if it is local or remote.
- X */
- X found.pid = flock.l_pid;
- X if (kill(found.pid, 0))
- X {
- X switch (errno)
- X {
- X default:
- X fatal("kill(%d, 0)", found.pid);
- X
- X case EPERM:
- X found.pid_is_local = 1;
- X break;
- X
- X case ESRCH:
- X found.pid_is_local = 0;
- X break;
- X }
- X }
- X else
- X found.pid_is_local = 1;
- X
- X /*
- X * do something with it
- X */
- X callback(&found);
- X }
- X
- X /*
- X * look for more locks on either side
- X */
- X if (flock.l_start)
- X lock_walk_hunt(min, flock.l_start, callback);
- X if (flock.l_len)
- X lock_walk_hunt(flock.l_start + flock.l_len, max, callback);
- X}
- X
- X
- Xvoid
- Xlock_walk(callback)
- X lock_walk_callback callback;
- X{
- X int flags;
- X int fildes;
- X
- X trace(("lock_walk()\n{\n"/*}*/));
- X assert(fd < 0);
- X assert(!nplaces);
- X if (!quitregd)
- X {
- X quitregd = 1;
- X quit_register(quitter);
- X }
- X if (!path)
- X path = gonzo_lockpath_get();
- X gonzo_become();
- X fd = glue_open(path->str_text, O_RDWR | O_CREAT | O_TRUNC, 0600);
- X if (fd < 0)
- X nfatal("open(\"%s\")", path->str_text);
- X trace_int(fd);
- X
- X /*
- X * make sure the file is closed when a child exec's
- X */
- X#ifndef CONF_NO_seteuid
- X if (fcntl(fd, F_GETFD, &flags))
- X nfatal("fcntl(\"%s\", F_GETFD)", path->str_text);
- X flags |= 1;
- X if (fcntl(fd, F_SETFD, flags))
- X nfatal("fcntl(\"%s\", F_SETFD, %d)", path->str_text, flags);
- X trace(("mark\n"));
- X#endif
- X gonzo_become_undo();
- X
- X /*
- X * chase all of the locks
- X */
- X lock_walk_hunt(0L, ((lock_mux_MAX + 1) << BITS), callback);
- X
- X /*
- X * close the file
- X */
- X gonzo_become();
- X trace_int(fd);
- X assert(fd >= 0);
- X assert(path);
- X fildes = fd;
- X fd = -1;
- X glue_close(fildes);
- X gonzo_become_undo();
- X trace((/*{*/"}\n"));
- X}
- END_OF_FILE
- if test 14304 -ne `wc -c <'aegis/lock.c'`; then
- echo shar: \"'aegis/lock.c'\" unpacked with wrong size!
- fi
- # end of 'aegis/lock.c'
- fi
- if test -f 'aux/CHANGES.1.1' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'aux/CHANGES.1.1'\"
- else
- echo shar: Extracting \"'aux/CHANGES.1.1'\" \(12490 characters\)
- sed "s/^X//" >'aux/CHANGES.1.1' <<'END_OF_FILE'
- XChange State Description
- X------- ------- -------------
- X1 completed New release derived from aegis.
- X2 completed generated Makefile with absolute dependencies
- X3 being_ the project does not yet make
- X integrated
- X
- XIDENTIFICATION
- X Project "aegis.1.1", change 1.
- X
- XSUMMARY
- X New release derived from aegis.
- X
- XDESCRIPTION
- X New release derived from aegis.
- X
- XCAUSE
- X internal_enhancement
- X
- XFILES
- X Type Action Edit File Name
- X ------- ------- ------- -----------
- X source create 1 ALPHA.NOTICE
- X source create 1 BUILDING
- X source create 1 CHANGES.sh
- X source create 1 COPYING
- X source create 1 Howto.cook
- X source create 1 Makefile.awk
- X source create 1 Makefile.sh
- X source create 1 README
- X source create 1 aegis/administ.c
- X source create 1 aegis/administ.h
- X source create 1 aegis/ansi.c
- X source create 1 aegis/archaeol.c
- X source create 1 aegis/archaeol.h
- X source create 1 aegis/arglex.c
- X source create 1 aegis/arglex.h
- X source create 1 aegis/build.c
- X source create 1 aegis/build.h
- X source create 1 aegis/cattr.def
- X source create 1 aegis/cattr_ed.c
- X source create 1 aegis/cattr_ed.h
- X source create 1 aegis/change.c
- X source create 1 aegis/change.h
- X source create 1 aegis/chdir.c
- X source create 1 aegis/chdir.h
- X source create 1 aegis/col.c
- X source create 1 aegis/col.h
- X source create 1 aegis/commit.c
- X source create 1 aegis/commit.h
- X source create 1 aegis/common.def
- X source create 1 aegis/copyfile.c
- X source create 1 aegis/copyfile.h
- X source create 1 aegis/cstate.def
- X source create 1 aegis/defaults.c
- X source create 1 aegis/defaults.h
- X source create 1 aegis/develop1.c
- X source create 1 aegis/develop1.h
- X source create 1 aegis/develop2.c
- X source create 1 aegis/develop2.h
- X source create 1 aegis/diff.c
- X source create 1 aegis/diff.h
- X source create 1 aegis/dir.c
- X source create 1 aegis/dir.h
- X source create 1 aegis/error.c
- X source create 1 aegis/error.h
- X source create 1 aegis/file.c
- X source create 1 aegis/file.h
- X source create 1 aegis/gate.h
- X source create 1 aegis/gonzo.c
- X source create 1 aegis/gonzo.h
- X source create 1 aegis/gram.y
- X source create 1 aegis/gstate.def
- X source create 1 aegis/help.c
- X source create 1 aegis/help.h
- X source create 1 aegis/indent.c
- X source create 1 aegis/indent.h
- X source create 1 aegis/integra1.c
- X source create 1 aegis/integra1.h
- X source create 1 aegis/integra2.c
- X source create 1 aegis/integra2.h
- X source create 1 aegis/io.c
- X source create 1 aegis/io.h
- X source create 1 aegis/lex.c
- X source create 1 aegis/lex.h
- X source create 1 aegis/list.c
- X source create 1 aegis/list.h
- X source create 1 aegis/lock.c
- X source create 1 aegis/lock.h
- X source create 1 aegis/log.c
- X source create 1 aegis/log.h
- X source create 1 aegis/main.c
- X source create 1 aegis/mem.c
- X source create 1 aegis/mem.h
- X source create 1 aegis/new_chan.c
- X source create 1 aegis/new_chan.h
- X source create 1 aegis/new_file.c
- X source create 1 aegis/new_file.h
- X source create 1 aegis/new_proj.c
- X source create 1 aegis/new_proj.h
- X source create 1 aegis/new_rele.c
- X source create 1 aegis/new_rele.h
- X source create 1 aegis/new_test.c
- X source create 1 aegis/new_test.h
- X source create 1 aegis/option.c
- X source create 1 aegis/option.h
- X source create 1 aegis/os.c
- X source create 1 aegis/os.h
- X source create 1 aegis/parse.c
- X source create 1 aegis/parse.h
- X source create 1 aegis/pattr.def
- X source create 1 aegis/pattr_ed.c
- X source create 1 aegis/pattr_ed.h
- X source create 1 aegis/pconf.def
- X source create 1 aegis/project.c
- X source create 1 aegis/project.h
- X source create 1 aegis/pstate.def
- X source create 1 aegis/rem_file.c
- X source create 1 aegis/rem_file.h
- X source create 1 aegis/review.c
- X source create 1 aegis/review.h
- X source create 1 aegis/reviewer.c
- X source create 1 aegis/reviewer.h
- X source create 1 aegis/str.c
- X source create 1 aegis/str.h
- X source create 1 aegis/sub.c
- X source create 1 aegis/sub.h
- X source create 1 aegis/test.c
- X source create 1 aegis/test.h
- X source create 1 aegis/trace.c
- X source create 1 aegis/trace.h
- X source create 1 aegis/tree.c
- X source create 1 aegis/tree.h
- X source create 1 aegis/type.c
- X source create 1 aegis/type.h
- X source create 1 aegis/uconf.def
- X source create 1 aegis/undo.c
- X source create 1 aegis/undo.h
- X source create 1 aegis/user.c
- X source create 1 aegis/user.h
- X source create 1 aegis/ustate.def
- X source create 1 aegis/version.c
- X source create 1 aegis/version.h
- X source create 1 aegis/word.c
- X source create 1 aegis/word.h
- X source create 1 common/main.h
- X source create 1 config
- X source create 1 doc/aegis.mm
- X source create 1 doc/c1.0.so
- X source create 1 doc/c1.1.so
- X source create 1 doc/c1.2.so
- X source create 1 doc/c1.3.so
- X source create 1 doc/c2.0.so
- X source create 1 doc/c2.1.so
- X source create 1 doc/c2.2.so
- X source create 1 doc/c2.3.so
- X source create 1 doc/c2.4.so
- X source create 1 doc/c3.0.so
- X source create 1 doc/c4.0.so
- X source create 1 doc/c5.0.so
- X source create 1 doc/c6.0.so
- X source create 1 doc/c7.0.so
- X source create 1 doc/c7.1.so
- X source create 1 doc/c7.2.so
- X source create 1 doc/cA.0.so
- X source create 1 dot.cshrc
- X source create 1 dot.profile
- X source create 1 fmtgen/ansi.c
- X source create 1 fmtgen/arglex.c
- X source create 1 fmtgen/arglex.h
- X source create 1 fmtgen/error.c
- X source create 1 fmtgen/error.h
- X source create 1 fmtgen/id.c
- X source create 1 fmtgen/id.h
- X source create 1 fmtgen/indent.c
- X source create 1 fmtgen/indent.h
- X source create 1 fmtgen/lex.c
- X source create 1 fmtgen/lex.h
- X source create 1 fmtgen/main.c
- X source create 1 fmtgen/mem.c
- X source create 1 fmtgen/mem.h
- X source create 1 fmtgen/parse.y
- X source create 1 fmtgen/str.c
- X source create 1 fmtgen/str.h
- X source create 1 fmtgen/type.c
- X source create 1 fmtgen/type.h
- X source create 1 fmtgen/type_enum.c
- X source create 1 fmtgen/type_integ.c
- X source create 1 fmtgen/type_list.c
- X source create 1 fmtgen/type_ref.c
- X source create 1 fmtgen/type_strin.c
- X source create 1 fmtgen/type_struc.c
- X source create 1 fmtgen/word.c
- X source create 1 fmtgen/word.h
- X source create 1 h/stdarg.h
- X source create 1 h/stddef.h
- X source create 1 h/stdlib.h
- X source create 1 man1/aea.1
- X source create 1 man1/aeb.1
- X source create 1 man1/aeca.1
- X source create 1 man1/aecd.1
- X source create 1 man1/aecp.1
- X source create 1 man1/aecpu.1
- X source create 1 man1/aed.1
- X source create 1 man1/aedb.1
- X source create 1 man1/aedbu.1
- X source create 1 man1/aede.1
- X source create 1 man1/aedeu.1
- X source create 1 man1/aega.1
- X source create 1 man1/aegis.1
- X source create 1 man1/aeib.1
- X source create 1 man1/aeibu.1
- X source create 1 man1/aeif.1
- X source create 1 man1/aeip.1
- X source create 1 man1/ael.1
- X source create 1 man1/aena.1
- X source create 1 man1/aenc.1
- X source create 1 man1/aencu.1
- X source create 1 man1/aend.1
- X source create 1 man1/aenf.1
- X source create 1 man1/aenfu.1
- X source create 1 man1/aeni.1
- X source create 1 man1/aenpr.1
- X source create 1 man1/aenrls.1
- X source create 1 man1/aenrv.1
- X source create 1 man1/aent.1
- X source create 1 man1/aentu.1
- X source create 1 man1/aepa.1
- X source create 1 man1/aera.1
- X source create 1 man1/aerd.1
- X source create 1 man1/aerf.1
- X source create 1 man1/aeri.1
- X source create 1 man1/aerm.1
- X source create 1 man1/aermu.1
- X source create 1 man1/aerp.1
- X source create 1 man1/aerpr.1
- X source create 1 man1/aerpu.1
- X source create 1 man1/aerrv.1
- X source create 1 man1/aet.1
- X source create 1 man1/aeua.1
- X source create 1 man1/aev.1
- X source create 1 man1/o__rules.so
- X source create 1 man1/o_anticip.so
- X source create 1 man1/o_auto.so
- X source create 1 man1/o_baselin.so
- X source create 1 man1/o_change.so
- X source create 1 man1/o_devdir.so
- X source create 1 man1/o_dir.so
- X source create 1 man1/o_help.so
- X source create 1 man1/o_indep.so
- X source create 1 man1/o_keep.so
- X source create 1 man1/o_lib.so
- X source create 1 man1/o_list.so
- X source create 1 man1/o_major.so
- X source create 1 man1/o_manual.so
- X source create 1 man1/o_min.so
- X source create 1 man1/o_minor.so
- X source create 1 man1/o_nolog.so
- X source create 1 man1/o_overw.so
- X source create 1 man1/o_page.so
- X source create 1 man1/o_project.so
- X source create 1 man1/o_terse.so
- X source create 1 man1/o_verbose.so
- X source create 1 man1/z_cr.so
- X source create 1 man1/z_exit.so
- X source create 1 man1/z_intuit.so
- X source create 1 man1/z_name.so
- X source create 1 man5/aecattr.5
- X source create 1 man5/aecstate.5
- X source create 1 man5/aedir.5
- X source create 1 man5/aegis.5
- X source create 1 man5/aegstate.5
- X source create 1 man5/aepattr.5
- X source create 1 man5/aepconf.5
- X source create 1 man5/aepstate.5
- X source create 1 man5/aeuconf.5
- X source create 1 man5/aeustate.5
- X source create 1 man5/z_cr.so
- X source create 1 man5/z_name.so
- X source create 1 notify/de.sh
- X source create 1 notify/deu.sh
- X source create 1 notify/if.sh
- X source create 1 notify/ip.sh
- X source create 1 notify/rf.sh
- X source create 1 notify/rp.sh
- X source create 1 notify/rpu.sh
- X test create 1 test/00/t0001a.sh
- X test create 1 test/00/t0002a.sh
- X test create 1 test/00/t0003a.sh
- X test create 1 test/00/t0004a.sh
- X test create 1 test/00/t0005a.sh
- X test create 1 test/00/t0006a.sh
- X test create 1 test/00/t0007a.sh
- X test create 1 test/00/t0008a.sh
- X test create 1 test/00/t0009a.sh
- X test create 1 test/00/t0010a.sh
- X test create 1 test/00/t0011a.sh
- X
- XHISTORY
- X What When Who Comment
- X ------ ------ ----- ---------
- X new_change Wed Jun 17 pmiller Elapsed time: 0.000 days.
- X 10:01:50 1992
- X develop_begin Wed Jun 17 pmiller Elapsed time: 0.000 days.
- X 10:01:50 1992
- X develop_end Wed Jun 17 pmiller Elapsed time: 0.000 days.
- X 10:01:50 1992
- X review_pass Wed Jun 17 pmiller Elapsed time: 0.000 days.
- X 10:01:50 1992
- X integrate_begin Wed Jun 17 pmiller Elapsed time: 0.015 days.
- X 10:01:50 1992
- X integrate_pass Wed Jun 17 pmiller
- X 10:08:27 1992
- X
- XIDENTIFICATION
- X Project "aegis.1.1", build 2, change 2.
- X
- XSUMMARY
- X generated Makefile with absolute dependencies
- X
- XDESCRIPTION
- X 1. A number of problems were found with the Makefile: it contained
- X absolute path name dependencies, it did not include any tests.
- X 2. The build instructions are completely inadequate.
- X 3. come kind of config include is required.
- X 4. some way to test before making it set-uid-root is needed.
- X 5. the tests use fcomp and sc!
- X 6. some systems don't have the tcgetpgrp function.
- X
- X My thanks to Peter Chubb <peterc@suite.sw.oz.au> for reporting these
- X problems.
- X
- XCAUSE
- X external_bug
- X
- XFILES
- X Type Action Edit File Name
- X ------- ------- ------- -----------
- X source remove 1 BUILDING
- X source modify 2 Howto.cook
- X source modify 2 Makefile.sh
- X source remove 1 aegis/ansi.c
- X source modify 2 aegis/commit.c
- X source modify 2 aegis/gate.h
- X source modify 2 aegis/gonzo.c
- X source modify 2 aegis/log.c
- X source modify 2 aegis/os.c
- X source modify 2 aegis/os.h
- X source create 1 common/ansi.c
- X source create 1 conf/SunOS-4.1.2
- X source create 1 conf/SysV-4.0
- X source create 1 doc/build.man
- X source remove 1 fmtgen/ansi.c
- X source modify 2 man1/aegis.1
- X source create 1 man1/install.sh
- X source modify 2 man5/aeustate.5
- X source create 1 man5/install.sh
- X test modify 2 test/00/t0002a.sh
- X test modify 2 test/00/t0004a.sh
- X test modify 2 test/00/t0005a.sh
- X test modify 2 test/00/t0006a.sh
- X test modify 2 test/00/t0007a.sh
- X test modify 2 test/00/t0009a.sh
- X test modify 2 test/00/t0010a.sh
- X test modify 2 test/00/t0011a.sh
- X
- XHISTORY
- X What When Who Comment
- X ------ ------ ----- ---------
- X new_change Wed Jun 17 pmiller Elapsed time: 0.001 days.
- X 13:11:31 1992
- X develop_begin Wed Jun 17 pmiller Elapsed time: 0.884 days.
- X 13:12:03 1992
- X develop_end Thu Jun 18 pmiller Elapsed time: 0.002 days.
- X 12:19:56 1992
- X review_pass Thu Jun 18 pmiller Elapsed time: 0.001 days.
- X 12:20:37 1992
- X integrate_begin Thu Jun 18 pmiller Elapsed time: 0.226 days.
- X 12:21:11 1992
- X integrate_pass Thu Jun 18 pmiller
- X 14:03:04 1992
- X
- XIDENTIFICATION
- X Project "aegis.1.1", build 3, change 3.
- X
- XSUMMARY
- X the project does not yet make
- X
- XDESCRIPTION
- X 1. There are flaws in the generated Makefile which result in the make
- X failing.
- X 2. There are flaws on some tests which make them behave differently
- X under make athan aet.
- X
- XCAUSE
- X internal_bug
- X
- XSTATE
- X being_integrated
- X
- XFILES
- X Type Action Edit File Name
- X ------- ------- ------- -----------
- X source modify 2 Makefile.sh
- X source modify 2 aegis/os.c
- X test modify 1 test/00/t0001a.sh
- X test modify 1 test/00/t0003a.sh
- X
- XHISTORY
- X What When Who Comment
- X ------ ------ ----- ---------
- X new_change Fri Jun 19 pmiller Elapsed time: 0.001 days.
- X 09:11:25 1992
- X develop_begin Fri Jun 19 pmiller Elapsed time: 0.212 days.
- X 09:11:51 1992
- X develop_end Fri Jun 19 pmiller Elapsed time: 0.006 days.
- X 10:47:05 1992
- X review_pass Fri Jun 19 pmiller Elapsed time: 0.001 days.
- X 10:49:50 1992
- X integrate_begin Fri Jun 19 pmiller Elapsed time: 0.244 days.
- X 10:50:24 1992
- END_OF_FILE
- if test 12490 -ne `wc -c <'aux/CHANGES.1.1'`; then
- echo shar: \"'aux/CHANGES.1.1'\" unpacked with wrong size!
- fi
- # end of 'aux/CHANGES.1.1'
- fi
- if test -f 'doc/c6.0.so' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'doc/c6.0.so'\"
- else
- echo shar: Extracting \"'doc/c6.0.so'\" \(13918 characters\)
- sed "s/^X//" >'doc/c6.0.so' <<'END_OF_FILE'
- X.\"
- X.\" aegis - project change supervisor
- X.\" Copyright (C) 1991, 1992, 1993 Peter Miller.
- X.\" All rights reserved.
- X.\"
- X.\" This program is free software; you can redistribute it and/or modify
- X.\" it under the terms of the GNU General Public License as published by
- X.\" the Free Software Foundation; either version 2 of the License, or
- X.\" (at your option) any later version.
- X.\"
- X.\" This program is distributed in the hope that it will be useful,
- X.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
- X.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- X.\" GNU General Public License for more details.
- X.\"
- X.\" You should have received a copy of the GNU General Public License
- X.\" along with this program; if not, write to the Free Software
- X.\" Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- X.\"
- X.\" MANIFEST: User Guide, Tips and Traps
- X.\"
- X.bp
- X.2C
- X.nh 1 "Tips and Traps"
- X.LP
- XThis chapter contains hints for how to use the aegis program
- Xmore efficiently
- Xand documents a number of pitfalls you may encounter.
- X.LP
- XThis chapter is at present very "ad hoc" with no particular ordering.
- XFortunately, it is, as yet, rather small.
- XThe final size of this chapter is expected to be quite large.
- X.nh 2 "C Include Semantics"
- X.LP
- XThe semantics of C include directives make the
- X.E(
- X#include "\fIfilename\fP"
- X.E)
- Xdirective dangerous in a project developed with the aegis program.
- X.LP
- XDepending on the age of your compiler,
- Xwhether it is AT&T traditional C or newer ANSI C,
- Xthis form of directive will search first in the current directory and then
- Xalong the search path,
- Xor in the directory of the including file and then along the search path.
- X.LP
- XThe first case is fairly benign,
- Xexcept that compilers are rapidly becoming ANSI C compliant,
- Xand an operating system upgrade could result in a nasty surprise.
- X.LP
- XThe second case is bad news.
- XIf the source file is in the baseline and the include file is in the change,
- Xyou don't want the source file to use the include file in the baseline.
- X.LP
- XAlways use the
- X.E(
- X#include <\fIfilename\fP>
- X.E)
- Xform of the include directive,
- Xand set the include search path explicitly on the command line
- Xused by the dependency maintenance tool.
- X.LP
- XThe dependency maintenance tool needs to be able to dynamically adapt
- Xto include file dependencies,
- Xbecause they are not static.
- XThe presence of an include file in a change
- Xmeans that any file which includes this include file,
- Xwhether that source file is in the baseline or in the change,
- Xmust have a dependency on the change's include file.
- XPotentially,
- Xfiles in the baseline will need to be recompiled,
- Xand the object file stored in the change,
- Xnot the baseline.
- XSubsequent linking needs to pick up the object file
- Xin the change, not from the baseline.
- X.nh 2 "Renaming Include Files"
- X.LP
- XRenaming include files can be a disaster,
- Xeither finding all of the clients,
- Xor making sure the new copy is used rather than the old copy
- Xstill in the baseline.
- X.LP
- XIf an include file is to be completely renamed,
- Xnot moved to another directory
- Xbut retain the same basename,
- Xthen create a file in the development directory (\fIwithout\fP telling aegis)
- Xwith the old name,
- Xand put a syntax error in it.
- XCompiles will fail very diagnostically,
- Xand you can change the reference in the source file,
- Xprobably after \fIaecp\fP(1)ing it first.
- X.LP
- XIf you are moving an include file from one directory to another,
- Xbut leaving the basename unchanged,
- Xcreate a link\**
- X.FS
- XA hard link uses fewer disk blocks.
- XSymbolic links survive the subject file being deleted and recreated.
- X.FE
- Xbetween the new and old names,
- Xbut only in the development directory.
- XCreate the link after \fIaenf\fP(1)ing the new name.
- XThis insulates you from a number of nasty Catch-22 situations
- Xin writing the dependency maintenance tool's rules file.
- X.nh 2 "Writing Tests"
- X.LP
- XThis section describes a number of things you can do to write better tests,
- Xand some pitfalls to be avoided.
- X.LP
- XThe are a number of suggestions for portability of tests;
- Xthis will definitely be important if you are writing software
- Xto publish on USENET or for FTP.
- XPortability is often require
- X.I within
- Xan organization, also.
- XExamples include a change in company policy from one 386
- X.UX
- Xto another
- X(e.g. company doesn't like Linux, now you must use AT&T's SVR4 offering),
- Xor the development team use
- X.I gcc
- Xuntil the company finds out and forces you to use the prototype-less
- Xcompiler supplied with the operating system.
- XThings like this really have happened to the author!
- X.nh 3 "Bourne Shell"
- X.LP
- XThe aegis program mandates that all tests be Bourne shell scripts.
- XThis is because this shell is available on all flavours of the
- X.UX
- Xoperating system.
- XThe script files need not have execute permissions set,
- Xbecause the aegis program always invokes them as
- X.E(
- Xsh \fIfilename\fP
- X.E)
- Xso tests should not expect command line arguments.
- XThe test is not passed the name of the project nor the number of the change.
- X.LP
- XThis means that if you can write in in a shell script,
- Xyou can test it.
- XThis includes such things as client-server model interfaces,
- Xand multi-user synchronization testing.
- X.LP
- XSome indication that the test script is a Bourne shell script is
- Xa good idea.
- XWhile many systems accept that a first line starting with a colon is a
- XBourne shell "magic number",
- Xa more widely understood "magic number" is
- X.E(
- X#! /bin/sh
- X.E)
- Xas the first line of the script file.
- X.nh 3 "Current Directory"
- X.LP
- XTests are always run with the current directory set to either the
- Xdevelopment directory
- Xchange under test when testing a change,
- Xor the integration directory when integrating a change,
- Xor the baseline when performing independent tests.
- X.LP
- XA test must not make assumptions about where it is being executed from,
- Xexcept to the extent that it is somewhere a build has been performed.
- XA test must not assume that the current directory is writable,
- Xand must not try to write to it,
- Xas this could damage the source code of a change
- Xunder development,
- Xpotentially destroying weeks of work.
- X.nh 3 "Check Exit Status"
- X.LP
- XA test script should check the exit status of every single command,
- Xeven those which cannot fail.
- XDo not rely on, or use, the
- X.I "set -e"
- Xshell option (it provides no ability to clean up on error).
- X.LP
- XChecking the exit status involves testing the contents of the
- X.B $?
- Xshell variable.
- XDo not use an
- X.I if
- Xstatement wrapped around an execution of the program under test
- Xas this will miss core dumps and other terminations caused by signals.
- X.LP
- XChecking the exit status of every command in the script
- Xensures that strange permission settings,
- Xor disk space problems,
- Xwill cause the test to fail,
- Xrather than plow on and produce spurious results.
- X.nh 3 "Trap Interrupts"
- X.LP
- XUse the
- X.I trap
- Xstatement to catch interrupts 1 2 3 and 15 an cause the test to fail.
- XThis should perform any cleanup the test requires
- X(such as removing the temporary directory; see next item).
- X.nh 3 "Temporary Directory"
- X.LP
- XTests should create a temporary directory in
- X.I /tmp
- Xand then
- X.I cd
- Xinto this directory.
- X.LP
- XThis tends to isolate any vandalism that the program under test may indulge in,
- Xand serves as a place to write temporary files.
- XAt the end of the test, it is sufficient to
- X.I cd
- Xout of the temporary directory and then
- X.I "rm -rf"
- Xit,
- Xrather than track and remove all test files which may or may not be created.
- X.nh 3 "PAGER"
- X.LP
- XIf the program under test invokes pagers on its output,
- Xa la \fImore\fP(1) et al,
- Xit should be coded to use the PAGER
- Xenvironment variable.
- XTests of such programs should always set PAGER to
- X.I cat
- Xso that tests always behave the same,
- Xirrespective of invocation method (either by aegis or from the command line).
- X.nh 3 "[ test ]"
- X.LP
- XYou should always use the
- X.I test
- Xcommand,
- Xrather than the square bracket form,
- Xas many systems do not have the square bracket form,
- Xif you publish to USENET or for FTP.
- X.nh 3 "Auxiliary Files"
- X.LP
- XIf a test requires extra files as input or output to a command,
- Xit must construct them itself,
- Xusing \fIhere\fP documents (see \fIsh\fP(1) for more information).
- X.LP
- XIt is almost impossible to determine the location of an auxiliary file,
- Xif that auxiliary file is part of the project source.
- XIt could be in either the change under test or the baseline.
- X.nh 3 "New Test Templates"
- X.LP
- XIt is possible to specify most of the repetitious
- Xitems above in a
- X.I "file template"
- Xused every time a user creates a new test.
- XSee the \fIaent\fP(1) command for more information.
- X.LP
- XHaving the machine do it for you
- Xmeans that you are more likely to do it.
- X.nh 2 "Symbolic Links"
- X.LP
- XIf you are on a flavour of
- X.UX
- Xwhich has symbolic links,
- Xit is often useful to create a symbolic link from the development directory
- Xto the baseline.
- XThis can make browsing the baseline very simple.
- X.LP
- XAssuming that the project and change defaults are appropriate,
- Xthe following command
- X.E(
- Xln -s `aegis -cd -bl` bl
- X.E)
- Xis all that is required to create a symbolic link called
- X.I bl
- Xpointing to the baseline.
- XNote that the
- X.I aecd
- Xalias is inappropriate in this case.
- X.LP
- XThis can be done automatically for every change,
- Xby placing the line
- X.E(
- Xdevelop_begin_command =
- X "ln -s $baseline bl";
- X.E)
- Xinto the
- X.I config
- Xfile.
- X.nh 2 "User Setup"
- X.LP
- XThere are a number of things which users
- Xof aegis can do to make it more useful,
- Xor more user friendly.
- XThis section describes just a few of them.
- X.nh 3 "\&.cshrc"
- X.LP
- XThe aliases for the various user commands used throughout this manual
- Xare obtained by appending a line of the form
- X.E(
- X.ps -2
- Xsource /usr/local/lib/aegis/cshrc
- X.ps +2
- X.E)
- Xto the
- X.I \&.cshrc
- Xfile in the user's home directory.
- X.nh 3 "The AEGIS environment variable"
- X.LP
- XIf users wish to use aegis for their own projects,
- Xin addition to the "system" projects,
- Xthe
- XAEGIS
- Xenvironment variable forms a colon separated search path
- Xof aegis "library" directories.
- XThe
- X.I /usr/local/lib/aegis
- Xdirectory is always implicitly added to this list.
- X.LP
- XThe user should not create this library directory,
- Xbut let aegis do this for itself (otherwise you will get an error message).
- X.LP
- XThe
- X.I AEGIS
- Xenvironment variable should be set in the
- X.I \&.cshrc
- Xfile in the user's home directory.
- XTypical setting is
- X.E(
- Xsetenv AEGIS ~/lib/aegis
- X.E)
- X.nh 3 "The \&.aegisrc file"
- X.LP
- XThe
- X.I \&.aegisrc
- Xfile in the user's home directory
- Xcontains a number of useful fields.
- XSee
- X.I aeuconf (5)
- Xfor more information.
- X.nh 3 "The defaulting mechanism"
- X.LP
- XIn order for you to specify the minimum possible information
- Xon the command line,
- Xaegis has been designed to work most of it out itself.
- X.LP
- XThe default project is the project which you are working on changes for,
- Xif there is only one, otherwise it is gleaned from the
- X.I \&.aegisrc
- Xfile.
- XThe command line overrides any default.
- X.LP
- XThe default change is the one you are
- Xworking on within the (default or specified) project,
- Xif there is only one.
- XThe command line overrides any default.
- X.nh 2 "The Project Owner"
- X.LP
- XFor the greatest protection from accidental change,
- Xit is best if the project is owned by a
- X.UX
- Xaccount which is none of the staff.
- XThis account is often named the same as the project,
- Xor sometimes there is a single umbrella account for all projects.
- X.LP
- XWhen an aegis project is created,
- Xthe owner is the user creating the project,
- Xand the group is the user's default group.
- XThe creating user is installed as the project's first administrator.
- X.LP
- XA new project administrator should be created - an actual user account.
- XThe
- X.UX
- Xpassword should then be disabled on the project
- Xaccount - it will never be necessary to use it again.\**
- X.FS
- XUnless bugs in aegis corrupt the database,
- Xin which case repairs can be accomplished as
- Xthe project account using a text editor.
- X.FE
- X.LP
- XThe user nominated as project administrator many then assign
- Xall of the other staff roles.
- XAegis takes care of ensuring that the baseline is owned by the project account,
- Xnot any of the other staff,
- Xwhile development directories always belong to the developer
- X(but the group will always be the project group,
- Xirrespective of the developer's default group).
- X.LP
- XAll of the staff working on a project should be members of the
- Xproject's group,
- Xto be able to browse the baseline,
- Xfor reviewers to be able to review changes.
- XThis use of
- X.UX
- Xgroups means that projects may be as secure or open as desired.
- X.nh 2 "USENET Publication Standards"
- X.LP
- XIf you are writing software to publish on USENET,
- Xa number of the source newsgroups have publication standards.
- XThis section describes ways of generating the following files,
- Xrequired by many of the newsgroups' moderators:
- X.TS
- Xtab(;);
- Xl lw(1.5i).
- XMANIFEST;T{
- XList of files in the distribution.
- XT}
- XMakefile;T{
- XHow to build the distribution.
- XT}
- XCHANGES;T{
- XWhat happened for this distribution.
- XT}
- Xpatchlevel.h;T{
- XAn identification of this distribution.
- XT}
- X.TE
- X.LP
- XEach of these files may be generated from information
- Xknown to aegis,
- Xwith the aid of some fairly simple shell scripts.
- X.nh 3 "CHANGES"
- X.LP
- XWrite this section.
- X.LP
- XLook in the
- X.I aux/CHANGES.sh
- Xfile included in the aegis distribution
- Xfor an example of one way to do this.
- X.nh 3 "MANIFEST"
- X.LP
- XWrite this section.
- X.LP
- XLook in the
- X.I aux/MANIFEST.sh
- Xand
- X.I aux/MANIFEST.awk
- Xfiles included in the aegis distribution
- Xfor an example of one way to do this.
- X.nh 3 "Makefile"
- X.LP
- XWrite this section.
- X.LP
- XLook in the
- X.I aux/Makefile.sh
- Xand
- X.I aux/Makefile.awk
- Xfiles included in the aegis distribution
- Xfor an example of one way to do this.
- X.nh 3 "patchlevel.h"
- X.LP
- XWrite this section.
- X.LP
- XLook in the
- X.I aux/Howto.cook
- Xfile included in the aegis distribution
- Xfor an example of one way to do this.
- X.nh 3 "Building Patch Files"
- X.LP
- XThe
- X.I patch
- Xprogram by Larry Wall is one of the enduring marvels of USENET.
- XThis section describes how to build input files
- Xfor this miracle program.
- X.LP
- XWrite this section.
- X.LP
- XLook in the
- X.I aux/patches.sh
- Xfile included in the aegis distribution
- Xfor an example of one way to do this.
- X.1C
- END_OF_FILE
- if test 13918 -ne `wc -c <'doc/c6.0.so'`; then
- echo shar: \"'doc/c6.0.so'\" unpacked with wrong size!
- fi
- # end of 'doc/c6.0.so'
- fi
- echo shar: End of archive 9 \(of 19\).
- cp /dev/null ark9isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 19 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-