home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
unix
/
volume27
/
aegis-2.1
/
part10
< prev
next >
Wrap
Text File
|
1993-09-24
|
149KB
|
5,613 lines
Newsgroups: comp.sources.unix
From: pmiller@bmr.gov.au (Peter Miller)
Subject: v27i045: aegis - project change supervisor (V2.1), Part10/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 45
Archive-Name: aegis-2.1/part10
#! /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 10 (of 19)."
# Contents: aegis/aeb.c aegis/aeca.c aegis/aede.c aegis/aeif.c
# aegis/aemv.c aegis/aepa.c aegis/gonzo.c lib/aegis.pgm
# test/00/t0002a.sh
# Wrapped by vixie@gw.home.vix.com on Sat Sep 25 03:00:43 1993
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'aegis/aeb.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'aegis/aeb.c'\"
else
echo shar: Extracting \"'aegis/aeb.c'\" \(14439 characters\)
sed "s/^X//" >'aegis/aeb.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 perform development and integration builds
X */
X
X#include <stdio.h>
X#include <stdlib.h>
X#include <time.h>
X#include <errno.h>
X
X#include <aeb.h>
X#include <ael.h>
X#include <arglex2.h>
X#include <col.h>
X#include <commit.h>
X#include <change.h>
X#include <error.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 <sub.h>
X#include <trace.h>
X#include <user.h>
X
X
X/*
X * NAME
X * build_usage
X *
X * SYNOPSIS
X * void build_usage(void);
X *
X * DESCRIPTION
X * The build_usage function is used to
X * briefly describe how to used the 'aegis -Build' command.
X */
X
Xstatic void build_usage _((void));
X
Xstatic void
Xbuild_usage()
X{
X char *progname;
X
X progname = option_progname_get();
X fprintf(stderr, "usage: %s -Build [ <option>... ]\n", progname);
X fprintf(stderr, " %s -Build -List [ <option>... ]\n", progname);
X fprintf(stderr, " %s -Build -Help\n", progname);
X quit(1);
X}
X
X
X/*
X * NAME
X * build_help
X *
X * SYNOPSIS
X * void build_help(void);
X *
X * DESCRIPTION
X * The build_help function is used to
X * describe in detail how to use the 'aegis -Build' command.
X */
X
Xstatic void build_help _((void));
X
Xstatic void
Xbuild_help()
X{
X static char *text[] =
X {
X"NAME",
X" %s -Build - build a project",
X"",
X"SYNOPSIS",
X" %s -Build [ option... ]",
X" %s -Build -List [ option... ]",
X" %s -Build -Help",
X"",
X"DESCRIPTION",
X" The %s -Build command is used to build a project. The",
X" project configuration file is consulted for the",
X" appropriate build command, and that command is executed",
X" (see aepconf(5) for more information.) Output of the",
X" command is automatically logged to the %s.log file at",
X" the root of the development directory tree. The build",
X" command will be executed with its current directory being",
X" the root of the development directory, irrespective of",
X" there the %s -Build command was exectuted.",
X"",
X" If the change is in the 'being_integrated' state,",
X" references to the development directory, above, should be",
X" read as the integration directory. Integration build",
X" commands are executed with the user and group set to the",
X" project's owning user and group. That is, it is not",
X" necessary for an integrator to log in as someone else,",
X" the project account for instance, in order to do an",
X" integration.",
X"",
X" While there is a build in progress for any change in a",
X" project, an integrate pass for the project will wait until",
X" all the builds are completed before starting. This is to",
X" ensure that the baseline is consistent for the entire build.",
X" Similarly, while an integrate pass is in progress for a",
X" project, any builds will wait until it is completed before",
X" starting.",
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 are case insensitive. Options may be",
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"RECOMMENDED ALIAS",
X" The recommended alias for this command is",
X" csh%% alias aeb '%s -b \\!* -v'",
X" sh$ aeb(){%s -b $* -v}",
X"",
X"ERRORS",
X" It is an error if the change is not assigned to the",
X" curent user.",
X" It is an error if the change is not in one of the",
X" 'being_developed' or 'being_integrated' states.",
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), build_usage);
X}
X
X
X/*
X * NAME
X * build_list
X *
X * SYNOPSIS
X * void build_list(void);
X *
X * DESCRIPTION
X * The build_list function is used to
X * list the changes which may be built within the project.
X */
X
Xstatic void build_list _((void));
X
Xstatic void
Xbuild_list()
X{
X string_ty *project_name;
X
X trace(("build_list()\n{\n"/*}*/));
X arglex();
X project_name = 0;
X while (arglex_token != arglex_token_eoln)
X {
X switch (arglex_token)
X {
X default:
X generic_argument(build_usage);
X continue;
X
X case arglex_token_project:
X if (arglex() != arglex_token_string)
X build_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_in_state_mask
X (
X project_name,
X (
X (1 << cstate_state_being_developed)
X |
X (1 << cstate_state_being_integrated)
X )
X );
X if (project_name)
X str_free(project_name);
X trace((/*{*/"}\n"));
X}
X
X
X/*
X * NAME
X * build_main
X *
X * SYNOPSIS
X * void build_main(void);
X *
X * DESCRIPTION
X * The build_main function is used to
X * build a change in the "being developed" or "being integrated" states.
X * It extracts what to do from the command line.
X */
X
Xstatic void build_main _((void));
X
Xstatic void
Xbuild_main()
X{
X string_ty *the_command;
X cstate cstate_data;
X pstate pstate_data;
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
X trace(("build_main()\n{\n"/*}*/));
X nolog = 0;
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(build_usage);
X continue;
X
X case arglex_token_change:
X if (arglex() != arglex_token_number)
X build_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 build_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 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
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 an advisory write lock on this row of the change table.
X * Block if necessary.
X */
X change_cstate_lock_prepare(cp);
X project_build_read_lock_prepare(pp);
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 in-development state.
X * It is an error if the change is not assigned to the current user.
X * It is an error if the change has no files assigned.
X */
X switch (cstate_data->state)
X {
X default:
X change_fatal(cp, "not in 'being_developed' state");
X break;
X
X case cstate_state_being_developed:
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 assert(cstate_data->src);
X if (!cstate_data->src->length)
X change_fatal(cp, "has no files");
X break;
X
X case cstate_state_being_integrated:
X if (!str_equal(change_integrator_name(cp), user_name(up)))
X {
X change_fatal
X (
X cp,
X "user \"%S\" is not the integrator",
X user_name(up)
X );
X }
X break;
X }
X
X /*
X * Update the time the build was done.
X * This will not be written out if the build fails.
X */
X time(&cstate_data->build_time);
X
X /*
X * get the command to execute
X * 1. if the change is editing config, use that
X * 2. if the baseline contains config, use that
X * 3. error if can't find one (DON'T look for file existence)
X */
X pconf_data = change_pconf_get(cp);
X if
X (
X !pconf_data->development_build_command
X ||
X !pconf_data->build_command
X )
X {
X change_fatal
X (
X cp,
X "you need to create a new \"%s\" file before you can build",
X THE_CONFIG_FILE
X );
X }
X
X /*
X * work out the build command
X */
X trace(("work out the build command\n"));
X if (cstate_data->state == cstate_state_being_integrated)
X {
X /*
X * %1 = project name
X * %2 = change number
X * %3 = identifying string, in the form "a.b.Dnnn"
X * where 'a' is the major version number,
X * 'b' is the minor version number,
X * and 'nnn' is the build number.
X */
X sub_var_set("1", "${project}");
X sub_var_set("2", "${change}");
X sub_var_set("3", "${version}");
X the_command = pconf_data->build_command;
X the_command = substitute(cp, the_command);
X }
X else
X {
X /*
X * %1 = project name
X * %2 = change number
X * %3 = identifying string, in the form "a.b.Cnnn"
X * where 'a' is the major version number,
X * 'b' is the minor version number,
X * and 'nnn' is the change number.
X * %4 = the absolute path of the project baseline directory.
X */
X sub_var_set("1", "${project}");
X sub_var_set("2", "${change}");
X sub_var_set("3", "${version}");
X sub_var_set("4", "${baseline}");
X the_command = pconf_data->development_build_command;
X the_command = substitute(cp, the_command);
X }
X
X /*
X * the program has changed, so it needs testing again,
X * so stomp on the validation fields.
X */
X trace(("nuke time stamps\n"));
X cstate_data->test_time = 0;
X cstate_data->regression_test_time = 0;
X cstate_data->test_baseline_time = 0;
X
X /*
X * do the build
X */
X trace(("open the log file\n"));
X trace(("do the build\n"));
X if (cstate_data->state == cstate_state_being_integrated)
X {
X string_ty *id;
X
X if (!nolog)
X {
X user_ty *pup;
X
X pup = project_user(pp);
X log_open(change_logfile_get(cp), pup);
X user_free(pup);
X }
X change_verbose(cp, "integration build started");
X id = change_integration_directory_get(cp, 0);
X project_become(pp);
X os_execute(the_command, OS_EXEC_FLAG_NO_INPUT, id);
X project_become_undo();
X change_verbose(cp, "integration build complete");
X }
X else
X {
X string_ty *dd;
X
X if (!nolog)
X log_open(change_logfile_get(cp), up);
X change_verbose(cp, "development build started");
X change_run_project_file_command(cp);
X dd = change_development_directory_get(cp, 0);
X user_become(up);
X os_execute(the_command, OS_EXEC_FLAG_NO_INPUT, dd);
X user_become_undo();
X change_verbose(cp, "development build complete");
X }
X
X /*
X * Update change data with result of build.
X * (This will be used when validating developer sign off.)
X * Release advisory write lock on row of change table.
X */
X change_cstate_write(cp);
X commit();
X lock_release();
X project_free(pp);
X change_free(cp);
X user_free(up);
X trace((/*{*/"}\n"));
X}
X
X
X/*
X * NAME
X * build
X *
X * SYNOPSIS
X * void build(void);
X *
X * DESCRIPTION
X * The build function is used to
X * dispatch the 'aegis -Build' command to the relevant functionality.
X * Where it goes depends on the command line.
X */
X
Xvoid
Xbuild()
X{
X trace(("build()\n{\n"/*}*/));
X switch (arglex())
X {
X default:
X build_main();
X break;
X
X case arglex_token_help:
X build_help();
X break;
X
X case arglex_token_list:
X build_list();
X break;
X }
X trace((/*{*/"}\n"));
X}
END_OF_FILE
if test 14439 -ne `wc -c <'aegis/aeb.c'`; then
echo shar: \"'aegis/aeb.c'\" unpacked with wrong size!
fi
# end of 'aegis/aeb.c'
fi
if test -f 'aegis/aeca.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'aegis/aeca.c'\"
else
echo shar: Extracting \"'aegis/aeca.c'\" \(14427 characters\)
sed "s/^X//" >'aegis/aeca.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 list and modify change attributes
X */
X
X#include <stdio.h>
X#include <stdlib.h>
X
X#include <aeca.h>
X#include <arglex2.h>
X#include <cattr.h>
X#include <commit.h>
X#include <change.h>
X#include <error.h>
X#include <help.h>
X#include <lock.h>
X#include <project.h>
X#include <option.h>
X#include <os.h>
X#include <trace.h>
X#include <user.h>
X
X
Xstatic void change_attributes_usage _((void));
X
Xstatic void
Xchange_attributes_usage()
X{
X char *progname;
X
X progname = option_progname_get();
X fprintf(stderr, "usage: %s -Change_Attributes <attr-file> [ <option>... ]\n", progname);
X fprintf(stderr, " %s -Change_Attributes -Edit [ <option>... ]\n", progname);
X fprintf(stderr, " %s -Change_Attributes -List [ <option>... ]\n", progname);
X fprintf(stderr, " %s -Change_Attributes -Help\n", progname);
X quit(1);
X}
X
X
Xstatic void change_attributes_help _((void));
X
Xstatic void
Xchange_attributes_help()
X{
X static char *text[] =
X {
X"NAME",
X" %s -Change_Attributes - modify the attributes of a",
X" change",
X"",
X"SYNOPSIS",
X" %s -Change_Attributes <attr-file> [ <option>... ]",
X" %s -Change_Attributes -Edit [ <option>... ]",
X" %s -Change_Attributes -List [ <option>... ]",
X" %s -Change_Attributes -Help",
X"",
X"DESCRIPTION",
X" The %s -Change_Attributes command is used to set, edit",
X" or list the attributes of a change.",
X"",
X" The output of the -List variant is suitable for use as",
X" input at a later time.",
X"",
X" See aecattr(5) for a description of the file format.",
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 aeca '%s -ca \\!* -v'",
X" sh$ aeca(){%s -ca $* -v}",
X"",
X"ERRORS",
X" It is an error if the current user is not an",
X" administrator of 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), change_attributes_usage);
X}
X
X
Xstatic void cattr_copy _((cattr, cstate));
X
Xstatic void
Xcattr_copy(a, s)
X cattr a;
X cstate s;
X{
X if (!a->description && s->description)
X {
X a->description = str_copy(s->description);
X a->mask |= cattr_description_mask;
X }
X if (!a->brief_description && s->brief_description)
X {
X a->brief_description = str_copy(s->brief_description);
X a->mask |= cattr_brief_description_mask;
X }
X if (!(a->mask & cattr_cause_mask))
X {
X a->cause = s->cause;
X a->mask |= cattr_cause_mask;
X }
X if (!(a->mask & cattr_regression_test_exempt_mask))
X {
X a->regression_test_exempt = s->regression_test_exempt;
X a->mask |= cattr_regression_test_exempt_mask;
X }
X if (!(a->mask & cattr_test_exempt_mask))
X {
X a->test_exempt = s->test_exempt;
X a->mask |= cattr_test_exempt_mask;
X }
X if (!(a->mask & cattr_test_baseline_exempt_mask))
X {
X a->test_baseline_exempt = s->test_baseline_exempt;
X a->mask |= cattr_test_baseline_exempt_mask;
X }
X}
X
X
Xstatic void change_attributes_list _((void));
X
Xstatic void
Xchange_attributes_list()
X{
X string_ty *project_name;
X project_ty *pp;
X cattr cattr_data;
X cstate cstate_data;
X long change_number;
X change_ty *cp;
X user_ty *up;
X
X trace(("change_attributes_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(change_attributes_usage);
X continue;
X
X case arglex_token_change:
X if (arglex() != arglex_token_number)
X change_attributes_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 change_attributes_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
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 * build the cattr data
X */
X cstate_data = change_cstate_get(cp);
X cattr_data = (cattr)cattr_type.alloc();
X cattr_copy(cattr_data, cstate_data);
X
X /*
X * print the cattr data
X */
X cattr_write_file((char *)0, cattr_data);
X cattr_type.free(cattr_data);
X project_free(pp);
X change_free(cp);
X user_free(up);
X trace((/*{*/"}\n"));
X}
X
X
Xvoid
Xcattr_verify(fn, d)
X char *fn;
X cattr d;
X{
X if (!d->brief_description)
X fatal("%s: contains no \"brief_description\" field", fn);
X if (!(d->mask & cattr_cause_mask))
X fatal("%s: contains no \"cause\" field", fn);
X}
X
X
Xvoid
Xcattr_edit(dp)
X cattr *dp;
X{
X cattr d;
X string_ty *filename;
X
X /*
X * write attributes to temporary file
X */
X d = *dp;
X assert(d);
X filename = os_edit_filename();
X os_become_orig();
X cattr_write_file(filename->str_text, d);
X cattr_type.free(d);
X
X /*
X * edit the file
X */
X os_edit(filename);
X
X /*
X * read it in again
X */
X d = cattr_read_file(filename->str_text);
X os_unlink(filename);
X os_become_undo();
X cattr_verify(filename->str_text, d);
X str_free(filename);
X *dp = d;
X}
X
X
Xstatic void change_attributes_main _((void));
X
Xstatic void
Xchange_attributes_main()
X{
X string_ty *project_name;
X project_ty *pp;
X cattr cattr_data = 0;
X cstate cstate_data;
X long change_number;
X change_ty *cp;
X user_ty *up;
X int edit;
X
X trace(("change_attributes_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(change_attributes_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 assert(cattr_data);
X break;
X
X case arglex_token_change:
X if (arglex() != arglex_token_number)
X change_attributes_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 change_attributes_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 cattr_data = (cattr)cattr_type.alloc();
X if (!cattr_data)
X fatal("no file 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 * edit the attributes
X */
X if (edit)
X {
X /*
X * fill in any other fields
X */
X cstate_data = change_cstate_get(cp);
X cattr_copy(cattr_data, cstate_data);
X
X /*
X * edit the attributes
X */
X cattr_edit(&cattr_data);
X }
X
X /*
X * lock the change
X */
X change_cstate_lock_prepare(cp);
X lock_take();
X cstate_data = change_cstate_get(cp);
X
X /*
X * It is an error if the change is not in the "being developed" state.
X * It is an error if the user is not an administrator or the developer.
X */
X if
X (
X !project_administrator_query(pp, user_name(up))
X &&
X (
X cstate_data->state != cstate_state_being_developed
X ||
X !str_equal(change_developer_name(cp), user_name(up))
X )
X )
X {
X change_fatal
X (
X cp,
X "attributes may only be changed by a project \
Xadministrator, or by the developer during development"
X );
X }
X
X /*
X * copy the attributes across
X */
X if (cattr_data->description)
X {
X if (cstate_data->description)
X str_free(cstate_data->description);
X cstate_data->description = str_copy(cattr_data->description);
X }
X if (cattr_data->brief_description)
X {
X if (cstate_data->brief_description)
X str_free(cstate_data->brief_description);
X cstate_data->brief_description =
X str_copy(cattr_data->brief_description);
X }
X if (cattr_data->mask & cattr_cause_mask)
X cstate_data->cause = cattr_data->cause;
X if (project_administrator_query(pp, user_name(up)))
X {
X if (cattr_data->mask & cattr_test_exempt_mask)
X cstate_data->test_exempt = cattr_data->test_exempt;
X if (cattr_data->mask & cattr_test_baseline_exempt_mask)
X cstate_data->test_baseline_exempt =
X cattr_data->test_baseline_exempt;
X if (cattr_data->mask & cattr_regression_test_exempt_mask)
X cstate_data->regression_test_exempt =
X cattr_data->regression_test_exempt;
X }
X else
X {
X if
X (
X (
X cattr_data->test_exempt
X &&
X !cstate_data->test_exempt
X )
X ||
X (
X cattr_data->test_baseline_exempt
X &&
X !cstate_data->test_baseline_exempt
X )
X ||
X (
X cattr_data->regression_test_exempt
X &&
X !cstate_data->regression_test_exempt
X )
X )
X {
X change_fatal
X (
X cp,
X "only project administrators may exempt changes from testing"
X );
X }
X else
X {
X /*
X * developers may remove exemptions
X */
X if
X (
X (cattr_data->mask & cattr_test_exempt_mask)
X &&
X !cattr_data->test_exempt
X )
X cstate_data->test_exempt = 0;
X if
X (
X (cattr_data->mask & cattr_test_baseline_exempt_mask)
X &&
X !cattr_data->test_baseline_exempt
X )
X cstate_data->test_baseline_exempt = 0;
X if
X (
X (cattr_data->mask & cattr_regression_test_exempt_mask)
X &&
X !cattr_data->regression_test_exempt
X )
X cstate_data->regression_test_exempt = 0;
X }
X }
X
X cattr_type.free(cattr_data);
X change_cstate_write(cp);
X commit();
X lock_release();
X change_verbose(cp, "attributes changed");
X project_free(pp);
X change_free(cp);
X user_free(up);
X trace((/*{*/"}\n"));
X}
X
X
Xvoid
Xchange_attributes()
X{
X trace(("change_attributes()\n{\n"/*}*/));
X switch (arglex())
X {
X default:
X change_attributes_main();
X break;
X
X case arglex_token_help:
X change_attributes_help();
X break;
X
X case arglex_token_list:
X change_attributes_list();
X break;
X }
X trace((/*{*/"}\n"));
X}
END_OF_FILE
if test 14427 -ne `wc -c <'aegis/aeca.c'`; then
echo shar: \"'aegis/aeca.c'\" unpacked with wrong size!
fi
# end of 'aegis/aeca.c'
fi
if test -f 'aegis/aede.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'aegis/aede.c'\"
else
echo shar: Extracting \"'aegis/aede.c'\" \(17211 characters\)
sed "s/^X//" >'aegis/aede.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 end
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 <aede.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_end_usage _((void));
X
Xstatic void
Xdevelop_end_usage()
X{
X char *progname;
X
X progname = option_progname_get();
X fprintf(stderr, "usage: %s -Develop_End [ <option>... ]\n", progname);
X fprintf(stderr, " %s -Develop_End -List [ <option>... ]\n", progname);
X fprintf(stderr, " %s -Develop_End -Help\n", progname);
X quit(1);
X}
X
X
Xstatic void develop_end_help _((void));
X
Xstatic void
Xdevelop_end_help()
X{
X static char *text[] =
X {
X"NAME",
X" %s -Develop_End - complete development of a change",
X"",
X"SYNOPSIS",
X" %s -Develop_End [ <option>... ]",
X" %s -Develop_End -List [ <option>... ]",
X" %s -Develop_End -Help",
X"",
X"DESCRIPTION",
X" The %s -Develop_End command is used to notify",
X" %s of the completion of the development of a change.",
X"",
X" Successful execution of the command advances the change",
X" from the 'being_developed' state to the 'being_reviewed'",
X" state.",
X"",
X" The ownership of files in the development directory is",
X" changed to the project owner and group, and the files",
X" changed to be read-only. This prevents accidental",
X" alterations of the change's files between development and",
X" integration.",
X"",
X" The change is no longer considered assigned to the",
X" current user.",
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 aede '%s -de \\!* -v'",
X" sh$ aede(){%s -de $* -v}",
X"",
X"ERRORS",
X" It is an error if the change is not assigned to the",
X" current user.",
X" It is an error if The change is not in the",
X" 'being_developed' state.",
X" It is an error if there has been no successful '%s",
X" -Build' command since a change file was last edited.",
X" It is an error if there has been no successful '%s",
X" -DIFFerence' command since a change file was last edited.",
X" It is an error if there has been no successful '%s",
X" -Test' command since a change file was last edited.",
X" It is an error if there has been no successful '%s",
X" -Test -BaseLine' command since a change file was last",
X" edited.",
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_end_usage);
X}
X
X
Xstatic void develop_end_list _((void));
X
Xstatic void
Xdevelop_end_list()
X{
X string_ty *project_name;
X
X trace(("develop_end_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_end_usage);
X continue;
X
X case arglex_token_project:
X if (arglex() != arglex_token_string)
X develop_end_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_developed
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 de_func _((void *, dir_walk_message_ty, string_ty *, struct stat *));
X
Xstatic void
Xde_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(("de_func(message = %d, path = \"%s\", st = %08lX)\n{\n"/*}*/,
X message, path->str_text, st));
X cp = (change_ty *)arg;
X switch (message)
X {
X case dir_walk_file:
X case dir_walk_dir_after:
X os_become_query(&uid, (int *)0, (int *)0);
X if (st->st_uid == uid)
X {
X os_chmod(path, st->st_mode & 07555);
X undo_chmod(path, st->st_mode);
X }
X repair_diff_time(cp, path);
X break;
X
X case dir_walk_special:
X case dir_walk_symlink:
X case dir_walk_dir_before:
X break;
X }
X trace((/*{*/"}\n"));
X}
X
X
Xstatic void develop_end_main _((void));
X
Xstatic void
Xdevelop_end_main()
X{
X string_ty *dd;
X cstate cstate_data;
X pstate pstate_data;
X int j;
X cstate_history history_data;
X string_ty *project_name;
X project_ty *pp;
X long change_number;
X change_ty *cp;
X user_ty *up;
X int build_whine;
X int test_whine;
X int test_bl_whine;
X int reg_test_whine;
X int diff_whine;
X int errs;
X
X trace(("develop_end_main()\n{\n"/*}*/));
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(develop_end_usage);
X continue;
X
X case arglex_token_change:
X if (arglex() != arglex_token_number)
X develop_end_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 develop_end_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 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 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. Block until can get both simultaneously.
X */
X project_pstate_lock_prepare(pp);
X change_cstate_lock_prepare(cp);
X user_ustate_lock_prepare(up);
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 in-development state.
X * It is an error if the change is not assigned to the current user.
X * It is an error if the change has no current diff.
X * It is an error if the change has no current build.
X * It is an error if the change has no current test pass.
X * It is an error if the change has no current baseline test pass.
X * It is an error if the change has no new test associtaed with it.
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 if (!cstate_data->src->length)
X change_fatal(cp, "no files");
X errs = 0;
X build_whine = 0;
X test_whine = 0;
X test_bl_whine = 0;
X reg_test_whine = 0;
X diff_whine = 0;
X
X /*
X * It is an error if any files in the change file table have been
X * modified since the last build.
X * It is an error if any files in the change file table have been
X * modified since the last diff.
X */
X dd = change_development_directory_get(cp, 1);
X user_become(up);
X for (j = 0; j < cstate_data->src->length; ++j)
X {
X cstate_src c_src_data;
X pstate_src p_src_data;
X string_ty *path;
X string_ty *path_d;
X long when;
X long when_d;
X int file_required;
X int diff_file_required;
X
X file_required = 1;
X diff_file_required = 1;
X c_src_data = cstate_data->src->list[j];
X if (c_src_data->action == file_action_remove)
X file_required = 0;
X if (c_src_data->usage == file_usage_build)
X {
X file_required = 0;
X diff_file_required = 0;
X }
X
X /*
X * make sure the file exists
X */
X path = str_format("%S/%S", dd, c_src_data->file_name);
X if (os_exists(path))
X when = os_mtime(path);
X else
X when = 0;
X if (file_required && !when)
X {
X change_error
X (
X cp,
X "file \"%s\" not found",
X c_src_data->file_name->str_text
X );
X str_free(path);
X errs++;
X continue;
X }
X
X /*
X * get the difference time
X */
X path_d = str_format("%S,D", path);
X str_free(path);
X if (os_exists(path_d))
X when_d = os_mtime(path_d);
X else
X when_d = 0;
X str_free(path_d);
X
X if
X (
X file_required
X &&
X (
X when >= cstate_data->build_time
X ||
X !cstate_data->build_time
X )
X )
X {
X if (!build_whine)
X change_error
X (
X cp,
X "no current '%s -Build' registration",
X option_progname_get()
X );
X build_whine++;
X errs++;
X }
X if
X (
X (
X file_required
X &&
X (
X when != c_src_data->diff_time
X ||
X !c_src_data->diff_time
X )
X )
X ||
X (
X diff_file_required
X &&
X (
X when_d != c_src_data->diff_file_time
X ||
X !c_src_data->diff_file_time
X )
X )
X )
X {
X if (!diff_whine)
X change_error
X (
X cp,
X "no current '%s -Diff' registration",
X option_progname_get()
X );
X diff_whine++;
X errs++;
X }
X if
X (
X !cstate_data->test_exempt
X &&
X file_required
X &&
X (
X when >= cstate_data->test_time
X ||
X !cstate_data->test_time
X )
X )
X {
X if (!test_whine)
X change_error
X (
X cp,
X "no current '%s -Test' registration",
X option_progname_get()
X );
X test_whine++;
X errs++;
X }
X if
X (
X !cstate_data->test_baseline_exempt
X &&
X file_required
X &&
X (
X when >= cstate_data->test_baseline_time
X ||
X !cstate_data->test_baseline_time
X )
X )
X {
X if (!test_bl_whine)
X change_error
X (
X cp,
X "no current '%s -Test -BaseLine' registration",
X option_progname_get()
X );
X test_bl_whine++;
X errs++;
X }
X if
X (
X !cstate_data->regression_test_exempt
X &&
X file_required
X &&
X (
X when >= cstate_data->regression_test_time
X ||
X !cstate_data->regression_test_time
X )
X )
X {
X if (!reg_test_whine)
X change_error
X (
X cp,
X "no current '%s -Test -REGression' registration",
X option_progname_get()
X );
X reg_test_whine++;
X errs++;
X }
X
X /*
X * It is an error if any files in the change file table haved
X * different edit numbers to the baseline file table edit
X * numbers.
X */
X if (c_src_data->action != file_action_create)
X {
X p_src_data = project_src_find(pp, c_src_data->file_name);
X if (!p_src_data)
X {
X change_error
X (
X cp,
X "file \"%S\" no longer in baseline",
X c_src_data->file_name
X );
X errs++;
X }
X if
X (
X !str_equal
X (
X c_src_data->edit_number,
X p_src_data->edit_number
X )
X )
X {
X change_error
X (
X cp,
X "file \"%S\" in baseline has changed since last '%s -DIFFerence' command",
X c_src_data->file_name,
X option_progname_get()
X );
X errs++;
X }
X
X /*
X * make sure we can lock the file
X */
X if (p_src_data->locked_by)
X {
X change_error
X (
X cp,
X "file \"%S\" locked for change %d",
X c_src_data->file_name,
X p_src_data->locked_by
X );
X errs++;
X }
X }
X else
X {
X /*
X * add a new entry to the pstate src list,
X * and mark it as "about to be created".
X */
X p_src_data = project_src_new(pp, c_src_data->file_name);
X p_src_data->usage = c_src_data->usage;
X p_src_data->about_to_be_created_by = change_number;
X }
X p_src_data->locked_by = change_number;
X }
X if (errs)
X quit(1);
X
X /*
X * Change all of the files in the development directory
X * to be read-only, and record the new ctime.
X */
X dir_walk(dd, de_func, cp);
X user_become_undo();
X
X /*
X * add to history for state change
X */
X history_data = change_history_new(cp, up);
X history_data->what = cstate_history_what_develop_end;
X
X /*
X * Advance the change to the being-reviewed state.
X * Clear the build-time field.
X * Clear the test-time field.
X * Clear the test-baseline-time field.
X */
X cstate_data->state = cstate_state_being_reviewed;
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 * Remove the change from the list of assigned changes in the user
X * change table (in the user row).
X */
X user_own_remove(up, project_name_get(pp), change_number);
X
X /*
X * Write the change table row.
X * Write the user table row.
X * Release advisory locks.
X */
X change_cstate_write(cp);
X project_pstate_write(pp);
X user_ustate_write(up);
X commit();
X lock_release();
X
X /*
X * run the notify command
X */
X change_run_develop_end_notify_command(cp);
X
X /*
X * verbose success message
X */
X change_verbose(cp, "development completed");
X change_free(cp);
X project_free(pp);
X user_free(up);
X trace((/*{*/"}\n"));
X}
X
X
Xvoid
Xdevelop_end()
X{
X trace(("develop_end()\n{\n"/*}*/));
X switch (arglex())
X {
X default:
X develop_end_main();
X break;
X
X case arglex_token_help:
X develop_end_help();
X break;
X
X case arglex_token_list:
X develop_end_list();
X break;
X }
X trace((/*{*/"}\n"));
X}
END_OF_FILE
if test 17211 -ne `wc -c <'aegis/aede.c'`; then
echo shar: \"'aegis/aede.c'\" unpacked with wrong size!
fi
# end of 'aegis/aede.c'
fi
if test -f 'aegis/aeif.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'aegis/aeif.c'\"
else
echo shar: Extracting \"'aegis/aeif.c'\" \(14342 characters\)
sed "s/^X//" >'aegis/aeif.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 for implementing integrate fail
X */
X
X#include <stdio.h>
X#include <stdlib.h>
X#include <string.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X
X#include <aeif.h>
X#include <ael.h>
X#include <arglex2.h>
X#include <commit.h>
X#include <change.h>
X#include <dir.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 <sub.h>
X#include <trace.h>
X#include <undo.h>
X#include <user.h>
X
X
Xstatic void integrate_fail_usage _((void));
X
Xstatic void
Xintegrate_fail_usage()
X{
X char *progname;
X
X progname = option_progname_get();
X fprintf(stderr, "usage: %s -Integrate_FAIL <reason-file> [ <option>... ]\n", progname);
X fprintf(stderr, " %s -Integrate_FAIL -Edit [ <option>... ]\n", progname);
X fprintf(stderr, " %s -Integrate_FAIL -List [ <option>... ]\n", progname);
X fprintf(stderr, " %s -Integrate_FAIL -Help\n", progname);
X quit(1);
X}
X
X
Xstatic void integrate_fail_help _((void));
X
Xstatic void
Xintegrate_fail_help()
X{
X static char *text[] =
X {
X"NAME",
X" %s -Integrate_FAIL - fail a change integration",
X"",
X"SYNOPSIS",
X" %s -Integrate_FAIL <reason-file> [ <option>... ]",
X" %s -Integrate_FAIL -Edit [ <option>... ]",
X" %s -Integrate_FAIL -List [ <option>... ]",
X" %s -Integrate_FAIL -Help",
X"",
X"DESCRIPTION",
X" The %s -Integrate_FAIL command is used to inform %s",
X" that a change has failed integration.",
X"",
X" The change will be returned from the 'being_integrated'",
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. The integration",
X" directory will be deleted.",
X"",
X" The reviewer and the developer will be notified by mail.",
X" See the integrate_fail_notify_command in aepconf(5) for",
X" more information.",
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" -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 aeif '%s -if \\!* -v'",
X" sh$ aeif(){%s -if $* -v}",
X"",
X"ERRORS",
X" It is an error if the change is not in the",
X" 'being_integrated' 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), integrate_fail_usage);
X}
X
X
Xstatic void integrate_fail_list _((void (*)(void)));
X
Xstatic void
Xintegrate_fail_list(usage)
X void (*usage)_((void));
X{
X string_ty *project_name;
X
X trace(("integrate_fail_list()\n{\n"/*}*/));
X arglex();
X project_name = 0;
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 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_integrated
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 if_func _((void *, dir_walk_message_ty, string_ty *, struct stat *));
X
Xstatic void
Xif_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(("if_func(message = %d, path = \"%s\", st = %08lX)\n{\n"/*}*/,
X message, path->str_text, st));
X cp = (change_ty *)arg;
X switch (message)
X {
X case dir_walk_dir_before:
X case dir_walk_file:
X os_become_query(&uid, (int *)0, (int *)0);
X if (st->st_uid == uid)
X {
X os_chmod
X (
X path,
X (st->st_mode | 0644) & ~change_umask(cp)
X );
X undo_chmod(path, st->st_mode);
X repair_diff_time(cp, path);
X }
X break;
X
X case dir_walk_special:
X case dir_walk_symlink:
X case dir_walk_dir_after:
X break;
X }
X trace((/*{*/"}\n"));
X}
X
X
Xstatic void integrate_fail_main _((void));
X
Xstatic void
Xintegrate_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 string_ty *rev_name;
X string_ty *int_name;
X string_ty *dir;
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(("integrate_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(integrate_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 integrate_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 integrate_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 users 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_integrated' state.
X */
X if (cstate_data->state != cstate_state_being_integrated)
X change_fatal(cp, "not in 'being_integrated' state");
X if (!str_equal(change_integrator_name(cp), user_name(up)))
X {
X change_fatal
X (
X cp,
X "user \"%S\" not the integrator",
X user_name(up)
X );
X }
X
X /*
X * Change the state.
X * Add to the change's history.
X */
X history_data = change_history_new(cp, up);
X history_data->what = cstate_history_what_integrate_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 rev_name = change_reviewer_name(cp);
X int_name = change_integrator_name(cp);
X cstate_data->delta_number = 0;
X dir = str_copy(change_integration_directory_get(cp, 1));
X change_integration_directory_clear(cp);
X cstate_data->state = cstate_state_being_developed;
X
X /*
X * Complain if they are in the integration directory,
X * because the rmdir at the end can't then run to completion.
X */
X os_become_orig();
X if (os_below_dir(dir, os_curdir()))
X change_fatal(cp, "please leave the integration directory");
X os_become_undo();
X
X /*
X * note that the project has no current integration
X */
X pstate_data->currently_integrating_change = 0;
X
X /*
X * Remove it from the integrator's change list, and
X * add it back into the developer's change list.
X */
X user_own_remove(up, project_name_get(pp), change_number);
X devup = user_symbolic(pp, change_developer_name(cp));
X user_own_add(devup, project_name_get(pp), change_number);
X
X /*
X * make the change files writable again
X */
X change_verbose(cp, "make the development directory writable again");
X dd = change_development_directory_get(cp, 1);
X user_become(devup);
X dir_walk(dd, if_func, cp);
X user_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 * remove the integration directory
X */
X change_verbose(cp, "remove the integration directory");
X project_become(pp);
X commit_rmdir_tree_errok(dir);
X project_become_undo();
X
X /*
X * write out the data and release the locks
X */
X change_cstate_write(cp);
X user_ustate_write(up);
X user_ustate_write(devup);
X project_pstate_write(pp);
X str_free(dir);
X commit();
X lock_release();
X
X /*
X * run the notify command
X */
X change_run_integrate_fail_notify_command(cp);
X
X /*
X * verbose success message
X */
X change_verbose(cp, "failed integration, 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
Xintegrate_fail()
X{
X trace(("integrate_fail()\n{\n"/*}*/));
X switch (arglex())
X {
X default:
X integrate_fail_main();
X break;
X
X case arglex_token_help:
X integrate_fail_help();
X break;
X
X case arglex_token_list:
X integrate_fail_list(integrate_fail_usage);
X break;
X }
X trace((/*{*/"}\n"));
X}
END_OF_FILE
if test 14342 -ne `wc -c <'aegis/aeif.c'`; then
echo shar: \"'aegis/aeif.c'\" unpacked with wrong size!
fi
# end of 'aegis/aeif.c'
fi
if test -f 'aegis/aemv.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'aegis/aemv.c'\"
else
echo shar: Extracting \"'aegis/aemv.c'\" \(14640 characters\)
sed "s/^X//" >'aegis/aemv.c' <<'END_OF_FILE'
X/*
X * aegis - project change supervisor
X * Copyright (C) 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 manipulate mvs
X */
X
X#include <stdio.h>
X
X#include <ael.h>
X#include <aemv.h>
X#include <arglex2.h>
X#include <change.h>
X#include <commit.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 <user.h>
X#include <word.h>
X
X
Xstatic void move_file_usage _((void));
X
Xstatic void
Xmove_file_usage()
X{
X char *progname;
X
X progname = option_progname_get();
X fprintf
X (
X stderr,
X "usage: %s -MoVe_file [ <option>... ] <old-name> <new-name>...\n",
X progname
X );
X fprintf
X (
X stderr,
X " %s -MoVe_file -List [ <option>... ]\n",
X progname
X );
X fprintf(stderr, " %s -MoVe_file -Help\n", progname);
X quit(1);
X}
X
X
Xstatic void move_file_help _((void));
X
Xstatic void
Xmove_file_help()
X{
X static char *text[] =
X {
X"NAME",
X" aegis -MoVe_file - copy a file into a change",
X"",
X"SYNOPSIS",
X" aegis -MoVe_file [ <option>... ] <old-name> <new-name>",
X" aegis -MoVe_file -List [ <option>... ]",
X" aegis -MoVe_file -Help",
X"",
X"DESCRIPTION",
X" The aegis -MoVe_file command is used to copy a file into",
X" a change, while changing its name at the same time.",
X"",
X" The aegis program will attempt to determine the project",
X" file names from the file names given on the command line.",
X" All file names are stored within aegis projects as",
X" relative to the root of the baseline directory tree. The",
X" development directory and the integration directory are",
X" shadows of this baseline directory, and so these relative",
X" names apply here, 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, the development",
X" directory path, and the integration directory path, to",
X" determine a baseline-relative name. It is an error if",
X" the file named is outside one of these directory trees.",
X"",
X" The named files will be copied from the baseline (old-",
X" file) into the development directory (new-file), and",
X" added to the list of files in the change.",
X"",
X" This command will cancel any build or test registrations,",
X" because adding another file logically invalidates them.",
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/.aegisrc 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" -Help",
X" This option may be used to obtain more",
X" information about how to use the aegis 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" -Not_Logging",
X" This option may be used to disable the automatic",
X" logging of output and errors to a file. This is",
X" often useful when several aegis commands are",
X" combined in a shell script.",
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/.aegisrc 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 aegis to produce",
X" more output. By default aegis 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"",
X"RECOMMENDED ALIAS",
X" The recommended alias for this command is",
X" csh%% alias aemv 'aegis -mv \\!* -v'",
X" sh$ aemv(){aegis -mv $* -v}",
X"",
X"ERRORS",
X" It is an error if the change is not in the being",
X" developed state.",
X" It is an error if the change is not assigned to the",
X" current user.",
X" It is an error if either file is already in the change.",
X"",
X"EXIT STATUS",
X" The aegis command will exit with a status of 1 on any",
X" error. The aegis 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), move_file_usage);
X}
X
X
Xstatic void move_file_list _((void));
X
Xstatic void
Xmove_file_list()
X{
X string_ty *project_name;
X long change_number;
X
X trace(("move_file_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(move_file_usage);
X continue;
X
X case arglex_token_change:
X if (arglex() != arglex_token_number)
X move_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 move_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 move_file_main _((void));
X
Xstatic void
Xmove_file_main()
X{
X string_ty *dd;
X string_ty *bl;
X string_ty *old_name;
X string_ty *new_name;
X string_ty *s1;
X string_ty *s2;
X cstate cstate_data;
X pstate pstate_data;
X wlist wl;
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 *config_name;
X string_ty *from;
X string_ty *to;
X cstate_src c_src_data;
X pstate_src p_src_data;
X
X trace(("move_file_main()\n{\n"/*}*/));
X old_name = 0;
X new_name = 0;
X project_name = 0;
X change_number = 0;
X nolog = 0;
X while (arglex_token != arglex_token_eoln)
X {
X switch (arglex_token)
X {
X default:
X generic_argument(move_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 str_free(s1);
X if (!old_name)
X old_name = s2;
X else if (!new_name)
X new_name = s2;
X else
X fatal("too many file names");
X break;
X
X case arglex_token_change:
X if (arglex() != arglex_token_number)
X move_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 (project_name)
X goto duplicate;
X if (arglex() != arglex_token_string)
X move_file_usage();
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 arglex();
X }
X if (!old_name || !new_name)
X move_file_usage();
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 * To cope with automounters, directories are stored as given,
X * or are derived from the home directory in the passwd file.
X * Within aegis, pathnames have their symbolic links resolved,
X * and any comparison of paths is done on this "system idea"
X * of the pathname.
X */
X config_name = str_from_c(THE_CONFIG_FILE);
X if
X (
X str_equal(old_name, config_name)
X ||
X str_equal(new_name, config_name)
X )
X fatal("may not rename the \"%s\" file", THE_CONFIG_FILE);
X str_free(config_name);
X
X dd = change_development_directory_get(cp, 1);
X bl = project_baseline_path_get(pp, 1);
X
X os_become_orig();
X assert(old_name->str_text[0] == '/');
X s2 = os_below_dir(dd, old_name);
X if (!s2)
X s2 = os_below_dir(bl, old_name);
X if (!s2)
X change_fatal(cp, "path \"%S\" unrelated", old_name);
X str_free(old_name);
X old_name = s2;
X
X assert(new_name->str_text[0] == '/');
X s2 = os_below_dir(dd, new_name);
X if (!s2)
X s2 = os_below_dir(bl, new_name);
X if (!s2)
X change_fatal(cp, "path \"%S\" unrelated", new_name);
X str_free(new_name);
X new_name = s2;
X os_become_undo();
X
X /*
X * ensure that the old file
X * 1. is not already part of the change
X * 2. is in the baseline
X * 3. is not a test
X */
X if (change_src_find(cp, old_name))
X change_fatal(cp, "file \"%S\" already in change", old_name);
X p_src_data = project_src_find(pp, old_name);
X if
X (
X !p_src_data
X ||
X p_src_data->about_to_be_created_by
X ||
X p_src_data->deleted_by
X )
X project_fatal(pp, "file \"%S\" unknown", old_name);
X if
X (
X p_src_data->usage == file_usage_test
X ||
X p_src_data->usage == file_usage_manual_test
X )
X project_fatal(pp, "may not move tests");
X
X /*
X * ensure that the new file
X * 1. is not already part of the change
X * 2. is not in the baseline
X */
X if (change_src_find(cp, new_name))
X change_fatal(cp, "file \"%S\" already in change", new_name);
X p_src_data = project_src_find(pp, new_name);
X if
X (
X p_src_data
X &&
X !p_src_data->about_to_be_created_by
X &&
X !p_src_data->deleted_by
X )
X {
X project_fatal
X (
X pp,
X "file \"%S\" is already in the baseline",
X new_name
X );
X }
X
X /*
X * Copy the file into the development directory.
X * Create any necessary directories along the way.
X */
X from = str_format("%S/%S", bl, old_name);
X to = str_format("%S/%S", dd, new_name);
X user_become(up);
X os_mkdir_between(dd, new_name, 02755);
X copy_whole_file(from, to, 0);
X user_become_undo();
X str_free(from);
X str_free(to);
X
X /*
X * Add the files to the change
X */
X p_src_data = project_src_find(pp, old_name);
X assert(p_src_data);
X c_src_data = change_src_new(cp);
X c_src_data->file_name = str_copy(old_name);
X c_src_data->action = file_action_remove;
X c_src_data->usage = p_src_data->usage;
X c_src_data->move = str_copy(new_name);
X c_src_data->edit_number = str_copy(p_src_data->edit_number);
X
X c_src_data = change_src_new(cp);
X c_src_data->file_name = str_copy(new_name);
X c_src_data->action = file_action_create;
X c_src_data->usage = p_src_data->usage;
X c_src_data->move = str_copy(old_name);
X
X /*
X * the number of files changed,
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 change_verbose(cp, "file \"%S\" moving to \"%S\"", old_name, new_name);
X
X /*
X * run the change file command
X */
X if (!nolog)
X log_open(change_logfile_get(cp), up);
X wl_zero(&wl);
X wl_append(&wl, old_name);
X wl_append(&wl, new_name);
X change_run_change_file_command(cp, &wl, up);
X wl_free(&wl);
X str_free(old_name);
X str_free(new_name);
X project_free(pp);
X change_free(cp);
X user_free(up);
X trace((/*{*/"}\n"));
X}
X
X
Xvoid
Xmove_file()
X{
X trace(("move_file()\n{\n"/*}*/));
X switch (arglex())
X {
X default:
X move_file_main();
X break;
X
X case arglex_token_help:
X move_file_help();
X break;
X
X case arglex_token_list:
X move_file_list();
X break;
X }
X trace((/*{*/"}\n"));
X}
END_OF_FILE
if test 14640 -ne `wc -c <'aegis/aemv.c'`; then
echo shar: \"'aegis/aemv.c'\" unpacked with wrong size!
fi
# end of 'aegis/aemv.c'
fi
if test -f 'aegis/aepa.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'aegis/aepa.c'\"
else
echo shar: Extracting \"'aegis/aepa.c'\" \(15749 characters\)
sed "s/^X//" >'aegis/aepa.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 list and modify project attributes
X */
X
X#include <stdio.h>
X#include <stdlib.h>
X
X#include <aepa.h>
X#include <arglex2.h>
X#include <commit.h>
X#include <conf.h>
X#include <error.h>
X#include <help.h>
X#include <lock.h>
X#include <option.h>
X#include <os.h>
X#include <pattr.h>
X#include <project.h>
X#include <trace.h>
X#include <user.h>
X
X
Xstatic void project_attributes_usage _((void));
X
Xstatic void
Xproject_attributes_usage()
X{
X char *progname;
X
X progname = option_progname_get();
X fprintf(stderr, "usage: %s -Project_Attributes <attr-file> [ <option>... ]\n", progname);
X fprintf(stderr, " %s -Project_Attributes -Edit [ <option>... ]\n", progname);
X fprintf(stderr, " %s -Project_Attributes -List [ <option>... ]\n", progname);
X fprintf(stderr, " %s -Project_Attributes -Help\n", progname);
X quit(1);
X}
X
X
Xstatic void project_attributes_help _((void));
X
Xstatic void
Xproject_attributes_help()
X{
X static char *text[] =
X {
X"NAME",
X" %s -Project_Attributes - modify the attributes of a",
X" project",
X"",
X"SYNOPSIS",
X" %s -Project_Attributes <attr-file> [ <option>... ]",
X" %s -Project_Attributes -Edit [ <option>... ]",
X" %s -Project_Attributes -List [ <option>... ]",
X" %s -Project_Attributes -Help",
X"",
X"DESCRIPTION",
X" The %s -Project_Attributes command is used to set,",
X" edit or list the attributes of a project.",
X"",
X" The output of the -List variant is suitable for use as",
X" input at a later time.",
X"",
X" See aepattr(5) for a description of the file format.",
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 aepa '%s -pa \\!* -v'",
X" sh$ aepa(){%s -pa $* -v}",
X"",
X"ERRORS",
X" It is an error if the current user is not an",
X" administrator of 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), project_attributes_usage);
X}
X
X
Xstatic void pattr_copy _((pattr, pstate));
X
Xstatic void
Xpattr_copy(a, s)
X pattr a;
X pstate s;
X{
X if (!a->description && s->description)
X a->description = str_copy(s->description);
X if (!a->owner_name && s->owner_name)
X a->owner_name = str_copy(s->owner_name);
X if (!a->group_name && s->group_name)
X a->group_name = str_copy(s->group_name);
X if
X (
X !a->default_development_directory
X &&
X s->default_development_directory
X )
X a->default_development_directory =
X str_copy(s->default_development_directory);
X
X if (!(a->mask & pattr_developer_may_review_mask))
X a->developer_may_review = s->developer_may_review;
X if (!(a->mask & pattr_developer_may_integrate_mask))
X a->developer_may_integrate = s->developer_may_integrate;
X if (!(a->mask & pattr_reviewer_may_integrate_mask))
X a->reviewer_may_integrate = s->reviewer_may_integrate;
X if (!(a->mask & pattr_developers_may_create_changes_mask))
X a->developers_may_create_changes =
X s->developers_may_create_changes;
X if (!(a->mask & pattr_umask_mask))
X a->umask = s->umask;
X if (!(a->mask & pattr_default_test_exemption_mask))
X a->default_test_exemption = s->default_test_exemption;
X
X if (!a->develop_end_notify_command && s->develop_end_notify_command)
X a->develop_end_notify_command =
X str_copy(s->develop_end_notify_command);
X if
X (
X !a->develop_end_undo_notify_command
X &&
X s->develop_end_undo_notify_command
X )
X a->develop_end_undo_notify_command =
X str_copy(s->develop_end_undo_notify_command);
X if
X (
X !a->review_pass_notify_command
X &&
X s->review_pass_notify_command
X )
X a->review_pass_notify_command =
X str_copy(s->review_pass_notify_command);
X if
X (
X !a->review_pass_undo_notify_command
X &&
X s->review_pass_undo_notify_command
X )
X a->review_pass_undo_notify_command =
X str_copy(s->review_pass_undo_notify_command);
X if
X (
X !a->review_fail_notify_command
X &&
X s->review_fail_notify_command
X )
X a->review_fail_notify_command =
X str_copy(s->review_fail_notify_command);
X if
X (
X !a->integrate_pass_notify_command
X &&
X s->integrate_pass_notify_command
X )
X a->integrate_pass_notify_command =
X str_copy(s->integrate_pass_notify_command);
X if
X (
X !a->integrate_fail_notify_command
X &&
X s->integrate_fail_notify_command
X )
X a->integrate_fail_notify_command =
X str_copy(s->integrate_fail_notify_command);
X}
X
X
Xstatic void project_attributes_list _((void));
X
Xstatic void
Xproject_attributes_list()
X{
X pattr pattr_data;
X pstate pstate_data;
X string_ty *project_name;
X project_ty *pp;
X
X trace(("project_attributes_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(project_attributes_usage);
X continue;
X
X case arglex_token_project:
X if (arglex() != arglex_token_string)
X project_attributes_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 pstate_data = project_pstate_get(pp);
X pattr_data = (pattr)pattr_type.alloc();
X pattr_copy(pattr_data, pstate_data);
X pattr_write_file((char *)0, pattr_data);
X pattr_type.free(pattr_data);
X project_free(pp);
X trace((/*{*/"}\n"));
X}
X
X
Xstatic void pattr_edit _((pattr *));
X
Xstatic void
Xpattr_edit(dp)
X pattr *dp;
X{
X pattr d;
X string_ty *filename;
X
X /*
X * write attributes to temporary file
X */
X d = *dp;
X assert(d);
X filename = os_edit_filename();
X os_become_orig();
X pattr_write_file(filename->str_text, d);
X pattr_type.free(d);
X
X /*
X * edit the file
X */
X os_edit(filename);
X
X /*
X * read it in again
X */
X d = pattr_read_file(filename->str_text);
X os_unlink(filename);
X os_become_undo();
X str_free(filename);
X *dp = d;
X}
X
X
Xstatic void project_attributes_main _((void));
X
Xstatic void
Xproject_attributes_main()
X{
X pattr pattr_data = 0;
X pstate pstate_data;
X string_ty *project_name;
X project_ty *pp;
X string_ty *s;
X int edit;
X user_ty *up;
X
X trace(("project_attributes_main()\n{\n"/*}*/));
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(project_attributes_usage);
X continue;
X
X case arglex_token_string:
X if (pattr_data)
X fatal("too many files named");
X os_become_orig();
X pattr_data = pattr_read_file(arglex_value.alv_string);
X os_become_undo();
X assert(pattr_data);
X break;
X
X case arglex_token_project:
X if (arglex() != arglex_token_string)
X project_attributes_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 && !pattr_data)
X pattr_data = (pattr)pattr_type.alloc();
X if (!pattr_data)
X fatal("no project attributes file 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 * edit the attributes
X */
X if (edit)
X {
X /*
X * copy things from project
X */
X pstate_data = project_pstate_get(pp);
X pattr_copy(pattr_data, pstate_data);
X
X /*
X * edit them
X */
X pattr_edit(&pattr_data);
X }
X
X /*
X * take project lock
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 the user is not an administrator
X */
X if (!project_administrator_query(pp, user_name(up)))
X {
X project_fatal
X (
X pp,
X "attributes may only be changed by a project administrator"
X );
X }
X
X if (pattr_data->description)
X {
X if (pstate_data->description)
X str_free(pstate_data->description);
X pstate_data->description = str_copy(pattr_data->description);
X }
X
X if (pattr_data->owner_name)
X {
X if (!user_uid_check(pattr_data->owner_name))
X {
X fatal
X (
X "user \"%s\" is too privileged",
X pattr_data->owner_name->str_text
X );
X }
X if (pstate_data->owner_name)
X str_free(pstate_data->owner_name);
X pstate_data->owner_name = str_copy(pattr_data->owner_name);
X }
X
X if (pattr_data->group_name)
X {
X if (!user_gid_check(pattr_data->group_name))
X {
X fatal
X (
X "group \"%s\" is too privileged",
X pattr_data->group_name->str_text
X );
X }
X if (pstate_data->group_name)
X str_free(pstate_data->group_name);
X pstate_data->group_name = str_copy(pattr_data->group_name);
X }
X
X if (pattr_data->mask & pattr_developer_may_review_mask)
X pstate_data->developer_may_review =
X pattr_data->developer_may_review;
X if (pattr_data->mask & pattr_developer_may_integrate_mask)
X pstate_data->developer_may_integrate =
X pattr_data->developer_may_integrate;
X if (pattr_data->mask & pattr_reviewer_may_integrate_mask)
X pstate_data->reviewer_may_integrate =
X pattr_data->reviewer_may_integrate;
X if (pattr_data->mask & pattr_developers_may_create_changes_mask)
X pstate_data->developers_may_create_changes =
X pattr_data->developers_may_create_changes;
X
X /*
X * only some combos work,
X * umask is basically for the "other" permissions
X */
X if (pattr_data->mask & pattr_umask_mask)
X pstate_data->umask = (pattr_data->umask & 5) | 022;
X
X if (pattr_data->mask & pattr_default_test_exemption_mask)
X pstate_data->default_test_exemption =
X pattr_data->default_test_exemption;
X
X if (pattr_data->develop_end_notify_command)
X {
X if (pstate_data->develop_end_notify_command)
X str_free(pstate_data->develop_end_notify_command);
X pstate_data->develop_end_notify_command =
X str_copy(pattr_data->develop_end_notify_command);
X }
X
X if (pattr_data->develop_end_undo_notify_command)
X {
X if (pstate_data->develop_end_undo_notify_command)
X str_free(pstate_data->develop_end_undo_notify_command);
X pstate_data->develop_end_undo_notify_command =
X str_copy(pattr_data->develop_end_undo_notify_command);
X }
X
X if (pattr_data->review_pass_notify_command)
X {
X if (pstate_data->review_pass_notify_command)
X str_free(pstate_data->review_pass_notify_command);
X pstate_data->review_pass_notify_command =
X str_copy(pattr_data->review_pass_notify_command);
X }
X
X if (pattr_data->review_pass_undo_notify_command)
X {
X if (pstate_data->review_pass_undo_notify_command)
X str_free(pstate_data->review_pass_undo_notify_command);
X pstate_data->review_pass_undo_notify_command =
X str_copy(pattr_data->review_pass_undo_notify_command);
X }
X
X if (pattr_data->review_fail_notify_command)
X {
X if (pstate_data->review_fail_notify_command)
X str_free(pstate_data->review_fail_notify_command);
X pstate_data->review_fail_notify_command =
X str_copy(pattr_data->review_fail_notify_command);
X }
X
X if (pattr_data->integrate_pass_notify_command)
X {
X if (pstate_data->integrate_pass_notify_command)
X str_free(pstate_data->integrate_pass_notify_command);
X pstate_data->integrate_pass_notify_command =
X str_copy(pattr_data->integrate_pass_notify_command);
X }
X
X if (pattr_data->integrate_fail_notify_command)
X {
X if (pstate_data->integrate_fail_notify_command)
X str_free(pstate_data->integrate_fail_notify_command);
X pstate_data->integrate_fail_notify_command =
X str_copy(pattr_data->integrate_fail_notify_command);
X }
X
X if (pattr_data->default_development_directory)
X {
X if (pstate_data->default_development_directory)
X str_free(pstate_data->default_development_directory);
X s = pattr_data->default_development_directory;
X if (!s->str_length)
X pstate_data->default_development_directory = 0;
X else
X {
X if (s->str_text[0] != '/')
X {
X fatal
X (
X "default development directory must be specified as an absolute path"
X );
X }
X pstate_data->default_development_directory =
X str_copy(s);
X }
X }
X
X pattr_type.free(pattr_data);
X project_pstate_write(pp);
X commit();
X lock_release();
X project_verbose(pp, "attributes changed");
X project_free(pp);
X user_free(up);
X trace((/*{*/"}\n"));
X}
X
X
Xvoid
Xproject_attributes()
X{
X trace(("project_attributes()\n{\n"/*}*/));
X switch (arglex())
X {
X default:
X project_attributes_main();
X break;
X
X case arglex_token_help:
X project_attributes_help();
X break;
X
X case arglex_token_list:
X project_attributes_list();
X break;
X }
X trace((/*{*/"}\n"));
X}
END_OF_FILE
if test 15749 -ne `wc -c <'aegis/aepa.c'`; then
echo shar: \"'aegis/aepa.c'\" unpacked with wrong size!
fi
# end of 'aegis/aepa.c'
fi
if test -f 'aegis/gonzo.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'aegis/gonzo.c'\"
else
echo shar: Extracting \"'aegis/gonzo.c'\" \(16800 characters\)
sed "s/^X//" >'aegis/gonzo.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 for manipulating global state data
X */
X
X#include <stdio.h>
X#include <stdlib.h>
X#include <string.h>
X#include <unistd.h>
X
X#include <commit.h>
X#include <conf.h>
X#include <error.h>
X#include <gonzo.h>
X#include <gstate.h>
X#include <lock.h>
X#include <mem.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 <ustate.h>
X#include <word.h>
X
Xtypedef struct gonzo_ty gonzo_ty;
Xstruct gonzo_ty
X{
X string_ty *dir;
X string_ty *gstate_filename;
X gstate gstate_data;
X int is_a_new_file;
X int modified;
X long lock_magic;
X int temporary;
X};
X
Xstatic size_t ngonzos;
Xstatic gonzo_ty **gonzo;
Xstatic int done_tail;
X
X
Xstatic user_ty *gonzo_user _((void));
X
Xstatic user_ty *
Xgonzo_user()
X{
X static user_ty *u;
X
X if (!u)
X {
X string_ty *s;
X
X s = str_from_c(AEGIS_USER);
X u = user_symbolic((project_ty *)0, s);
X u->umask = 022;
X str_free(s);
X }
X return u;
X}
X
X
Xstatic int is_temporary _((string_ty *));
X
Xstatic int
Xis_temporary(s)
X string_ty *s;
X{
X return
X (
X !strncmp(s->str_text, "/tmp/", 5)
X ||
X !strncmp(s->str_text, "/usr/tmp/", 9)
X ||
X !strncmp(s->str_text, "/var/tmp/", 9)
X );
X}
X
X
Xvoid
Xgonzo_library_append(s)
X char *s;
X{
X gonzo_ty *gp;
X string_ty *tmp;
X string_ty *dir;
X
X /*
X * resolve the pathname
X */
X trace(("gonzo_library_append(s = \"%s\")\n{\n"/*}*/, s));
X assert(s);
X assert(!done_tail);
X tmp = str_from_c(s);
X os_become_orig();
X dir = os_pathname(tmp, 1);
X os_become_undo();
X str_free(tmp);
X
X /*
X * append the new entry to the end of the list
X */
X gp = (gonzo_ty *)mem_alloc_clear(sizeof(gonzo_ty));
X gp->dir = dir;
X gp->temporary = is_temporary(dir);
X gp->gstate_filename = str_format("%S/state", gp->dir);
X *(gonzo_ty **)
X enlarge
X (
X &ngonzos,
X (char **)&gonzo, sizeof(gonzo_ty *)
X ) =
X gp;
X trace((/*{*/"}\n"));
X}
X
X
Xstatic void lock_sync _((gonzo_ty *));
X
Xstatic void
Xlock_sync(gp)
X gonzo_ty *gp;
X{
X long n;
X
X trace(("lock_sync(gp = %08lX)\n{\n"/*}*/, gp));
X n = lock_magic();
X if (gp->lock_magic == n)
X goto ret;
X gp->lock_magic = n;
X
X if (gp->gstate_data && !gp->is_a_new_file)
X {
X gstate_type.free(gp->gstate_data);
X gp->gstate_data = 0;
X }
X ret:
X trace((/*{*/"}\n"));
X}
X
X
X
Xstatic gstate gonzo_gstate_get _((gonzo_ty *));
X
Xstatic gstate
Xgonzo_gstate_get(gp)
X gonzo_ty *gp;
X{
X trace(("gonzo_gstate_get(gp = %08lX)\n{\n"/*}*/, gp));
X lock_sync(gp);
X if (!gp->gstate_data)
X {
X gonzo_become();
X gp->is_a_new_file = !os_exists(gp->gstate_filename);
X if (!gp->is_a_new_file)
X {
X os_chown_check
X (
X gp->gstate_filename,
X 0644,
X user_id(gonzo_user()),
X user_gid(gonzo_user())
X );
X gp->gstate_data =
X gstate_read_file(gp->gstate_filename->str_text);
X }
X else
X gp->gstate_data = (gstate)gstate_type.alloc();
X if (!gp->gstate_data->where)
X gp->gstate_data->where =
X (gstate_where_list)
X gstate_where_list_type.alloc();
X gonzo_become_undo();
X }
X trace(("return %08lX;\n", gp->gstate_data));
X trace((/*{*/"}\n"));
X return gp->gstate_data;
X}
X
X
X/*
X * NAME
X * construct_library_directory
X *
X * SYNOPSIS
X * void construct_library_directory(gonzo_ty *gp);
X *
X * DESCRIPTION
X * The construct_library_directory function is used to
X * construct missing elements of the aegis library search path.
X * These elements must be constructed with great care so that
X * they may work on NFS mounted disks of "data-less" clients.
X *
X * The path up to, but not including, the library directory must
X * be owned by the executing user. The actions will fail if the
X * executing user does not have sufficient permissions, as
X * one would expect.
X *
X * The library directory itself must be owned by AEGIS_USER.
X * This is to defend against tampering and ignorance.
X * Having this change of ownership requires some fast footwork
X * with chmod's to allow AEGIS_USER temporary access.
X *
X * ARGUMENTS
X * gp - library directory to act upon
X *
X * CAVEAT
X * The chown() system call will not work on data-less clients,
X * because the remote hosts which owns the NFS mounted disks
X * will rarely trust the local "root" user, and map all
X * foreign "root" users to the "unknown" user instead.
X */
X
Xstatic void construct_library_directory _((gonzo_ty *));
X
Xstatic void
Xconstruct_library_directory(gp)
X gonzo_ty *gp;
X{
X int exists;
X string_ty *above;
X string_ty *above2;
X string_ty *root;
X int mode;
X
X /*
X * If the library directory already exists,
X * then we need do nothing.
X */
X os_become_orig();
X exists = os_exists(gp->dir);
X if (exists)
X {
X os_become_undo();
X return;
X }
X
X /*
X * Construct all directories up to,
X * but not including, the library directory,
X * if they do not already exist.
X * Construct these directories as the original user,
X * possibly discovering relevant permission problems.
X */
X above = os_dirname(gp->dir);
X above2 = str_n_from_c(above->str_text + 1, above->str_length - 1);
X root = str_from_c("/");
X os_mkdir_between(root, above2, 0755); /* NOT setgid */
X str_free(root);
X str_free(above2);
X
X /*
X * Get the mode of the directory containing the library directory,
X * so that we may restore it later. Change the mode to world
X * writable, so that the library directory itself may be created
X * belonging to gonzo.
X */
X mode = os_chmod_query(above);
X mode |= 0111; /* minimum: all may search */
X undo_chmod_errok(above, mode);
X os_chmod(above, mode | 0777);
X os_become_undo();
X
X /*
X * Create the library directory itself belonging to gonzo,
X * and make sure it is world accessable.
X * (must be world writable in testing situations)
X */
X gonzo_become();
X os_mkdir(gp->dir, 0755);
X if (gp->temporary)
X os_chmod(gp->dir, 0777);
X gonzo_become_undo();
X
X /*
X * Restore permissions for the containing directory.
X */
X os_become_orig();
X os_chmod(above, mode);
X os_become_undo();
X str_free(above);
X}
X
X
Xstatic void gonzo_gstate_write_sub _((gonzo_ty *));
X
Xstatic void
Xgonzo_gstate_write_sub(gp)
X gonzo_ty *gp;
X{
X string_ty *filename_new;
X string_ty *filename_old;
X static int count;
X
X if (!gp->modified)
X return;
X trace(("gonzo_gstate_write_sub()\n{\n"/*}*/));
X assert(gp->gstate_data);
X assert(gp->gstate_filename);
X filename_new = str_format("%S,%d", gp->gstate_filename, ++count);
X filename_old = str_format("%S,%d", gp->gstate_filename, ++count);
X if (gp->is_a_new_file)
X {
X construct_library_directory(gp);
X gonzo_become();
X undo_unlink_errok(filename_new);
X gstate_write_file(filename_new->str_text, gp->gstate_data);
X commit_rename(filename_new, gp->gstate_filename);
X os_chmod(filename_new, 0644);
X gonzo_become_undo();
X }
X else
X {
X gonzo_become();
X undo_unlink_errok(filename_new);
X gstate_write_file(filename_new->str_text, gp->gstate_data);
X commit_rename(gp->gstate_filename, filename_old);
X commit_rename(filename_new, gp->gstate_filename);
X commit_unlink_errok(filename_old);
X os_chmod(filename_new, 0644);
X gonzo_become_undo();
X }
X str_free(filename_new);
X str_free(filename_old);
X gp->modified = 0;
X trace((/*{*/"}\n"));
X}
X
X
Xstatic void do_tail _((void));
X
Xstatic void
Xdo_tail()
X{
X string_ty *s1;
X string_ty *s2;
X char *cp;
X wlist path;
X size_t j;
X
X /*
X * only do this once
X */
X if (done_tail)
X return;
X
X /*
X * fetch the environment variable
X */
X trace(("do_tail()\n{\n"/*}*/));
X s1 = str_from_c(option_progname_get());
X s2 = str_upcase(s1);
X str_free(s1);
X cp = getenv(s2->str_text);
X str_free(s2);
X if (cp)
X {
X s1 = str_from_c(cp);
X str2wl(&path, s1, ":");
X str_free(s1);
X for (j = 0; j < path.wl_nwords; ++j)
X {
X s1 = path.wl_word[j];
X if (!os_testing_mode() || is_temporary(s1))
X gonzo_library_append(s1->str_text);
X }
X wl_free(&path);
X }
X
X if (os_testing_mode())
X {
X if (!ngonzos)
X {
X fatal
X (
X"There was no -LIBrary option specified. This is mandatory in \"test\" mode."
X );
X }
X }
X else
X {
X /*
X * always have the system one last
X * (this is where locks are taken)
X */
X gonzo_library_append(LIB);
X }
X done_tail = 1;
X trace((/*{*/"}\n"));
X}
X
X
Xstatic gonzo_ty *gonzo_nth _((size_t));
X
Xstatic gonzo_ty *
Xgonzo_nth(j)
X size_t j;
X{
X gonzo_ty *result;
X
X trace(("gonzo_nth(j = %ld)\n{\n"/*}*/, j));
X do_tail();
X if (j >= ngonzos)
X result = 0;
X else
X result = gonzo[j];
X trace(("return %08lX;\n", result));
X trace((/*{*/"}\n"));
X return result;
X}
X
X
Xvoid
Xgonzo_gstate_write()
X{
X size_t j;
X gonzo_ty *gp;
X
X trace(("gonzo_gstate_write()\n{\n"/*}*/));
X for (j = 0; ; ++j)
X {
X gp = gonzo_nth(j);
X if (!gp)
X break;
X gonzo_gstate_write_sub(gp);
X }
X trace((/*{*/"}\n"));
X}
X
X
Xstatic string_ty *gonzo_project_home_path_sub _((gonzo_ty *, string_ty *));
X
Xstatic string_ty *
Xgonzo_project_home_path_sub(gp, name)
X gonzo_ty *gp;
X string_ty *name;
X{
X gstate gstate_data;
X size_t j;
X string_ty *result;
X
X /*
X * find the project in the gstate
X */
X trace(("gonzo_project_home_path_sub(gp = %08lX, name = \"%s\")\n{\n"/*}*/, gp, name->str_text));
X gstate_data = gonzo_gstate_get(gp);
X assert(gstate_data->where);
X result = 0;
X for (j = 0; j < gstate_data->where->length; ++j)
X {
X gstate_where addr;
X
X addr = gstate_data->where->list[j];
X if (str_equal(addr->project_name, name))
X {
X result = addr->directory;
X break;
X }
X }
X trace(("return \"%s\";\n", (result ? result->str_text : "")));
X trace((/*{*/"}\n"));
X return result;
X}
X
X
Xstring_ty *
Xgonzo_project_home_path_from_name(name)
X string_ty *name;
X{
X gonzo_ty *gp;
X size_t j;
X string_ty *result;
X string_ty *s;
X
X /*
X * find the project in the gstate list
X */
X trace(("gonzo_project_home_path_from_name(name = \"%s\")\n{\n"/*}*/, name->str_text));
X result = 0;
X for (j = 0; ; ++j)
X {
X gp = gonzo_nth(j);
X if (!gp)
X break;
X s = gonzo_project_home_path_sub(gp, name);
X if (s)
X {
X result = s;
X break;
X }
X }
X trace(("return \"%s\";\n", (result ? result->str_text : "")));
X trace((/*{*/"}\n"));
X return result;
X}
X
X
Xvoid
Xgonzo_project_list(result)
X wlist *result;
X{
X size_t n;
X size_t j;
X gonzo_ty *gp;
X gstate gstate_data;
X
X trace(("gonzo_project_list(result = %08lX)\n{\n"/*}*/, result));
X wl_zero(result);
X for (n = 0; ; ++n)
X {
X gp = gonzo_nth(n);
X if (!gp)
X break;
X
X /*
X * read the gstate file
X */
X gstate_data = gonzo_gstate_get(gp);
X
X /*
X * list the projects
X */
X assert(gstate_data->where);
X for (j = 0; j < gstate_data->where->length; ++j)
X {
X wl_append_unique
X (
X result,
X gstate_data->where->list[j]->project_name
X );
X }
X }
X trace((/*{*/"}\n"));
X}
X
X
Xvoid
Xgonzo_project_list_user(uname, result)
X string_ty *uname;
X wlist *result;
X{
X size_t n;
X size_t j;
X
X trace(("gonzo_project_list_user(uname = \"%s\", \
Xresult = %08lX)\n{\n"/*}*/, uname->str_text, result));
X wl_zero(result);
X for (n = 0; ; ++n)
X {
X string_ty *ustate_path;
X ustate ustate_data;
X gonzo_ty *gp;
X
X gp = gonzo_nth(n);
X if (!gp)
X break;
X
X /*
X * check out the ustate
X */
X ustate_path = str_format("%S/user/%S", gp->dir, uname);
X trace(("ustate_path = \"%s\";\n", ustate_path->str_text));
X gonzo_become();
X if (!os_exists(ustate_path))
X {
X gonzo_become_undo();
X str_free(ustate_path);
X continue;
X }
X ustate_data = ustate_read_file(ustate_path->str_text);
X gonzo_become_undo();
X if (!ustate_data->own)
X ustate_data->own =
X (ustate_own_list)
X ustate_own_list_type.alloc();
X str_free(ustate_path);
X
X /*
X * collect all projects this user owns changes in
X */
X for (j = 0; j < ustate_data->own->length; ++j)
X {
X trace(("remember \"%s\";\n",
X ustate_data->own->list[j]->project_name->str_text));
X wl_append_unique
X (
X result,
X ustate_data->own->list[j]->project_name
X );
X }
X ustate_type.free(ustate_data);
X }
X trace(("found %d items\n", result->wl_nwords));
X trace((/*{*/"}\n"));
X}
X
X
Xvoid
Xgonzo_project_add(pp)
X project_ty *pp;
X{
X gstate_where *addr_p;
X gstate_where addr;
X gonzo_ty *gp;
X type_ty *type_p;
X
X trace(("gonzo_project_add(pp = %08lX)\n{\n"/*}*/, pp));
X gp = gonzo_nth(0);
X gstate_where_list_type.list_parse
X (
X gp->gstate_data->where,
X &type_p,
X (void **)&addr_p
X );
X addr = (gstate_where)gstate_where_type.alloc();
X *addr_p = addr;
X trace_pointer(addr);
X addr->project_name = str_copy(project_name_get(pp));
X addr->directory = str_copy(project_home_path_get(pp));
X gp->modified = 1;
X trace((/*{*/"}\n"));
X}
X
X
Xstatic int gonzo_project_delete_sub _((gonzo_ty *, project_ty *));
X
Xstatic int
Xgonzo_project_delete_sub(gp, pp)
X gonzo_ty *gp;
X project_ty *pp;
X{
X gstate gstate_data;
X size_t j;
X int result;
X
X /*
X * find the project in the gstate
X */
X trace(("gonzo_project_delete_sub(gp = %08lX, pp = %08lX)\n{\n"/*}*/,
X gp, pp));
X gstate_data = gonzo_gstate_get(gp);
X assert(gstate_data->where);
X result = 0;
X for (j = 0; j < gstate_data->where->length; ++j)
X {
X gstate_where addr;
X long k;
X
X addr = gstate_data->where->list[j];
X if (!str_equal(addr->project_name, project_name_get(pp)))
X continue;
X
X /*
X * delete the item from the list
X */
X for (k = j + 1; k < gstate_data->where->length; ++k)
X gstate_data->where->list[k - 1] =
X gstate_data->where->list[k];
X gstate_data->where->length--;
X
X /*
X * free the item
X */
X gstate_where_type.free(addr);
X
X /*
X * mark this gstate file as modified
X */
X gp->modified = 1;
X result = 1;
X break;
X }
X trace(("return %d;\n", result));
X trace((/*{*/"}\n"));
X return result;
X}
X
X
Xvoid
Xgonzo_project_delete(pp)
X project_ty *pp;
X{
X gonzo_ty *gp;
X long j;
X
X trace(("gonzo_project_delete(pp = %08lX)\n{\n"/*}*/, pp));
X for (j = 0; ; ++j)
X {
X gp = gonzo_nth(j);
X if (!gp)
X break;
X if (gonzo_project_delete_sub(gp, pp))
X break;
X }
X trace((/*{*/"}\n"));
X}
X
X
Xvoid
Xgonzo_gstate_lock_prepare_new()
X{
X trace(("gonzo_gstate_lock_prepare_new()\n{\n"/*}*/));
X lock_prepare_gstate();
X trace((/*{*/"}\n"));
X}
X
X
Xstring_ty *
Xgonzo_lockpath_get()
X{
X static string_ty *path;
X gonzo_ty *gp;
X
X trace(("gonzo_lockpath_get()\n{\n"/*}*/));
X if (!path)
X {
X do_tail();
X gp = gonzo[ngonzos - 1];
X construct_library_directory(gp);
X path = str_format("%S/lockfile", gp->dir);
X }
X trace(("return \"%s\";\n", path->str_text));
X trace((/*{*/"}\n"));
X return path;
X}
X
X
Xstatic int gonzo_ustate_path_sub _((gonzo_ty *, string_ty *));
X
Xstatic int
Xgonzo_ustate_path_sub(gp, project_name)
X gonzo_ty *gp;
X string_ty *project_name;
X{
X gstate gstate_data;
X size_t j;
X int result;
X
X /*
X * find the project in the gstate
X */
X trace(("gonzo_ustate_path_sub(gp = %08lX)\n{\n"/*}*/, gp));
X gstate_data = gonzo_gstate_get(gp);
X assert(gstate_data->where);
X result = 0;
X for (j = 0; j < gstate_data->where->length; ++j)
X {
X gstate_where addr;
X
X addr = gstate_data->where->list[j];
X if (str_equal(addr->project_name, project_name))
X {
X result = 1;
X break;
X }
X }
X trace(("return %d;\n", result));
X trace((/*{*/"}\n"));
X return result;
X}
X
X
Xstring_ty *
Xgonzo_ustate_path(project_name, user_name)
X string_ty *project_name;
X string_ty *user_name;
X{
X gonzo_ty *gp;
X size_t j;
X string_ty *dir;
X string_ty *result;
X
X /*
X * find the project in the gstate list
X * the user state file contains an index into the project files
X * and is thus kept in the same directory
X */
X trace(("gonzo_ustate_path(project_name = \"%s\", user_name = \"%s\")\n{\n"/*}*/, project_name->str_text, user_name->str_text));
X for (j = 0; ; ++j)
X {
X gp = gonzo_nth(j);
X if (!gp)
X {
X fatal
X (
X "project \"%s\" unknown (bug)",
X project_name->str_text
X );
X }
X if (gonzo_ustate_path_sub(gp, project_name))
X break;
X }
X
X /*
X * make sure that the directory for the user state files exists
X * (must be world writable in testing situations)
X */
X gonzo_become();
X assert(os_exists(gp->dir));
X dir = str_format("%S/user", gp->dir);
X if (!os_exists(dir))
X {
X os_mkdir(dir, 0755);
X if (gp->temporary)
X os_chmod(dir, 0777);
X }
X str_free(dir);
X gonzo_become_undo();
X
X /*
X * build the user state file name
X */
X result = str_format("%S/user/%S", gp->dir, user_name);
X trace(("return \"%s\";\n", result->str_text));
X trace((/*{*/"}\n"));
X return result;
X}
X
X
Xvoid
Xgonzo_become()
X{
X trace(("gonzo_become()\n{\n"/*}*/));
X user_become(gonzo_user());
X trace((/*{*/"}\n"));
X}
X
X
Xvoid
Xgonzo_become_undo()
X{
X trace(("gonzo_become_undo()\n{\n"/*}*/));
X user_become_undo();
X trace((/*{*/"}\n"));
X}
END_OF_FILE
if test 16800 -ne `wc -c <'aegis/gonzo.c'`; then
echo shar: \"'aegis/gonzo.c'\" unpacked with wrong size!
fi
# end of 'aegis/gonzo.c'
fi
if test -f 'lib/aegis.pgm' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'lib/aegis.pgm'\"
else
echo shar: Extracting \"'lib/aegis.pgm'\" \(16905 characters\)
sed "s/^X//" >'lib/aegis.pgm' <<'END_OF_FILE'
XP2
X# aegis - project change supervisor
X# Copyright (C) 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: portable graymap of aegis icon
X#
X64 64
X255
X255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
X255 255 255 255 255 255 223 175 112 64 64 32 32 0 0 0 16 48 80 143 175
X207 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
X255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
X255 255 255 255 255 255 255 255 255 255 207 96 48 12 61 97 133 169 168
X192 191 190 190 153 153 129 82 58 23 64 112 175 255 255 255 255 255 255
X255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
X255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 223 143 48
X37 86 159 195 194 193 192 191 191 190 189 189 188 188 187 187 186 186
X185 149 91 34 32 128 255 255 255 255 255 255 255 255 255 255 255 255
X255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
X255 255 255 255 255 239 96 32 75 148 196 195 194 193 192 191 190 190
X189 189 188 188 187 187 186 186 185 185 184 184 183 182 136 78 27 112
X239 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
X255 255 255 255 255 255 255 255 255 255 255 255 255 255 143 32 87 173
X197 195 194 193 192 191 190 190 189 189 188 188 187 187 186 186 185 185
X185 184 184 183 183 182 181 180 168 66 27 143 255 255 255 255 255 255
X255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
X255 255 255 255 207 48 50 162 197 196 194 193 192 191 190 190 189 189
X188 188 187 187 186 186 185 185 185 184 184 184 183 183 182 182 181 181
X180 178 143 44 48 239 255 255 255 255 255 255 255 255 255 255 255 255
X255 255 255 255 255 255 255 255 255 255 255 255 255 159 29 125 198 196
X195 193 192 191 191 190 189 189 188 188 187 187 186 173 165 146 173 184
X184 184 183 183 183 182 182 182 181 180 180 179 178 176 98 16 159 255
X255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
X255 255 255 239 128 38 150 198 196 194 193 192 191 190 189 189 188 188
X187 187 186 186 167 183 186 163 111 136 184 183 183 183 182 182 182 181
X181 180 180 179 178 177 175 151 21 128 255 255 255 255 255 255 255 255
X255 255 255 255 255 255 255 255 255 255 255 255 239 80 38 187 197 195
X194 193 192 191 190 189 189 188 187 187 187 186 186 182 171 200 198 176
X133 56 172 183 182 182 182 181 181 181 180 180 179 179 178 177 176 175
X161 53 96 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
X255 255 255 239 64 75 199 197 195 194 192 191 190 190 189 188 188 187
X187 186 186 186 185 170 162 190 188 165 123 51 126 182 182 182 181 181
X181 180 180 180 179 179 178 177 177 175 174 171 52 64 239 255 255 255
X255 255 255 255 255 255 255 255 255 255 255 255 255 96 63 199 197 195
X193 192 191 190 189 189 188 188 187 187 186 186 185 185 185 177 130 159
X159 134 93 26 114 182 182 181 181 181 180 180 180 179 179 179 178 177
X177 176 175 173 159 62 96 255 255 255 255 255 255 255 255 255 255 255
X255 255 255 255 96 50 199 197 195 193 192 191 190 189 189 188 187 187
X186 186 186 185 185 185 184 184 122 102 106 84 40 36 170 182 181 181
X181 180 180 180 179 179 179 178 178 177 177 176 175 174 172 168 41 128
X255 255 255 255 255 255 255 255 255 255 255 255 255 159 38 187 197 195
X193 192 191 190 189 188 188 187 187 186 186 186 185 185 184 184 184 183
X183 127 44 35 68 148 182 181 181 181 180 180 180 179 179 179 178 178
X178 177 177 176 175 174 172 170 156 20 159 255 255 255 255 255 255 255
X255 255 255 255 223 13 175 197 195 193 192 191 190 189 188 188 187 187
X186 186 185 185 185 184 184 184 183 183 183 183 182 182 182 181 181 181
X181 180 180 180 180 179 179 179 178 178 177 177 176 176 175 174 173 171
X168 123 42 207 255 255 255 255 255 255 255 255 255 255 64 138 198 195
X193 192 191 190 184 175 181 187 187 186 186 185 185 185 184 184 184 183
X183 183 182 182 182 182 181 181 181 181 180 180 180 180 179 179 179 178
X178 178 177 168 164 176 175 174 173 172 170 166 81 64 239 255 255 255
X255 255 255 255 255 128 50 198 196 194 192 191 190 174 166 159 131 136
X186 186 185 185 185 184 184 184 183 183 183 182 182 182 182 181 181 181
X181 180 180 180 180 179 179 179 178 178 178 177 168 167 160 131 119 174
X173 172 170 168 164 40 175 255 255 255 255 255 255 255 255 16 174 196
X194 193 191 190 176 185 199 189 155 99 146 185 185 185 184 184 184 183
X183 183 182 182 182 182 181 181 181 181 180 180 180 180 179 179 179 178
X178 178 178 168 182 200 188 156 97 116 173 172 171 169 166 131 26 255
X255 255 255 255 255 255 112 62 197 195 193 191 190 189 161 189 198 185
X153 100 75 185 185 184 184 184 183 183 183 182 182 182 182 181 181 181
X181 180 180 180 180 179 179 179 179 178 178 178 177 161 189 199 185 154
X102 36 173 172 171 169 167 163 49 128 255 255 255 255 255 223 12 186
X196 193 192 191 190 189 147 169 176 164 133 79 32 185 184 184 183 183
X183 183 182 182 182 182 181 181 181 181 180 180 180 180 179 179 179 179
X178 178 178 177 177 135 168 177 163 132 79 7 173 172 171 170 168 164
X139 0 239 255 255 255 255 128 74 197 194 192 191 190 189 188 149 118
X135 123 92 33 81 184 184 183 183 183 183 182 182 182 182 181 181 181
X181 180 180 180 180 179 179 179 179 178 178 178 177 177 177 155 119 134
X122 91 34 11 173 172 171 170 168 165 161 48 143 255 255 255 255 48 173
X195 193 191 190 189 188 188 187 120 63 55 24 36 161 184 183 183 183 183
X182 182 182 182 181 181 181 181 180 180 180 180 179 179 179 179 178 178
X178 178 177 177 177 176 119 58 54 25 12 130 173 172 171 170 168 166 162
X117 32 255 255 255 175 50 196 194 192 191 189 189 188 187 186 186 151
X116 138 184 184 183 183 183 183 182 182 182 181 181 181 181 181 180 180
X180 180 179 179 179 179 178 178 178 178 177 177 177 176 176 176 164 109
X120 163 173 173 172 171 170 169 167 163 158 29 159 255 255 112 123 195
X193 191 190 189 188 187 187 186 186 185 185 184 184 184 183 183 183 182
X182 182 181 181 181 181 181 180 180 180 180 179 179 179 179 178 178 178
X178 177 177 177 177 176 176 176 175 175 174 174 173 173 172 171 170 169
X167 164 159 76 96 255 255 32 147 194 192 190 189 188 187 187 186 186
X185 185 184 184 184 183 183 183 182 182 182 181 181 181 181 181 180 180
X180 180 179 179 179 179 178 178 178 178 177 177 177 177 176 176 176 175
X175 175 174 174 173 172 172 171 170 169 167 164 160 125 32 255 239 25
X195 193 191 190 189 188 187 186 186 185 185 184 184 184 183 183 183 182
X182 182 181 181 181 181 180 180 180 180 180 179 179 179 179 178 178 178
X178 177 177 177 177 176 176 176 175 175 175 174 174 173 173 172 172 171
X170 168 167 165 161 145 18 239 175 73 194 192 190 189 188 187 187 186
X185 185 184 184 184 183 183 183 182 182 182 181 181 181 181 180 180 180
X180 180 179 179 179 179 178 178 178 178 177 177 177 177 176 176 176 176
X175 175 175 174 174 173 173 172 171 171 170 168 167 165 162 155 55 175
X128 110 193 191 190 189 188 187 186 186 185 185 184 184 183 183 183 182
X182 182 181 181 181 181 180 180 180 180 180 179 179 179 179 178 178 178
X178 178 177 177 177 177 176 176 176 175 175 175 174 174 173 173 172 172
X171 170 169 168 167 165 162 156 74 143 112 146 192 190 189 188 187 186
X186 185 185 184 184 183 183 183 182 182 182 182 181 181 181 180 180 180
X180 180 179 179 179 179 178 178 178 178 178 177 177 177 177 176 176 176
X175 175 175 174 174 174 173 173 172 172 171 170 169 168 167 165 162 157
X94 64 16 145 191 190 188 188 187 186 185 185 184 184 183 183 183 182
X182 182 182 181 181 181 180 180 180 180 180 179 179 179 179 171 174 178
X178 178 177 177 177 177 176 176 176 176 175 175 175 174 174 173 173 172
X172 171 171 170 169 168 166 164 162 157 130 64 32 156 191 189 188 187
X186 186 185 184 184 184 183 183 182 182 182 182 181 181 181 181 180 180
X180 180 179 179 179 172 166 168 146 123 163 177 177 177 177 176 176 176
X176 175 175 175 174 174 174 173 173 172 172 171 170 170 169 168 166 164
X161 157 139 0 32 192 190 189 188 187 186 185 185 184 184 183 183 183
X182 182 182 181 181 181 181 180 180 180 180 179 179 179 179 166 197 197
X173 131 67 177 177 177 176 176 176 176 175 175 175 174 174 174 173 173
X172 172 171 171 170 169 168 167 166 164 161 157 139 0 0 191 189 188 187
X186 186 185 184 184 183 183 183 182 182 182 181 181 181 181 180 180 180
X180 179 179 179 179 163 167 197 194 172 131 58 122 177 176 176 176 176
X175 175 175 175 174 174 173 173 173 172 172 171 171 170 169 168 167 165
X164 161 156 148 0 0 190 189 188 187 186 185 185 184 184 183 183 182 182
X182 181 181 181 181 180 180 180 180 179 179 179 179 178 170 145 174 172
X150 107 37 110 176 176 176 176 175 175 175 175 174 174 174 173 173 172
X172 171 171 170 170 169 168 167 165 163 160 156 147 0 0 178 188 187 186
X185 185 184 184 169 168 182 182 182 181 181 181 181 180 180 180 180 179
X179 179 179 178 178 178 107 130 130 107 65 7 143 176 176 176 175 175
X175 175 174 174 174 173 173 173 172 172 171 171 164 162 168 167 166 165
X163 160 155 137 0 32 153 188 187 186 185 184 181 166 171 155 115 139
X181 181 181 181 180 180 180 180 179 179 179 179 178 178 178 178 162 67
X57 38 10 55 176 176 176 175 175 175 175 174 174 174 173 173 173 172 172
X171 167 168 169 142 109 148 166 164 162 159 154 127 0 48 141 187 186
X185 185 184 168 195 199 181 140 75 181 181 181 180 180 180 180 179 179
X179 179 178 178 178 178 178 177 166 111 121 132 176 176 176 175 175 175
X175 174 174 174 174 173 173 172 172 172 171 168 199 195 169 122 73 165
X164 161 158 153 117 48 64 129 187 186 185 184 184 156 195 195 176 139
X74 126 181 180 180 180 180 179 179 179 179 178 178 178 178 178 177 177
X177 177 176 176 176 176 175 175 175 175 174 174 174 174 173 173 173 172
X172 171 162 177 197 191 166 120 46 113 163 161 157 151 89 80 143 93 186
X185 185 184 183 136 173 172 153 116 50 102 180 180 180 180 179 179 179
X179 178 178 178 178 178 177 177 177 177 176 176 176 176 175 175 175 175
X174 174 174 174 173 173 173 172 172 171 171 151 154 176 170 142 98 25
X92 162 160 156 149 70 128 159 70 186 185 184 184 183 118 125 131 112 73
X12 124 180 180 180 179 179 179 179 178 178 178 178 177 177 177 177 177
X176 176 176 176 175 175 175 175 174 174 174 174 173 173 173 172 172 171
X171 171 164 104 131 128 102 53 5 112 161 159 154 147 35 175 207 23 185
X184 184 183 183 182 75 56 39 10 68 180 180 180 179 179 179 179 178 178
X178 178 177 177 177 177 177 176 176 176 176 175 175 175 175 174 174 174
X174 173 173 173 172 172 172 171 171 170 170 138 67 57 32 4 41 163 160
X157 153 143 0 207 255 32 149 184 183 183 182 182 181 136 102 124 180
X180 180 179 179 179 179 178 178 178 178 177 177 177 177 177 176 176 176
X176 175 175 175 175 174 174 174 174 173 173 173 172 172 172 171 171 170
X170 169 169 168 125 83 113 163 162 159 156 150 115 32 255 255 128 91
X183 183 182 182 182 181 181 180 180 180 180 179 179 179 179 178 178 178
X178 177 177 177 177 176 176 176 176 176 175 175 175 175 174 174 174 174
X173 173 173 172 172 172 171 171 170 170 169 169 168 167 166 165 164 163
X161 158 154 147 69 128 255 255 223 34 182 182 182 182 181 181 180 180
X180 180 179 179 179 178 178 178 178 178 177 177 177 177 176 176 176 176
X176 175 175 175 175 174 174 174 174 173 173 173 172 172 172 171 171 170
X170 169 169 168 168 167 166 165 163 162 160 156 152 143 17 223 255 255
X255 48 124 181 181 181 181 180 180 180 179 179 179 179 178 178 178 178
X177 177 177 177 177 176 176 176 176 175 175 175 175 175 174 174 174 174
X173 173 173 172 172 172 171 171 171 170 170 169 168 168 167 166 165 164
X162 161 158 154 149 113 16 255 255 255 255 143 67 180 181 181 180 180
X180 179 179 179 179 178 178 178 178 177 177 177 177 177 176 176 176 176
X175 175 175 175 175 174 174 174 174 173 173 173 172 172 172 171 171 171
X170 170 169 168 168 167 166 165 164 163 161 159 156 152 144 51 143 255
X255 255 255 255 0 157 180 180 180 179 179 179 179 178 178 178 178 178
X177 177 177 177 176 176 176 176 176 175 175 175 175 174 174 174 174 173
X173 173 173 172 172 172 171 171 171 170 170 169 169 168 167 167 166 165
X163 162 160 158 154 149 121 16 255 255 255 255 255 255 128 66 178 179
X179 179 179 179 178 178 178 178 177 177 177 177 177 176 176 176 176 175
X175 175 175 175 174 174 174 174 173 173 173 173 172 172 172 171 171 170
X170 170 169 169 168 167 167 166 165 164 162 161 158 156 151 144 51 96
X255 255 255 255 255 255 239 32 143 178 178 178 178 178 178 178 177 177
X177 177 177 176 176 176 176 176 175 175 175 175 174 174 174 174 173 173
X173 173 172 172 172 171 171 171 170 170 170 169 169 168 167 167 166 165
X164 163 161 159 157 153 147 121 24 239 255 255 255 255 255 255 255 159
X44 176 177 177 177 177 177 177 177 177 177 176 176 176 176 176 175 175
X175 175 175 174 174 174 174 173 173 173 173 172 172 172 171 171 171 170
X170 169 169 169 168 167 167 166 165 164 163 161 160 157 154 150 141 33
X128 255 255 255 255 255 255 255 255 255 48 98 175 176 177 177 177 177
X176 176 176 176 176 176 175 169 158 143 135 152 174 174 174 173 173 173
X173 172 172 172 172 171 171 171 162 164 157 135 129 168 167 167 166 165
X164 163 162 160 158 155 151 144 77 80 255 255 255 255 255 255 255 255
X255 255 223 0 151 175 175 176 176 176 176 176 176 175 175 175 170 188
X197 180 145 66 164 173 173 173 173 172 172 172 172 171 171 171 170 167
X171 196 191 161 108 123 167 166 165 164 163 162 160 158 155 152 146 128
X16 207 255 255 255 255 255 255 255 255 255 255 255 159 21 161 174 175
X175 175 175 175 175 175 175 175 165 194 199 181 147 85 104 173 173 172
X172 172 172 171 171 171 171 170 170 161 184 200 191 164 119 33 155 165
X164 163 162 160 158 156 152 148 121 17 159 255 255 255 255 255 255 255
X255 255 255 255 255 255 112 63 171 173 174 174 174 174 174 174 174 174
X132 176 180 162 126 70 67 172 172 172 172 171 171 171 171 170 170 170
X169 155 165 181 172 146 99 21 123 164 163 161 160 158 156 153 147 139
X33 128 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 80
X53 170 172 173 173 173 173 173 173 173 130 136 140 125 89 29 64 172 172
X171 171 171 171 170 170 170 169 169 168 148 119 144 136 107 59 2 133
X162 161 160 158 155 152 148 140 42 80 239 255 255 255 255 255 255 255
X255 255 255 255 255 255 255 255 255 64 62 158 170 171 172 172 172 172
X172 156 104 78 62 25 1 150 171 171 171 170 170 170 170 169 169 168 168
X168 167 124 70 69 42 7 30 162 161 159 157 155 152 147 131 42 80 239 255
X255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 64
X41 156 169 170 171 171 171 171 171 160 86 66 75 128 171 170 170 170 170
X169 169 169 168 168 168 167 167 166 165 134 52 41 71 151 160 159 157
X154 151 146 114 42 64 255 255 255 255 255 255 255 255 255 255 255 255
X255 255 255 255 255 255 255 255 255 112 31 133 167 168 169 169 170 170
X170 170 170 170 170 170 169 169 169 169 168 168 168 167 167 167 166 165
X165 164 163 163 162 161 159 158 156 153 150 144 112 16 128 255 255 255
X255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
X255 255 143 16 91 164 166 167 168 168 168 169 169 169 168 168 168 168
X168 167 167 167 167 166 166 165 165 164 163 163 162 161 159 158 156 154
X151 148 141 76 40 143 255 255 255 255 255 255 255 255 255 255 255 255
X255 255 255 255 255 255 255 255 255 255 255 255 255 223 48 40 131 163
X164 165 166 167 167 167 167 167 167 167 166 166 166 165 165 165 164 164
X163 162 161 160 159 158 156 154 152 148 143 104 42 64 239 255 255 255
X255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
X255 255 255 255 255 255 255 175 0 69 129 161 163 164 164 164 165 165
X165 165 164 164 164 164 163 163 162 161 160 160 159 157 156 154 152 149
X144 130 51 16 143 255 255 255 255 255 255 255 255 255 255 255 255 255
X255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
X223 128 10 49 127 157 159 160 161 161 162 162 162 161 161 161 160 160
X159 158 157 156 154 153 150 147 143 113 51 16 128 223 255 255 255 255
X255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
X255 255 255 255 255 255 255 255 255 255 255 255 239 143 32 29 76 116
X154 155 156 157 157 157 157 156 156 155 154 153 151 150 147 144 106 77
X17 16 128 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
X255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
X255 255 255 255 255 255 255 223 112 32 19 55 74 93 112 139 148 148 147
X146 136 125 98 71 52 17 32 112 191 255 255 255 255 255 255 255 255 255
X255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
X255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
X207 159 112 80 48 32 48 0 0 0 32 48 64 128 175 223 255 255 255 255 255
X255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
X255
END_OF_FILE
if test 16905 -ne `wc -c <'lib/aegis.pgm'`; then
echo shar: \"'lib/aegis.pgm'\" unpacked with wrong size!
fi
# end of 'lib/aegis.pgm'
fi
if test -f 'test/00/t0002a.sh' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'test/00/t0002a.sh'\"
else
echo shar: Extracting \"'test/00/t0002a.sh'\" \(14483 characters\)
sed "s/^X//" >'test/00/t0002a.sh' <<'END_OF_FILE'
X#! /bin/sh
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: Test core functionality.
X#
X
Xunset AEGIS_PROJECT
Xunset AEGIS_CHANGE
Xumask 022
X
XUSER=${USER:-${LOGNAME:-`whoami`}}
X
Xwork=${AEGIS_TMP:-/tmp}/$$
X
Xfail()
X{
X set +x
X echo FAILED test of core functionality 1>&2
X find $work -type d -user $USER -exec chmod u+w {} \;
X rm -rf $work
X exit 1
X}
Xpass()
X{
X set +x
X echo PASSED 1>&2
X find $work -type d -user $USER -exec chmod u+w {} \;
X rm -rf $work
X exit 0
X}
Xtrap "fail" 1 2 3 15
X
X#
X# some variable to make things earier to read
X#
XPAGER=cat
Xexport PAGER
Xworklib=$work/lib
Xworkproj=$work/foo.proj
Xworkchan=$work/foo.chan
Xtmp=$work/tmp
X
X#
X# make the directories
X#
Xmkdir $work
Xif test $? -ne 0 ; then exit 1; fi
X
X#
X# make a new project
X# and check files it should have made
X#
X./bin/aegis -newpro foo -dir $workproj -lib $worklib
Xif test $? -ne 0 ; then fail; fi
X./bin/aegis -newpro -list -lib $worklib
Xif test $? -ne 0 ; then fail; fi
Xif test ! -r $worklib/state ; then fail; fi
Xif test ! -r $workproj/info/state ; then fail; fi
X
X#
X# change project attributes
X#
Xcat > $tmp << 'end'
Xdescription = "A bogus project created to test things.";
Xdeveloper_may_review = true;
Xdeveloper_may_integrate = true;
Xreviewer_may_integrate = true;
Xend
X./bin/aegis -proatt -list --proj=foo -lib $worklib
Xif test $? -ne 0 ; then fail; fi
X./bin/aegis -proatt $tmp -proj foo -lib $worklib
Xif test $? -ne 0 ; then fail; fi
X
X#
X# create a new change
X# make sure it creates the files it should
X#
Xcat > $tmp << 'end'
Xbrief_description = "This change is used to test the aegis functionality \
Xwith respect to change descriptions.";
Xcause = internal_bug;
Xend
X./bin/aegis -newcha -list -pro foo -lib $worklib
Xif test $? -ne 0 ; then fail; fi
X./bin/aegis -new_change $tmp -project foo -lib $worklib
Xif test $? -ne 0 ; then fail; fi
Xif test ! -r $workproj/info/state ; then fail; fi
Xif test ! -r $workproj/info/change/0/001 ; then fail; fi
X
X#
X# create a second change
X# make sure it creates the files it should
X#
Xcat > $tmp << 'end'
Xbrief_description = "This change was added to make the various listings \
Xmuch more interesting.";
Xcause = internal_bug;
Xend
X./bin/aegis -new_change $tmp -project foo -lib $worklib
Xif test $? -ne 0 ; then fail; fi
X./bin/aegis -new_change -list -project foo -lib $worklib
Xif test $? -ne 0 ; then fail; fi
X
X#
X# add a new developer
X#
X./bin/aegis -newdev -list -pr foo -lib $worklib
Xif test $? -ne 0 ; then fail; fi
X./bin/aegis -newdev $USER -p foo -lib $worklib
Xif test $? -ne 0 ; then fail; fi
X./bin/aegis -newdev -list -pr foo -lib $worklib
Xif test $? -ne 0 ; then fail; fi
X
X#
X# begin development of a change
X# check it made the files it should
X#
X./bin/aegis -devbeg -list -project foo -lib $worklib
Xif test $? -ne 0 ; then fail; fi
X./bin/aegis -devbeg 1 -p foo -dir $workchan -lib $worklib
Xif test $? -ne 0 ; then fail; fi
Xif test ! -r $workproj/info/change/0/001 ; then fail; fi
Xif test ! -r $worklib/user/$USER ; then fail; fi
X./bin/aegis -new_change -list -project foo -lib $worklib
Xif test $? -ne 0 ; then fail; fi
X
X#
X# add a new files to the change
X#
X./bin/aegis -new_file -list -lib $worklib -proJ foo
Xif test $? -ne 0 ; then fail; fi
X./bin/aegis -new_file $workchan/main.c -nl -lib $worklib -Pro foo
Xif test $? -ne 0 ; then fail; fi
X./bin/aegis -new_file $workchan/config -nl -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
Xif test ! -r $workproj/info/change/0/001 ; then fail; fi
X./bin/aegis -new_file -list -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
Xcat > $workchan/main.c << 'end'
Xvoid
Xmain()
X{
X exit(0);
X}
Xend
Xcat > $workchan/config << 'end'
Xbuild_command = "rm -f foo; cc -o foo -D'VERSION=\"$v\"' main.c";
X
Xhistory_get_command =
X "co -u'$e' -p $h,v > $o";
Xhistory_create_command =
X "ci -u -m/dev/null -t/dev/null $i $h,v; rcs -U $h,v";
Xhistory_put_command =
X "ci -u -m/dev/null -t/dev/null $i $h,v; rcs -U $h,v";
Xhistory_query_command =
X "rlog -r $h,v | awk '/^head:/ {print $$2}'";
X
Xdiff_command = "set +e; diff $orig $i > $out; test $$? -le 1";
X
Xdiff3_command = "(diff3 -e $mr $orig $i | sed -e '/^w$$/d' -e '/^q$$/d'; \
X echo '1,$$p' ) | ed - $mr > $out";
X
X/*
X * file templates
X */
Xfile_template =
X[
X {
X pattern = [ "*" ];
X body = "hello\n";
X },
X {
X pattern = [ "test/*/*.sh" ];
X body = "#!/bin/sh\nexit 1\n";
X }
X];
Xend
X
X#
X# create a new test
X#
X./bin/aegis -nt -l -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
X./bin/aegis -nt -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
Xcat > $workchan/test/00/t0001a.sh << 'end'
X#!/bin/sh
X#
X# Project: "foo"
X# Change: 1
X#
X
Xfail()
X{
X echo SHUZBUTT 1>&2
X exit 1
X}
Xpass()
X{
X exit 0
X}
Xtrap "fail" 1 2 3 15
X
X./foo
Xq=$?
X
X# check for signals
Xif test $q -ge 128
Xthen
X fail
Xfi
X
X# should not complain
Xif test $q -ne 0
Xthen
X fail
Xfi
X
X# it probably worked
Xpass
Xend
X
X#
X# let the clock tick over, so the build will be happy
X#
Xsleep 1
X
X#
X# build the change
X#
X./bin/aegis -build -list -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
X./bin/aegis -build -nl -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
Xif test ! -r $workproj/info/change/0/001 ; then fail; fi
X
X#
X# difference the change
X#
X./bin/aegis -diff -list -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
X./bin/aegis -diff -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
X
X#
X# test the change
X#
X./bin/aegis -test -l -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
X./bin/aegis -test -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
Xif test ! -r $workproj/info/change/0/001 ; then fail ; fi
X
X#
X# finish development of the change
X#
X./bin/aegis -dev_end -list -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
X./bin/aegis -dev_end -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
Xif test ! -r $workproj/info/change/0/001 ; then fail ; fi
Xif test ! -r $workproj/info/state ; then fail ; fi
Xif test ! -r $worklib/user/$USER ; then fail ; fi
X
X#
X# add a new reviewer
X#
X./bin/aegis -newrev -list -pr foo -lib $worklib
Xif test $? -ne 0 ; then fail; fi
X./bin/aegis -newrev $USER -p foo -lib $worklib
Xif test $? -ne 0 ; then fail; fi
X./bin/aegis -newrev -list -pr foo -lib $worklib
Xif test $? -ne 0 ; then fail; fi
X
X#
X# fail the review
X#
X./bin/aegis -review_fail -list -p foo -lib $worklib
Xif test $? -ne 0 ; then fail; fi
Xcat > $tmp << 'end'
XThis is a failed review comment.
Xend
X./bin/aegis -review_fail $tmp -chan 1 -proj foo -lib $worklib
Xif test $? -ne 0 ; then fail; fi
Xif test ! -r $workproj/info/change/0/001 ; then fail ; fi
Xif test ! -r $workproj/info/state ; then fail ; fi
Xif test ! -r $worklib/user/$USER ; then fail ; fi
X
X#
X# build the change again
X# and difference
X# and test
X# end finish, again
X#
Xsleep 1
X./bin/aegis -build -nl -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
X./bin/aegis -diff -nl -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
X./bin/aegis -test -nl -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
X./bin/aegis -dev_end -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
Xif test ! -r $workproj/info/change/0/001 ; then fail ; fi
Xif test ! -r $workproj/info/state ; then fail ; fi
Xif test ! -r $worklib/user/$USER ; then fail ; fi
X
X#
X# pass the review
X#
X./bin/aegis -review_pass -list -proj foo -lib $worklib
Xif test $? -ne 0 ; then fail; fi
X./bin/aegis -review_pass -chan 1 -proj foo -lib $worklib
Xif test $? -ne 0 ; then fail; fi
Xif test ! -r $workproj/info/change/0/001 ; then fail ; fi
Xif test ! -r $workproj/info/state ; then fail ; fi
Xif test ! -r $worklib/user/$USER ; then fail ; fi
X
X#
X# add an integrator
X#
X./bin/aegis -newint -list -pr foo -lib $worklib
Xif test $? -ne 0 ; then fail; fi
X./bin/aegis -newint $USER -p foo -lib $worklib
Xif test $? -ne 0 ; then fail; fi
X./bin/aegis -newint -list -pr foo -lib $worklib
Xif test $? -ne 0 ; then fail; fi
X
X#
X# start integrating
X#
X./bin/aegis -intbeg -l -p foo -lib $worklib
Xif test $? -ne 0 ; then fail; fi
X./bin/aegis -intbeg 1 -p foo -lib $worklib
Xif test $? -ne 0 ; then fail; fi
Xif test ! -r $workproj/info/change/0/001 ; then fail ; fi
Xif test ! -r $workproj/info/state ; then fail ; fi
Xif test ! -r $worklib/user/$USER ; then fail ; fi
X./bin/aegis -integrate_begin_undo -l -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
X
X#
X# make sure -chdir works
X#
X./bin/aegis -cd -l -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
Xdir=`./bin/aegis -cd fred -bl -p foo -lib $worklib`
Xif test $? -ne 0 ; then fail; fi
Xif test $dir != $workproj/baseline/fred ; then fail; fi
Xdir=`./bin/aegis -cd -dd -p foo -c 1 fred -lib $worklib`
Xif test $? -ne 0 ; then fail; fi
Xif test $dir != $workchan/fred ; then fail; fi
Xdir=`./bin/aegis -cd -p foo -c 1 fred -lib $worklib`
Xif test $? -ne 0 ; then fail; fi
Xif test $dir != $workproj/delta.001/fred ; then fail; fi
X
X#
X# integrate build
X#
X./bin/aegis -build -l -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
Xsleep 1
X./bin/aegis -build -nl -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
X./bin/aegis -test -nl -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
Xif test ! -r $workproj/info/change/0/001 ; then fail ; fi
Xif test -f $workproj/delta.001/aegis.log ; then fail; fi
X
X#
X# fail the integration
X#
X./bin/aegis -intfail -l -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
Xcat > $tmp << 'end'
XThis is a failed integration comment.
Xend
X./bin/aegis -intfail $tmp -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
Xif test ! -r $workproj/info/change/0/001 ; then fail ; fi
Xif test ! -r $workproj/info/state ; then fail ; fi
Xif test ! -r $worklib/user/$USER ; then fail ; fi
X
X
X#
X# build the change again
X# and difference
X# and test
X# and finish, again
X# and review pass again
X# and start integrating again
X#
Xsleep 1
X./bin/aegis -build -nl -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
X./bin/aegis -diff -nl -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
X./bin/aegis -test -nl -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
X./bin/aegis -dev_end -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
X./bin/aegis -review_pass -chan 1 -proj foo -lib $worklib
Xif test $? -ne 0 ; then fail; fi
X./bin/aegis -intbeg 1 -p foo -lib $worklib
Xif test $? -ne 0 ; then fail; fi
Xif test ! -r $workproj/info/change/0/001 ; then fail ; fi
Xif test ! -r $workproj/info/state ; then fail ; fi
Xif test ! -r $worklib/user/$USER ; then fail ; fi
X
X#
X# build and test the integration
X#
Xsleep 1
X./bin/aegis -build -nl -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
X./bin/aegis -test -nl -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
Xif test ! -r $workproj/info/change/0/001 ; then fail ; fi
X
X#
X# pass the integration
X#
X./bin/aegis -intpass -l -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
X./bin/aegis -intpass -nl -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
Xif test ! -r $workproj/info/change/0/001 ; then fail ; fi
Xif test ! -r $workproj/info/state ; then fail ; fi
Xif test ! -r $worklib/user/$USER ; then fail ; fi
X
X#
X# check out the listings
X#
X./bin/aegis -list -list -lib $worklib
Xif test $? -ne 0 ; then fail; fi
X./bin/aegis -list chahist -c 1 -p foo -lib $worklib
Xif test $? -ne 0 ; then fail; fi
X
X#
X# start work on change 2
X#
X./bin/aegis -devbeg 2 -p foo -dir $workchan -lib $worklib
Xif test $? -ne 0 ; then fail; fi
X./bin/aegis -cp -l -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
X
X#
X# copy a file into the change
X#
X./bin/aegis -cp $workchan/main.c -nl -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
Xif test ! -r $workproj/info/change/0/002 ; then fail ; fi
Xif test ! -r $workproj/info/state ; then fail ; fi
Xif test ! -r $worklib/user/$USER ; then fail ; fi
X
X#
X# change the file
X#
Xcat > $workchan/main.c << 'end'
X
X#include <stdio.h>
X
Xvoid
Xmain(argc, argv)
X int argc;
X char **argv;
X{
X if (argc != 1)
X {
X fprintf(stderr, "usage: %s\n", argv[0]);
X exit(1);
X }
X printf("hello, world\n");
X exit(0);
X}
Xend
X
X#
X# need another test
X#
X./bin/aegis -nt -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
Xcat > $workchan/test/00/t0002a.sh << 'end'
X#!/bin/sh
X#
X# Project: "foo"
X# Change: 2
X#
X
Xfail()
X{
X echo SHUZBUTT 1>&2
X exit 1
X}
Xpass()
X{
X exit 0
X}
Xtrap "fail" 1 2 3 15
X
X./foo ickky
Xq=$?
X
X# check for signals
Xif test $q -ge 128
Xthen
X fail
Xfi
X
X# should have complained
Xif test $q -eq 0
Xthen
X fail
Xfi
X
X# it probably worked
Xpass
Xend
X
X#
X# tick over clock to keep build happy
X#
Xsleep 1
X
X#
X# build the change
X# diff the change
X# test the change
X#
X./bin/aegis -b -nl -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
X./bin/aegis -diff -nl -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
X./bin/aegis -test -nl -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
X./bin/aegis -test -bl -nl -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
Xif test ! -r $workchan/main.c,D ; then fail ; fi
X
X
X#
X# end development
X# review pass
X# start integrating
X#
X./bin/aegis -devend -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
X./bin/aegis -revpass -c 2 -p foo -lib $worklib
Xif test $? -ne 0 ; then fail; fi
X./bin/aegis -intbeg -c 2 -p foo -lib $worklib
Xif test $? -ne 0 ; then fail; fi
X
X#
X# build the integration
X# test the integration
X# test the integration against the baseline
X#
Xsleep 1
X./bin/aegis -b -nl -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
X./bin/aegis -t -nl -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
X./bin/aegis -t -bl -nl -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
X
X#
X# pass the integration
X# make sure it create the files, etc
X#
X./bin/aegis -intpass -nl -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
Xif test ! -r $workproj/info/change/0/002 ; then fail ; fi
Xif test ! -r $workproj/info/state ; then fail ; fi
Xif test ! -r $worklib/user/$USER ; then fail ; fi
X./bin/aegis -l projhist -p foo -lib $worklib
Xif test $? -ne 0 ; then fail; fi
X
X# should be no automatic logging
Xif test "`find $work -name 'aegis.log' -print`" != "" ; then fail; fi
X
X#
X# the things tested in this test, worked
X#
Xpass
END_OF_FILE
if test 14483 -ne `wc -c <'test/00/t0002a.sh'`; then
echo shar: \"'test/00/t0002a.sh'\" unpacked with wrong size!
fi
# end of 'test/00/t0002a.sh'
fi
echo shar: End of archive 10 \(of 19\).
cp /dev/null ark10isdone
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