





.













                           Aegis

                A Project Change Supervisor




                         User Guide







                        Peter Miller

                  _m_i_l_l_e_r_p_@_c_a_n_b_._a_u_u_g_._o_r_g_._a_u































User Guide                                             Aegis


.






                        DEDICATIONS

          This user guide is dedicated to my wife
                    Mary Therese Miller
                for all her love and support
                   despite the computers.

                   And to my grandmother
                    Jean Florence Pelham
                        1905 -- 1992
                   Always in our hearts.






This document describes Aegis version 4.16
and was prepared 13 October 2004.






This  document  describing  the Aegis program, and the Aegis
program itself, are
Copyright (C) 1991, 1992,  1993,  1994,  1995,  1996,  1997,
1998,  1999,  2000, 2001, 2002, 2003, 2004 Peter Miller; All
rights reserved.

This program is  free  software;  you  can  redistribute  it
and/or  modify  it under the terms of the GNU General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later ver-
sion.

This program is distributed in the hope that it will be use-
ful, but WITHOUT ANY WARRANTY; without even the implied war-
ranty of MERCHANTABILITY or FITNESS FOR  A  PARTICULAR  PUR-
POSE.   See the GNU General Public License for more details.

You should have received a copy of the  GNU  General  Public
License  along  with this program; if not, write to the Free
Software Foundation,  Inc.,  59  Temple  Place,  Suite  330,
Boston, MA 02111, USA.




Page 2           (lib/en/user-guide/c1.0.so)    Peter Miller





Aegis                                             User Guide


11..  IInnttrroodduuccttiioonn

Aegis  is  a  CASE tool with a difference.  In the spirit of
the UNIX(R) Operating System, Aegis  is  a  small  component
designed to work with other programs.

Many CASE systems attempt to provide everything, from bubble
charts to source control to compilers.   Users  are  trapped
with  the components supplied by the CASE system, and if you
don't like one of the components (it may be too limited, for
instance), then that is just tough.

In  contrast, UNIX provides many components of a CASE system
- compilers,  editors,  dependency  tools  (such  as  make),
source  control (such as SCCS).  You may substitute the tool
of your choice - gcc, jove, cake, rcs (to name a few) if you
don't like the ones supplied with the system.

Aegis  adds to this list with software configuration manage-
ment (SCM), and consistent with UNIX philosophy, Aegis  does
not  dictate  the choice of any of the other tools (although
it may stretch them to their limits).

11..11..  YYeeaarr 22000000 SSttaattuuss

Aegis does not suffer from Year 2000 problems.

+o Aegis stores dates internally in Unix style (_i_._e_.  seconds
offset),  so  internal  storage  of times and dates does not
suffer from any Y2K problems.

+o Aegis always uses the ANSI C standard strftime function to
display times and dates.  (This assumes that your vendor has
supplied a compliant strftime.)  This means that  displaying
dates  does  not assume fixed field widths, nor will it dis-
play the year 2000 as ``100''.

+o There is no user-input of years at any time, so  there  is
no issue surrounding ``guessing'' the century.

11..22..  WWhhaatt ddooeess aaeeggiiss ddoo??

Just  what is software configuration management?  This ques-
tion is sufficiently broad as to require a book  in  answer.
In  essence,  the aegis program is a project change supervi-
sor.  It provides a framework within which a team of  devel-
opers  may  work on many changes to a program independently,
and the aegis program coordinates integrating these  changes
back  into  the master source of the program, with as little
disruption as possible.  Resolution of contention for source
files,  a  major headache for any project with more than one
developer, is one of the aegis program's major functions.





Peter Miller     (lib/en/user-guide/c1.1.so)          Page 3





User Guide                                             Aegis


It should be noted that the aegis program is  a  developer's
tool,  in  the  same  sense  as  make or RCS are developer's
tools.  It is not a manager's tool -  it  does  not  provide
progress tracking or help with work allocation.

11..33..  WWhhyy uussee aaeeggiiss??

So  why should you use the aegis program?  The aegis program
uses a particular  model  of  the  development  of  software
projects.  This model has a master source (or baseline) of a
project, consisting of several  (possibly  several  hundred)
files,  and a team of developers creating changes to be made
to this baseline.  When a change is complete,  it  is  inte-
grated with the baseline, to become  the new baseline.  Each
change must be  atomic  and  self-contained,  no  change  is
allowed  to  cause the baseline to cease to work.  "Working"
is defined as passing its own tests.  The tests are  consid-
ered  part  of the baseline.  Aegis provides support for the
developer so that an entire copy of the baseline need not be
taken  to  change a few files, only those files which are to
be changed need to be copied.

The win in using the aegis program is that  there  are  _O_(_n_)
interactions  between developers and the baseline.  Contrast
this with a master source which is being edited directly  by
the developers - there is _O_(_n_!_)  interactions between devel-
opers - this makes adding "just one" more developer a poten-
tial disaster.

Another  win  is  that  the  project  baseline always works.
Always having a working baseline means  that  a  version  is
always  available  for demonstrations, or those "pre-release
snapshots" we are always forced to provide.

The above advantages are all  very  well  -  for  management
types.  Why should Joe Average Programmer use the aegis pro-
gram?  Recall that RCS provides file locking, but  only  for
one  file  at  a  time.  The aegis program provides the file
locking, atomically, for the set of  files  in  the  change.
Recall  also  that  correct  RCS  usage  locks  the file the
instant you start editing it.  This makes  popular  files  a
project  bottleneck.   The  aegis  program allows concurrent
editing, and a resolution mechanism just before  the  change
must be integrated, meaning fewer delays for J.A.Programmer.













Page 4           (lib/en/user-guide/c1.4.so)    Peter Miller





Aegis                                             User Guide


11..44..  HHooww ttoo uussee tthhiiss mmaannuuaall

This manual assumes the reader is already familiar with  the
UNIX  operating  system,  and with developing software using
the UNIX operating system and  the  tools  available;  terms
such as _R_C_S and _S_C_C_S and _m_a_k_e(1) are not explained.

There  is  also  the  assumption that the reader is familiar
with the issues surrounding team  development  of  software;
coordination  and  multiple version issues, for example, are
not explained.

This manual is broken into a number of sections.

Chapter 2
     describes how aegis works and  some  of  the  reasoning
     behind  the design and implementation of the aegis pro-
     gram.  Look here for answers to "Why does it..."  ques-
     tions.

Chapter 3
     is  a  worked  example of how particular users interact
     with the aegis program.  Look here for answers to  "How
     do I..." questions.

Chapter 4
     is a discussion of how aegis interacts with the History
     Tool, and provides templates and suggestions  for  his-
     tory tools known to work with aegis.

Chapter 5
     is  a discussion of how aegis interacts with the Depen-
     dency Maintenance Tool (DMT),  and  provides  templates
     and suggestions for DMTs known to work with aegis.

Chapter 6
     is a discussion of how aegis interacts with the Differ-
     ence Tools, and provides templates and suggestions  for
     difference tools known to work with aegis.

Chapter 7
     describes  the  project  attributes and how the various
     parameters may be used for particular projects.

Chapter 8
     describes managing tests and testing with Aegis.

Chapter 9
     describes the branching mechanism used in Aegis.

Chapter 10
     is a collection of helpful hints on how  to  use  aegis
     effectively,  based  on real-world experience.  This is
     of most use when initially placing projects  under  the



Peter Miller     (lib/en/user-guide/c1.4.so)          Page 5





User Guide                                             Aegis


     supervision of the aegis program.

Chapter 11
     describes  how  to  manage  geographically  distributed
     development using Aegis.

Appendix A
     is a quick reference for placing  an  existing  project
     under aegis.

Appendix B
     is a glossary of terms.

Appendix D
     is a description of why Aegis must be set-uid-root, for
     system administrators who are concerned about the secu-
     rity issues.

Appendix I
     is  a  brief look at internationalization and localiza-
     tion if Aegis.

11..55..  GGNNUU GGPPLL

Aegis is distributed under the terms and conditions  of  the
GNU  General  Public  License.  Programs which are developed
using Aegis are not automatically subject to  the  GNU  GPL.
Only  programs  which  are derivative works based on GNU GPL
code are automatically subject to the  GNU  GPL.   We  still
encourage  software  authors  to distribute their work under
terms like those of  the  GNU  GPL,  but  doing  so  is  not
required to use Aegis.

























Page 6           (lib/en/user-guide/c7.0.so)    Peter Miller





Aegis                                             User Guide


22..  HHooww AAeeggiiss WWoorrkkss

Before  you  will  be  able to exploit Aegis fully, you will
need to know what Aegis does and why.

The Aegis program provides a change control mechanism and  a
repository, a subset of the functionality which CASE vendors
call Software Configuration Management (SCM).  In  order  to
fit  into  a  software engineering environment, or any place
software  is written, Aegis needs a clearly defined place in
the scheme of things.

This chapter describes the model of the software development
process embodied in the Aegis program, some of the  deliber-
ate  design  decisions  made  for  Aegis, some of the things
Aegis will and wont do for you,  and  the  situations  where
Aegis is most and least useful.

22..11..  TThhee MMooddeell

The  model of the software development process used by Aegis
evolved and grew with time in a commercial software develop-
ment environment, and it has continued to be used and devel-
oped.  Unfortunately, this environment was the largest expe-
rienced  by  the author to date, and consisted of only about
forty software engineers working on a single project.1

22..11..11..  TThhee BBaasseelliinnee

Most CASE systems revolve around a repository: a place where
_s_t_u_f_f  is kept.  This _s_t_u_f_f is the raw material that is pro-
cessed in some way to produce the  final  product,  whatever
that  may  be.  This _s_t_u_f_f is the preferred form for editing
or composing or whatever.

In the Aegis program, the repository is known as  the  _b_a_s_e_-
_l_i_n_e  and the units of _s_t_u_f_f are UNIX files.  The Aegis pro-
gram makes no distinction between text and binary files,  so
both are supported.

The  history mechanism which must be included in any reposi-
tory function is not provided by the Aegis program.   It  is
instead  provided  by  some  other  per-project configurable
software, such as RCS.  This means that the user may  select
the  history tool most suited to any given project.  It also
means that Aegis is that much smaller to test and  maintain.


-----------
  1 "Unfortunately,"   because   many   real-world
projects are far larger, but the author has yet to
experience, and understand, the issues and  proce-
dures required.  (Think of problems, yes; think of
real-world solutions, no.)



Peter Miller     (lib/en/user-guide/c7.1.so)          Page 7





User Guide                                             Aegis


The  structure  of the baseline is dictated by the nature of
each project, with some minor exceptions.  The Aegis program
attempts  to make as few arbitrary rules as possible.  There
is one mandatory file in the  baseline,  and  one  mandatory
directory.  The file is called _c_o_n_f_i_g, and contains the per-
project configuration information; the directory  is  called
_t_e_s_t,  and  contains  all  of  the  tests.  The contents and
structure of the _t_e_s_t directory are also dictated by  Aegis.
Tests  are  treated just like any other source file, and are
subject to the same process.

The baseline in  Aegis  has  one  particular  attribute:  it
always  works.   It  is always there to show off to visiting
big-wigs, it is always there to grab a copy of  and  ship  a
"pre-release  snapshot"  to some overly anxious customer, it
is always there to let upper management "touch and feel" the
progress being made towards the next release.

You  may  claim that "works" is comfortably fuzzy, but it is
not.  The  baseline  contains  not  only  the  source  of  a
project,  but  also  the  tests  for  a  project.  Tests are
treated just like any other source file, and are subject  to
the  same  process.   A baseline is defined to "work" if and
only if it passes all of its own tests.  The  Aegis  program
has  mandatory  testing,  to  ensure that all changes to the
baseline are accompanied by tests, and that those tests have
been  run  and are known to pass.  This means that no change
to the baseline may result in the baseline ceasing to work2.

The model may be summarized briefly: it consists of a  _b_a_s_e_-
_l_i_n_e (master source), updated through the agency of an _i_n_t_e_-
_g_r_a_t_o_r, who is in turn fed _c_h_a_n_g_e_s by a team of  _d_e_v_e_l_o_p_e_r_s.
These  terms  will  be  explained in the following sections.
See figure 1 for a picture of how files flow around the sys-
tem.

The  baseline  is  a set of files including the source files
for a projects, and also all derived files (such  as  gener-
ated  code, binary files from the compiler, etc), and all of
the tests.  Tests are treated just  like  any  other  source
file, and are subject to the same process.  All files in the
baseline are consistent with each other.

Thus the baseline may be considered to be the _c_l_o_s_u_r_e of the
source  files,  in  mathematical  terms.  That is, it is the
source files and all implications flowing from those  source
files,  such  as object files and executables.  All files in
-----------
  2 Well,  mostly.   It  is  possible   for   this
restriction  to  be  relaxed if you feel there are
special circumstances  for  a  particular  change.
The  danger  is  that  a change will be integrated
with the baseline when that change is not actually
of acceptable quality.



Page 8           (lib/en/user-guide/c7.1.so)    Peter Miller





Aegis                                             User Guide






                        baseline





                 developmentdevelopment
                  directory directory




                       integrator
                              integrate
                            |      pass
                  integrate |
                      begin |
                            |
                      integration
                       directory




         FFiigguurree 11:: Flow of Files through the Model


the baseline are consistent with each other; this means that
development  builds  can take object files from the baseline
rather than rebuild them within the development directory.

The baseline is readable by all staff, and usually  writable
by  no-one.   When it is necessary to write to the baseline,
this is done by Aegis, as will be shown below.

In many ways, the baseline may be thought of as a  database,
and  all derived files are projections (views) of the source
files.  Passing its own tests may be  thought  of  as  input
validation  of  fields.   This  is  a  powerful concept, and
indeed the implementation of the Aegis program performs many
of the locking and synchronization tasks demanded of a data-
base engine.

All of the files forming this database are text files.  This
means  that  they may be repaired with an ordinary text edi-
tor, should remedial action be  necessary.   The  format  is
documented in section 5 of the reference manual.  Should you
wish to perform some query not yet available in  Aegis,  the
files  are  readily accessible to members of the appropriate
UNIX group.



Peter Miller     (lib/en/user-guide/c7.1.so)          Page 9





User Guide                                             Aegis


Tests are treated just like any other source file,  and  are
subject to the same process.

22..11..22..  TThhee CChhaannggee MMeecchhaanniissmm

Any  changes  to the baseline are made by atomic increments,
known (unoriginally) as "changes".  A change is a collection
of  files  to be added to, modified in, or deleted from, the
baseline.  These files must all be so altered simultaneously
for the baseline to continue to "work".3

For  example,  if  the  calling interface to a function were
changed in one file, all calls to that function in any other
file  must also change for the baseline to continue to work.
All of the files must be changed  simultaneously,  and  thus
must  all  be included in the one change.  Other files which
would logically be included in such an  change  include  the
reference manual entry for the function, the design document
relating to that area of functionality,  the  relevant  user
documentation, tests would have to be included for the func-
tionality, and existing tests may need to be revised.

Changes must be accompanied  by  tests.   These  tests  will
either establish that a bug has been fixed (in the case of a
bug fix) or will establish that new functionality works  (in
the case of an enhancement).

Tests  are shell scripts, and as such are capable of testing
anything which has functionality accessible from the command
line.   The  ability to run background processes allows even
client-server models to be  tested.   Tests  are  thus  text
files, and are treated as source files; they may be modified
by the same process as any other source file.  Tests usually
need to be revised as a project grows and adapts to changing
requirements,  or  to  be  extended  as   functionality   is
extended.   Tests  can  even be deleted if the functionality
they test has been deleted; tests are deleted  by  the  same
process as any other source file.

22..11..33..  CChhaannggee SSttaatteess

As  a change is developed using Aegis, it passes through six
states.  Many Aegis commands relate to  transitions  between
these  states,  and  Aegis  performs any validation at these
times.

-----------
  3 Whether to allow several logically independent
changes to be included in the one change is a pol-
icy  decision for individual projects to make, and
is not dictated by the Aegis  program.   It  is  a
responsibility of reviewers to ensure that all new
and changed  functionality  is  tested  and  docu-
mented.



Page 10          (lib/en/user-guide/c7.1.so)    Peter Miller





Aegis                                             User Guide


The six  states  of  a  change  are  described  as  follows,
although  the  various  state  transitions, and their condi-
tions, will be described later.

22..11..33..11..  AAwwaaiittiinngg DDeevveellooppmmeenntt

A change is in this state after it  has  been  created,  but
before  it  has  been  assigned  to a developer.  This state
can't be skipped: a change can't be immediately assigned  to
a  developer  by  an administrator, because this disempowers
the staff.

The Aegis program is not a progress tracking tool, nor is it
a work scheduling tool; plenty of both already exist.

22..11..33..22..  BBeeiinngg DDeevveellooppeedd

A  change  is  in this state after it has been assigned to a
developer, by the developer.  This is  the  coal  face:  all
development  is  carried  out  in  this state.  Files can be
edited in no other state, this particularly means that  only
developers  can develop, reviewers and integrators only have
the power to veto a change.  Staff roles will  be  described
more fully in a later section.

To advance to the next state, the change must build success-
fully, it must have tests, and it must pass those tests.4

The  new  tests must also _f_a_i_l against the baseline; this is
to establish that tests for bug-fixes actually reproduce the
bug and then demonstrate that it is gone.  New functionality
added by a change will naturally fail when tested in the old
baseline, because it is not there.

When  these  conditions are met, the Aegis program marks all
of the changes files as locked, simultaneously.  If any  one
of  them is already locked, you can't leave the _b_e_i_n_g _d_e_v_e_l_-
_o_p_e_d state, because the file is part of a  change  which  is
somewhere between _b_e_i_n_g _r_e_v_i_e_w_e_d and _b_e_i_n_g _i_n_t_e_g_r_a_t_e_d.

If  any one of them is out-of-date with respect to the base-
line, the lock is not taken, either.  Locking the  files  at
this  state transition means that popular files may be modi-
fied simultaneously in many changes, but that  only  differ-
ences  to the latest version are ever submitted for integra-
tion.  The Aegis program  provides  a  mechanism,  described
later,  for bringing out-of-date files in changes up-to-date
-----------
  4 It is possible for these testing  requirements
to be waived on either a per-project or per-change
basis.  How is described in a later section.   The
power  to  waive this requirement is not automati-
cally granted to  developers,  as  experience  has
shown that it is usually abused.



Peter Miller     (lib/en/user-guide/c7.1.so)         Page 11





User Guide                                             Aegis


without losing the edits made by the developer.

22..11..33..33..  BBeeiinngg RReevviieewweedd

A change is in this state after a  developer  has  indicated
that development is complete.  The change is inspected, usu-
ally by a second party  (or  parties),  to  ensure  that  it
matches  the change description as to what it is meant to be
doing, and meets other project or company standards you  may
have.

The  style of review, and who may review, is not dictated by
the Aegis  program.   A  number  of  alternative  have  been
observed:

+o You may have a single person who coordinates review panels
of, say, 4 peers, with  this  coordinator  the  only  person
allowed to sign-off review passes or fails.

+o  You  may  allow any of the developers to review any other
developer's changes.

+o You may require that  only  senior  staff,  familiar  with
large portions of the code, be allowed to review.

The  Aegis  program enforces that a developer may not review
their own code.  This ensures that at least one person other
than  the developer has scrutinized the code, and eliminates
a rather obvious conflict of interest.  It  is  possible  to
turn  this  requirement off on a per-project basis, but this
is only desirable for projects with a one  person  team  (or
maybe  two).   The  Aegis program has no way of knowing that
the user passing a review has actually looked at, and under-
stood, the code.

The  reviewer  knows certain things about a change for it to
reach this state:  it  has  passed  all  of  the  conditions
required  to  reach this state.  The change compiles, it has
tests and it passes those tests, and the changes are to  the
current version of the baseline.  The reviewer may thus con-
centrate on  issues  of  completeness,  implementation,  and
standards - to name only a few.

22..11..33..44..  AAwwaaiittiinngg IInntteeggrraattiioonn

A  change  is  in  this state after a reviewer has indicated
that a change is acceptable to  the  reviewer(s).   This  is
essentially  a  queue,  as there may be many developers, but
only one integration may proceed at any one time.

The issue of one integration at a time  is  a  philosophical
one: all of the changes in the queue are physically indepen-
dent; because of the _D_e_v_e_l_o_p _E_n_d locking rules they  do  not
have intersecting sets of files.  The problem comes when one



Page 12          (lib/en/user-guide/c7.1.so)    Peter Miller





Aegis                                             User Guide


change would break another, in these  cases  the  integrator
needs  to  know  which to bounce and which to accept.  Inte-
grating one change at a time greatly  simplifies  this,  and
enforces  the "only change one thing at a time" maxim, occa-
sionally at the expense of integrator throughput.

22..11..33..55..  BBeeiinngg IInntteeggrraatteedd

A change is in this state when the integration of the change
back  into  the  baseline is commenced.  A (logical) copy of
the baseline is taken, and the change  is  applied  to  that
copy.  In this state, the change is compiled and tested once
again.

The additional compilation has two purposes: it ensures that
the  successful compile performed by the developer was not a
fluke of the developer's environment, and it also allows the
baseline  to  be the closure of the sources files.  That is,
all of the implications flowing from the source files,  such
as object files and linked programs or libraries.  It is not
possible for Aegis to know which  files  these  are  in  the
development  directory,  because Aegis is decoupled from the
build mechanism (this will discussed later).

To advance to the next state, the integration copy must have
been  compiled,  and  the  tests included in the change must
have been run and passed.

The integrator also has the power of  veto.   A  change  may
fail  an  integration  because  it  fails  to build or fails
tests, and also just because the integrator says  so.   This
allows  the  _b_e_i_n_g  _i_n_t_e_g_r_a_t_e_d  state  to  be another review
state, if desired.  The _b_e_i_n_g _i_n_t_e_g_r_a_t_e_d state is  also  the
place to monitor the quality of reviews and reviewers.

Should  a faulty change manage to reach this point, it is to
be hoped that the integration process, and the  integrator's
sharp eyes, will detect it.

While most of this task is automated, this step is necessary
to ensure that some strange quirk of the  developer's  envi-
ronment  was  not  responsible  for the change reaching this
stage.  The change is built once more, and tested once more.
If  a  change  fails to build or test, it is returned to the
developer for further work; the integrator may  also  choose
to fail it for other reasons.  If the integrator passes that
change, the integrated version becomes the new baseline.

22..11..33..66..  CCoommpplleetteedd

A change reaches this state when  integration  is  complete.
The  (logical)  copy of the baseline used during integration
has replaced the previous copy of the baseline, and the file
histories  have  been updated.  Once in this state, a change



Peter Miller     (lib/en/user-guide/c7.1.so)         Page 13





User Guide                                             Aegis


may never leave it, unlike all other states.

If you wish to remove a change which is in this  state  from
the baseline, you will have to submit another change.

22..11..44..  TThhee SSooffttwwaarree EEnnggiinneeeerrss

The  model  of  software  development used by Aegis has four
different roles for software engineers to fill.  These  four
roles  may be overlapping sets of people, or be distinct, as
appropriate for your project.

22..11..44..11..  DDeevveellooppeerr

This is the coal-face.  This role is where almost everything
is  done.   This  is  the only role allowed to edit a source
file of a project.

Most staff will be developers.  There is nothing stopping  a
developer  from  also being an administrator, except for the
possible conflict  of  interests  with  respect  to  testing
exemptions.

A  developer  may  edit  many  of the attributes of a change
while it is being  developed.   This  is  mostly  useful  to
update  the description of the change to say why it was done
and what was actually done.  A developer may not grant test-
ing exemptions (but they may be relinquished).

22..11..44..22..  RReevviieewweerr

The  role  of  the  reviewer is to check a developer's work.
This review may consist of a peer examining the code, or  it
may  be  handled  by a single member of staff setting up and
scheduling multi-person review panels.   The  Aegis  program
does not mandate what style of review, it only requires that
a reviewer pass or fail each change.  If it passes, an inte-
grator  will handle it next, otherwise it is returned to the
developer for further work.

In a large team, the reviewers are usually selected from the
more  senior  members of the team, because of their depth of
experience at spotting problems, but also because this is an
opportunity  for  more  senior  members  of  staff  to coach
juniors on the finer points of the art.

The Aegis programs makes some of the reviewer's task easier,
because  the  reviewer knows several specific things about a
change before it comes up for  review:  it  builds,  it  has
tests,  and  they  have  run  successfully.   There  is also
optional (per project) additional conditions imposed at  the
end  of development, such as line length limits, or anything
else which is automatically  testable.   The  Aegis  program
also  provides a difference listing to the reviewer, so that



Page 14          (lib/en/user-guide/c7.1.so)    Peter Miller





Aegis                                             User Guide


each and every edit, to each and every file, can be  pointed
out to the reviewer.

There  is  nothing  stopping a reviewer from being either an
administrator or a developer.  The  Aegis  program  specifi-
cally  prevents  a developer from reviewing his own work, to
avoid conflicts of  interest.   (It  is  possible  for  this
restriction  to be waived, but that only makes sense for one
person projects.)

It will occasionally be necessary  to  arbitrate  between  a
developer and a reviewer.  The appropriate person to do this
would have line responsibility above  both  staff  involved.
Thus  it  is  desirable  that  supervisors/managers  not  be
reviewers, except in very small teams.

22..11..44..33..  IInntteeggrraattoorr

The role of the integrator is to take  a  change  which  has
already been reviewed and integrate it with the baseline, to
form a new baseline.  The integrator is thus the  last  line
of defense for the baseline.

There  is  nothing  preventing  an  integrator from being an
administrator, a developer or a reviewer.  The Aegis program
specifically prevents a developer or reviewer from integrat-
ing his own work, eliminating  any  conflict  of  interests.
(It  is possible for this restriction to be waived, but that
only makes sense for one and two person projects.)

It will occasionally be necessary to  arbitrate  between  an
integrator and a reviewer and/or a developer.  The appropri-
ate person to do this would have line  responsibility  above
all of the staff involved.  Thus it is desirable that super-
visors/mangers not be  integrators,  except  in  very  small
teams.

The   baseline  is  readable  by  all  developers,  but  not
writable.  All updates of the baseline  to  reflect  changes
produced  by  developers are performed through the agency of
the integrator.

22..11..44..44..  AAddmmiinniissttrraattoorr

The project administrator has the following duties:

+o Create new changes.  These may be the result of some  cus-
tomer  bug  reporting mechanism, it may be the result of new
functionality being requested.

+o Grant testing exemptions.  By default, Aegis insists  that
all  changes  be accompanied by tests.  The project adminis-
trator may grant case-by-case exemptions, or a  project-wide
exemption.



Peter Miller     (lib/en/user-guide/c7.1.so)         Page 15





User Guide                                             Aegis


+o  Add  or  remove  staff.  The four roles described in this
section may be assigned to, or removed from,  specific  UNIX
logins by the project administrator.

+o  Edit  project  attributes.   There  are  many  attributes
attached to a project,  only  a  project  administrator  may
alter them.

+o   Edit  change  attributes.   There  are  many  attributes
attached to a change, only a project administrator may alter
all of them.

A  project usually has only one or two administrators at any
one time.

22..11..55..  TThhee CChhaannggee PPrroocceessss

This section  will  examine  the  progression  of  a  change
through  the  six change states.  Most of the attention will
be given to the conditions which must be  met  in  order  to
progress  from  one  state to the next, as this is where the
software development model employed by Aegis is  most  often
expressed.

See  figure  2  for  a  picture of how all of the states and
transitions fit together.

22..11..55..11..  NNeeww CChhaannggee

A project administrator creates a change.  This change  will
consist  mostly  of a description at this time.  The project
administrator is not able (through Aegis) to assign it to  a
specific developer.

The  change  is  awaiting development; it is in the awaiting
development state.

22..11..55..22..  NNeeww CChhaannggee UUnnddoo

It is possible to abandon a change if it is in the  _a_w_a_i_t_i_n_g
_d_e_v_e_l_o_p_m_e_n_t  state.  All record of the change, including its
description, will be deleted.

It is called _n_e_w _c_h_a_n_g_e _u_n_d_o to emphasize the state it  must
be in to delete it.

22..11..55..33..  DDeevveelloopp BBeeggiinn

A  developer, for whatever reason, scans the list of changes
awaiting development.  Having selected a change, the  devel-
oper then assigns that change to herself.

The change is now being developed; it is in the being devel-
oped state.



Page 16          (lib/en/user-guide/c7.1.so)    Peter Miller





Aegis                                             User Guide


                              |
                    new       |new
                  change      |change
                   undo       |
                          awaiting
                        development
                              |
                  develop     |develop
                  begin       |begin
                  undo        |


                           being
                         developed

                              |
                     develop  |devreelvoipew
                     end      |end fail
                     undo     |
                develop    being
                end       reviewed integrate
                undo          |         fail
                              |revrieevwiew
                              |passpass
                              |    undo
                          awaiting
                        integration
                              |
                  integrate   |integrate
                  begin       |begin
                  undo        |
                           being
                         integrated
                              |
                              |integrate
                              |pass
                              |

                         completed


          FFiigguurree 22:: Change States and Transitions


A number of Aegis commands only work in this state,  includ-
ing  commands  to  include files and tests in the change (be
they new files to be added to the  baseline,  files  in  the
baseline  to  be  modified,  or files to be deleted from the
baseline), commands to build the change,  commands  to  test
the change, and commands to difference the change.

The  process of taking sources files, the preferred form for
editing of a project, and transforming them, through various
manipulations and translations, into a "finished" product is



Peter Miller     (lib/en/user-guide/c7.1.so)         Page 17





User Guide                                             Aegis


known as building.  In the UNIX  world  this  usually  means
things  like  compiling  and linking a program, but as fancy
graphical programs become more wide-spread, the source files
could be the binary output from a graphical Entity-Relation-
ship-Diagram editor, which would then be run through a data-
base schema generator.

The process of testing a change has three aspects.  The most
intuitive is that a test must be run  to  determine  of  the
functionality  works.   The  second  requirement is that the
test be run against the baseline and fail; this is to ensure
that  bugs  are not just fixed, but reproduced as well.  The
third requirement is optional: all  or  some  of  the  tests
already  in  the baseline may also be run.  Tests consist of
UNIX shell scripts - anything that can be done  in  a  shell
script can be tested.

In  preparation  for  review, a change is differenced.  This
usually consists of automatically comparing the present con-
tents of the baseline with what the change proposes to do to
the baseline, on a file-by-file basis.  The results  of  the
difference,  such  as UNIX _d_i_f_f _-_c output, is kept in a dif-
ference file, for examination by the reviewer(s).  The bene-
fit  of  this  procedure is that reviewers may examine these
files to see every change the developer  made,  rather  than
only  the  obvious ones.  The differencing commands are per-
project configurable, and other validations,  such  as  line
length restrictions, may also be imposed at this time.

To  leave  this state, the change must have source files, it
must have tests, it must have built  successfully,  it  must
have passed all its own tests, and it must have been differ-
enced.

22..11..55..44..  DDeevveelloopp BBeeggiinn UUnnddoo

It is possible to return a change from the  being  developed
state  to  the  awaiting development state.  This is usually
desired if a developer selected the wrong change by mistake.
It also provides a method to start over on a change for some
other reason.

22..11..55..55..  DDeevveelloopp EEnndd

When the conditions for the end of development have been met
(the  change  must have source files, it must have tests, it
must have built successfully, it must have  passed  all  its
own  tests, and it must have been differenced) the developer
may cause the change to leave the being developed state  and
enter  the  being  reviewed  state.   The Aegis program will
check to see that all the conditions are met at  this  time.
There  is  no  history  kept  of  unsuccessful  develop  end
attempts.




Page 18          (lib/en/user-guide/c7.1.so)    Peter Miller





Aegis                                             User Guide


Most of these preconditions are determined  by  the  use  of
time  stamps  which  are recorded for various operations, in
addition to file system timestamps on the files  themselves.
Logical  sequencing  (_e_._g_.   tests  being run after building
after editing) is also verified.

Note that there are 3 kinds of tests

1.
  If a change contains a new test or a test which  is  being
  modified,  this  test  must pass against the code compiled
  and linked in the change.  This is simply referred to as a
  ``test''.   Changes  may be granted an exemption from such
  tests.

2.
  If a change contains a new test and the change  is  a  bug
  fix, this test must _f_a_i_l against the old code in the base-
  line.  This is to confirm that the  bug  has  been  fixed.
  This  is  referred to as a ``baseline test''.  Changes may
  be granted an exemption from such tests.

3.
  Tests which already exist  in  the  baseline  may  be  run
  against the code compiled and linked in the change.  These
  tests must pass.  This is to confirm that the project  has
  not regressed, which is why these tests are referred to as
  ``regression tests''.  Changes may be granted an exemption
  from such tests.

A  successful  develop  end  command  results  in the change
advancing from  the  _b_e_i_n_g  _d_e_v_e_l_o_p_e_d  state  to  the  _b_e_i_n_g
_r_e_v_i_e_w_e_d  state.   (It  is  also  possible to advance to the
_a_w_a_i_t_i_n_g _r_e_v_i_e_w state or  the  _a_w_a_i_t_i_n_g  _i_n_t_e_g_r_a_t_i_o_n  state.
See _a_e_d_e(1) or _a_e_p_a_t_t_r(5) for more information.)

22..11..55..66..  DDeevveelloopp EEnndd UUnnddoo

There  are  many times when a developer thinks that a change
is completed, and goes hunting for  a  reviewer.   Half  way
down the hall, she thinks of something that should have been
included.

It is possible for a developer to rescind a _D_e_v_e_l_o_p  _E_n_d  to
allow  further  work  on a change.  No reason need be given.
This request may be issued to a change in either  the  _b_e_i_n_g
_r_e_v_i_e_w_e_d or _a_w_a_i_t_i_n_g _i_n_t_e_g_r_a_t_i_o_n states.

22..11..55..77..  RReevviieeww PPaassss

This  event is used to notify Aegis that the change has been
examined, by a method unspecified as  discussed  above,  and
has been found to be acceptable.




Peter Miller     (lib/en/user-guide/c7.1.so)         Page 19





User Guide                                             Aegis


22..11..55..88..  RReevviieeww PPaassss UUnnddoo

The reviewer of a change may rescind a _R_e_v_i_e_w _P_a_s_s while the
change remains in the _a_w_a_i_t_i_n_g _i_n_t_e_g_r_a_t_i_o_n state.  No reason
need  be supplied.  The change will be returned to the _b_e_i_n_g
_r_e_v_i_e_w_e_d state.

22..11..55..99..  RReevviieeww FFaaiill

This event is used to notify Aegis that the change has  been
examined,  by  a  method unspecified as discussed above, and
has been found to be unacceptable.

A file containing a brief summary of the  problems  must  be
given, and will be included in the change's history.

The change will be returned to the _b_e_i_n_g _d_e_v_e_l_o_p_e_d state for
further work.

It is not the responsibility of any reviewer to fix a defec-
tive change.

22..11..55..1100..  IInntteeggrraattee BBeeggiinn

This  command  is  used  to commence integration of a change
into the project baseline.

Whether a physical copy of the baseline is used, or a  logi-
cal  copy using links, is controlled by the project configu-
ration file.  The change is then applied to this copy.

The integrator must then issue build and  test  commands  as
appropriate.  This is not automated as some integrator tasks
may be required in and around these commands.

22..11..55..1111..  IInntteeggrraattee BBeeggiinn UUnnddoo

This command is used to return a change to  the  integration
queue, without prejudice.  No reason need be given.

This is usually done when a particularly important change is
in the queue, and the current  integration  is  expected  to
take a long time.

22..11..55..1122..  IInntteeggrraattee PPaassss

This  command  is used to notify Aegis that the change being
integrated is acceptable.

The current baseline is replaced with the integration  copy,
and the history is updated.






Page 20          (lib/en/user-guide/c7.1.so)    Peter Miller





Aegis                                             User Guide


22..11..55..1133..  IInntteeggrraattee FFaaiill

This  command is used to notify Aegis that an integration is
unacceptable, usually because it failed to build or test  in
some  way, or sometimes because the integrator found a defi-
ciency.

A file containing a _b_r_i_e_f summary of the  problems  must  be
given, and the summary will be included in the change's his-
tory.

The change will be returned to the _b_e_i_n_g _d_e_v_e_l_o_p_e_d state for
further  work.   The  integration  copy  of  the baseline is
deleted, leaving the original baseline unchanged.

It is not the responsibility of  any  integrator  to  fix  a
defective change, or even diagnose what the defect may be.








































Peter Miller     (lib/en/user-guide/c7.2.so)         Page 21





User Guide                                             Aegis


22..22..  PPhhiilloossoopphhyy

The  philosophy is simple, and that makes some of the imple-
mentation complex.

+o When a change is in the _b_e_i_n_g _d_e_v_e_l_o_p_e_d state,  the  aegis
program is a developer's tool.  Its purpose is to make it as
easy for a developer to develop changes as possible.

+o When a change leaves (or  attempts  to  leave)  the  _b_e_i_n_g
_d_e_v_e_l_o_p_e_d   state,  the  aegis  program  is  protecting  the
project baseline, and does not exist to make  the  developer
happy.

+o  The aegis program attempts to adhere to the UNIX minimal-
ist philosophy.  Least  unnecessary  output,  least  command
line length, least dependence on _s_p_e_c_i_f_i_c 3rd party tools.

+o  No  overlap in functionality of cooperating tools.  (I.e.
no internal build mechanism, no internal history  mechanism,
etc.)

22..22..11..  DDeevveellooppmmeenntt

During the development of a change, the aegis program exists
to help the developer.  It helps  him  navigate  around  his
change  and  the  project, it copies file for him, and keeps
track of the versions.  It can even tell him what changes he
has made.

22..22..22..  PPoosstt DDeevveellooppmmeenntt

When  a change has left the "being developed" state, or when
it is attempting to leave  that  state,  the  aegis  program
ceases  to  attempt  to  help  the developer and proceeds to
defend the project baseline.  The model used by aegis states
that  "the  baseline  always  works",  and aegis attempts to
guarantee this.

22..22..33..  MMiinniimmaalliissmm

The idea of minimalism is to help the user out.  It  is  the
intention  that the aegis program can work out unstated com-
mand line options for itself, in cases where it is "safe" to
do  so.   This  means a number of defaulting mechanisms, all
designed to help the user.

22..22..44..  OOvveerrllaapp

It was very tempting while writing the aegis program to have
it  grow and cover source control and dependency maintenance
roles.  Unfortunately, this would have meant that  the  user
would have been trapped with whatever the aegis program pro-
vided, and the aegis program is already plenty big.  To  add



Page 22          (lib/en/user-guide/c7.2.so)    Peter Miller





Aegis                                             User Guide


this  functionality would have diverted effort, resulting in
an inferior result.  It would also have violated the  under-
lying UNIX philosophy.

22..22..55..  DDeessiiggnn GGooaallss

A  number  of  specific  ideas molded the shape of the aegis
program.  These include:

The UNIX philosophy of  writing  small  tools  for  specific
tasks  with  little  or no overlap.  Tools should be written
with the expectation of use in pipes or  scripts,  or  other
combinations.

+o  Stay  out of the way.  If it is possible to let a project
do whatever it likes, write the code to let it.  It  is  not
possible  to  anticipate even a fraction of the applications
of a software tool.

+o People.  The staff using aegis should be in charge of  the
development process.  They should not feel that some machine
is giving them orders.

+o Users aren't psychic.  Feedback must  be  clear,  accurate
and appropriate.
































Peter Miller     (lib/en/user-guide/c7.5.so)         Page 23





User Guide                                             Aegis


22..33..  SSeeccuurriittyy

Access to project data is controlled by the UNIX group mech-
anism.  The group may  be  selected  as  suitable  for  your
project, as may the umask.

All  work done by developers (build, difference, etc) is all
with a default group of the project's group, irrespective of
the  user's  default group.  Directories (when BSD semantics
are available)  are  all  created  so  that  their  contents
default  to  the correct group.  This ensures that reviewers
and integrators are able to examine the change.

Other UNIX users not in the project's group may be excluded,
or  not,  by  the  appropriate setting of the project umask.
This umask is used by all Aegis actions, assuring  appropri-
ate default behaviour.

A second aspect of security is to ensure that developers are
unable to deliberately deceive Aegis.  Should the  files  be
tampered with at any later date, Aegis will notice.

22..44..  SSccaallaabbiilliittyy

How  big can a project get before Aegis chokes?  There are a
huge number of variables in this question.

The most obvious bottleneck is the integrator.   An  artifi-
cial "big project" example: Assume that the average integra-
tion takes an hour to build and test.  A full-time  integra-
tor  could  be  expected to get 7 or 8 of these done per day
(this was the observed average on one project the author was
involved  in).  Assume that the average time for a developer
to develop a change is two weeks; a  figure  recommended  by
many  text books as "_t_h_e _m_o_s_t _y_o_u _c_a_n _a_f_f_o_r_d _t_o _t_h_r_o_w _a_w_a_y".
These two assumptions mean that for this "big project" Aegis
can  cope  with  70  to  80  developers, before integrations
become a bottleneck.

The more serious bottle neck is the  dependency  maintenance
tool.   Seventy developers can churn out a staggering volume
of code.  It takes a very long time to wade through the file
times and the rules, just to find the one or two files which
changed.  This can easily push the integrate build time past
the  one  hour mark.  Developers also become very vocal when
build times are this long.











Page 24          (lib/en/user-guide/c1.3.so)    Peter Miller





Aegis                                             User Guide


22..55..  WWhheenn ((nnoott)) ttoo uussee AAeeggiiss

The aegis program is not a silver bullet; it will not  solve
all  of  your problems.  Aegis is suitable for some kinds of
projects, useful for others, and useless for a few.

The software development process embodied by Aegis  has  the
following attributes:

+o Each change set is applied atomically.

+o Each  change set must build successfully before it will be
  accepted.  (This can be trivial, if desired.)

+o Each change set must test successfully before it  will  be
  accepted.  (This can be disabled, if desired.)

+o Each  change set must pass a peer review before it will be
  accepted.  (This can be a rubber stamp, if desired.)

The most difficult thing about  Aegis  program  is  that  it
takes  management  buy-in.  It takes effort to convince many
people that the model used by aegis has  benefits,  and  you
need  management backing you up when some person comes along
with a way of developing software "without the  extra  work"
imposed by the model used by Aegis.

22..55..11..  BBuuiillddiinngg

If  the  source code to your software product doesn't build,
it isn't a product.  However,  many  software  shops  commit
changes  to their repository without preconditions, and then
do a daily build (or worse, weekly).  The  problem  here  is
that  "pollution"  by  defective  changes is already _i_n _y_o_u_r
_p_r_o_d_u_c_t before it is detected.  Aegis will  not  let  it  be
committed in the first place.

If your product is entirely composed of scripts or HTML, you
can make the build step completely trivial: "exit 0" is usu-
ally  used  for this purpose.  Thus, this requirement, while
usually highly desirable, may be avoided if desired.

22..55..22..  TTeessttiinngg

There is extra up-front work: writing  tests.   The  win  is
that the tests hang around forever, catching minor and major
slips  before  they  become  embarrassing  "features"  in  a
released  product.   Prevention is cheaper than cure in this
case, the tests save work down the track.  See  the  _t_e_s_t_i_n_g
chapter for more information.







Peter Miller     (lib/en/user-guide/c1.3.so)         Page 25





User Guide                                             Aegis


22..55..33..  RReevviieewwiinngg

Code  reviews  of  some  sort  are  normal  in most software
houses.   Often,  unfortunately,  time  pressures  or  other
political  pressures  mean  that  code reviews manage not to
happen.  Yet the literature repeatedly cites reviews as  one
of  the  most  important  factors in removing defects before
they reach your code  repository.   Aegis  requires  a  code
review  before it will commit code into your product; again,
the idea is to remove defects _b_e_f_o_r_e they pollute the  prod-
uct.














































Page 26          (lib/en/user-guide/c7.4.so)    Peter Miller





Aegis                                             User Guide


22..66..  FFuurrtthheerr WWoorrkk

The  Aegis  program  is far from finished.  A number of fea-
tures are known to be lacking.

     At the date of this writing, Aegis  is  being  actively
supported and improved.

22..66..11..  CCooddee CCoovveerraaggee TTooooll

It  would  be  very helpful if a code coverage tool could be
used to analyze tests included with changes to  ensure  that
the  tests  actually  exercised the lines of code changed in
the change.

Another use of the code coverage tool  would  be  to  select
regression  tests  based on the object files recompiled by a
change, and those  regression  tests  which  exercise  those
files.

While  there  is  freeware  C  code coverage tool available,
based on GNU C, the interfacing  and  semantics  still  need
more thought.

NNoottee:: A fairly good approximation is already available using
the _-_-_s_u_g_g_e_s_t option of the _a_e_t(1) command.  It works on the
correlation  of  sources  file  versus  tests in the various
change sets.  See _a_e_t(1) for more information.

22..66..22..  VViirrttuuaall FFiillee SSyysstteemm

There is almost sufficient information  in  the  Aegis  data
base  to create a virtual file system, overlaying the devel-
opment  directory  atop the baseline5.  This could be imple-
mented similarly to automounters, intercepting  file  system
operations  by pretending to be an NFS server.  Many commer-
cial CASE products provide such a facility.

Such a virtual file system has a number of  advantages:  you
don't  need  such a capable DMT, for starters; it only needs
the dynamic include dependencies, and does not need a search
path6.  Second, many horrible and  dumb  compilers,  notably
FORTRAN and "fourth" GLs, don't have adequate include seman-
tics; overlaying the two directories make this  much  easier
to deal with7.  Many graphical tools, such as  bubble  chart
-----------
  5 Reminiscent of Sun's TFS, but  not  the  same.
Similar  to  AT&T's  3D-FS.   Similar  to TeamNet.
Similar to ClearCase, but I wasn't thinking of the
time-travel aspects which they implement.
  6 Discussed  in  the _D_e_p_e_n_d_e_n_c_y _M_a_i_n_t_e_n_a_n_c_e _T_o_o_l
chapter.
  7 There  are  other  ways, discussed in the _T_i_p_s
_a_n_d _T_r_a_p_s chapter.



Peter Miller     (lib/en/user-guide/c7.4.so)         Page 27





User Guide                                             Aegis


drawers, etc, when they do actually have include files, have
no command line specifiable search path.

The disadvantage is that this adds significant complexity to
an  already  large program.  Also, implementation is limited
to NFS capable systems, or would have to be rewritten for  a
variety  of  other  systems.   The semantics of interactions
between the daemon and other Aegis commands,  while  clearly
specifiable,  are  challenging  to  implement.   Performance
could also be a significant factor.

The question is "is it really necessary?"  If the job can be
done  without  it,  does  the effort of writing such a beast
result in significant productivity gains?

The addition of the  _c_r_e_a_t_e___s_y_m_l_i_n_k_s___b_e_f_o_r_e___b_u_i_l_d  field  to
the  project  _c_o_n_f_i_g  file  has greatly reduced the need for
this functionality.  However, it does not  provide  copy-on-
write  semantics,  nor automatic _a_e_c_p functionality; which a
virtual file system could do.





































Page 28          (lib/en/user-guide/c2.0.so)    Peter Miller





Aegis                                             User Guide


33..  TThhee CChhaannggee DDeevveellooppmmeenntt CCyyccllee

As a change to a project is developed using Aegis, it passes
through several states.  Each state is characterized by dif-
ferent quality requirements, different  sets  of  applicable
Aegis  commands, and different responsibilities for the peo-
ple involved.

These people may be divided into four  categories:  develop-
ers,  reviewers,  integrators  and administrators.  Each has
different responsibilities, duties and permissions; although
one  person  may belong to more than one category, depending
on how a project is administered.

This chapter looks at each of these categories, by way of an
example  project  undergoing  its  first four changes.  This
example will be examined from the perspective of each  cate-
gory of people in the following sections.

There  are six hypothetical users in the example: the devel-
opers are Pat, Jan and Sam; the reviewers are Robyn and Jan;
the  integrator  is  Isa;  and  the  administrator is Alex8.
There need not have been this many people involved,  but  it
keeps things slightly cleaner for this example.

The  project is called "example".  It implements a very sim-
ple calculator.  Many features important to a quality  prod-
uct  are  missing,  checking for divide-by-zero for example.
These have been omitted for brevity.






















-----------
  8 The  names  are  deliberately  gender-neutral.
Finding such a name starting with "I" is not easy!



Peter Miller     (lib/en/user-guide/c2.0.so)         Page 29





User Guide                                             Aegis


33..11..  TThhee DDeevveellooppeerr

The developer role is the coal face9.   This  is  where  new
software is written, and bugs are fixed.  This example shows
only the addition of new functionality, but usually a change
will include modifications of existing code, similar to bug-
fixing activity.

33..11..11..  BBeeffoorree YYoouu SSttaarrtt

Have you configured your account to use Aegis?  See the _U_s_e_r
_S_e_t_u_p  section  of  the _T_i_p_s _a_n_d _T_r_a_p_s chapter for how to do
this.

33..11..22..  TThhee FFiirrsstt CChhaannggee

While  the  units  of  change,  unoriginally,   are   called
"changes",  this  also applies to the start of a project - a
change to nothing, if you like.  The developer of this first
change will be Pat.

First,  Pat  has been told by the project administrator that
the change has been created.  How Alex created  this  change
will  be  detailed  in the "Administrator" section, later in
this chapter.  Pat then acquires the change and starts work.

     pat% aaeeddbb --ll --pp eexxaammppllee..11..00
     Project "example.1.0"
     List of Changes













-----------
  9 I thought this expression  was  fairly  common
English  usage,  until  I  had a query.  "The Coal
Face" is an expression  meaning  "where  the  _r_e_a_l
work  is done" in reference to old-style coal min-
ing which was hard, tiring, hot,  very  dangerous,
and  bad  for  your  health even if you were lucky
enough not to be killed.  It was a 14-hour per day
job,  and you walked to and from work in the dark,
even in summer.  Unlike the mine owners, who  rode
expensive horses and saw sunlight most days of the
week.



Page 30          (lib/en/user-guide/c2.1.so)    Peter Miller





Aegis                                             User Guide


     Change  State           Description
     ------- -------         -------------
       10    awaiting_       Create initial skeleton.
             development
     pat% aaeeddbb eexxaammppllee..11..00 1100
     aegis: project "example.1.0": change 10: development directory "/u/pat/
             example.1.0.C010"
     aegis: project "example.1.0": change 10: user "pat" has begun development
     pat% aaeeccdd
     aegis: project "example.1.0": change 10: /u/pat/example.1.0.C010
     pat%


At  this point Aegis has created a development directory for
the change and Pat has changed directory to the  development
directory10.

Five files will be created by this change.

     pat% aaeennff ccoonnffiigg HHoowwttoo..ccooookk ggrraamm..yy lleexx..ll mmaaiinn..cc
     aegis: project "example.1.0": change 10: file "Howto.cook" added
     aegis: project "example.1.0": change 10: file "config" added
     aegis: project "example.1.0": change 10: file "gram.y" added
     aegis: project "example.1.0": change 10: file "lex.l" added
     aegis: project "example.1.0": change 10: file "main.c" added
     pat%


The  contents  of  the  _c_o_n_f_i_g file will not be described in
this section, mostly because it is a rather complex subject;
so  complex  it requires four chapters to describe: the _H_i_s_-
_t_o_r_y _T_o_o_l chapter, the _D_e_p_e_n_d_e_n_c_y _M_a_i_n_t_e_n_a_n_c_e _T_o_o_l  chapter,
the  _D_i_f_f_e_r_e_n_c_e  _T_o_o_l_s  chapter  and  the _P_r_o_j_e_c_t _A_t_t_r_i_b_u_t_e_s
chapter.  The contents of the _H_o_w_t_o_._c_o_o_k file  will  not  be
described  in  this  section, as it is covered in the _D_e_p_e_n_-
_d_e_n_c_y _M_a_i_n_t_e_n_a_n_c_e _T_o_o_l chapter.

The file _m_a_i_n_._c will have been created by Aegis as an  empty
file.  Pat edits it to look like this

     #include <stdio.h>


     static void
     usage()
     {
             fprintf(stderr, "usage: example\n");
             exit(1);
     }

-----------
  10 The  default  directory in which to place new
development directories is configurable  for  each
user.



Peter Miller     (lib/en/user-guide/c2.1.so)         Page 31





User Guide                                             Aegis


     void
     main(argc, argv)
             int     argc;
             char    **argv;
     {
             if (argc != 1)
                     usage();
             yyparse();
             exit(0);
     }


The file _g_r_a_m_._y describes the grammar accepted by the calcu-
lator.  This file was also created empty by Aegis,  and  Pat
edits it to look like this:

     %token  DOUBLE
     %token  NAME


     %union
     {
             int     lv_int;
             double  lv_double;
     }


     %type <lv_double> DOUBLE expr
     %type <lv_int> NAME


     %left '+' '-'
     %left '*' '/'
     %right UNARY


     %%




















Page 32          (lib/en/user-guide/c2.1.so)    Peter Miller





Aegis                                             User Guide


     example
             : /* empty */
             | example command '\n'
                     { yyerrflag = 0; fflush(stderr); fflush(stdout); }
     command
             : expr
                     { printf("%g\n", $1); }
             | error
     expr
             : DOUBLE
                     { $$ = $1; }
             | '(' expr ')'
                     { $$ = $2; }
             | '-' expr
                     %prec UNARY
                     { $$ = -$2; }
             | expr '*' expr
                     { $$ = $1 * $3; }
             | expr '/' expr
                     { $$ = $1 / $3; }
             | expr '+' expr
                     { $$ = $1 + $3; }
             | expr '-' expr
                     { $$ = $1 - $3; }


The file _l_e_x_._l describes a simple lexical analyzer.  It will
be processed by _l_e_x(1) to produce C  code  implementing  the
lexical  analyzer.   This  kind  of  simple lexer is usually
hand crafted, but using lex allows the  example  to  be  far
smaller.  Pat edits the file to look like this:

     %{
     #include <math.h>
     #include <gram.h>
     %}
     %%
     [ \t]+      ;
     [0-9]+(\.[0-9]*)?([eE][+-]?[0-9]+)?    {
                     yylval.lv_double = atof(yytext);
                     return DOUBLE;
             }
     [a-z]   {
                     yylval.lv_int = yytext[0] - 'a';
                     return NAME;
             }
     \n      |
     .       return yytext[0];


Note  how  the  _g_r_a_m_._h  file  is included using the #include
<_f_i_l_e_n_a_m_e> form.  This is very important for builds in later
changes,  and is discussed more fully in the _U_s_i_n_g _C_o_o_k sec-
tion of the _D_e_p_e_n_d_e_n_c_y _M_a_i_n_t_e_n_a_n_c_e _T_o_o_l chapter.



Peter Miller     (lib/en/user-guide/c2.1.so)         Page 33





User Guide                                             Aegis


The files are processed, compiled and linked together  using
the  _a_e_b  command; this is known as _b_u_i_l_d_i_n_g a change.  This
is done through Aegis so that Aegis can know the success  or
failure  of the build.  (Build success is a precondition for
a change to leave the _b_e_i_n_g  _d_e_v_e_l_o_p_e_d  state.)   The  build
command  is in the _c_o_n_f_i_g file so vaguely described earlier.
In this example it will use the  _c_o_o_k(1)  command  which  in
turn  will use the _H_o_w_t_o_._c_o_o_k file, also alluded to earlier.
This file describes the commands and  dependencies  for  the
various processing, compiling and linking.

     pat% aaeebb
     aegis: project "example.1.0": change 10: development build started
     aegis: cook -b Howto.cook project=example.1.0 change=10
             version=1.0.C010 -nl
     cook: yacc -d gram.y
     cook: mv y.tab.c gram.c
     cook: mv y.tab.h gram.h
     cook: cc -I. -I/projects/example/branch.1./branch0/baseline -O -c gram.c
     cook: lex lex.l
     cook: mv lex.yy.c lex.c
     cook: cc -I. -I/projects/example/branch.1/branch.0/baseline -O -c lex.c
     cook: cc -I. -I/projects/example/baseline -O -c main.c
     cook: cc -o example gram.o lex.o main.o -ll -ly
     aegis: project "example.1.0": change 10: development build complete
     pat%


The example program is built, and Pat could even try it out:

     pat% eexxaammppllee
     11 ++ 22
     3
     ^^DD
     pat%


At this point the change is apparently finished.   The  com-
mand to tell Aegis this is the _d_e_v_e_l_o_p _e_n_d command:

     pat% aaeeddee
     aegis: project "example.1.0": change 10: no current 'aegis -DIFFerence'
             registration
     pat%


It  didn't  work,  because  Aegis thinks you have missed the
difference step.

The difference step is used  to  produce  files  useful  for
reviewing  changes, mostly in the form of context difference
files between  the  project  baseline  and  the  development
directory.   Context  differences  allow  reviewers  to  see
exactly what has changed, and not have to try to track  them



Page 34          (lib/en/user-guide/c2.1.so)    Peter Miller





Aegis                                             User Guide


down  and  inevitably  miss  obscure  but important edits to
large or complex files.

     pat% aaeedd
     aegis: set +e; diff -c /dev/null /u/pat/example.1.0.C010/Howto.cook >
             /u/pat/example.1.0.C010/Howto.cook,D; test $? -eq 0 -o $? -eq 1
     aegis: set +e; diff -c /dev/null /u/pat/example.1.0.C010/config >
             /u/pat/example.1.0.C010/config,D; test $? -eq 0 -o $? -eq 1
     aegis: set +e; diff -c /dev/null /u/pat/example.1.0.C010/gram.y >
             /u/pat/example.1.0.C010/gram.y,D; test $? -eq 0 -o $? -eq 1
     aegis: set +e; diff -c /dev/null /u/pat/example.1.0.C010/lex.l >
             /u/pat/example.1.0.C010/lex.l,D; test $? -eq 0 -o $? -eq 1
     aegis: set +e; diff -c /dev/null /u/pat/example.1.0.C010/main.c >
             /u/pat/example.1.0.C010/main.c,D; test $? -eq 0 -o $? -eq 1
     aegis: project "example.1.0": change 10: difference complete
     pat%


Doing a difference for a new file may appear a little pedan-
tic, but when a change consists of tens of files, so modifi-
cations of existing files and some new, there is  a  tempta-
tion  for  reviewers  to  use "more *,D" and thus completely
miss the new files if it were not for this pedanticism11.

So that reviewers, and conscientious developers, may  locate
and view all of these difference files, the command

     pat% mmoorree ``ffiinndd .. --nnaammee ""**,,DD"" --pprriinntt || ssoorrtt``
     _._._._e_x_a_m_i_n_e_s _e_a_c_h _f_i_l_e_._._.
     pat%

could  be used, however this is a little too long winded for
most users, and so the  _a_e_d_m_o_r_e  alias  does  exactly  this.
There  is  a  similar _a_e_d_l_e_s_s alias for those who prefer the
_l_e_s_s(1) command.

So now Pat is done, let's try to sign off again:

     pat% aaeeddee
     aegis: project "example.1.0": change 10: no current 'aegis -Test'
             registration
     pat%


It didn't work, again.  This time  Aegis  is  reminding  Pat
that  every change must be accompanied by at least one test.
This is so that the project team can  be  confident  at  all

-----------
  11 This is especially true when you use  a  tool
such as _f_c_o_m_p(1) which gives a complete file list-
ing with the inserts and  deletes  marked  in  the
margin.   This  tool  is  also  available from the
author of Aegis.



Peter Miller     (lib/en/user-guide/c2.1.so)         Page 35





User Guide                                             Aegis


times that a project works12.  Making this a precondition to
leave the _b_e_i_n_g _d_e_v_e_l_o_p_e_d state means that a reviewer can be
sure that a change builds and passes its tests before it can
ever be reviewed.  Pat adds the truant test:

     pat% aaeenntt
     aegis: project "example.1.0": change 10: file "test/00/t0001a.sh" new
             test
     pat%


The test file is in a weird place, eh?  This is because many
flavors of UNIX are slow at searching  directories,  and  so
Aegis  limits  itself  to 100 tests per directory.  Whatever
the name, Pat edits the test file to look like this:

     #!/bin/sh
     #
     # test simple arithmetic
     #
     tmp=/tmp/$$
     here=`pwd`
     if [ $? -ne 0 ]; then exit 1; fi


     fail()
     {
             echo FAILED 1>&2
             cd $here
             rm -rf $tmp
             exit 1
     }


     pass()
     {
             cd $here
             rm -rf $tmp
             exit 0
     }
     trap "fail" 1 2 3 15






-----------
  12 As  discussed in the _H_o_w _A_e_g_i_s _W_o_r_k_s chapter,
aegis has the objective of ensuring that  projects
always  work,  where "works" is defined as passing
all tests in the  project's  baseline.   A  change
"works"  if  it  passes  all  of  its accompanying
tests.



Page 36          (lib/en/user-guide/c2.1.so)    Peter Miller





Aegis                                             User Guide


     mkdir $tmp
     if [ $? -ne 0 ]; then exit 1; fi
     cd $tmp
     if [ $? -ne 0 ]; then fail; fi


     #
     # with input like this
     #
     cat > test.in << 'foobar'
     1
     (24 - 22)
     -(4 - 7)
     2 * 2
     10 / 2
     4 + 2
     10 - 3
     foobar
     if [ $? -ne 0 ]; then fail; fi


     #
     # the output should look like this
     #
     cat > test.ok << 'foobar'
     1
     2
     3
     4
     5
     6
     7
     foobar
     if [ $? -ne 0 ]; then fail; fi


     #
     # run the calculator
     # and see if the results match
     #
     $here/example < test.in > test.out
     if [ $? -ne 0 ]; then fail; fi
     diff test.ok test.out
     if [ $? -ne 0 ]; then fail; fi


     #
     # this much worked
     #
     pass


There are several things to notice about this test file:




Peter Miller     (lib/en/user-guide/c2.1.so)         Page 37





User Guide                                             Aegis


+o It is a Bourne shell script.  All test  files  are  Bourne
     shell scripts because they  are  the  most  portable.13
     (Actually, Aegis likes test files not to be executable,
     it passes them to the Bourne shell explicitly when run-
     ning them.)

+o  It  makes  the  assumption  that the current directory is
     either the development directory or the baseline.  This
     is  valid, aegis always runs tests this way; if you run
     one manually, you must take care of this yourself.

+o It checks the exit status of each and every  command.   It
     is  essential that even unexpected and impossible fail-
     ures are handled.

+o A temporary directory is created for temporary files.   It
     cannot be assumed that a test will be run from a direc-
     tory which is writable; it is also easier to  clean  up
     after  strange  errors,  since  you need only throw the
     directory away, rather than track down individual  tem-
     porary  files.   It  mostly protects against rogue pro-
     grams scrambling files in the current directory, too.

+o Every test is self-contained.   The  test  uses  auxiliary
     files, but they are not separate source files (figuring
     where they are when some are in a change and  some  are
     in  the  baseline can be a nightmare).  If a test wants
     an auxiliary file, it must construct the  file  itself,
     in a temporary directory.

+o  Two  functions have been defined, one for success and one
     for failure.  Both forms remove  the  temporary  direc-
     tory.   A  test is defined as passing if it returns a 0
     exit status, and failing if it returns anything else.

+o Tests are treated just like any other source file, and are
     subject  to  the  same process.  They may be altered in
     another change, or even deleted later if  they  are  no
     longer useful.

The  most  important  feature to note about this test, after
ignoring all of the trappings, is that it  doesn't  do  much
you wouldn't do manually!  To test this program manually you
would fire it up, just as the test does, you would  give  it
some input, just as the test does, and you would compare the
output against your expectations of what it will do, just as
the test does.
-----------
  13 Portable  for  Aegis'  point  of view: Bourne
shell is the  most  widely  available  shell.   Of
course,  if  you  are  writing  code to publish on
USENET or for FTP, portability of the  tests  will
be  important  from  the developer's point of view
also.



Page 38          (lib/en/user-guide/c2.1.so)    Peter Miller





Aegis                                             User Guide


The difference with using this test script and doing it man-
ually is that most development contains many  iterations  of
the "build, test, _t_h_i_n_k, edit, build, test..." cycle.  After
a couple of iterations, the manual testing, the constant re-
typing, becomes obviously unergonomic.  Using a shell script
is more efficient, doesn't forget to test things later,  and
is preserved for posterity (i.e. adds to the regression test
suite).

This  efficiency is especially evident when using commands14
such as

     pat% aaeebb &&&& aaeett ;; vvii aaeeggiiss..lloogg
     ...
     pat% !!aaeebb
     ...
     pat%


It is possible to talk to the shell  extremely  rarely,  and
then only to re-issue the same command, using a work pattern
such as this.

As you have already guessed, Pat  now  runs  the  test  like
this:

     pat% aaeett
     aegis: sh /u/pat/example.1.0.C010/test/00/t0001a.sh
     aegis: project "example.1.0": change 10: test "test/00/t0001a.sh"
             passed
     aegis: project "example.1.0": change 10: passed 1 test
     pat%


Finally,  Pat  has  built the change, prepared it for review
and tested it.  It is now ready for sign off.

     pat% aaeeddee
     aegis: project "example.1.0": change 10: no current 'aegis -Build'
             registration
     pat%


Say what?  The problem is that the use of _a_e_n_t canceled  the
previous  build  registration.   This  was  because Aegis is
decoupled from the dependency maintenance tool (_c_o_o_k in this
case), and thus has no way of knowing whether or not the new
file in the change would affect the success or failure of  a
build15.   All that is required is to re-build, re-test, re-
-----------
  14 This is a _c_s_h specific example,  unlike  most
others.
  15 Example:  in  addition to the executable file
"example" shown here, the build may  also  produce



Peter Miller     (lib/en/user-guide/c2.1.so)         Page 39





User Guide                                             Aegis


difference (yes, the test gets differenced,  too)  and  sign
off.

     pat% aaeebb
     aegis: logging to "/u/pat/example.1.0.C010/aegis.log"
     aegis: project "example.1.0": change 10: development build started
     aegis: cook -b Howto.cook project=example.1.0 change=10
             version=1.0.C001 -nl
     cook: "all" is up-to-date
     aegis: project "example.1.0": change 10: development build complete
     pat% aaeett
     aegis: logging to "/u/pat/example.1.0.C010/aegis.log"
     aegis: sh /u/pat/example..1.0.C010/test/00/t0001a.sh
     aegis: project "example.1.0": change 10: test "test/00/t0001a.sh"
             passed
     aegis: project "example.1.0": change 10: passed 1 test
     pat% aaeedd
     aegis: logging to "/u/pat/example.1.0.C010/aegis.log"
     aegis: set +e; diff -c /dev/null /u/pat/example.1.0.C010/test/00/
             t0001a.sh > /u/pat/example.1.0.C010/test/00/t0001a.sh,D; test
             $? -eq 0 -o $? -eq 1
     aegis: project "example.1.0": change 10: difference complete
     pat% aaeeddee
     aegis: sh /usr/local/lib/aegis/de.sh example.1.0 10 pat
     aegis: project "example.1.0": change 10: development completed
     pat%


The  change  is  now  ready to be reviewed.  This section is
about developers, so we will have to leave  this  change  at
this  point in its history.  Some time in the next day or so
Pat receives electronic mail that  this  change  has  passed
review, and another later to say that it passed integration.
Pat is now free to develop another change,  possibly  for  a
different project.

33..11..33..  TThhee SSeeccoonndd CChhaannggee

The second change was created because someone wanted to name
input and output files on the command line, and  called  the
absence  of  this feature a bug.  When Jan arrived for work,
and lists the changes awaiting  development,  the  following
list appeared:

     jan% aaeeddbb --ll --pp eexxaammppllee..11..00
     Project "example.1.0"
     List of Changes

-----------
an  archive  file  of  the  project's  source  for
export.  The addition of one more  file  may  push
the  size of this archive beyond a size limit; the
build would thus fail because of the addition of a
test.



Page 40          (lib/en/user-guide/c2.1.so)    Peter Miller





Aegis                                             User Guide


     Change  State           Description
     ------  ------          ------------
       11    awaiting_       Add input and output file names to the
             development     command line.
       12    awaiting_       add variables
             development
       13    awaiting_       add powers
             development
     jan%


The first on the list is chosen.

     jan% aaeeddbb --cc 1111 --pp eexxaammppllee..11..00
     aegis: project "example.1.0": change 11: development directory "/u/
             jan/example.1.0.C011"
     aegis: project "example.1.0": change 11: user "jan" has begun
             development
     jan% aaeeccdd
     aegis: project "example.1.0": change 11: /u/jan/example.002
     jan%


The  best  way  to get details about a change is to used the
"change details" listing.

     jan% aaeell ccdd
     Project "example.1.0", Change 11
     Change Details


     NAME
             Project "example.1.0", Change 11.


     SUMMARY
             file names on command line


     DESCRIPTION
             Optional input and output files may be specified on the
             command line.


     CAUSE
             This change was caused by internal_bug.


     STATE
             This change is in 'being_developed' state.







Peter Miller     (lib/en/user-guide/c2.1.so)         Page 41





User Guide                                             Aegis


     FILES
             Change has no files.


     HISTORY
             What            When            Who     Comment
             ------          ------          -----   ---------
             new_change      Fri Dec 11      alex
                             14:55:06 1992
             develop_begin   Mon Dec 14      jan
                             09:07:08 1992
     jan%


Through one process or  another,  Jan  determines  that  the
_m_a_i_n_._c  file is the one to be modified.  This file is copied
into the change:

     jan% aaeeccpp mmaaiinn..cc
     aegis: project "example.1.0": change 11: file "main.c" copied
     jan%


This file is now extended to look like this:

     #include <stdio.h>


     static void
     usage()
     {
             fprintf(stderr, "usage: example [ <infile> [ <outfile> ]]\n");
             exit(1);
     }


     void
     main(argc, argv)
             int     argc;
             char    **argv;
     {
             char    *in = 0;
             char    *out = 0;
             int     j;













Page 42          (lib/en/user-guide/c2.1.so)    Peter Miller





Aegis                                             User Guide


             for (j = 1; j < argc; ++j)
             {
                     char *arg = argv[j];
                     if (arg[0] == '-')
                             usage();
                     if (!in)
                             in = arg;
                     else if (!out)
                             out = arg;
                     else
                             usage();
             }


             if (in && !freopen(in, "r", stdin))
             {
                     perror(in);
                     exit(1);
             }
             if (out && !freopen(out, "w", stdout))
             {
                     perror(out);
                     exit(1);
             }


             yyparse();
             exit(0);
     }


A new test is also required,

     jan% aaeenntt
     aegis: project "example.1.0": change 11: file "test/00/t0002a.sh" new
             test
     jan%

which is edited to look like this:

     #!/bin/sh
     #
     # test command line arguments
     #
     tmp=/tmp/$$
     here=`pwd`
     if [ $? -ne 0 ]; then exit 1; fi










Peter Miller     (lib/en/user-guide/c2.1.so)         Page 43





User Guide                                             Aegis


     fail()
     {
             echo FAILED 1>&2
             cd $here
             rm -rf $tmp
             exit 1
     }


     pass()
     {
             cd $here
             rm -rf $tmp
             exit 0
     }
     trap "fail" 1 2 3 15


     mkdir $tmp
     if [ $? -ne 0 ]; then exit 1; fi
     cd $tmp
     if [ $? -ne 0 ]; then fail; fi


     #
     # with input like this
     #
     cat > test.in << 'foobar'
     1
     (24 - 22)
     -(4 - 7)
     2 * 2
     10 / 2
     4 + 2
     10 - 3
     foobar
     if [ $? -ne 0 ]; then fail; fi


     #
     # the output should look like this
     #
     cat > test.ok << 'foobar'
     1
     2
     3
     4
     5
     6
     7
     foobar
     if [ $? -ne 0 ]; then fail; fi





Page 44          (lib/en/user-guide/c2.1.so)    Peter Miller





Aegis                                             User Guide


     #
     # run the calculator
     # and see if the results match
     #
     # (Use /dev/null for input in case input redirect fails;
     # don't want the test to hang!)
     #
     $here/example test.in test.out < /dev/null
     if [ $? -ne 0 ]; then fail; fi
     diff test.ok test.out
     if [ $? -ne 0 ]; then fail; fi
     $here/example test.in < /dev/null > test.out.2
     if [ $? -ne 0 ]; then fail; fi
     diff test.ok test.out.2
     if [ $? -ne 0 ]; then fail; fi


     #
     # make sure complains about rubbish
     # on the command line
     #
     $here/example -trash < test.in > test.out
     if [ $? -ne 1 ]; then fail; fi


     #
     # this much worked
     #
     pass


Now it is time  for  Jan  to  build  and  test  the  change.
Through  the magic of static documentation, this works first
time, and here is how it goes:

     jan% aaeebb
     aegis: logging to "/u/pat/example.1.0.C011/aegis.log"
     aegis: project "example.1.0": change 11: development build started
     aegis: cook -b /projects/example/baseline/Howto.cook
             project=example.1.0 change=11 version=1.0.C011 -nl
     cook: cc -I. -I/projects/example/baseline -O -c main.c
     cook: cc -o example main.o /projects/example/baseline/gram.o
             /projects/example/baseline/lex.o -ll -ly
     aegis: project "example.1.0": change 11: development build complete
     jan% aaeett
     aegis: logging to "/u/pat/example.1.0.C011/aegis.log"
     aegis: sh /u/jan/example.1.0.C011/test/00/t0002a.sh
     aegis: project "example.1.0e": change 11: test "test/00/t0002a.sh"
             passed
     aegis: project "example.1.0": change 11: passed 1 test
     jan%






Peter Miller     (lib/en/user-guide/c2.1.so)         Page 45





User Guide                                             Aegis


All that remains if to difference the change and sign off.

     jan% aaeedd
     aegis: logging to "/u/pat/example.1.0.C011/aegis.log"
     aegis: set +e; diff -c /projects/example/main.c /u/jan/
             example.1.0.C011/main.c > /u/jan/example.1.0.C011/main.c,D; test $?
             -eq 0 -o $? -eq 1
     aegis: project "example.1.0": change 11: difference complete
     jan% aaeeddmmoorree
     _._._._e_x_a_m_i_n_e_s _t_h_e _f_i_l_e_._._.
     jan%

Note how the  context  difference  shows  exactly  what  has
changed.  And now the sign-off:

     jan% aaeeddee
     aegis: project "example.1.0": change 11: no current 'aegis -Test
             -BaseLine' registration
     jan%


No,  it  wasn't  enough.  Tests must not only pass against a
new change, but must  fail  against  the  project  baseline.
This is to establish, in the case of bug fixes, that the bug
has been isolated _a_n_d fixed.  New functionality will usually
fail  against the baseline, because the baseline can't do it
(if it could, you wouldn't be adding it!).  So, Jan needs to
use a variant of the _a_e_t command.

     jan% aaeett --bbll
     aegis: sh /u/jan/example.1.0.C011/test/00/t0002a.sh
     usage: example
     FAILED
     aegis: project "example.1.0": change 11: test "test/00/t0002a.sh" on
             baseline failed (as it should)
     aegis: project "example.1.0": change 11: passed 1 test
     jan%

Running the regression tests is also a good idea

     jan% aaeett --rreegg
     aegis: logging to "/u/pat/example.1.0.C011/aegis.log"
     aegis: sh /projects/example/baseline/test/00/t0001a.sh
     aegis: project "example.1.0": change 11: test "test/00/t0001a.sh"
             passed
     aegis: project "example.1.0": change 11: passed 1 test
     jan%


Now Aegis will be satisfied







Page 46          (lib/en/user-guide/c2.1.so)    Peter Miller





Aegis                                             User Guide


     jan% aaeeddee
     aegis: sh /usr/local/lib/aegis/aegis/de.sh example.1.0 11 jan
     aegis: project "example.1.0": change 11: development completed
     jan%


Like  Pat  in the change before, Jan will receive email that
this change passed review, and later that it passed integra-
tion.

33..11..44..  TThhee TThhiirrdd aanndd FFoouurrtthh CChhaannggeess

This  section  will  show two people performing two changes,
one each.  The twist is that they have a file in common.

First Sam looks for a change to work  on  and  starts,  like
this:

     sam% aaeeddbb --ll
     Project "example.1.0"
     List of Changes

     Change  State           Description
     ------- -------         -------------
       12    awaiting_       add powers
             development
       13    awaiting_       add variables
             development
     sam% aaeeddbb 1122
     aegis: project "example.1.0": change 12: development directory "/u/
             sam/example.1.0.C012"
     aegis: project "example.1.0": change 12: user "sam" has begun
             development
     sam% aaeeccdd
     aegis: project "example.1.0": change 12: /u/sam/example.1.0.C012
     sam%


A  little sniffing around reveals that only the _g_r_a_m_._y gram-
mar file needs to be altered,  so  it  is  copied  into  the
change.

     sam% aaeeccpp ggrraamm..yy
     aegis: project "example.1.0": change 12: file "gram.y" copied
     sam%


The grammar file is changed to look like this:









Peter Miller     (lib/en/user-guide/c2.1.so)         Page 47





User Guide                                             Aegis


     %token DOUBLE
     %token NAME
     %union
     {
             double  lv_double;
             int     lv_int;
     };


     %type <lv_double> DOUBLE expr
     %type <lv_int> NAME
     %left '+' '-'
     %left '*' '/'
     %right '^'
     %right UNARY


     %%
     example
             : /* empty */
             | example command '\n'
                     { yyerrflag = 0; fflush(stderr); fflush(stdout); }
             ;


     command
             : expr
                     { printf("%g\n", $1); }
             | error
             ;


     expr
             : DOUBLE
             | '(' expr ')'
                     { $$ = $2; }
             | '-' expr
                     %prec UNARY
                     { $$ = -$2; }
             | expr '^' expr
                     { $$ = pow($1, $3); }
             | expr '*' expr
                     { $$ = $1 * $3; }
             | expr '/' expr
                     { $$ = $1 / $3; }
             | expr '+' expr
                     { $$ = $1 + $3; }
             | expr '-' expr
                     { $$ = $1 - $3; }
             ;


The  changes  are very small.  Sam checks to make sure using
the difference command:



Page 48          (lib/en/user-guide/c2.1.so)    Peter Miller





Aegis                                             User Guide


     sam% aaeedd
     aegis: logging to "/u/sam/example.1.0.C012/aegis.log"
     aegis: set +e; diff -c /projects/example/baseline/gram.y /u/sam/
             example.1.0.C012/gram.y > /u/sam/example.1.0.C012/gram.y,D; test $?
             -eq 0 -o $? -eq 1
     aegis: project "example.1.0": change 12: difference complete
     sam% aaeeddmmoorree
     _._._._e_x_a_m_i_n_e_s _t_h_e _f_i_l_e_._._.
     sam%

The difference file looks like this

     *** /projects/example/baseline/gram.y
     --- /u/sam/example.1.0.C012/gram.y
     ***************
     *** 1,5 ****
     --- 1,6 ----
       %{
       #include <stdio.h>
     + #include <math.h>
       %}
       %token DOUBLE
       %token NAME


     ***************
     *** 13,18 ****
     --- 14,20 ----
       %type <lv_int> NAME
       %left '+' '-'
       %left '*' '/'
     + %right '^'
       %right UNARY
       %%
       example


     ***************
     *** 32,37 ****
     --- 34,41 ----
             | '-' expr
                     %prec UNARY
                     { $$ = -$2; }
     +       | expr '^' expr
     +               { $$ = pow($1, $3); }
             | expr '*' expr
                     { $$ = $1 * $3; }
             | expr '/' expr


These are the differences Sam expected to see.

At this point Sam creates a test.  All good software  devel-
opers create the tests first, don't they?



Peter Miller     (lib/en/user-guide/c2.1.so)         Page 49





User Guide                                             Aegis


     sam% aaeenntt
     aegis: project "example.1.0": change 12: file "test/00/t0003a.sh" new
             test
     sam%


The  test  is  created  empty,  and Sam edit it to look like
this:

     :
     here=`pwd`
     if test $? -ne 0 ; then exit 1; fi
     tmp=/tmp/$$
     mkdir $tmp
     if test $? -ne 0 ; then exit 1; fi
     cd $tmp
     if test $? -ne 0 ; then exit 1; fi


     fail()
     {
             echo FAILED 1>&2
             cd $here
             chmod u+w `find $tmp -type d -print`
             rm -rf $tmp
             exit 1
     }


     pass()
     {
             cd $here
             chmod u+w `find $tmp -type d -print`
             rm -rf $tmp
             exit 0
     }
     trap "fail" 1 2 3 15


     cat > test.in << 'end'
     5.3 ^ 0
     4 ^ 0.5
     27 ^ (1/3)
     end
     if test $? -ne 0 ; then fail; fi


     cat > test.ok << 'end'
     1
     2
     3
     end
     if test $? -ne 0 ; then fail; fi




Page 50          (lib/en/user-guide/c2.1.so)    Peter Miller





Aegis                                             User Guide


     $here/example test.in < /dev/null > test.out 2>&1
     if test $? -ne 0 ; then fail; fi


     diff test.ok test.out
     if test $? -ne 0 ; then fail; fi


     $here/example test.in test.out.2 < /dev/null
     if test $? -ne 0 ; then fail; fi


     diff test.ok test.out.2
     if test $? -ne 0 ; then fail; fi


     # it probably worked
     pass


Everything is ready.   Now  the  change  can  be  built  and
tested, just like the earlier changes.

     sam% aaeebb
     aegis: logging to "/u/sam/example.1.0.C012/aegis.log"
     aegis: project "example1.0": change 12: development build started
     aegis: cook -b /projects/example/baseline/Howto.cook
             project=example.1.0 change=12 version=1.0.C012 -nl
     cook: yacc -d gram.y
     cook: mv y.tab.c gram.c
     cook: mv y.tab.h gram.h
     cook: cc -I. -I/projects/example/baseline -O -c gram.c
     cook: cc -I. -I/projects/example/baseline -O -c /projects/
             example/baseline/lex.c
     cook: cc -o example gram.o lex.o /projects/example/baseline/
             main.o -ll -ly -lm
     aegis: project "example": change 3: development build complete
     sam%


Notice  how  the  yacc run produces a _g_r_a_m_._h which logically
invalidates the _l_e_x_._o in the baseline, and so the _l_e_x_._c file
in the baseline is recompiled, using the _g_r_a_m_._h include file
from the development directory, leaving a new _l_e_x_._o  in  the
development directory.  This is the reason for the use of

     #include <_f_i_l_e_n_a_m_e>

directives, rather then the double quote form.

     Now the change is tested.






Peter Miller     (lib/en/user-guide/c2.1.so)         Page 51





User Guide                                             Aegis


     sam% aaeett
     aegis: logging to "/u/sam/example.1.0.C012/aegis.log"
     aegis: sh /u/sam/example.1.0.C012/test/00/t0003a.sh
     aegis: project "example.1.0": change 12: test "test/00/t0003a.sh"
             passed
     aegis: project "example.1.0": change 12: passed 1 test
     sam%


The  change  must  also  be tested against the baseline, and
fail.  Sam knows this, and does it here.

     sam% aaeett --bbll
     aegis: logging to "/u/sam/example.1.0.C012/aegis.log"
     aegis: sh /u/sam/example.1.0.C012/test/00/t0003a.sh
     1,3c1,6
     < 1
     < 2
     < 3
     ---
     > syntax error
     > 5.3
     > syntax error
     > 4
     > syntax error
     > 27
     FAILED
     aegis: project "example.1.0": change 12: test "test/00/t0003a.sh" on
             baseline failed (as it should)
     aegis: project "example.1.0": change 12: passed 1 test
     sam%


Running the regression tests is also a good idea.

     sam% aaeett --rreegg
     aegis: logging to "/u/sam/example.1.0.C012/aegis.log"
     aegis: sh /projects/example/baseline/test/00/t0001a.sh
     aegis: project "example.1.0": change 12: test "test/00/t0001a.sh"
             passed
     aegis: sh /projects/example/baseline/test/00/t0002a.sh
     aegis: project "example.1.0": change 12: test "test/00/t0002a.sh"
             passed
     aegis: project "example.1.0": change 12: passed 2 tests
     sam%


A this point  Sam  has  just  enough  time  to  get  to  the
lunchtime aerobics class in the staff common room.

Earlier  the  same  day, Pat arrived for work a little after
Sam, and also looked for a change to work on.





Page 52          (lib/en/user-guide/c2.1.so)    Peter Miller





Aegis                                             User Guide


     pat% aaeeddbb --ll
     Project "example.1.0"
     List of Changes

     Change  State           Description
     ------- -------         -------------
       13    awaiting_       add variables
             development
     pat%


With such a wide choice, Pat selected change 13.

     pat% aaeeddbb 1133
     aegis: project "example.1.0": change 13: development directory "/u/
             pat/example.1.0.C013"
     aegis: project "example.1.0": change 13: user "pat" has begun
             development
     pat% aaeeccdd
     aegis: project "example.1.0": change 13: /u/pat/example.1.0.C013
     pat%


To get more information about the change, Pat then uses  the
"change details" listing:

     pat% aaeell ccdd
     Project "example.1.0", Change 13
     Change Details


     NAME
             Project "example.1.0", Change 13.


     SUMMARY
             add variables


     DESCRIPTION
             Enhance the grammar to allow variables. Only single
             letter variable names are required.


     CAUSE
             This change was caused by internal_enhancement.


     STATE
             This change is in 'being_developed' state.







Peter Miller     (lib/en/user-guide/c2.1.so)         Page 53





User Guide                                             Aegis


     FILES
             This change has no files.


     HISTORY
             What            When            Who     Comment
             ------          ------          -----   ---------
             new_change      Mon Dec 14      alex
                             13:08:52 1992
             develop_begin   Tue Dec 15      pat
                             13:38:26 1992
     pat%


To  add  the  variables  the grammar needs to be extended to
understand them, and a new file for remembering and  recall-
ing the values of the variables needs to be added.

     pat% aaeeccpp ggrraamm..yy
     aegis: project "example.1.0": change 13: file "gram.y" copied
     pat% aaeennff vvaarr..cc
     aegis: project "example.1.0": change 13: file "var.c" added
     pat%


Notice  how  Aegis  raises  no objection to both Sam and Pat
having a copy of the _g_r_a_m_._y file.  Resolving this contention
is the subject of this section.

Pat now edits the grammar file.

     pat% vvii ggrraamm..yy
     _._._._e_d_i_t _t_h_e _f_i_l_e_._._.
     pat% aaeedd
     aegis: logging to "/u/pat/example.1.0.C013/aegis.log"
     aegis: set +e; diff -c /projects/example/baseline/gram.y /u/pat/
             example.1.0.C013/gram.y > /u/pat/example.1.0.C013/gram.y,D; test $?
             -eq 0 -o $? -eq 1
     aegis: project "example.1.0": change 13: difference complete
     pat%


The difference file looks like this

     ..._h_e_y_, _s_o_m_e_o_n_e _f_i_l_l _m_e _i_n_!_._._.


The new _v_a_r_._c file was created empty by Aegis, and Pat edits
it to look like this:

     static double memory[26];






Page 54          (lib/en/user-guide/c2.1.so)    Peter Miller





Aegis                                             User Guide


     void
     assign(name, value)
             int     name;
             double  value;
     {
             memory[name] = value;
     }


     double
     recall(name)
             int     name;
     {
             return memory[name];
     }


Little remains except to build the change.

     pat% aaeebb
     aegis: logging to "/u/pat/example.1.0.C013/aegis.log"
     aegis: cook -b /example.proj/baseline/Howto.cook
             project=example.1.0 change=13 version=1.0.C013 -nl
     cook: yacc -d gram.y
     cook: mv y.tab.c gram.c
     cook: mv y.tab.h gram.h
     cook: cc -I. -I/projects/example/baseline -O -c gram.c
     cook: cc -I. -I/projects/example/baseline -O -c /projects/
             example/baseline/lex.c
     cook: cc -I. -I/projects/example/baseline -O -c var.c
     cook: cc -o example gram.o lex.o /projects/example/baseline/
             main.o var.o -ll -ly -lm
     aegis: project "example.1.0": change 13: development build complete
     pat%


A new test for the new functionality  is  required  and  Pat
creates one like this.

     :
     here=`pwd`
     if test $? -ne 0 ; then exit 1; fi
     tmp=/tmp/$$
     mkdir $tmp
     if test $? -ne 0 ; then exit 1; fi
     cd $tmp
     if test $? -ne 0 ; then exit 1; fi










Peter Miller     (lib/en/user-guide/c2.1.so)         Page 55





User Guide                                             Aegis


     fail()
     {
             echo FAILED 1>&2
             cd $here
             chmod u+w `find $tmp -type d -print`
             rm -rf $tmp
             exit 1
     }
     pass()
     {
             cd $here
             chmod u+w `find $tmp -type d -print`
             rm -rf $tmp
             exit 0
     }
     trap "fail" 1 2 3 15


     cat > test.in << 'end'
     a = 1
     a + 1
     c = a * 40 + 5
     c / (a + 4)
     end
     if test $? -ne 0 ; then fail; fi


     cat > test.ok << 'end'
     2
     9
     end
     if test $? -ne 0 ; then fail; fi


     $here/example test.in < /dev/null > test.out 2>&1
     if test $? -ne 0 ; then fail; fi


     diff test.ok test.out
     if test $? -ne 0 ; then fail; fi


     $here/example test.in test.out.2 < /dev/null
     if test $? -ne 0 ; then fail; fi


     diff test.ok test.out.2
     if test $? -ne 0 ; then fail; fi


     # it probably worked
     pass





Page 56          (lib/en/user-guide/c2.1.so)    Peter Miller





Aegis                                             User Guide


The new files are then differenced:

     pat% aaeedd
     aegis: logging to "/u/pat/example.1.0.C013/aegis.log"
     aegis: set +e; diff -c /projects/example/baseline/gram.y /u/pat/
             example.1.0.C013/gram.y > /u/pat/example.1.0.C013/gram.y,D; test $?
             -eq 0 -o $? -eq 1
     aegis: set +e; diff -c /dev/null /u/pat/example.1.0.C013/test/00/
             t0004a.sh > /u/pat/example.1.0.C013/test/00/t0004a.sh,D; test
             $? -eq 0 -o $? -eq 1
     aegis: set +e; diff -c /dev/null /u/pat/example.1.0.C013/var.c > /u/
             pat/example.1.0.C013/var.c,D; test $? -eq 0 -o $? -eq 1
     aegis: project "example.1.0": change 13: difference complete
     pat%


Notice  how the difference for the _g_r_a_m_._y file is still cur-
rent, and so is not run again.

The change is tested.

     pat% aaeett
     aegis: logging to "/u/pat/example.1.0.C013/aegis.log"
     aegis: sh /u/pat/example.1.0.C013/test/00/t0001a.sh
     aegis: project "example.1.0": change 13: test "test/00/t0004a.sh"
             passed
     aegis: project "example.1.0": change 13: passed 2 tests
     pat%


The change is tested against the baseline.

     pat% aaeett --bbll
     aegis: logging to "/u/pat/example.1.0.C013/aegis.log"
     aegis: sh /u/pat/example.1.0.C013/test/00/t0001a.sh
     1,2c1,4
     < 2
     < 9
     ---
     > syntax error
     > syntax error
     > syntax error
     > syntax error
     FAILED
     aegis: project "example.1.0": change 13: test "test/00/t0004a.sh" on
             baseline failed (as it should)
     pat%


And the regression tests







Peter Miller     (lib/en/user-guide/c2.1.so)         Page 57





User Guide                                             Aegis


     pat% aaeett --rreegg
     aegis: logging to "/u/pat/example.1.0.C013/aegis.log"
     aegis: sh /projects/example/baseline/test/00/t0001a.sh
     aegis: project "example.1.0": change 13: test "test/00/t0001a.sh"
             passed
     aegis: sh /projects/example/baseline/test/00/t0002a.sh
     aegis: project "example.1.0": change 13: test "test/00/t0002a.sh"
             passed
     aegis: project "example.1.0": change 13: passed 2 tests
     pat%


Note how test 3 has not been run, in any  form  of  testing.
This is because test 3 is part of another change, and is not
yet integrated with the baseline.

All is finished for this change,

     pat% aaeeddee
     aegis: sh /usr/local/lib/aegis/de.sh example.1.0 13 pat
     aegis: project "example.1.0": change 13: development completed
     pat%


Anxious to get this change into the baseline, Pat  now  wan-
ders down the hall in search of a reviewer, but more of that
in the next section.

Some time later, San  returns  from  aerobics  feeling  much
improved.   All  that  is  required  for  change 12 is to do
develop end, or is it?

     sam% aaeeddee
     aegis: project "example.1.0": change 12: file "gram.y" in baseline
             has changed since last 'aegis -DIFFerence' command
     sam%


A little sleuthing on Sam's part with the Aegis list command
will  reveal  how  this came about.  The way to resolve this
problem is with the difference command, but the merge  vari-
ant  -  this  will merge the new baseline version, and Sam's
edit together.














Page 58          (lib/en/user-guide/c2.1.so)    Peter Miller





Aegis                                             User Guide


     sam% aaeemm
     aegis: logging to "/u/pat/example.1.0.C012/aegis.log"
     aegis: co -u'1.1' -p /projects/example/history/gram.y,v > /tmp/
             aegis.14594
     /projects/example/history/gram.y,v  -->  stdout revision 1.1 (unlocked)
     aegis: (diff3 -e /projects/example/baseline/gram.y /tmp/
             aegis.14594 /u/sam/example.003/gram.y | sed -e '/^w$/d'
             -e '/^q$/d';     echo '1,$p' ) | ed - /projects/example/
             baseline/gram.y,B > /u/sam/example.003/gram.y
     aegis: project "example.1.0": change 12: merge complete
     aegis: project "example.1.0": change 12: file "gram.y" was out of
             date and has been merged, see "gram.y,B" for original source
     aegis: new 'aegis -Build' required
     sam%


This was caused by the conflict between change 13, which  is
now integrated, and change 12; both of which are editing the
_g_r_a_m_._y file.  Sam examines the _g_r_a_m_._y file, and is satisfied
that  it  contains  an  accurate  merge  of the edit done by
change 13 and the edits for this change.  The merged  source
file looks like this:

     %{
     #include <stdio.h>
     #include <math.h>
     %}
     %token DOUBLE
     %token NAME
     %union
     {
             double  lv_double;
             int     lv_int;
     };


     %type <lv_double> DOUBLE expr
     %type <lv_int> NAME
     %left '+' '-'
     %left '*' '/'
     %right '^'
     %right UNARY


     %%
     example
             : /* empty */
             | example command '\n'
                     { yyerrflag = 0; fflush(stderr); fflush(stdout); }
             ;







Peter Miller     (lib/en/user-guide/c2.1.so)         Page 59





User Guide                                             Aegis


     command
             : expr
                     { printf("%g\n", $1); }
             | NAME '=' expr
                     { assign($1, $3); }
             | error
             ;


     expr
             : DOUBLE
             | NAME
                     { extern double recall(); $$ = recall($1); }
             | '(' expr ')'
                     { $$ = $2; }
             | '-' expr
                     %prec UNARY
                     { $$ = -$2; }
             | expr '^' expr
                     { $$ = pow($1, $3); }
             | expr '*' expr
                     { $$ = $1 * $3; }
             | expr '/' expr
                     { $$ = $1 / $3; }
             | expr '+' expr
                     { $$ = $1 + $3; }
             | expr '-' expr
                     { $$ = $1 - $3; }
             ;

The  automatic  merge worked because most such conflicts are
actually working on logically separate portions of the file.
Two  different  areas of the grammar in this case.  In prac-
tice, there is rarely a real conflict,  and  it  is  usually
small enough to detect fairly quickly.

Sam now rebuilds:




















Page 60          (lib/en/user-guide/c2.1.so)    Peter Miller





Aegis                                             User Guide


     sam% aaeebb
     aegis: logging to "/u/sam/example.1.0.C012/aegis.log"
     aegis: project "example.1.0": change 12: development build started
     aegis: cook -b /projects/example/baseline/Howto.cook
             project=example.1.0 change=12 version=1.0.C012 -nl
     cook: rm gram.c
     cook: rm gram.h
     cook: yacc -d gram.y
     cook: mv y.tab.c gram.c
     cook: mv y.tab.h gram.h
     cook: rm gram.o
     cook: cc -I. -I/projects/example/baseline -O -c gram.c
     cook: rm lex.o
     cook: cc -I. -I/projects/example/baseline -O -c /projects/
             example/baseline/lex.c
     cook: rm example
     cook: cc -o example gram.o lex.o /projects/example/baseline/
             main.o /projects/example/baseline/var.o -ll -ly -lm
     aegis: project "example.1.0": change 12: development build complete
     sam%


Notice  how the list of object files linked has also adapted
to the addition of another file in the baseline, without any
extra work by Sam.

All that remains is to test the change again.

     sam% aaeett
     aegis: /bin/sh /u/sam/example.1.0.C012/test/00/t0003a.sh
     aegis: project "example.1.0": change 12: test "test/00/t0003a.sh"
             passed
     aegis: project "example.1.0": change 12: passed 1 test
     sam%

And test against the baseline,





















Peter Miller     (lib/en/user-guide/c2.1.so)         Page 61





User Guide                                             Aegis


     sam% aaeett --bbll
     aegis: /bin/sh /u/sam/example.1.0.C012/test/00/t0003a.sh
     1,3c1,6
     < 1
     < 2
     < 3
     ---
     > syntax error
     > 5.3
     > syntax error
     > 4
     > syntax error
     > 27
     FAILED
     aegis: project "example.1.0": change 12: test "test/00/t0003a.sh" on
             baseline failed (as it should)
     aegis: project "example.1.0": change 12: passed 1 test
     sam%


Perform  the regression tests, too.  This is important for a
merged change, to make sure you didn't break the functional-
ity of the code you merged with.

     sam% aaeett --rreegg
     aegis: logging to "/u/sam/example.1.0.C012/aegis.log"
     aegis: /bin/sh /projects/example/baseline/test/00/
             t0001a.sh
     aegis: project "example.1.0": change 12: test "test/00/t0001a.sh"
             passed
     aegis: /bin/sh /projects/example/baseline/test/00/
             t0002a.sh
     aegis: project "example.1.0": change 12: test "test/00/t0002a.sh"
             passed
     aegis: /bin/sh /projects/example/baseline/test/00/
             t0004a.sh
     aegis: project "example.1.0": change 12: test "test/00/t0004a.sh"
             passed
     aegis: project "example.1.0": change 12: passed 3 tests
     sam%

All done, or are we?

     sam% aaeeddee
     aegis: project "example.1.0": change 12: no current 'aegis -Diff'
             registration
     sam%

The  difference  we did earlier, which revealed that we were
out of date, does not show the  differences  since  the  two
changes were merged, and possibly further edited.






Page 62          (lib/en/user-guide/c2.1.so)    Peter Miller





Aegis                                             User Guide


     sam% aaeedd
     aegis: logging to "/u/sam/example.1.0.C012/aegis.log"
     aegis: set +e; diff /projects/example/baseline/gram.y /u/pat/
             example.1.0.C012/gram.y > /u/pat/example.1.0.C012/gram.y,D;
             test $? -le 1
     aegis: project "example.1.0": change 12: difference complete
     sam%

This time everything will run smoothly,

     sam% aaeeddee
     aegis: project "example.1.0": change 12: development completed
     sam%

Some  time  soon  Sam  will  receive  email that this change
passed review, and later that it passed integration.

Within the scope of a limited example, you have seen most of
what  Aegis  can  do.  To get a true feeling for the program
you need to try it in a similarly simple  case.   You  could
even try doing this example manually.




































Peter Miller     (lib/en/user-guide/c2.1.so)         Page 63





User Guide                                             Aegis


33..11..55..  DDeevveellooppeerr CCoommmmaanndd SSuummmmaarryy

Only  a  few  of  the Aegis commands available to developers
have been used in the example.  The  following  table  (very
tersely)  describes the Aegis commands most useful to devel-
opers.

          Command   Description
          ----------------------------------------
          aeb       Build
          aeca      edit Change Attributes
          aecd      Change Directory
          aeclean   Clean a development directory
          aeclone   copy a whole change
          aecp      Copy File
          aecpu     Copy File Undo
          aed       Difference
          aedb      Develop Begin
          aedbu     Develop Begin Undo
          aede      Develop End
          aedeu     Develop End Undo
          ael       List Stuff
          aenf      New File
          aenfu     New File Undo
          aent      New Test
          aentu     New Test Undo
          aerm      Remove File
          aermu     Remove File Undo
          aet       Test


You will want to read the manual entries for  all  of  these
commands.  Note that all Aegis commands have a _-_H_e_l_p option,
which will give a result very similar to  the  corresponding
_m_a_n(1)  output.   Most  Aegis  commands  also  have  a _-_L_i_s_t
option, which usually lists  interesting  context  sensitive
information.




















Page 64          (lib/en/user-guide/c2.2.so)    Peter Miller





Aegis                                             User Guide


33..22..  TThhee RReevviieewweerr

The role of a reviewer is to check another user's work.  You
are helped in this by Aegis, because changes can never reach
the _b_e_i_n_g _r_e_v_i_e_w_e_d state without several preconditions:

+o  The  change is known to build.  You know that it compiled
successfully, so there is  no  need  to  search  for  syntax
errors.

+o  The  change has tests, and those tests have been run, and
have passed.

This information allows you to concentrate on implementation
issues, completeness issues, and local standards issues.

To  help the reviewer, a set of "comma D" files is available
in the change development directory.  Every file which is to
be  added  to  the  baseline,  removed from the baseline, or
changed in some way, has a corresponding "comma D" file.

33..22..11..  BBeeffoorree YYoouu SSttaarrtt

Have you configured your account to use Aegis?  See the _U_s_e_r
_S_e_t_u_p  section  of  the _T_i_p_s _a_n_d _T_r_a_p_s chapter for how to do
this.

33..22..22..  TThhee FFiirrsstt CChhaannggee

Robyn finds out what changes are  available  for  review  by
asking Aegis:

     robyn% aaeerrppaassss --ll --pp eexxaammppllee..11..00

     Project "example.1.0"
     List of Changes

     Change  State           Description
     ------- -------         -------------
       10    being_reviewed  Place under Aegis
     robyn%

Any  of  the  above changes could be reviewed, Robyn chooses
the first.

     robyn% aaeeccdd --pp eexxaammppllee..11..00 --cc 1100
     aegis: project "example": change 1: /u/pat/example.1.0.C010
     robyn% aaeeddmmoorree
     _._._._e_x_a_m_i_n_e_s _e_a_c_h _f_i_l_e_._._.
     robyn%

The _a_e_d_m_o_r_e command walks the development directory tree  to
find  all  of  the  "comma D" files, and displays them using
_m_o_r_e(1).  There is a corresponding  _a_e_d_l_e_s_s  for  those  who



Peter Miller     (lib/en/user-guide/c2.2.so)         Page 65





User Guide                                             Aegis


prefer the _l_e_s_s(1) command.

Once  the  change has been reviewed and found acceptable, it
is passed:

     robyn% aaeerrppaassss --pp eexxaammppllee..11..00 1100
     aegis: sh /usr/local/lib/aegis/rp.sh example.1.0 10 pat robyn
     aegis: project "example.1.0": change 10: passed review
     robyn%

Some time soon Isa will notice the  email  notification  and
commence integration of the change.

33..22..33..  TThhee SSeeccoonndd CChhaannggee

Most reviews have the same pattern as the first.

     robyn% aaeerrppaassss --ll --pp eexxaammppllee..11..00

     Project "example.1.0"
     List of Changes

     Change  State           Description
     ------- -------         -------------
       11    being_reviewed  file names on command line
     robyn%


Always  change  directory to the change's development direc-
tory, otherwise you will not be able to review the files.

     robyn% aaeeccdd --pp eexxaammppllee..11..00 --cc 1111
     aegis: project "example.1.0": change 11: /u/jan/example.1.0.C011
     robyn%


Another useful way of finding out  about  a  change  is  the
"list change details" command, viz:

     robyn% aaeell ccdd --pp eexxaammppllee..11..00 --cc 1111

     Project "example.1.0", Change 11
     Change Details


     NAME
             Project "example.1.0", Change 11.


     SUMMARY
             file names on command line






Page 66          (lib/en/user-guide/c2.2.so)    Peter Miller





Aegis                                             User Guide


     DESCRIPTION
             Optional input and output files may be specified on
             the command line.


     CAUSE
             This change was caused by internal_bug.


     STATE
             This change is in 'being_reviewed' state.


     FILES
             Type    Action  Edit    File Name
             ------- ------- ------- -----------
             source  modify  1.1     main.c
             test    create          test/00/t0002a.sh


     HISTORY
             What            When            Who     Comment
             ------          ------          -----   ---------
             new_change      Fri Dec 11      alex
                             14:55:06 1992
             develop_begin   Mon Dec 14      jan
                             09:07:08 1992
             develop_end     Mon Dec 14      jan
                             11:43:23 1992
     robyn%


Once  Robyn  knows what the change is meant to be doing, the
files are then examined:

     robyn% aaeeddmmoorree
     _._._._e_x_a_m_i_n_e_s _e_a_c_h _f_i_l_e_._._.
     robyn%


Once the change is found to be acceptable, it is passed:

     robyn% aaeerrppaassss --pp eexxaammppllee..11..00 1111
     aegis: sh /usr/local/lib/aegis/rp.sh example.1.0 11 jan robyn
     aegis: project "example.1.0": change 11: passed review
     robyn%


Some time soon Isa will notice the  email  notification  and
commence integration of the change.

The  reviews  of  the  third  and fourth changes will not be
given here, because they are almost identical to  the  other
changes.   If you want to know how to fail a review, see the



Peter Miller     (lib/en/user-guide/c2.2.so)         Page 67





User Guide                                             Aegis


_a_e_r_f_a_i_l(1) manual entry.

33..22..44..  RReevviieewweerr CCoommmmaanndd SSuummmmaarryy

Only a few of the Aegis commands available to reviewers have
been  used  in  this  example.   The  following  table (very
tersely) describes the Aegis commands most useful to review-
ers.


                 Command   Description
                 ---------------------------
                 aecd      Change Directory
                 aerpass   Review Pass
                 aerpu     Review Pass Undo
                 aerfail   Review Fail
                 ael       List Stuff


You  will  want  to read the manual entries for all of these
commands.  Note that all Aegis commands have a _-_H_e_l_p option,
which  will  give a result very similar to the corresponding
_m_a_n(1) output.   Most  Aegis  commands  also  have  a  _-_L_i_s_t
option,  which  usually  lists interesting context sensitive
information.
































Page 68          (lib/en/user-guide/c2.3.so)    Peter Miller





Aegis                                             User Guide


33..33..  TThhee IInntteeggrraattoorr

This section shows what the integrator must do for  each  of
the changes shown to date.  The integrator does not have the
ability to alter anything in the change; if a  change  being
integrated  is  defective,  it  is simply failed back to the
developer.  This documented example has no such failures, in
order to keep it manageably small.

33..33..11..  BBeeffoorree YYoouu SSttaarrtt

Have you configured your account to use Aegis?  See the _U_s_e_r
_S_e_t_u_p section of the _T_i_p_s _a_n_d _T_r_a_p_s chapter for  how  to  do
this.

33..33..22..  TThhee FFiirrsstt CChhaannggee

The  first  change  of a project is often the trickiest, and
the integrator is the  last  to  know.   This  example  goes
smoothly,  and  you  may  want to consider using the example
project as a template.

The integrator for this example project is Isa.   Isa  knows
there  is  a change ready for integration from the notifica-
tion which arrived by email.

     isa% aaeeiibb --ll --pp eexxaammppllee..11..00

     Project "example.1.0"
     List of Changes

     Change  State           Description
     ------- -------         -------------
       10    awaiting_       Place under Aegis
             integration
     isa% aaeeiibb eexxaammppllee..11..00 1100
     aegis: project "example.1.0": change 10: link baseline to integration
             directory
     aegis: project "example.1.0": change 10: apply change to integration
             directory
     aegis: project "example.1.0": change 10: integration has begun
     isa%


The integrator must rebuild and retest  each  change.   This
ensures  that it was no quirk of the developer's environment
which resulted in the success at the development stage.










Peter Miller     (lib/en/user-guide/c2.3.so)         Page 69





User Guide                                             Aegis


     isa% aaeebb
     aegis: logging to "/projects/example/delta.001/aegis.log"
     aegis: project "example.1.0": change 10: integration build started
     aegis: cook -b Howto.cook project=example.1.0 change=10
             version=1.0.D001 -nl
     cook: yacc -d gram.y
     cook: mv y.tab.c gram.c
     cook: mv y.tab.h gram.h
     cook: cc -I. -O -c gram.c
     cook: lex lex.l
     cook: mv lex.yy.c lex.c
     cook: cc -I. -O -c lex.c
     cook: cc -I. -O -c main.c
     cook: cc -o example gram.o lex.o main.o -ll -ly
     aegis: project "example.1.0": change 10: integration build complete
     isa%


Notice how the above build differed  from  the  builds  that
were  done  while  in  the  _b_e_i_n_g _d_e_v_e_l_o_p_e_d state; the extra
baseline include is gone.  This is because  the  integration
directory  will  shortly  be  the  new baseline, and must be
entirely internally consistent and self-sufficient.

You are probably wondering why this isn't  all  rolled  into
the  one Aegis command.  It is not because there may be some
manual process to be performed after the  build  and  before
the  test.  This may be making a command set-uid-root (as in
the case of Aegis itself) or it may require  some  tinkering
with the local oracle or ingress database.  Instructions for
the integrator may be placed in the description field of the
change attributes.

The change is now re-tested:

     isa% aaeett
     aegis: logging to "/projects/example/delta.001/aegis.log"
     aegis: sh /project/example/delta.001/test/00/t0001a.sh
     aegis: project "example": change 1: test "test/00/t0001a.sh"
             passed
     aegis: project "example": change 1: passed 1 test
     isa%

The  change  builds  and  tests.  Once Isa is happy with the
change, perhaps after browsing the files,  Isa  then  passes
the integration, causing the history files to be updated and
the integration directory becomes the baseline.










Page 70          (lib/en/user-guide/c2.3.so)    Peter Miller





Aegis                                             User Guide


     isa% aaeeiippaassss
     aegis: logging to "/projects/example/delta.001/aegis.log"
     aegis: ci -u -m/dev/null -t/dev/null /projects/example/delta.001/
             Howto.cook /projects/example/history/Howto.cook,v;
             rcs -U /projects/example/history/Howto.cook,v
     /projects/example/history/Howto.cook,v  <--
             /projects/example/delta.001/Howto.cook
     initial revision: 1.1
     done
     RCS file: /projects/example/history/Howto.cook,v
     done
     aegis: rlog -r /projects/example/history/Howto.cook,v | awk
             '/^revision/ {print $2}' > /tmp/aegis.15309
     _._._._l_o_t_s _o_f _s_i_m_i_l_a_r _R_C_S _o_u_t_p_u_t_._._.
     aegis: project "example.1.0": change 10: remove development directory
     aegis: sh /usr/local/lib/aegis/ip.sh example.1.0 10 pat robyn isa
     aegis: project "example.1.0": change 10: integrate pass
     isa%


All of the staff involved, will receive email  to  say  that
the  change  has  been  integrated.   This notification is a
shell script, so USENET could be usefully used instead.

     You should note that the development directory has been
deleted.   It  is  expected  that each development directory
will only contain files necessary  to  develop  the  change.
You should keep "precious" files somewhere else.

33..33..33..  TThhee OOtthheerr CChhaannggeess

There  is  no  difference  to  integrating  any of the later
changes.  The integration process is very simple, as it is a
cut-down version of what the developer does, without all the
complexity.

Your project may elect to have the integrator  also  monitor
the  quality  of  the reviews.  An answer to "who will watch
the watchers" if you like.

It is also a good idea to rotate people out of the  integra-
tor  position after a few weeks in a busy project, this is a
very stressful position.  The position of integrator gives a
unique  perspective to software quality, but the person also
needs to be able to say "NO!" when  a  cruddy  change  comes
along.











Peter Miller     (lib/en/user-guide/c2.3.so)         Page 71





User Guide                                             Aegis


33..33..44..  IInntteeggrraattoorr CCoommmmaanndd SSuummmmaarryy

Only  a  few  of the Aegis commands available to integrators
have been used in this example.  The following  table  (very
tersely)  describes  the Aegis commands most useful to inte-
grators.


               Command   Description
               -------------------------------
               aeb       Build
               aecd      Change Directory
               aed       Difference
               aeib      Integrate Begin
               aeibu     Integrate Begin Undo
               aeifail   Integrate Fail
               ael       List Stuff
               aet       Test
               aeipass   Integrate Pass


You will want to read the manual entries for  all  of  these
commands.  Note that all Aegis commands have a _-_H_e_l_p option,
which will give a result very similar to  the  corresponding
_m_a_n(1)  output.   Most  Aegis  commands  also  have  a _-_L_i_s_t
option, which usually lists  interesting  context  sensitive
information.

33..33..55..  MMiinniimmuumm IInntteeggrraattiioonnss

The  aaeeggiiss  ----iinntteeggrraattee--bbeeggiinn  command  provides a ----mmiinniimmuumm
option which may be used for various reasons.  The term mmiinn--
iimmuumm  may  be  a  bit counter intuitive.  One might think it
means to the mmiinniimmuumm amount of  work,  however  it  actually
means use a mmiinniimmuumm of files from the baseline in populating
the _d_e_l_t_a directory.  This normally leads to actually build-
ing  everything  in  the  project from sources and, as such,
might be considered the most robust of builds.

Note that any change which removes a file, whether  by  _a_e_r_m
or  _a_e_m_v,  results in an implicit mmiinniimmuumm integration.  This
is intended to ensure nothing in the project references  the
removed file.

A  project  may adopt a policy that a product release should
be based on a minimum integration.  Such a policy may  be  a
reflection  of  local  confidence,  or  lack  therof, in the
projects DMT (Dependency Maintenance Tool) or build  system.
Or it may be based on a validation process wishing to make a
simple statement on how the released package was produced.

Another, more transient, reason a to require a minimum inte-
gration  might be when upgrading a third party library, com-
piler or maybe even OS level.  Any  of  these  events  would



Page 72          (lib/en/user-guide/c2.3.so)    Peter Miller





Aegis                                             User Guide


signal  the  need for a minimum integration to ensure every-
thing is rebuilt using the new resources.

The cost of a mmiinniimmuumm integration varies according  to  type
and  size  of  the  project.  For very large projects, espe-
cially those building large numbers of  binaries,  the  cost
can  be large.  However large projects also require signifi-
cant time to fully populate the delta directory.  A  minimum
integration  only  copies  those  files under aegis control,
skipping all ``produced'' files.  In the case where  a  file
upon which everything depends is changed, everything will be
built anyway so the copy of the already  built  files  is  a
waste  of  time.  This means that sometimes a minimum can be
as cheap as a normal integration.











































Peter Miller     (lib/en/user-guide/c2.4.so)         Page 73





User Guide                                             Aegis


33..44..  TThhee AAddmmiinniissttrraattoorr

The previous discussion of developers, reviewers  and  inte-
grators  has covered many aspects of the production of soft-
ware using Aegis.  The administrator has responsibility  for
everything they don't, but there is very little left.

These responsibilities include:

+o  access  control:  The  administrator adds and removes all
categories of user, including administrators.  This is on  a
per-project  basis,  and  has  nothing  to do with UNIX user
administration.  This simply nominates which  users  may  do
what.

+o  change  creation:  The  administrator adds (and sometimes
removes) changes to the system.  At later stages, developers
may  alter  some  attributes  of  the  change,  such  as the
description, to say what they fixed.

+o project creation: Aegis does  not  limit  who  may  create
projects, but when a project is created the user who created
the project is set to be the administrator of that  project.

All of these things will be examined

33..44..11..  BBeeffoorree YYoouu SSttaarrtt

Have you configured your account to use Aegis?  See the _U_s_e_r
_S_e_t_u_p section of the _T_i_p_s _a_n_d _T_r_a_p_s chapter for  how  to  do
this.

33..44..22..  TThhee FFiirrsstt CChhaannggee

Many  things  need to happen before development can begin on
the first change; the project must be created, the staff but
be  given  access permissions, the branches created, and the
change must be created.

     alex% aaeennpprr eexxaammppllee --ddiirr //pprroojjeeccttss//eexxaammppllee --vveerrssiioonn --
     aegis: project "example": project directory "/projects/example"
     aegis: project "example": created
     alex%


Once the project has been created,  the  project  attributes
are set.  Alex will set the desired project attributes using
the --EEddiitt option of the aaeeppaa command.  This will  invoke  an
editor  (_v_i(1)  by  default) to edit the project attributes.
Alex edits them to look like this:







Page 74          (lib/en/user-guide/c2.4.so)    Peter Miller





Aegis                                             User Guide


     description = "Aegis Documentation Example Project";
     developer_may_review = false;
     developer_may_integrate = false;
     reviewer_may_integrate = false;

The project attributes are set as follows:

     alex% aaeeppaa --eeddiitt --pp eexxaammppllee
     _._._._e_d_i_t _a_s _a_b_o_v_e_._._.
     aegis: project "example.1.0": attributes changed
     alex% aaeell pp
     List of Projects

     Project     Directory           Description
     -------     -----------         -------------
     example     /projects/example   Aegis Documentation Example
                                     Project
     alex%

The various staff must be added to the project.   Developers
are the only staff who may actually edit files.

     alex% aaeenndd ppaatt jjaann ssaamm --pp eexxaammppllee
     aegis: project "example": user "pat" is now a developer
     aegis: project "example": user "jan" is now a developer
     aegis: project "example": user "sam" is now a developer
     alex%

Reviewers  may  veto a change.  There may be overlap between
the various categories, as show here for Jan:

     alex% aaeennrrvv rroobbyynn jjaann --pp eexxaammppllee
     aegis: project "example": user "robyn" is now a reviewer
     aegis: project "example": user "jan" is now a reviewer
     alex%

The next role we need to fill is an integrator.

     alex% aaeennii iissaa --pp eexxaammppllee
     aegis: project "example": user "isa" is now an integrator
     alex%

Once the staff have been given access, it is time to  create
the  working  branch.  Branches inherit their attributes and
staff lists from their parent branches when they  are  first
created, which is why we set all that stuff first.

     alex% aaeeggiiss --nnbbrr eexxaammppllee 11
     aegis: project "example.1": created
     alex% aaeeggiiss --nnbbrr eexxaammppllee..11 00
     aegis: project "example.1.0": created
     alex%

This  is  for versioning; see the _B_r_a_n_c_h_i_n_g chapter for more



Peter Miller     (lib/en/user-guide/c2.4.so)         Page 75





User Guide                                             Aegis


information.  For the moment, we will simply work on  branch
1.0.   Notice  how  the  branches  appear as projects in the
project listing; in general  branches  can  be  used  inter-
changeably with projects.

     alex% aaeell pp
     List of Projects

     Project     Directory           Description
     -------     -----------         -------------
     example     /projects/example   Aegis Documentation Example
                                     Project
     example.1   /projects/example/  Aegis Documentation Example
                 branch.1            Project, branch.1.
     example.1.0 /projects/example/  Aegis Documentation Example
                 branch.1/branch.0   Project, branch.1.0.
     alex%

Once  the  working branch has been created, Alex creates the
first change.  The --EEddiitt option of the aaeenncc command is used,
to  create the attributes of the change.  They are edited to
look like this:

     brief_description = "Create initial skeleton.";
     description = "A simple calculator using native \
     floating point precision.  \
     The four basic arithmetic operators to be provided, \
     using conventional infix notation.  \
     Parentheses and negation also required.";
     cause = internal_enhancement;

The change is created as follows:

     alex% aaeenncc --eeddiitt --pp eexxaammppllee..11..00
     _._._._e_d_i_t _a_s _a_b_o_v_e_._._.
     aegis: project "example.1.0": change 10: created
     alex%

Notice that the first change number is ``10''.  This is done
so  that changes 1 to 9 could be used as bug-fix branches at
some future time.  See the _B_r_a_n_c_h_i_n_g chapter for more infor-
mation.  You can over-ride this is you need to.

The above was written almost a decade ago.  There is a newer
command, _t_k_a_e_n_c, which uses a GUI and is much easier to use,
with a much less fiddly interface.  You may want to try that
command, instead, for most routine change creation.

At this point, Alex walks down the hall to Pat's office,  to
ask Pat to develop the first change.  Pat has had some prac-
tice using Aegis, and can be relied on to do the rest of the
project configuration speedily.





Page 76          (lib/en/user-guide/c2.4.so)    Peter Miller





Aegis                                             User Guide


33..44..33..  TThhee SSeeccoonndd CChhaannggee

Some time later, Alex patiently sits through the whining and
grumbling of an especially  pedantic  user.   The  following
change description is duly entered:

     brief_description = "file names on command line";
     description = "Optional input and output files may be \
     specified on the command line.";
     cause = internal_bug;


The  pedantic  user  wanted  to be able to name files on the
command line, rather than use I/O redirection.  Also, having
a  bug  in this example is useful.  The change is created as
follows:

     alex% aaeenncc --eeddiitt --pp eexxaammppllee..11..00
     _._._._e_d_i_t _a_s _a_b_o_v_e_._._.
     aegis: project "example.1.0": change 11: created
     alex%

At some point a developer will notice this change and  start
work on it.

33..44..44..  TThhee TThhiirrdd CChhaannggee

Other features are required for the calculator, and also for
this example.  The third change adds exponentiation  to  the
calculator, and is described as follows:

     brief_description = "add powers";
     description = "Enhance the grammar to allow exponentiation.  \
     No error checking required.";
     cause = internal_enhancement;


The change is created as follows:

     alex% aaeenncc --eeddiitt --pp eexxaammppllee..11..00
     _._._._e_d_i_t _a_s _a_b_o_v_e_._._.
     aegis: project "example.1.0": change 12: created
     alex%

At  some point a developer will notice, and this change will
be worked on.

33..44..55..  TThhee FFoouurrtthh CChhaannggee

A fourth change, this time adding variables to the  calcula-
tor is added.






Peter Miller     (lib/en/user-guide/c2.4.so)         Page 77





User Guide                                             Aegis


     brief_description = "add variables";
     description = "Enhance the grammar to allow variables.  \
     Only single letter variable names are required.";
     cause = internal_enhancement;


The change is created as follows:

     alex% aaeenncc --eeddiitt --pp eexxaammppllee..11..00
     _._._._e_d_i_t _a_s _a_b_o_v_e_._._.
     aegis: project "example.1.0": change 13: created
     alex%

At  some point a developer will notice, and this change will
be worked on.

33..44..66..  AAddmmiinniissttrraattoorr CCoommmmaanndd SSuummmmaarryy

Only a few of the Aegis commands available to administrators
have  been  used in this example.  The following table lists
the Aegis commands most useful to administrators.


             Command   Description
             ----------------------------------
             aeca      edit Change Attributes
             ael       List Stuff
             aena      New Administrator
             aenc      New Change
             aencu     New Change Undo
             aend      New Developer
             aeni      New Integrator
             aenpr     New Project
             aenrv     New Reviewer
             aepa      edit Project Attributes
             aera      Remove Administrator
             aerd      Remove Developer
             aeri      Remove Integrator
             aermpr    Remove Project
             aerrv     Remove Reviewer


You will want to read the manual entries for  all  of  these
commands.  Note that all Aegis commands have a _-_H_e_l_p option,
which will give a result very similar to  the  corresponding
_m_a_n(1)  output.   Most  Aegis  commands  also  have  a _-_L_i_s_t
option, which usually lists  interesting  context  sensitive
information.









Page 78          (lib/en/user-guide/c2.0.so)    Peter Miller





Aegis                                             User Guide


33..55..  WWhhaatt ttoo ddoo NNeexxtt

This chapter has given an overview of what using Aegis feels
like.  As a next step in getting to know Aegis, it would  be
a  good  idea if you created a project and went through this
same exercise.  You could use this  exact  example,  or  you
could  use  a  similar small project.  The idea is simply to
run through many of the same steps as in the example.  Typos
and  other natural events will ensure that you come across a
number of situations not directly covered by this chapter.

If you have not already done do, a printed copy of the  sec-
tion  1  and  5  manual  entries will be invaluable.  If you
don't want to use that many trees, they  will  be  available
on-line, by using the "-Help" option of the appropriate com-
mand variant.  Try:

     % aaeeddbb --hheellpp
     _._._._m_a_n_u_a_l _e_n_t_r_y_._._.
     %


Note that this example  has  not  demonstrated  all  of  the
available functionality.  One item of particular interest is
that tests, like any other source file, may be copied into a
change  and  modified,  or even deleted, just like any other
source file.

33..66..  CCoommmmoonn QQuueessttiioonnss

There are a number of questions which are  frequently  asked
by  people  evaluating  Aegis.   This  section  attempts  to
address some of them.

33..66..11..  IInnssuullaattiioonn

The repository model used by Aegis is of the ``push'' type -
that  is,  changes  to  the baseline are ``pushed'' onto the
developer as soon as they are integrated.   Many  configura-
tion  management  systems  have  a ``pull'' model, where the
developer elects when to cope with changes  in  the  reposi-
tory.   At  first  glance,  Aegis  does not appear to have a
``pull'' equivalent.

It is possible to insulate your change from the baseline  as
much or as little as required.  The _a_e_c_p(1) command, used to
copy files into a change, has  a  --read-only  option.   The
files  copied in this way are marked as insulation (_i_._e_. you
don't intend to change them).  If  you  have  not  un-copied
them at develop end time, the _a_e_d_e(1) command will produce a
suitable error message, reminding you to un-copy the insula-
tion and verify that your change still builds and tests suc-
cessfully with the (probably) now-different baseline.




Peter Miller     (lib/en/user-guide/c2.6.so)         Page 79





User Guide                                             Aegis


33..66..11..11..  CCooppyy RReeaadd--OOnnllyy

It is possible to select the degree of insulation.  By using
``aecp  .''  at the top of a development directory, the com-
plete project source tree will be  copied,  thus  completely
insulating  you.   Mind  you, it comes at the cost of a com-
plete build.

If you are working on a library, and only want the  rest  of
the  library  to remain fixed, simply copy the whole library
(aecp library/fred), and allow the rest to track  the  base-
line.   This  comes  at  a smaller cost, because more of the
baseline's object files can be taken advantage of.

33..66..11..22..  BBrraanncchheess

It is also possible to create a sub-branch (see the  _B_r_a_n_c_h_-
_i_n_g  chapter).  This does not itself automatically insulate,
however the first change of a branch  intended  to  insulate
would  copy  and  integrate  _b_u_t  _n_o_t _m_o_d_i_f_y the files to be
insulated.  You need to remember to perform  a  _c_r_o_s_s_-_b_r_a_n_c_h
_m_e_r_g_e  with  the parent branch before integrating the branch
back into the parent branch.

33..66..11..33..  BBuuiillddss

You can also insulate yourself from baseline change by being
selective  about  what you choose to build.  You can do this
by giving specific build targets on the _a_e_b(1) command line,
or  you  could  copy the build tool's configuration file and
butcher it.  Remember to change it back before  you  _a_e_d_e(1)
your change!

33..66..11..44..  MMiixx--aanndd--MMaattcchh

Some  or all of the above techniques may be combined to pro-
vide an insulation technique best suited to your project and
development  policy.   _E_._g_. changing the build configuration
file for a branch dedicated to working on a small portion of
a  large  project; towards the ed of the development, change
the build configuration file back  and  perform  integration
testing.

33..66..11..55..  DDiissaaddvvaannttaaggeess

There  is  actually  a  down-side to insulating your changes
from the evolution of the baseline.  By noticing and  adapt-
ing to the baseline, you have much less merging to do at the
end of your change set.  Each integration will typically  be
be  modest,  but the cumulative effect could be substantial,
and  add  a  huge  unexpected  (and  un-budgeted  for)  time
penalty.





Page 80          (lib/en/user-guide/c2.6.so)    Peter Miller





Aegis                                             User Guide


It also means that if there are integration problems between
your work and  the  changes  which  were  integrated  before
yours,  or  if  your  work shows up a bug in their work, the
project find this out late, rather than early.  The  litera-
ture,  based  on  industrial  experience, indicates that the
earlier problems are found the cheaper they are to fix.

Insulated development directories also use more disk  space.
While  disk  space  is  relatively  cheap these days, it can
still add up to a substantial hit for  a  large  development
team.   Un-insulated development directories can take advan-
tage of the pre-compiled objects and libraries in the  base-
line.

33..66..22..  PPaarrttiiaall CChheecckk--IInn

In  the  course  of developing new functionality, it is very
common to come across a pre-existing bug which the new func-
tionality  exposes.   It is common for such bugs to be fixed
by the developer in the same development directory, in order
to get the new functionality to a testable state.

There are two common courses of action at this point: simply
include the bug fix with the rest of the  change,  or  inte-
grate the bug fix earlier than the rest of the change.  Com-
bining the bug fix with the rest  of  the  change  can  have
nasty  effects on statistics: it can hide the true bug level
from your metrics program, and  it  also  denies  Aegis  the
opportunity of having accurate test correlations (see _a_e_t(1)
for more information.)  It  also  denies  the  rest  of  the
development team the use of the bug fix, or worse, it allows
the possibility that more than one team member will fix  the
bug, wasting development effort and time.

Many configuration management systems allow you to perform a
partial check-in of a work area.  This means  that  you  can
check-in  just  the  bug  fix,  but  continue to work on the
unfinished portions of the functionality you are  implement-
ing.

Because  Aegis insists on atomic change sets which are known
to build and test successfully, such a partial  check-in  is
not  allowed  - because Aegis can't know for certain that it
works.

Instead, you are able to _c_l_o_n_e a change (see _a_e_c_l_o_n_e(1)  for
more  information).  This gives you a new change, and a sec-
ond development directory, with exactly the same files.  You
then  remove  from  this  second change all of the files not
related to the bug fix  (using  _a_e_c_p_u(1),  _a_e_n_f_u(11),  _e_t_c).
You  then  create  a  test, build, difference, run the test,
develop end, all as usual.





Peter Miller     (lib/en/user-guide/c2.6.so)         Page 81





User Guide                                             Aegis


The original change will then need to  be  merged  with  the
baseline,  because  the  bug fix change will have been inte-
grated before it.  Usually this is straight-forward, as  you
already  have the changes (some merge tools make this harder
than others).  Often, all that is required is to merge,  and
then  say  ``aecpu  -unch''  to  un-copy all files which are
(now) unchanged when compared to the current baseline.

33..66..33..  MMuullttiippllee AAccttiivvee BBrraanncchheess

Some companies have multiple branches  active  at  the  same
time, for different customers or distributions, _e_t_c.

They  often  need  to  make the same change to more than one
branch.  Some configuration management systems allow you  to
check-in  the  same file multiple times, once to each active
branch.  Aegis does not let you do this, because you need to
convince  Aegis  that  the  change  set  will build and test
cleanly on each branch.  It is quite common for  the  change
to require non-trivial edits to work on each branch.

33..66..33..11..  CClloonniinngg

Aegis  instead  provides two mechanisms to handle this.  The
first, and simplest to understand, is to  clone  the  change
onto each relevant branch (rather than onto the same branch,
as mentioned above for bug fixes).  Then build and  test  as
normal.

33..66..33..22..  AAnncceessttrraall

The  second  technique is more subtle.  Perform the fix as a
change to  the  common  ancestor  of  both  branches.   This
assumes  that  neither branch is insulated against the rele-
vant area of code, and that earlier changes to the branch do
not mask it in some way (otherwise a cross-branch merge with
the common ancestor will be needed to propagate the fix).

33..66..44..  CCoollllaabboorraattiioonn

It is often the case that difficult problems are tackled  by
small  groups of 2 or 3 staff working together.  In order to
do this, they often work in a shared work area  with  group-
writable  or  global-write permissions.  However, this tends
to give security auditor heart attacks.

Aegis has several different ways to achieve the  same  ends,
and still not give the auditors indigestion.

33..66..44..11..  CChhaannggee OOwwnneerr

The  simplest method available is to change the ownership of
a change from one developer to the next.  A new  development
directory  is  created for the new developer, and the source



Page 82          (lib/en/user-guide/c2.6.so)    Peter Miller





Aegis                                             User Guide


files  are  copied  across16.   This allows a kind of serial
collaboration between developers.

33..66..44..22..  BBrraanncchh

The other possibility is to create a branch to  perform  the
work in, rather than a simple change.  (A branch in Aegis is
literally just a big change, which has lots of sub-changes.)
This allows parallel collaboration between developers.

33..66..44..33..  VViieeww PPaatthh HHaacckkiinngg

Aegis  usually  provides  a ``view path'' to the build tool.
This specifies where to look for source  files  and  derived
files, in order to union together the development directory,
and the baseline, and the branch's ancestors' baselines.  If
you  run  the  build by hand, rather than through Aegis, you
can add another developer's  development  directory  to  the
view  path, after your own development directory, but before
the baseline.

This has many of the advantages of the  branch  method,  but
none  of the safeguards.  In particular, if the other devel-
oper edits a file, and it no longer compiles, your  develop-
ment directory will not, either.
























-----------
  16 For the technically minded: the _c_h_o_w_n(2) sys-
tem  call  has  semantics  which  vary  too widely
between UNIX variants and file-systems to be  use-
ful.



Peter Miller     (lib/en/user-guide/c3.0.so)         Page 83





User Guide                                             Aegis


44..  TThhee HHiissttoorryy TTooooll

Aegis  is decoupled from the history mechanism.  This allows
you to use the history mechanism of  your  choice,  SCCS  or
RCS, for example.  You may even wish to write your own.

The  intention  of this is that you may use a history mecha-
nism which suits your special needs, or the one  that  comes
free with your flavour of UNIX operating system.

Aegis  uses  the  history  mechanism for file _h_i_s_t_o_r_y and so
does not require many of the features of SCCS or RCS.   This
simplistic  approach  can  sometimes  make  the interface to
these utilities look a little strange.

44..11..  IInntteerrffaacciinngg

The history mechanism interface is found in the project con-
figuration  file  called _c_o_n_f_i_g, relative to the root of the
baseline.  It is a source file and subject to the same  con-
trols  as  any other source file.  The history fields of the
file are described as follows

44..11..11..  hhiissttoorryy__ccrreeaattee__ccoommmmaanndd

This field is used to create a new history.  The command  is
always  executed as the project owner.  Substitutions avail-
able for the command string are:

${Input}
     absolute path of source file

${History}
     absolute path of history file

In addition, all substitutions  described  in  _a_e_s_u_b(5)  are
available.

44..11..22..  hhiissttoorryy__ggeett__ccoommmmaanndd

This  field is used to get a file from history.  The command
may be executed by developers.  Substitutions available  for
the command string are:

${History}
     absolute path of history file

${Edit}
     edit number, as given by the history_query_command.

${Output}
     absolute path of destination file





Page 84          (lib/en/user-guide/c3.0.so)    Peter Miller





Aegis                                             User Guide


In  addition,  all  substitutions  described in _a_e_s_u_b(5) are
available.

44..11..33..  hhiissttoorryy__ppuutt__ccoommmmaanndd

This field is used to add a new change to the history.   The
command  is always executed as the project owner.  Substitu-
tions available for the command string are:

${Input}
     absolute path of source file

${History}
     absolute path of history file

In addition, all substitutions  described  in  _a_e_s_u_b(5)  are
available.

44..11..44..  hhiissttoorryy__qquueerryy__ccoommmmaanndd

This  field  is  used to query the topmost edit of a history
file.  Result to be printed on the  standard  output.   This
command may be executed by developers.  Substitutions avail-
able for the command string are:

${History}
     absolute path of history file

In addition, all substitutions  described  in  _a_e_s_u_b(5)  are
available.

44..11..55..  hhiissttoorryy__ccoonntteenntt__lliimmiittaattiioonn

This  field  describes  the  content style which the history
tool is capable of working with.

ascii_text
     The history tool can only cope with files which contain
     printable  ASCII  characters,  plus space, tab and new-
     line.    The file must end with a newline.  This is the
     default.

international_text
     The  history tool can only cope with files which do not
     contain the NUL character.  The file must  end  with  a
     newline.

binary_capable
     The  history tool can cope with files without any limi-
     tation on the form of the contents.

     When a file is added to  the  history  (by  either  the
_h_i_s_t_o_r_y___c_r_e_a_t_e___c_o_m_m_a_n_d  or the _h_i_s_t_o_r_y___p_u_t___c_o_m_m_a_n_d field) it
is examined for conformance to this limitation.  If there is



Peter Miller     (lib/en/user-guide/c3.0.so)         Page 85





User Guide                                             Aegis


a  problem,  the  file  is encoded in either the MIME quoted
printable or the MIME  Base  64  encoding  (see  RFC  1521),
whichever  is  smaller,  before  being  given to the history
tool.  The file in the baseline is unchanged.

     On extract (the _h_i_s_t_o_r_y___g_e_t___c_o_m_m_a_n_d field) the encoding
is  reversed,  using information attached to the change file
information.  This is because each put could use a different
encoding  (although in practice, file contents rarely change
that dramatically, and the same encoding  is  likely  to  be
deduced every time).

44..11..66..  hhiissttoorryy__ttooooll__ttrraasshheess__ffiillee

Many history tools (e.g. RCS) can modify the contents of the
file when it is committed.  While there are usually  options
to  turn this off, they are seldom used.  The problem is: if
the commit changes the file, the source  in  the  repository
now  no  longer  matches the object file in the repository -
_i_._e_.  the  history  tool  has  compromised  the  referential
integrity of the repository.

By default, when this happens Aegis issues a fatal error (at
_i_n_t_e_r_g_a_t_e _p_a_s_s time).  You can turn this into a  warning  if
you  are convinced this is irrelevant.  This would only make
sense if the substition only ever occurs in  comments.   See
_a_e_p_c_o_n_f(5)  for  more  information  on  the  values for this
field.

44..11..77..  QQuuoottiinngg FFiilleennaammeess

The default setting is for Aegis to reject  filenames  which
contain  shell  special characters.  This ensures that file-
names may be substituted into the commands without  worrying
about whether this is safe.  If you set the _s_h_e_l_l___s_a_f_e___f_i_l_e_-
_n_a_m_e_s field of the project _c_o_n_f_i_g file to  false,  you  will
need  to  surround filenames with the ${quote _f_i_l_e_n_a_m_e} sub-
stitution.  This will only quote  filenames  which  actually
need  to  be quoted, so users usually will not notice.  This
applies to all of the various filenames in the  commands  in
the sections which follow.
















Page 86          (lib/en/user-guide/c3.1.so)    Peter Miller





Aegis                                             User Guide


44..22..  UUssiinngg SSCCCCSS

The  entries for the commands are listed below.  SCCS uses a
slightly different model than Aegis wants, so some maneuver-
ing is required.  The command strings in this section assume
that the SCCS command _s_c_c_s is in the  command  search  PATH,
but  you  may like to hard-wire the path, or set PATH at the
start of each command.  (It is also possible that  you  need
to  say ``delta'' instead of ``sccs delta''.  if this is the
case, this command needs to be in  the  path.)   You  should
also  note  that the strings are always handed to the Bourne
shell to be executed, and are set  to  exit  with  an  error
immediately a sub-command fails.

One  further  assumption is that the _a_e_-_s_c_c_s_-_p_u_t(1) command,
which is distributed with Aegis, is in  the  command  search
path.   This  insulates some of the weirdness that SCCS car-
ries on with, and makes the commands below comprehensible.

44..22..11..  hhiissttoorryy__ccrreeaattee__ccoommmmaanndd

This command is used to create a new project  history.   The
command is always executed as the project owner.

The following substitutions are available:

${Input}
     absolute path of the source file

${History}
     absolute path of the history file

The entry in the _c_o_n_f_i_g file looks like this:

     history_create_command =
       "ae-sccs-put \
         -y$version -G$input \
         ${d $h}/s.${b $h}";


It  is  important  that  the  _h_i_s_t_o_r_y___c_r_e_a_t_e___c_o_m_m_a_n_d and the
_h_i_s_t_o_r_y___p_u_t___c_o_m_m_a_n_d be the  same.   This  is  necessary  for
branching to work correctly.

44..22..22..  hhiissttoorryy__ggeett__ccoommmmaanndd

This  command  is used to get a specific edit back from his-
tory.  The command may be executed by developers.

The following substitutions are available:

${History}
     absolute path of the history file




Peter Miller     (lib/en/user-guide/c3.1.so)         Page 87





User Guide                                             Aegis


${Edit}
     edit number, as given by history_query_command

${Output}
     absolute path of the destination file

The entry in the _c_o_n_f_i_g file looks like this:

     history_get_command =
       "get -r'$e' -s -p -k \
         ${d $h}/s.${b $h} > $o";


44..22..33..  hhiissttoorryy__ppuutt__ccoommmmaanndd

This command is used to add a new "top-most"  entry  to  the
history  file.   This  command  is  always  executed  as the
project owner.

The following substitutions are available:

${Input}
     absolute path of source file

${History}
     absolute path of history file

The entry in the _c_o_n_f_i_g file looks like this:

     history_put_command =
       "ae-sccs-put \
         -y$version -G$input \
         ${d $h}/s.${b $h}";


Note that the SCCS file is left in the _n_o_t_-_e_d_i_t  state,  and
that the source file is left in the baseline.

It  is  important  that  the  _h_i_s_t_o_r_y___c_r_e_a_t_e___c_o_m_m_a_n_d and the
_h_i_s_t_o_r_y___p_u_t___c_o_m_m_a_n_d be the  same.   This  is  necessary  for
branching to work correctly.

44..22..44..  hhiissttoorryy__qquueerryy__ccoommmmaanndd

This  command  is  used  to query what the history mechanism
calls the top-most edit of a history file.  The  result  may
be any arbitrary string, it need not be anything like a num-
ber, just so long as it uniquely identifies the edit for use
by the _h_i_s_t_o_r_y___g_e_t___c_o_m_m_a_n_d at a later date.  The edit number
is to be printed on the standard output.  This  command  may
be executed by developers.

The following substitutions are available:




Page 88          (lib/en/user-guide/c3.1.so)    Peter Miller





Aegis                                             User Guide


${History}
     absolute path of the history file

The entry in the _c_o_n_f_i_g file looks like this:

     history_query_command =
       "get -t -g ${d $h}/s.${b $h}";


Note that "get" reports the edit number on stdout.

44..22..55..  TTeemmppllaatteess

The  _l_i_b_/_c_o_n_f_i_g_._e_x_a_m_p_l_e_/_s_c_c_s  file in the Aegis distribution
contains all of the above commands, so that you may  readily
insert them into your project _c_o_n_f_i_g file.

Also,  there  are  some  subtleties to writing the commands,
which are not present in the above examples.  In particular,
being  able  to  support file names which contain characters
which are special to the  shell  requires  the  use  of  the
${quote}  substitution  around all of the files names in the
commands.

In addition, it is possible  to  have  a  much  more  useful
description  for  the  --yy  option.  For example: ``-y${quote
($version) ${change description}}'' inserts the version num-
ber  and  the  brief  description into the file's log.  This
means that using the _s_c_c_s _p_r_s(1) command will provide  quite
useful summaries.

44..22..66..  BBiinnaarryy FFiilleess

SCCS  is  unable  to cope with binary files.  However, Aegis
will transparently encode all such files, if you  leave  the
_h_i_s_t_o_r_y___c_o_n_t_e_n_t___l_i_m_i_t_a_t_i_o_n field unset.





















Peter Miller     (lib/en/user-guide/c3.2.so)         Page 89





User Guide                                             Aegis


44..33..  UUssiinngg RRCCSS

The  entries  for the commands are listed below.  RCS uses a
slightly different model than aegis wants, so some maneuver-
ing is required.  The command strings in this section assume
that the RCS commands _c_i and _c_o and _r_c_s and _r_l_o_g are in  the
command  search  PATH,  but  you  may  like to hard-wire the
paths, or set PATH at the start of each.   You  should  also
note  that the strings are always handed to the Bourne shell
to be executed, and are set to exit with  an  error  immedi-
ately a sub-command fails.

In these commands, the RCS file is kept unlocked, since only
the owner will be checking changes in.  The RCS  functional-
ity for coordinating shared access is not required.

One  advantage  of  using  RCS  version 5.6 or later is that
binary files are supported, should you want to  have  binary
files in the baseline.

44..33..11..  hhiissttoorryy__ccrreeaattee__ccoommmmaanndd

This  command  is  used  to create a new file history.  This
command is always executed as the project owner.

The following substitutions are available:

${Input}
     absolute path of the source file

${History}
     absolute path of the history file

The entry in the _c_o_n_f_i_g file looks like this:

     history_create_command =
       "ci -u -d -M -m$c -t/dev/null \
       $i $h,v; rcs -U $h,v";


The "ci -u" option is used to specify that an unlocked  copy
will  remain in the baseline.  The "ci -d" option is used to
specify that the file time rather than the current  time  is
to be used for the new revision.  The "ci -M" option is used
to specify that the mode date on the original file is not to
be  altered.   The  "ci  -t"  option is used to specify that
there is to be no description text for  the  new  RCS  file.
The "ci -m" option is used to specify that the change number
is to be stored in the file  log  if  this  is  actually  an
update  (typically  from  _a_e_n_f  after  _a_e_r_m on the same file
name).  The "rcs -U" option is used to specify that the  new
RCS file is to have unstrict locking.





Page 90          (lib/en/user-guide/c3.2.so)    Peter Miller





Aegis                                             User Guide


It  is  essential  that  the  _h_i_s_t_o_r_y___c_r_e_a_t_e___c_o_m_m_a_n_d and the
_h_i_s_t_o_r_y___p_u_t___c_o_m_m_a_n_d are identical.  It is a historical acci-
dent that there are two separate commands: before Aegis sup-
ported branches, this was not a requirement.

44..33..22..  hhiissttoorryy__ggeett__ccoommmmaanndd

This command is used to get a specific edit back  from  his-
tory.  This command is always executed as the project owner.

The following substitutions are available:

${History}
     absolute path of the history file

${Edit}
     edit number, as given by history_query_command

${Output}
     absolute path of the destination file

The entry in the _c_o_n_f_i_g file looks like this:

     history_get_command =
       "co -r'$e' -p $h,v > $o";


The "co -r  option  is  used  to  specify  the  edit  to  be
retrieved.   The  "co  -p option is used to specify that the
results be printed on the standard output; this  is  because
the  destination  filename will _n_e_v_e_r look anything like the
history source filename.

44..33..33..  hhiissttoorryy__ppuutt__ccoommmmaanndd

This command is used to add a new "top-most"  entry  to  the
history  file.   This  command  is  always  executed  as the
project owner.

The following substitutions are available:

${Input}
     absolute path of source file

${History}
     absolute path of history file

The entry in the _c_o_n_f_i_g file looks like this:

     history_put_command =
       "ci -u -d -M -m$c -t/dev/null \
       $i $h,v; rcs -U $h,v";





Peter Miller     (lib/en/user-guide/c3.2.so)         Page 91





User Guide                                             Aegis


Uses ci to deposit a  new  revision,  using  -d  and  -M  as
described  for  history_create_command.   The -m flag stores
the change number in the file log, which allows  _r_l_o_g(1)  to
be used to find the Aegis change numbers to which each revi-
sion of the file corresponds.

The "ci -u" option is used to specify that an unlocked  copy
will  remain in the baseline.  The "ci -d" option is used to
specify that the file time rather than the current  time  is
to be used for the new revision.  The "ci -M" option is used
to specify that the mode date on the original file is not to
be  altered.  The "ci -m" option is used to specify that the
change number is to be stored in the file log, which  allows
_r_l_o_g  to  be  used  to find the change numbers to which each
revision of the file corresponds.  You  might  want  to  use
-m$p,$c  instead  which stores both the project name and the
change number.  Or -m$version, which will be composed of the
branch  and  the  delta.  These make it much easier to track
changes across branches.

It is essential  that  the  _h_i_s_t_o_r_y___c_r_e_a_t_e___c_o_m_m_a_n_d  and  the
_h_i_s_t_o_r_y___p_u_t___c_o_m_m_a_n_d are identical.  It is a historical acci-
dent that there are two separate commands: before Aegis sup-
ported branches, this was not a requirement.

44..33..44..  hhiissttoorryy__qquueerryy__ccoommmmaanndd

This  command  is  used  to query what the history mechanism
calls the top-most edit of a history file.  The  result  may
be any arbitrary string, it need not be anything like a num-
ber, just so long as it uniquely identifies the edit for use
by the _h_i_s_t_o_r_y___g_e_t___c_o_m_m_a_n_d at a later date.  The edit number
is to be printed on the standard output.   This  command  is
always executed as the project owner.

The following substitutions are available:

${History}
     absolute path of the history file

The entry in the _c_o_n_f_i_g file looks like this:

     history_query_command =
       "rlog -r $h,v | \
        awk '/^revision/ {print $$2}'";


44..33..55..  mmeerrggee__ccoommmmaanndd

RCS also provides a _m_e_r_g_e program, which can be used to pro-
vide a three-way merge.

All of the command substitutions described in  _a_e_s_u_b(5)  are
available.   In  addition,  the  following substitutions are



Page 92          (lib/en/user-guide/c3.2.so)    Peter Miller





Aegis                                             User Guide


also available:

${ORiginal}
     The absolute path name of a file containing the version
     originally copied.  Usually in a temporary file.

${Most_Recent}
     The  absolute  path  name of a file containing the most
     recent version.  Usually in the baseline.

${Input}
     The absolute path name of the  edited  version  of  the
     file.   Usually  in  the  development directory.  Aegis
     usually moves the original source file aside,  so  that
     the output may have the source file's name.

${Output}
     The  absolute  path  name of the file in which to write
     the difference listing.   Usually  in  the  development
     directory, usually the name of a change source file.

The entry in the _c_o_n_f_i_g file looks like this:

     merge_command =
       "set +e; \
       merge -p -L baseline -L C$c \
       $mr $orig $in > $out; \
       test $? -le 1";


     The  "merge  -L" options are used to specify labels for
the baseline and the  development  directory,  respectively,
when  conflict  lines  are  inserted  into  the result.  The
"merge -p" options is used to specify that the  results  are
to be printed on the standard output.

     It  is  important  that  this command does not move its
input and output files around,  otherwise  this  contradicts
the warnings Aegis may issue to the user.  (In previous ver-
sions of Aegis, this  was  necessary,  however  this  is  no
longer the case.)

WWaarrnniinngg::  The  version of _d_i_f_f_3(1) available to RCS _m_e_r_g_e(1)
has a huge impact on its performance and utility.  You  need
to  grab  and  install  GNU  diff  to  get the best results.
_U_n_f_o_r_t_u_n_a_t_e_l_y the diff tool used by RCS _m_e_r_g_e(1)  is  deter-
mined  at  compile  time.  This means that you need to build
and install GNU diff package _b_e_f_o_r_e you  build  and  install
GNU RCS package.

44..33..66..  RReeffeerreennttiiaall IInntteeggrriittyy

Many  history  tools (including RCS) can modify the contents
of the file when it is committed.  While there  are  usually



Peter Miller     (lib/en/user-guide/c3.2.so)         Page 93





User Guide                                             Aegis


options to turn this off, they are seldom used.  The problem
is: if the commit changes the file, the source in the repos-
itory  now  no longer matches the object file in the reposi-
tory - _i_._e_. the history tool has compromised the referential
integrity of the repository.

     history_put_trashes_file = warn;

If  you  use  RCS  keyword  substitution, you will need this
line.  (The default is to report a fatal error.)

Another reason for this option is that  it  tells  Aegis  it
needs to recalculate the file's fingerprint after a checkin.

44..33..77..  TTeemmppllaatteess

The _l_i_b_/_c_o_n_f_i_g_._e_x_a_m_p_l_e_/_r_c_s file in  the  Aegis  distribution
contains  all of the above commands, so that you may readily
insert them into your project _c_o_n_f_i_g file.

Also, there are some subtleties  to  writing  the  commands,
which are not present in the above examples.  In particular,
being able to support file names  which  contain  characters
which  are  special  to  the  shell  requires the use of the
${quote} substitution around all of the files names  in  the
commands.

In  addition,  it  is  possible  to  have a much more useful
description for the --mm  option.   For  example:  ``-m${quote
($version) ${change description}}'' inserts the version num-
ber and the brief description into  the  file's  log.   This
means that using the _r_l_o_g(1) command will provide quite use-
ful summaries.

44..33..88..  BBiinnaarryy FFiilleess

RCS (version 5.6 and later) is  able  to  cope  with  binary
files.   It  does  so  by saving a whole copy of the file at
each check-in.

     If you want Aegis  to  transparently  encode  all  such
files,  simply  leave  the  _h_i_s_t_o_r_y___c_o_n_t_e_n_t___l_i_m_i_t_a_t_i_o_n field
unset.

     If you want to  check-in  binary  files,  add  the  -kb
option  to  each of the rcs -U commands in the fields above,
and also set

     history_content_limitation = binary_capable;

so that Aegis knows that no encoding is desired.






Page 94          (lib/en/user-guide/c3.2.so)    Peter Miller





Aegis                                             User Guide


44..33..99..  hhiissttoorryy__ppuutt__ttrraasshheess__ffiilleess

If you use RCS keywords, such as $id$ or  $log$,  this  will
result  in  the file in the baseline being changed by RCS at
integrate pass.  This is _a_f_t_e_r the  build.   The  result  is
that  the  source  files  no  longer match the object files.
Oops.

While such mechanism are essential when using only a  simple
history tool, far more information may be obtained using the
file history report (aer file_history  _f_i_l_e_n_a_m_e),  rendering
such crude methods unnecessary.

In  addition to expected expansions in file header comments,
this can also be very destructive if, for  example,  such  a
string appeared in a uuencoded or MIME base 64 encoded file.

If you wish to prevent RCS from  performing  keyword  expan-
sion, used the rcs -kb option.

If, however, you wish to keep using keyword expansion, set

     history_tool_trashes_file = warning;

to cause Aegis to warn you, rather than fail.
































Peter Miller     (lib/en/user-guide/c3.3.so)         Page 95





User Guide                                             Aegis


44..44..  UUssiinngg ffhhiisstt

The  _f_h_i_s_t  program  was  written  by  David  I. Bell and is
admirably suited to providing a history mechanism  with  out
the "cruft" that SCCS and RCS impose.

Please note that the [# edit #] feature needs to be avoided,
or the _-_F_o_r_c_e_d___U_p_d_a_t_e (-fu) flag needs to be used  in  addi-
tion   to  the  _-_C_o_n_d_i_t_i_o_n_a_l___U_p_d_a_t_e  (-cu)  flag,  otherwise
updates will complain that ``Input file "_X_X_X" contains  edit
_A instead of _B for module "_Y_Y_Y"''

The  _h_i_s_t_o_r_y___c_r_e_a_t_e___c_o_m_m_a_n_d  and the _h_i_s_t_o_r_y___p_u_t___c_o_m_m_a_n_d are
intentionally identical.  This minimizes problems when using
branches.

44..44..11..  hhiissttoorryy__ccrreeaattee__ccoommmmaanndd

This  command  is used to create a new project history.  The
command is always executed as the project owner.

The following substitutions are available:

${Input}
     absolute path of the source file

${History}
     absolute path of the history file

The entry in the _c_o_n_f_i_g file looks like this:

     history_create_command =
       "fhist ${b $i} -create -cu -i $i \
        -p ${d $h} -r";

Note that the source file is left in the baseline.

44..44..22..  hhiissttoorryy__ggeett__ccoommmmaanndd

This command is used to get a specific edit back  from  his-
tory.  The command may be executed by developers.

The following substitutions are available:

${History}
     absolute path of the history file

${Edit}
     edit number, as given by history_query_command

${Output}
     absolute path of the destination file





Page 96          (lib/en/user-guide/c3.3.so)    Peter Miller





Aegis                                             User Guide


The entry in the _c_o_n_f_i_g file looks like this:

     history_get_command =
       "fhist ${b $h} -e '$e' -o $o \
        -p ${d $h}";


Note  that the destination filename will _n_e_v_e_r look anything
like the history source filename, so the -p is essential.

44..44..33..  hhiissttoorryy__ppuutt__ccoommmmaanndd

This command is used to add a new "top-most"  entry  to  the
history  file.   This  command  is  always  executed  as the
project owner.

The following substitutions are available:

${Input}
     absolute path of source file

${History}
     absolute path of history file

The entry in the _c_o_n_f_i_g file looks like this:

     history_put_command =
       "fhist ${b $i} -create -cu -i $i \
        -p ${d $h} -r";


Note that the source file is left in the baseline.


44..44..44..  hhiissttoorryy__qquueerryy__ccoommmmaanndd

This command is used to query  what  the  history  mechanism
calls the "top-most" edit of a history file.  The result may
be any arbitrary string, it need not be anything like a num-
ber, just so long as it uniquely identifies the edit for use
by the _h_i_s_t_o_r_y___g_e_t___c_o_m_m_a_n_d at a later date.  The edit number
is  to  be printed on the standard output.  This command may
be executed by developers.

The following substitutions are available:

${History}
     absolute path of the history file

The entry in the _c_o_n_f_i_g file looks like this:







Peter Miller     (lib/en/user-guide/c3.3.so)         Page 97





User Guide                                             Aegis


     history_query_command =
       "fhist ${b $h} -l 0 \
        -p ${d $h} -q";


44..44..55..  TTeemmppllaatteess

The _l_i_b_/_c_o_n_f_i_g_._e_x_a_m_p_l_e_/_f_h_i_s_t file in the Aegis  distribution
contains  all of the above commands, so that you may readily
insert them into your project _c_o_n_f_i_g file.

44..44..66..  CCaappaabbiilliittiieess

By default, FHist is unable to cope will NUL  characters  in
its  input  files,  however this is the only limitation.  By
default, Aegis expects that history tools are only  able  to
cope with printable ASCII text.  To tell it ontherwise, set

     history_content_limitation = international_text;

in the project _c_o_n_f_i_g file.

     Aegis  will  transparently  encode  binary files (files
which contain NUL characters) on entry  and  exit  from  the
history  tool.  This means that you may have binary files in
your project without configuring anything special.

44..44..77..  BBiinnaarryy FFiilleess

FHist (version 1.7 and later) has support for binary  files.
The  _f_h_i_s_t  _-_b_i_n_a_r_y  option  may be used to specify that the
file is binary, that it may contain NUL characters.   It  is
essential  that  you  have consistent presence or absence of
the -binary option for each  file  when  combined  with  the
-CReate,  -Update, -Conditional_Update and -Extract options.
Failure to do so will produce inconsistent results.

     This means that you have  to  _a_l_w_a_y_s  use  the  -binary
option in the _h_i_s_t_o_r_y___c_r_e_a_t_e___c_o_m_m_a_n_d and _h_i_s_t_o_r_y___p_u_t___c_o_m_m_a_n_d
fields.  You have to decide right at the very  beginning  if
your  project  _h_i_s_t_o_r_y  will ever have binary files, or will
never have binary files.  You can't change your mind  later.
If you choose to use the -binary option, set

     history_content_limitation = binary_capable;


     However,  Aegis  would  transparently  encode  all such
files, if you leave the _h_i_s_t_o_r_y___c_o_n_t_e_n_t___l_i_m_i_t_a_t_i_o_n field set
for international text.  In some cases, Aegis' encoding will
be more efficient than fhist's.  And you have the  advantage
of being able to change your mind later.





Page 98          (lib/en/user-guide/c3.4.so)    Peter Miller





Aegis                                             User Guide


44..55..  DDeetteeccttiinngg FFiillee CCoorrrruuppttiioonn

When  you  have  files which exist for long periods of time,
particularly files such as the ones typically used  by  his-
tory tools, which are generally appended to, without modifi-
cation of the bulk of the file, there is a very real  possi-
bility  that a block of the file could become corrupted over
the years.  Unless you access the  file  versions  contained
within that block, you have no way of knowing whether or not
the history file is OK.   (Arguably,  the  operating  system
should  check for this, but many do not, and in any case the
error may not be detectable at that level.)

Using Aegis, you can add a simple checksum to  your  history
files  which  will  detect  many cases of corruption such as
this, for all of the commonly used history tools.  Note:  it
cannot  detect  all  corruptions  (nothing  can) but it will
detect more than many operating systems will.

You don't need to use this technique with SCCS,  it  already
has a checksum in its files.

44..55..11..  GGeenneerraall MMeetthhoodd

In general, you need to do three things:

1. You  need to create some kind of checksum of your history
   file each time you modify it.  Something  like  _m_d_5_s_u_m(1)
   from the GNU Fileutils would be good.  Store the checksum
   in a file next to the history file.  This would  be  done
   in  the  _h_i_s_t_o_r_y___c_r_e_a_t_e___c_o_m_m_a_n_d  and  _h_i_s_t_o_r_y___p_u_t___c_o_m_m_a_n_d
   fields of the project _c_o_n_f_i_g file.

2. Each time the file is read, you need to verify the file's
   checksum.   Use  the same checksum utility as before, and
   then compare it using, say, _c_m_p(1); it it  fails  (either
   an  IO error, or the checksum doesn't compare equal) then
   don't proceed with the history file access.  You may need
   to  repair or replace the disk.  You will need to restore
   from backup (yesterday's backup, see below).  This  would
   be  done  at the beginning of the _h_i_s_t_o_r_y___c_r_e_a_t_e___c_o_m_m_a_n_d,
   _h_i_s_t_o_r_y___p_u_t___c_o_m_m_a_n_d,  _h_i_s_t_o_r_y___g_e_t___c_o_m_m_a_n_d  and  _h_i_s_t_o_r_y___-
   _q_u_e_r_y___c_o_m_m_a_n_d fields of the project _c_o_n_f_i_g file.

3. Because  you  may not actually interact with the file for
   years at a time, you need to check the file  fingerprints
   much  more often.  Daily or at least weekly is suggested.
   You do this with a _c_r_o_n(1) job run nightly which compares
   all  of the history files with their _m_d_5_s_u_m(1) checksums.
   Email  failures  to  the  system  administrator  and  the
   project  administrators.   By doing this nightly, you not
   only avoid backing-up corrupted files,  you  will  always
   know on which backup tape the good copy resides - yester-
   day's.



Peter Miller     (lib/en/user-guide/c3.4.so)         Page 99





User Guide                                             Aegis


44..55..22..  CCoonnffiigguurraattiioonn CCoommmmaannddss

In order to implement this, you need to modify  some  fields
of your project _c_o_n_f_i_g file as follows:

history_create_command
        You  need to test if the history file and its check-
        sum file exist, and check the checksum  if  this  is
        the  case.   Then,  use  whichever  history tool you
        choose (see the previous sections of this  chapter).
        If  it succeeds, run _m_d_5_s_u_m(1) over the history file
        (_n_o_t the source file) and store the  checksum  in  a
        file  next  to  the  history tool's file.  Using the
        same filename plus a  .md5sum  extension  makes  the
        _c_r_o_n(1) job easier to write.

history_put_command
        You  need  to  test  if the file exists (it may, for
        example,  be  an  old  project  to  which  you  have
        recently  added this technique) and check the check-
        sum if this is the case.   Then,  use  your  history
        tool  as normal.  If it succeeds, run _m_d_5_s_u_m(1) over
        the history file (_n_o_t the source  file)  as  in  the
        create case.

history_get_command
        You  need  to  test  if the file exists (it may, for
        example,  be  an  old  project  to  which  you  have
        recently  added this technique) and check the check-
        sum if this is the case.  Then use your history tool
        as normal.

history_head_command
        This  command  is only used at _a_e_i_p_a_s_s file, immedi-
        ately after one  of  the  _h_i_s_t_o_r_y___c_r_e_a_t_e___c_o_m_m_a_n_d  or
        _h_i_s_t_o_r_y___p_u_t___c_o_m_m_a_n_d  commands.   It  is  up  to  you
        whether you think you need to add a guard as for the
        _h_i_s_t_o_r_y___g_e_t___c_o_m_m_a_n_d _f_i_e_l_d_.

44..55..33..  AAeeggiiss'' DDaattaabbaassee

In  addition  to your history files, Aegis maintains a data-
base of file meta-data.  In order to add a checksum  to  the
various  file  making  up  the  database,  turn  on the _c_o_m_-
_p_r_e_s_s_e_d___d_a_t_a_b_a_s_e project attribute.   In  addition  to  com-
pressing  the  database  (a  minor  savings) it also adds an
Adler32 checksum.

You can check this in the _c_r_o_n(1) job by using _g_z_c_a_t(1) sent
to _/_d_e_v_/_n_u_l_l.







Page 100         (lib/en/user-guide/c4.0.so)    Peter Miller





Aegis                                             User Guide


55..  TThhee DDeeppeennddeennccyy MMaaiinntteennaannccee TTooooll

The  aegis  program  places  heavy demands on the dependency
maintenance tool, so it is  important  that  you  select  an
appropriate one.  This chapter talks about what a dependency
tool requires, and gives examples of how to use the  various
alternatives.

At  this writing, the author has seen few sufficiently capa-
ble dependency maintenance tools.

55..11..  RReeqquuiirreedd FFeeaattuurreess

When selecting a Dependency Maintenance Tool it is important
to  keep in mind that, ideally, it must be able to cope with
a hierarchy of parallel source directory trees.

The heart of any DMT is an _i_n_f_e_r_e_n_c_e _e_n_g_i_n_e.  This inference
engine accepts a _g_o_a_l of what you want it to construct and a
set of _r_u_l_e_s for how to construct things,  and  attempts  to
construct  what you asked for given the rules you specified.
This is exactly a description of an expert system,  and  the
DMT needs to be an expert system for constructing files.

This  perspective on what the aegis program needs from a DMT
reveals that the old-faithful _m_a_k_e(1)  distributed  with  so
many  flavours  of  UNIX  really isn't good enough, and that
something like PROLOG is probably ideal.

55..11..11..  SSeeaarrcchh LLiissttss

For the union of all files in a project and all files  in  a
change (remembering that a change only copies those files it
is modifying, plus it may add or remove files) for all files
you must be able to say to the dependency maintenance tool,

     "If  and  only  if  the  file is up-to-date in the
     baseline, use the baseline copy of the file,  oth-
     erwise  construct  the  file  in  the  development
     directory".

The presence of a source file in the change makes  the  copy
in the baseline out-of-date.

Most  DMTs  with  this capability implement it by using some
sort of search path, allowing a hierarchy of directories  to
be scanned with little or no modification to the rules.

If  your  DMT of choice does not provide this functionality,
the _c_r_e_a_t_e___s_y_m_l_i_n_k_s___b_e_f_o_r_e___b_u_i_l_d field of the project _c_o_n_f_i_g
file  may be set to _t_r_u_e, which tells aegis to maintain sym-
bolic links in the development directory for  all  files  in
the baseline which are not present in the development direc-
tory.  (See _a_e_p_c_o_n_f(5) and  _a_e_b(1)  for  more  information.)



Peter Miller     (lib/en/user-guide/c4.1.so)        Page 101





User Guide                                             Aegis


This  incurs  a  certain amount of overhead when aegis main-
tains these links, but a similar  amount  of  work  is  done
within DMTs which have search path functionality.

55..11..22..  DDyynnaammiicc IInncclluuddee FFiillee DDeeppeennddeenncciieess

Include  file  dependencies  are  very  important, because a
change may alter an include file, and all of the sources  in
the baseline which use that include file must be recompiled.

Consider  the  example  given  earlier:  the  include   file
describing  the interface definition of a function is copied
into a change and edited, and so is the source file defining
the  function.  It is essential that all source files in the
baseline which include that file are recompiled, which  will
usually  result  in suitable diagnostic errors if any of the
clients of the altered function have yet to be  included  in
the change.

There are two ways of handling include file dependencies:

+o They can be kept in a file, and the file can be maintained
by suitable programs (maintaining it manually  never  works,
that's just human nature).

+o  They can be determined by the DMT when it is scanning the
rules to determine what needs updating.

55..11..22..11..  SSttaattiicc FFiillee

Keeping include dependencies in  a  file  has  a  number  of
advantages:

+o Most existing DMTs have the ability to include other rules
files, so that when performing a development  build  from  a
baseline rules file, it could include a dependencies file in
the development directory.

+o Reading a file is much faster than  scanning  all  of  the
source files.

Keeping  include dependencies in a file has a number of dis-
advantages:

+o The file is independent of the DMT, it is either generated
before the DMT is invoked, in which case it may do more work
than is necessary, or it may be invoked after  the  DMT  (or
after  the  DMT has scanned its rules), in which case it may
well be out-of-date when the DMT needs it.

For example, the use of _g_c_c _-_M produces "dot d" files, which
may  be  merged  to  construct such an includable dependency
file.  This happens after the DMT has read and  applied  the




Page 102         (lib/en/user-guide/c4.1.so)    Peter Miller





Aegis                                             User Guide


rules, but possibly before the DMT has finished executing.17

+o  Many  tools  which can generate this information, such as
the _g_c_c _-_M option, are triggered by source  files,  and  are
unable to manage a case where it is an include file which is
changing, to include a different set of other include files.
In  this  case, the inaccurate dependencies file may contain
references to the old set of nested include files,  some  of
which  may  no  longer  exist, This causes the DMT to incor-
rectly generate an error stating that the old  include  file
is missing, when it is actually no longer required.

If  a  DMT can only support this kind of include file depen-
dencies, it is not suitable for use with aegis.

55..11..22..22..  DDyynnaammiicc

In order for a DMT to be suitable for use with aegis, it  is
essential  that rules for the DMT may be specified in such a
way that include file dependencies are  determined  "on  the
fly" when the DMT is determining if a given rule is applica-
ble, and before the rule is applied.

This method suffers from the problem being rather slow;  but
this  is  amenable to some caching and the losses of perfor-
mance are not as bad as could be imagined.

This method has the advantage of correctness in  all  cases,
where a static file may at times be out-of-date.



















-----------
  17 See  the  _U_s_i_n_g _M_a_k_e section for how GNU Make
may be used.  It effectively combines  both  meth-
ods:  keeping  _._d  files  and dynamically updating
them.  Because it combines both  methods,  it  has
some  of the advantages and disadvantages of both.



Peter Miller     (lib/en/user-guide/c4.2.so)        Page 103





User Guide                                             Aegis


55..22..  UUssiinngg CCooookk

The  _c_o_o_k  program  is the only dependency maintenance tool,
known to the author, which is sufficiently capable to supply
aegis'  needs.18  Tools  such  as  _c_a_k_e  and  _G_N_U  _M_a_k_e  are
described later.  They need a special  tweak  to  make  them
work.

This   section   describes   appropriate  contents  for  the
_H_o_w_t_o_._c_o_o_k file, input to the _c_o_o_k(1) program.  It also dis-
cusses  the  _b_u_i_l_d___c_o_m_m_a_n_d  and  _i_n_t_e_g_r_a_t_e___b_u_i_l_d___c_o_m_m_a_n_d and
_l_i_n_k___b_a_s_e_l_i_n_e  and  _c_h_a_n_g_e___f_i_l_e___c_o_m_m_a_n_d  and  _p_r_o_j_e_c_t___f_i_l_e___-
_c_o_m_m_a_n_d  and _l_i_n_k___i_n_t_e_g_r_a_t_i_o_n___d_i_r_e_c_t_o_r_y fields of the _c_o_n_f_i_g
file.  See _a_e_p_c_o_n_f(5) for more information about this  file.

55..22..11..  IInnvvookkiinngg CCooookk

The _b_u_i_l_d___c_o_m_m_a_n_d field of the _c_o_n_f_i_g file is used to invoke
the relevant build command.  In this case, it is set as fol-
lows

     build_command =
       "cook -b ${s Howto.cook} -nl\
        project=$p change=$c version=$v";


This  command tells cook where to find the recipes.  The ${s
Howto.cook} expands to  a  path  into  the  baseline  during
development  if  the  file  is  not  in the change.  Look in
_a_e_s_u_b(5) for more information about command substitutions.

The recipes which  follow  will  all  remove  their  targets
before  constructing them, which qualifies them for the next
entry in the _c_o_n_f_i_g file:

     link_integration_directory = true;


The links must be  removed  first,  otherwise  the  baseline
would cease to be self-consistent.

55..22..22..  TThhee RReecciippee FFiillee

The  file containing the recipes is called _H_o_w_t_o_._c_o_o_k and is
given to cook on the command line.

The following items are preamble to the rest  of  the  file;
they  ask  aegis  for  the  source  files of the project and
change so that cook can determine what needs to be  compiled
and linked.
-----------
  18 The  version in use when writing this section
was 1.5.  All versions from 1.3 onwards are  known
to work with the recipes described here.



Page 104         (lib/en/user-guide/c4.2.so)    Peter Miller





Aegis                                             User Guide


     project_files =
       [collect aegis -l pf -terse
         -p [project] -c [change]];
     change_files =
       [collect aegis -l cf -terse
         -p [project] -c [change]];
     source_files =
       [stringset [project_files]
         [change_files]];


This  example continues the one from chapter 3, and thus has
a single executable to be linked from all the object files

     object_files =
       [fromto %.y %.o [match_mask %.y
         [source_files]]]
       [fromto %.l %.o [match_mask %.l
         [source_files]]]
       [fromto %.c %.o [match_mask %.c
         [source_files]]]
       ;


It is necessary to determine if this is a development build,
and   thus  has  the  baseline  for  additional  ingredients
searches, or an integration build, which does not.  The ver-
sion  supplied  by  aegis  will  tell  us  this information,
because  it  will  be  _m_a_j_o_r_._m_i_n_o_r_.C_c_h_a_n_g_e  for  development
builds and _m_a_j_o_r_._m_i_n_o_r_.D_d_e_l_t_a for integration builds.

     if [match_mask %1C%2 [version]] then
     {
       baseline = [collect aegis -cd -bl
         -p [project]];
       search_list = . [baseline];
     }


The  _s_e_a_r_c_h___l_i_s_t variable in cook is the list of directories
to search for dependencies; it defaults to only the  current
directory.  The _r_e_s_o_l_v_e builtin function of cook may be used
to ask cook for the  name  of  the  file  actually  used  to
resolve  dependencies,  so  that recipe bodies may reference
the appropriate file:

     example: [object_files]
     {
       [cc] -o example
         [resolve [object_files]]
         -ly -ll;
     }





Peter Miller     (lib/en/user-guide/c4.2.so)        Page 105





User Guide                                             Aegis


This recipe says that to cook the example program, you  need
the  object  files  determined  earlier,  and them link them
together.  Object files which were up to date in  the  base-
line are used wherever possible, but files which were out of
date are constructed in the current directory and those will
be linked.

55..22..33..  TThhee RReecciippee ffoorr CC

Next  we  need to tell cook how to manage C sources.  On the
surface, this is a simple recipe:

     %.o: %.c
     {
       rm %.o;
       [cc] [cc_flags] -c %.c;
     }


Unfortunately it has forgotten  about  finding  the  include
file  dependencies.   The  cook  package  includes a program
called _c___i_n_c_l which is used to find them.   The  recipe  now
becomes

     %.o: %.c: [collect c_incl -eia %.c]
     {
       rm %.o;
       [cc] [cc_flags] -c %.c;
     }


The  file may not always be present to be removed (causing a
fatal error), and it is irritating to  execute  a  redundant
command, so the remove is mangled to look like this:

     %.o: %.c: [collect c_incl -eia %.c]
     {
       if [exists %.o] then
         rm %.o
           set clearstat;
       [cc] [cc_flags] -c %.c;
     }


The  "set clearstat" clause tells cook that the command will
invalidate parts of its _s_t_a_t cache, and to look at the  com-
mand for what to invalidate.

Another  thing  this recipe needs is to use the baseline for
include files not in a change, and so the recipe is  altered
again:






Page 106         (lib/en/user-guide/c4.2.so)    Peter Miller





Aegis                                             User Guide


     %.o: %.c: [collect c_incl -eia
       [prepost "-I" "" [search_list]]
         %.c]
     {
      if [exists %.o] then
         rm %.o
           set clearstat;
       [cc] [cc_flags] [prepost "-I" ""
         [search_list]] -c %.c;
     }


See  the _C_o_o_k _R_e_f_e_r_e_n_c_e _M_a_n_u_a_l for a description of the _p_r_e_-
_p_o_s_t builtin function, and other cook details.

There is one last change that must be made to  this  recipe,
it  must use the resolve function to reference the appropri-
ate file once cook has found it on the search list:

     %.o: %.c: [collect c_incl -eia
       [prepost "-I" "" [search_list]]
         [resolve %.c]]
     {
       if [exists %.o] then
         rm %.o
           set clearstat;
       [cc] [cc_flags] [prepost "-I" ""
         [search_list]] -c [resolve %.c];
     }


Only use this last recipe for C sources, the others are only
shown  so  that the derivation of the recipe is clear; while
it is very similar to the original,  it  looks  daunting  at
first.

55..22..33..11..  CC IInncclluuddee SSeemmaannttiiccss

The semantics of C include directives make the

     #include "_f_i_l_e_n_a_m_e"

directive  dangerous  in  a project developed with the aegis
program and cook.

Depending on the age of your compiler, whether  it  is  AT&T
traditional  C  or newer ANSI C, this form of directive will
search first in the current directory  and  then  along  the
search  path,  or in the directory of the including file and
then along the search path.

The first case is fairly benign, except that  compilers  are
rapidly  becoming  ANSI C compliant, and an operating system
upgrade could result in a nasty surprise.



Peter Miller     (lib/en/user-guide/c4.2.so)        Page 107





User Guide                                             Aegis


The second case is bad news.  If the source file is  in  the
baseline  and  the  include file is in the change, you don't
want the source file to use the include file  in  the  base-
line.

Always use the

     #include <_f_i_l_e_n_a_m_e>

form  of  the  include directive, and set the include search
path explicitly on the command line used by cook.

Cook is able to dynamically adapt to include file  dependen-
cies,  because  they  are  not  static.   The presence of an
include file in a change means that any file which  includes
this  include file, whether that source file is in the base-
line or in  the  change,  must  have  a  dependency  on  the
change's  include  file.  Potentially, files in the baseline
will need to be recompiled, and the object  file  stored  in
the  change,  not the baseline.  Subsequent linking needs to
pick up the object file in the change, not  from  the  base-
line.

55..22..44..  TThhee RReecciippee ffoorr YYaacccc

Having  explained  the  complexities  of  the recipes in the
above section about C, the recipe for  yacc  will  be  given
without delay:

     %.c %.h: %.y
     {
       if [exists %.c] then
         rm %.c
           set clearstat;
       if [exists %.h] then
         rm %.h
           set clearstat;
       [yacc] [yacc_flags] -d
         [resolve %.y];
       mv y.tab.c %.c;
       mv y.tab.h %.h;
     }


This   recipe  could  be  jazzed up to cope with the listing
file, too, if that was desired, but this  is  sufficient  to
work with the example.

Cook's  ability  to  cope  with transitive dependencies will
pick up the generated .c file and construct the necessary .o
file.






Page 108         (lib/en/user-guide/c4.2.so)    Peter Miller





Aegis                                             User Guide


55..22..55..  TThhee RReecciippee ffoorr LLeexx

The recipe for lex is vary similar to the recipe for yacc.

     %.c: %.l
     {
       if [exists %.c] then
         rm %.c
           set clearstat;
       [lex] [lex_flags] -d [resolve %.l];
       mv lex.yy.c %.c;
     }


Cook's  ability  to  cope  with transitive dependencies will
pick up the generated .c file and construct the necessary .o
file.

55..22..66..  RReecciippeess ffoorr DDooccuummeennttss

You  can  format  documents,  such as user guides and manual
entries with aegis and cook, and the recipes are similar  to
the ones above.

     %.ps: %.ms: [collect c_incl -r -eia
       [prepost "-I" "" [search_list]]
       [resolve %.ms]]
     {
       if [exists %.ps] then
         rm %.ps
           set clearstat;
       roffpp [prepost "-I" ""
         [search_list]] [resolve %.ms]
         | groff -p -t -ms
         > [target];
     }


This recipe says to run the document through groff, with the
_p_i_c(1) and _t_b_l(1) filters, use the _m_s(7) macro  package,  to
produce  PostScript  output.   The _r_o_f_f_p_p program comes with
cook, and is like _s_o_e_l_i_m(1) but it  accepts  include  search
path options on the command line.

Manual entries may be handled in a similar way












Peter Miller     (lib/en/user-guide/c4.2.so)        Page 109





User Guide                                             Aegis


     %.cat: %.man: [collect c_incl -r -eia
       [prepost "-I" "" [search_list]]
       [resolve %.man]]
     {
       if [exists %.cat] then
         rm %.cat
           set clearstat;
       roffpp [prepost "-I" ""
         [search_list]] [resolve %.man]
         | groff -Tascii -t -man
         > [target];
     }


55..22..77..  TTeemmppllaatteess

The  _l_i_b_/_c_o_n_f_i_g_._e_x_a_m_p_l_e_/_c_o_o_k  file in the Aegis distribution
contains all of the above commands, so that you may  readily
insert them into your project _c_o_n_f_i_g file.






































Page 110         (lib/en/user-guide/c4.3.so)    Peter Miller





Aegis                                             User Guide


55..33..  UUssiinngg CCaakkee

This  section  describes  how  to use _c_a_k_e as the dependency
maintenance tool.  The _c_a_k_e package  was  published  in  the
_c_o_m_p_._s_o_u_r_c_e_s_._u_n_i_x  USENET newsgroup volume 12, around Febru-
ary 1988, and is thus easily accessible from  the  many  ar-
chives around the internet.

     It  does  not  have a search path of any form, not even
something like _V_P_A_T_H.  It does, however, have facilities for
dynamic include file dependencies.

55..33..11..  IInnvvookkiinngg CCaakkee

The _b_u_i_l_d___c_o_m_m_a_n_d field of the _c_o_n_f_i_g file is used to invoke
the relevant build command.  In this case, it is set as fol-
lows

     build_command =
       "cake -f ${s Cakefile} \
        -DPROJECT=$p -DCHANGE=$c \
        -DVERSION=$v";


This  command  tells  _c_a_k_e where to find the rules.  The ${s
Cakefile} expands to a path into the baseline during  devel-
opment  if  the file is not in the change.  Look in _a_e_s_u_b(5)
for more information about command substitutions.

The rules which follow will all remove their targets  before
constructing  them,  which qualifies them for the next entry
in the _c_o_n_f_i_g file:

     link_integration_directory = true;


The links must be  removed  first,  otherwise  the  baseline
would cease to be self-consistent.

Another field to be set in this file is

     create_symlinks_before_build =
       true;

which  tells  aegis  to  maintain symbolic links between the
development directory and the baseline.  This also  requires
that rules remove their targets before constructing them, to
ensure that rules do not attempt to write their results onto
the read-only versions in the baseline.

55..33..22..  TThhee RRuulleess FFiillee

The  file  containing  the  rules  is called _C_a_k_e_f_i_l_e and is
given to cake on the command line.



Peter Miller     (lib/en/user-guide/c4.3.so)        Page 111





User Guide                                             Aegis


The following items are preamble to the rest  of  the  file;
they  ask  aegis  for  the  source  files of the project and
change so that cake can determine what needs to be  compiled
and linked.

     #define project_files \
       [[aegis -l pf -terse -p PROJECT \
         -c CHANGE]];
     #define change_files \
       [[aegis -l cf -terse -p PROJECT \
        -c CHANGE]];
     #define source_files \
       project_files change_files

     #define CC     gcc
     #define CFLAGS -O


This  example parallels the one from chapter 3, and thus has
a single executable to be linked from all the object files

     #define object_files \
       [[sub -i X.c %.o source_files]] \
       [[sub -i X.y %.o source_files]] \
       [[sub -i X.l %.o source_files]]


Constructing the program is straightforward

     example: object_files
       rm -f example
       CC -o example object_files


This rule says that to construct the  example  program,  you
need the object files determined earlier, and them link them
together.  Object files which were up to date in  the  base-
line are used wherever possible, but files which were out of
date are constructed in the current directory and those will
be linked.

55..33..33..  TThhee RRuullee ffoorr CC

Next  we  need to tell cake how to manage C sources.  On the
surface, this is a simple rule:

     %.o: %.c
       CC CFLAGS -c %.c

paralleling that found in most makes, however  it  needs  to
delete  the  target first, and to avoid deleting the _._o file
whenever cake thinks it is transitive.





Page 112         (lib/en/user-guide/c4.3.so)    Peter Miller





Aegis                                             User Guide


     %.o!: %.c
       rm -f %.o
       CC CFLAGS -c %.c

The _-_f option to the _r_m command is because the file does not
always exist.

Unfortunately  this  rule  omits  finding  the  include file
dependencies.  The cake package includes  a  program  called
_c_c_i_n_c_l which is used to find them.  The rule now becomes

     %.o!: %.c* [[ccincl %.c]]
       rm -f %.o
       CC CFLAGS -c %.c

This  rule  is  a little quirky about include files which do
not yet exist, but must be constructed by some  other  rule.
You  may  want  to  use  _g_c_c _-_M_M instead, which is almost as
quirky when used with cake.  Another  alternative,  used  by
the  author with far more success, is to use the _c___i_n_c_l pro-
gram from the _c_o_o_k package, mentioned in an earlier section.
The  _g_c_c  _-_M_M understands C include semantics perfectly, the
_c___i_n_c_l command caches its results and thus goes  faster,  so
you will need to figure which you most want.

55..33..33..11..  IInncclluuddee DDiirreeccttiivveess

Unlike  _c_o_o_k  described in an earlier section, using _c_a_k_e as
described here allows you to continue using the

     #include "_f_i_l_e_n_a_m_e"

form of the include directive.  This is because the develop-
ment  directory  appears,  to the compiler, to be a complete
copy of the baseline.

55..33..44..  TThhee RRuullee ffoorr YYaacccc

Having explained the complexities of the rules in the  above
section  about  C,  the  rule for yacc will be given without
delay:

     #define YACC yacc
     #define YFLAGS

     %.c! %.h!: %.y  if exist %.y
       rm -f %.c %.h y.tab.c y.tab.h
       YACC YFLAGS -d %.y
       mv y.tab.c %.c
       mv y.tab.h %.h


This rule could be jazzed up to cope with the listing  file,
too,  if  that  was  desired, but this is sufficient to work



Peter Miller     (lib/en/user-guide/c4.3.so)        Page 113





User Guide                                             Aegis


with the example.

Cake's ability to cope  with  transitive  dependencies  will
pick up the generated _._c file and construct the necessary _._o
file.

55..33..55..  TThhee RRuullee ffoorr LLeexx

The rule for lex is vary similar to the rule for yacc.

     #define LEX lex
     #define LFLAGS

     %.c!: %.l  if exist %.l
       rm -f %.c
       LEX LFLAGS %.l
       mv lex.yy.c %.c


Cake's ability to cope  with  transitive  dependencies  will
pick up the generated _._c file and construct the necessary _._o
file.

55..33..66..  RRuulleess ffoorr DDooccuummeennttss

You can format documents, such as  user  guides  and  manual
entries  with  aegis  and cake, and the rules are similar to
the ones above.

     %.ps!: %.ms* [[soincl %.ms]]
       rm -f %.ps
       groff -s -p -t -ms %.ms > %.ps


This rule says to run the document through groff,  with  the
_s_o_e_l_i_m(1) and _p_i_c(1) and _t_b_l(1) filters, use the _m_s(7) macro
package, to produce PostScript output.

This suffers from many of the problems  with  include  files
which  need to be generated, as does the C rule, above.  You
may want to use _c___i_n_c_l _-_r from the _c_o_o_k package, rather than
the _s_o_i_n_c_l supplied by the _c_a_k_e package.

Manual entries may be handled in a similar way

     %.cat!: %.man* [[soincl %.man]]
       rm -f %.cat
       groff -Tascii -s -t -man %.man \
         > %.cat








Page 114         (lib/en/user-guide/c4.4.so)    Peter Miller





Aegis                                             User Guide


55..44..  UUssiinngg MMaakkee

The  _m_a_k_e(1)  program  exists  in many forms, usually one is
available with each UNIX version.  The one used in the writ-
ing of this section is _G_N_U _M_a_k_e _3_._7_0, available by anonymous
FTP from your nearest GNU archive site.  GNU Make was chosen
because  it  was  the  most powerful, it is widely available
(usually for little or no cost) and discussion of the alter-
natives  (SunOS  make, BSD 4.3 make, etc), would not be uni-
versally applicable.  "Plain vanilla" make (with no  transi-
tive  closure, no pattern rules, no functions) is not suffi-
ciently capable to satisfy  the  demands  placed  on  it  by
aegis.

As  mentioned  earlier  in  this chapter, _m_a_k_e is not really
sufficient, because it lacks dynamic  include  dependencies.
However,  GNU  Make  has a form of dynamic include dependen-
cies, and it has a few quirks, but mostly works well.

The other feature lacking in _m_a_k_e is a search  path.   While
GNU  Make has functionality called _V_P_A_T_H, the implementation
leaves something to be desired, and can't be  used  for  the
search  path  functionality  required  by aegis.  Because of
this, the _c_r_e_a_t_e___s_y_m_l_i_n_k_s___b_e_f_o_r_e___b_u_i_l_d field of the  project
_c_o_n_f_i_g  file  is  set to _t_r_u_e so that aegis will arrange for
the development directory to be full of symbolic links, mak-
ing  it  appear  that the entire project is in each change's
development directory.

55..44..11..  IInnvvookkiinngg MMaakkee

The _b_u_i_l_d___c_o_m_m_a_n_d field of the project _c_o_n_f_i_g file  is  used
to  invoke  the relevant build command.  In this case, it is
set as follows

     build_command =
       "gmake -f ${s Makefile} project=$p \
        change=$c version=$v";


This command tells make where to find the  rules.   The  ${s
Makefile}  expands to a path into the baseline during devel-
opment if the file is not in the change.  Look  in  _a_e_s_u_b(5)
for more information about command substitutions.

The  rules which follow will all remove their targets before
constructing them, which qualifies them for the  next  entry
in the _c_o_n_f_i_g file:

     link_integration_directory = true;


The  files  must  be  removed  first, otherwise the baseline
would cease to be self-consistent.



Peter Miller     (lib/en/user-guide/c4.4.so)        Page 115





User Guide                                             Aegis


Another field to be set in this file is

     create_symlinks_before_build =
       true;

which tells aegis to maintain  symbolic  links  between  the
development  directory and the baseline.  This also requires
that rules remove their targets before constructing them, to
ensure that rules do not attempt to write their results onto
the read-only versions in the baseline.

55..44..22..  TThhee RRuullee FFiillee

The file containing the rules  is  called  _M_a_k_e_f_i_l_e  and  is
given to make on the command line.

The  following  items  are preamble to the rest of the file;
they ask aegis for the  source  files  of  the  project  and
change  so that make can determine what needs to be compiled
and linked.

     project_files := \
       $(shell aegis -l pf -terse -p \
         $(project) -c $(change))
     change_files := \
       $(shell aegis -l cf -terse -p \
         $(project) -c $(change))
     source_files := \
       $(sort $(project_files) \
         $(change_files))
     CC := gcc
     CFLAGS := -O


This example parallels the one from chapter 3, and thus  has
a single executable to be linked from all the object files

     object_files := \
       $(patsubst %.y,%.o,$(filter \
         %.y,$(source_files)))     \
       $(patsubst %.l,%.o,$(filter \
         %.l,$(source_files)))     \
       $(patsubst %.c,%.o,$(filter \
         %.c,$(source_files)))


Constructing  the program is straightforward, remembering to
remove the target first.

     example: $(object_files)
       rm -f example
       $(CC) -o example $(object_files) \
         -ly -ll




Page 116         (lib/en/user-guide/c4.4.so)    Peter Miller





Aegis                                             User Guide


This rule says that to make the example  program,  you  need
the  object  files  determined  earlier,  and them link them
together.  Object files which were up to date in  the  base-
line are used wherever possible, but files which were out of
date are constructed in the current directory and those will
be linked.

55..44..33..  TThhee RRuullee ffoorr CC

Next  we  need to tell make how to manage C sources.  On the
surface, this is a simple rule:

     %.o: %.c
       $(CC) $(CFLAGS) -c $*.c

This example matches the built-in rule for most _m_a_k_es.   But
it forgets to remove the target before constructing it.

     %.o: %.c
       rm -f $*.o
       $(CC) $(CFLAGS) -c $*.c

The target may not yet exist, hence the _-_f option.

Something missing from this rule is finding the include file
dependencies.  The GNU Make User Guide  describes  a  method
for  obtaining  include  file dependencies.  A set of depen-
dency files are constructed, one per _._c file.

     %.d: %.c
       rm -f %.d
       $(CC) $(CFLAGS) -MM $*.c \
       | sed 's/^\(.*\).o :/\1.o \1.d :/' \
       > $*.d

These dependency files are then included into  the  _M_a_k_e_f_i_l_e
to inform GNU Make of the dependencies.

     include $(patsubst \
       %.o,%.d,$(object_files))

GNU  Make  has  the  property of making sure all its include
files are up-to-date.  If any are not, they  are  made,  and
then GNU Make starts over, and re-reads the Makefile and the
include files from scratch, before proceeding with the oper-
ation requested.  In this case, it means that our dependency
construction rule will be applied before any of the  sources
are constructed.

This  method  is  occasionally  quirky  about absent include
files which you have yet to write, or  which  are  generated
and  don't  yet exist, but this is usually easily corrected,
though you do need to watch out for things which will  stall
an integration.



Peter Miller     (lib/en/user-guide/c4.4.so)        Page 117





User Guide                                             Aegis


The  _-_M_M  option  to  the $(CC) command means that this rule
requires the _g_c_c program in order to work correctly.  It may
be  possible  to  use _c___i_n_c_l(1) from cook, or _c_c_i_n_c_l(1) from
cake to build the dependency lists instead; but  they  don't
understand  the  conditional  preprocessing  as  well as _g_c_c
does.

This method also suffers when heterogeneous  development  is
performed.  If you include different files, depending on the
environment being compiled  within,  the  _._d  files  may  be
incorrect, and GNU Make has no way of knowing this.

55..44..33..11..  IInncclluuddee DDiirreeccttiivveess

Unlike  _c_o_o_k described in an earlier section, using GNU Make
as described here allows you to continue using the

     #include "_f_i_l_e_n_a_m_e"

form of the include directive.  This is because the develop-
ment  directory  appears,  to the compiler, to be a complete
copy of the baseline.

55..44..44..  TThhee RRuullee ffoorr YYaacccc

Having explained the complexities of the rules in the  above
section  about  C,  the  rule for yacc will be given without
delay:

     %.c %.h: %.y
       rm -f $*.c $*.h y.tab.c y.tab.h
       $(YACC) $(YFLAGS) -d $*.y
       mv y.tab.c $*.c
       mv y.tab.h $*.h


This  rule could be jazzed up to cope with the listing file,
too,  if  that  was  desired, but this is sufficient to work
with the example.

GNU Make's ability to cope with transitive closure will pick
up  the  generated  _._c  file  and construct the necessary _._o
file.

To prevent GNU Make throwing away the transitive files,  and
thus slowing things down in some cases, make them precious:

     .PRECIOUS: \
       $(patsubst %.y,%.c,$(filter \
         %.y,$(source_files)))     \
       $(patsubst %.y,%.h,$(filter \
         %.y,$(source_files)))





Page 118         (lib/en/user-guide/c4.4.so)    Peter Miller





Aegis                                             User Guide


55..44..55..  TThhee RRuullee ffoorr LLeexx

The rule for lex is vary similar to the rule for yacc.

     %.c: %.l
       rm -f $*.c lex.yy.c
       $(LEX) $(LFLAGS) $*.l
       mv lex.yy.c $*.c


GNU Make's ability to cope with transitive closure will pick
up the generated _._c file  and  construct  the  necessary  _._o
file.

To  prevent GNU Make throwing away the transitive files, and
thus slowing things down in some cases, make them precious:

     .PRECIOUS: \
       $(patsubst %.l,%.c,$(filter \
         %.l,$(source_files)))


55..44..66..  RRuulleess ffoorr DDooccuummeennttss

You can format documents, such as  user  guides  and  manual
entries  with  aegis and GNU Make, and the rules are similar
to the ones above.

     %.ps: %.ms
       rm -f $*.ps
       groff -p -t -ms $*.ms > $*.ps


This rule says to run the document through groff,  with  the
_p_i_c(1)  and  _t_b_l(1) filters, use the _m_s(7) macro package, to
produce PostScript output.

This omits include file dependencies.  If this is  important
to  you,  the  _c___i_n_c_l  program from _c_o_o_k can be used to find
them.  Filtering its output can then produce  the  necessary
dependency  files  to  be included, rather like the C rules,
above.

Manual entries may be handled in a similar way

     %.cat: %.man
       rm $*.cat
       groff -Tascii -s -t -man $*.man \
         > $*.cat








Peter Miller     (lib/en/user-guide/c4.4.so)        Page 119





User Guide                                             Aegis


55..44..77..  OOtthheerr MMaakkeess

All of the above discussion assumes that GNU  Make  and  GCC
are used.  If you do not want to do this, or may not do this
because of internal company politics, it is possible to per-
form all of the automated features manually.

This  may,  however,  rapidly  become spectacularly tedious.
For example: if a user needs to copy the _M_a_k_e_f_i_l_e into their
change  for  any  reason,  they  will need to constantly use
_a_e_d(1) to "catch up" with integrations into the baseline.

Reviewers are also  affected:  they  must  check  that  each
change  to  the _M_a_k_e_f_i_l_e accurately reflects the object list
and the dependencies of each source file.

55..44..88..  TTeemmppllaatteess

The _l_i_b_/_c_o_n_f_i_g_._e_x_a_m_p_l_e_/_m_a_k_e file in the  Aegis  distribution
contains  all of the above commands, so that you may readily
insert them into your project _c_o_n_f_i_g file.

55..44..99..  GGNNUU MMaakkee VVPPAATTHH PPaattcchh

Version 3.76 and later of GNU Make include  this  patch,  so
you don't need to read this section unless you have GNU Make
3.75 or earlier.

There is a patch available for GNU  Make  3.75  and  earlier
which gives it improved VPATH semantics.  At the time it was
not maintained by the same person who maintained  GNU  Make.
Since  then,  the  maintaier changed, and the patch has been
incorporated.

The patch is the  work  of  Paul  D.  Smith  <psmith@BayNet-
works.com> and may be fetched By Anonymous FTP from

Host:   ftp.wellfleet.com
Dir:    /netman/psmith/gmake
File:   vpath+.README
File:   vpath+.patch._v_e_r_s_i_o_n

The version numbers track the GNU Make version numbers.

For  a  description of the VPATH problem, and how this patch
addresses it, see the README file referenced.

55..44..1100..  GGNNUU MMaakkee''ss VVPPAATTHH++

In theory, using GNU Make  3.76  or  later  (or  a  suitable
patched  earlier  version)  is  similar  to using Cook.  The
project _c_o_n_f_i_g file now requires





Page 120         (lib/en/user-guide/c4.4.so)    Peter Miller





Aegis                                             User Guide


     link_integration_directory = false;

which is the default.  The _M_a_k_e_f_i_l_e now requires

     VPATH . bl

Assuming that _b_l is a symbolic link to the baseline.  The .d
files continue to be used.

55..55..  BBuuiillddiinngg EExxeeccuuttaabbllee SSccrriippttss

Aegis  treats  source  files  as,  well, source files.  This
means that it forgets any executable  bits  (and  any  other
mode  bits)  you may set on the file.  Usually, this isn't a
problem - except for scripts.

So, just how _d_o you get Aegis  to  give  you  an  executable
script?   Well,  you  add  a  build rule.  However, since it
can't depend on itself, it  needs  to  depend  on  something
else.

Using a Cook example, we could write

     bin/%: script/%.sh
     {
         /* copy the script */
         cp script/%.sh bin/%;
         /* make it executable */
         chmod a+rx bin/%;
         /* syntax check */
         bash -n bin/%;
     }

There  is a small amout of value-added here: we did a syntax
check along the way, which catches all sorts of problems.

The same technique also works for Perl

     bin/%: script/%.pl
     {
         cp script/%.pl bin/%;
         chmod a+rx bin/%;
         perl -cw bin/%;
     }


The same technique also works for TCL










Peter Miller     (lib/en/user-guide/c4.5.so)        Page 121





User Guide                                             Aegis


     bin/%: script/%.tcl
     {
         cp script/%.rcl bin/%;
         chmod a+rx bin/%;
         procheck -nologo bin/%;
     }

The _p_r_o_c_h_e_c_k(1) command ios part of the TclPro package.

Many tools have a similar options.

You can also combine  this  with  GNU  Autoconf  to  produce
architecture  specific  shell scripts from architecture neu-
tral sources.











































Page 122         (lib/en/user-guide/c8.0.so)    Peter Miller





Aegis                                             User Guide


66..  TThhee DDiiffffeerreennccee TToooollss

This  chapter  describes  the  difference  commands  in  the
project configuration file.  Usually these commands are used
by the _a_e_g_i_s _-_D_I_F_F_e_r_e_n_c_e command  when  differencing  files,
but they may be used to accomplish some other things.

The  default  setting is for Aegis to reject filenames which
contain shell special characters.  This ensures  that  file-
names  may be substituted into the commands without worrying
about whether this is safe.  If you set the _s_h_e_l_l___s_a_f_e___f_i_l_e_-
_n_a_m_e_s  field  of  the project _c_o_n_f_i_g file to false, you will
need to surround filenames with the ${quote  _f_i_l_e_n_a_m_e}  sub-
stitution.   This  will  only quote filenames which actually
need to be quoted, so users usually will not  notice.   This
command  applies to all of the various filenames in the sec-
tions which follow.

66..11..  BBiinnaarryy FFiilleess

Aegis doesn't  particularly  care  whether  your  files  are
binary  or  text.   However, your difference and merge tools
certainly will.  In general, you need  format-specific  dif-
ference and merge tools for each of the file formats used in
your project.  Unfortunately, most vendors of software which
make  use  of proprietary file formats do not supply differ-
ence and merge tools.

The simplest compromise is to treat all files as text,  with
manual repairs for binary files.

A  more elegant solution is to use a shell script invoked by
the _d_i_f_f___c_o_m_m_a_n_d in the project  _c_o_n_f_i_g  file.   This  shell
script  examines  the file to determine the file format, and
then runs the appropriate difference tool.  Similar  consid-
erations apply to the _m_e_r_g_e___c_o_m_m_a_n_d field.

66..22..  IInntteerrffaacciinngg

The  build  commands  are  accessed  from  two fields of the
project configuration file (_c_o_n_f_i_g).

66..22..11..  ddiiffff__ccoommmmaanndd

This command is used by _a_e_d(1) to produce a difference list-
ing  when  file  in the development directory was originally
copied from the current version in the baseline19.

All of the command substitutions described in  _a_e_s_u_b(5)  are
available.   In  addition,  the  following substitutions are
also available:

-----------
  19 Or this is logically the case.



Peter Miller     (lib/en/user-guide/c8.1.so)        Page 123





User Guide                                             Aegis


${ORiginal}
     The absolute path name of a file containing the version
     originally copied.  Usually in the baseline.

${Input}
     The  absolute  path  name  of the edited version of the
     file.  Usually in the development directory.

${Output}
     The absolute path name of the file in  which  to  write
     the  difference  listing.   Usually  in the development
     directory.

An exit status of 0 means successful, even of the files dif-
fer (and they usually do).  An exit status which is non-zero
means something is wrong.

The non-zero exit status may be used to overload  this  com-
mand with extra tests, such as line length limits.  The dif-
ference files must be produced in addition  to  these  extra
tests.

66..22..22..  mmeerrggee__ccoommmmaanndd

This command is used by _a_e_d(1) to produce a difference list-
ing when file in the development directory is  out  of  date
compared to the current version in the baseline.

All  of  the command substitutions described in _a_e_s_u_b(5) are
available.  In addition,  the  following  substitutions  are
also available:

${ORiginal}
     The absolute path name of a file containing the version
     originally copied.  Usually in a temporary file.

${Most_Recent}
     The absolute path name of a file  containing  the  most
     recent version.  Usually in the baseline.

${Input}
     The  absolute  path  name  of the edited version of the
     file.  Usually in  the  development  directory.   Aegis
     usually moves the source file aside, so that the output
     can replace the source file.

${Output}
     The absolute path name of the file in  which  to  write
     the  difference  listing.   Usually  in the development
     directory.  This is usually the name of a change source
     file.

An exit status of 0 means successful, even of the files dif-
fer (and they usually do).  An exit status which is non-zero



Page 124         (lib/en/user-guide/c8.1.so)    Peter Miller





Aegis                                             User Guide


means something is wrong.
























































Peter Miller     (lib/en/user-guide/c8.2.so)        Page 125





User Guide                                             Aegis


66..33..  UUssiinngg ddiiffff aanndd mmeerrggee

These  two  tools  are available with most flavours of UNIX,
but often in a very limited form.  One severe limitation  is
the  _d_i_f_f_3(1)  command,  which  often can only cope with 200
lines of differences.  The best alternative is  to  use  GNU
diff,  with  context  differences  available, and a far more
robust diff3.

See  the  earlier  _I_n_t_e_r_f_a_c_i_n_g  section   for   substitution
details.

66..33..11..  ddiiffff__ccoommmmaanndd

The entry in the _c_o_n_f_i_g file looks like this:

     diff_command =
       "set +e; diff -c $original \
        $input > $output; test $? -le 1";


This needs a little explanation:
+o This command is always executed with the shell's --ee option
enabled, causing the shell to exit on the first error.   The
"set +e" turns this off.
+o  The _d_i_f_f(1) command exits with a status of 0 if the files
are identical, and a status of 1 if they differ.  Any  other
status  means  something horrible happened.  The "test" com-
mand is used  to  change  this  to  the  exit  status  aegis
expects.

The  --cc  option  says  to  produce  a context diff.  You may
choose to use the --uu option, to produce uni-diffs,  if  your
_d_i_f_f command supports it.

You  may  also wish to consider ignoring white space in com-
parisons, as these tend to be cosmetic changes and not  very
interesting  to  code  reviewers.  The --bb option of GNU Diff
will ignore changes to the amount of white space, and the --ww
option will ignore white space altogether.

Binary files will often cause modern versions of GNU Diff to
exit with an exit status of 2, which is probably  reasonable
most  of  the  time.  If your project contains binary files,
you may want to treat all files as text files.  Use the  GNU
Diff --aa option in this case.

66..33..22..  mmeerrggee__ccoommmmaanndd

Note:  The  _m_e_r_g_e(1)  command is better than this use of the
_d_i_f_f_3(1) command.  See the RCS chapter for more details.

The entry in the _c_o_n_f_i_g file looks like this:




Page 126         (lib/en/user-guide/c8.2.so)    Peter Miller





Aegis                                             User Guide


     merge_command =
       "(diff3 -e $MostRecent $original  \
        $input | sed -e '/^w$$/d' -e     \
        '/^q$$/d'; echo '1,$$p' ) | ed - \
        $MostRecent > $output";


This needs a lot of explanation.
+o The _d_i_f_f_3(1) command is used to  produce  an  edit  script
that  will  incorporate  into  $MostRecent,  all the changes
between $original and $input.  You may want the  --aa  option,
to treat all files as ACSII.
+o  The  _s_e_d(1)  command  is  used  to remove the "write" and
"quit" commands from the generated edit script.
+o The _e_d(1) command is used  to  apply  the  generated  edit
script to the $MostRecent file, and print the results on the
standard output, which are redirected into the $output file.

66..44..  UUssiinngg ffhhiisstt

The ffhhiisstt program by David I. Bell also comes with two other
utilities, _f_c_o_m_p and _f_m_e_r_g_e, which use the same minimal dif-
ference algorithm.

See   the   earlier  _I_n_t_e_r_f_a_c_i_n_g  section  for  substitution
details.

66..44..11..  ddiiffff__ccoommmmaanndd

The entry in the _c_o_n_f_i_g file looks like this:

     diff_command =
       "fcomp -w $original $input \
        -o $output";


The --ww option produces an output of the  entire  file,  with
insertions and deletions marked by "change bars" in the left
margin.  This is superior to context difference, as it shows
the entire file as context.

For more information, see the _f_c_o_m_p(1) manual entry.

66..44..22..  mmeerrggee__ccoommmmaanndd

The entry in the _c_o_n_f_i_g file looks like this:

     merge_command =
       "fmerge $original $MostRecent \
        $input -o $output -c /dev/null";


The  output  of this command is similar to the output of the
merge_command in the last section.  Conflicts are marked  in



Peter Miller     (lib/en/user-guide/c8.3.so)        Page 127





User Guide                                             Aegis


the  output.  For more information, see the _f_m_e_r_g_e(1) manual
entry.























































Page 128         (lib/en/user-guide/c5.0.so)    Peter Miller





Aegis                                             User Guide


77..  TThhee PPrroojjeecctt AAttttrriibbuutteess

The project attributes are  manipulated  using  the  _a_e_p_a(1)
command.   This  command  reads a project attributes file to
set the project attributes.  This file can be thought of  as
having  several  sections,  each of which will be covered by
this chapter.  You should see the  _a_e_p_a_t_t_r(5)  manual  entry
for more details.

77..11..  DDeessccrriippttiioonn aanndd AAcccceessss

The  _d_e_s_c_r_i_p_t_i_o_n field is a string which contains a descrip-
tion of  the  project.   Large  amounts  of  prose  are  not
required; a single line is sufficient.

The  _d_e_f_a_u_l_t___d_e_v_e_l_o_p_m_e_n_t___d_i_r_e_c_t_o_r_y  field  is a string which
contains the pathname of  where  to  place  new  development
directories.   The pathname must be absolute.  This field is
only consulted if the _u_c_o_n_f(5) field of the same name is not
set.  Defaults to _$_H_O_M_E.

The  _u_m_a_s_k field is an integer which is set to the file per-
mission mode mask.  See _u_m_a_s_k(2) for more information.  This
value  will always be OR'ed with 022, because aegis is para-
noid.

77..22..  NNoottiiffiiccaattiioonn CCoommmmaannddss

The _d_e_v_e_l_o_p___e_n_d___n_o_t_i_f_y___c_o_m_m_a_n_d field is a string which  con-
tains  a command to be used to notify that a change requires
reviewing.  All of the substitutions described  in  _a_e_s_u_b(5)
are  available.  This field is optional, if it is not speci-
fied no notification will be  issued.   This  command  could
also  be  used  to  notify other management systems, such as
progress and  defect  tracking,  in  addition  to  notifying
users.

The  _d_e_v_e_l_o_p___e_n_d___u_n_d_o___n_o_t_i_f_y___c_o_m_m_a_n_d  field is a string con-
taining a command used to notify  that  a  change  has  been
withdrawn  from  review for further development.  All of the
substitutions described in  _a_e_s_u_b(5)  are  available.   This
field  is  optional,  if it is not specified no notification
will be issued.  This command could also be used  to  notify
other management systems, such as progress and defect track-
ing, in addition to notifying users.

The _r_e_v_i_e_w___p_a_s_s___n_o_t_i_f_y___c_o_m_m_a_n_d field is a string  containing
the  command  to  notify that the review has passed.  All of
the substitutions described in _a_e_s_u_b(5) are available.  This
field  is  optional,  if it is not specified no notification
will be issued.  This command could also be used  to  notify
other management systems, such as progress and defect track-
ing, in addition to notifying users.




Peter Miller     (lib/en/user-guide/c5.0.so)        Page 129





User Guide                                             Aegis


The _r_e_v_i_e_w___p_a_s_s___u_n_d_o___n_o_t_i_f_y___c_o_m_m_a_n_d field is a  string  con-
taining  the  command  to  notify that a review pass has has
been rescinded.   All  of  the  substitutions  described  in
_a_e_s_u_b(5)   are  available.   This  field  is  optional,  and
defaults to  the  _d_e_v_e_l_o_p___e_n_d___n_o_t_i_f_y___c_o_m_m_a_n_d  field  if  not
specified.  If neither is specified, no notification will be
issued.  This command could also be  used  to  notify  other
management systems, such as progress and defect tracking, in
addition to notifying users.

The _r_e_v_i_e_w___f_a_i_l___n_o_t_i_f_y___c_o_m_m_a_n_d field is a string  containing
the  command  to  notify that the review has failed.  All of
the substitutions described in _a_e_s_u_b(5) are available.  This
field  is  optional,  if it is not specified no notification
will be issued.  This command could also be used  to  notify
other management systems, such as progress and defect track-
ing, in addition to notifying users.

The _i_n_t_e_g_r_a_t_e___p_a_s_s___n_o_t_i_f_y___c_o_m_m_a_n_d field is a string contain-
ing  the  command to notify that the integration has passed.
All of the substitutions described in  _a_e_s_u_b(5)  are  avail-
able.   This  field  is  optional, if it is not specified no
notification will be issued.  This  command  could  also  be
used  to  notify  other management systems, such as progress
and defect tracking, in addition to notifying users.

The _i_n_t_e_g_r_a_t_e___f_a_i_l___n_o_t_i_f_y___c_o_m_m_a_n_d field is a string contain-
ing  the  command to notify that the integration has failed.
All of the substitutions described in  _a_e_s_u_b(5)  are  avail-
able.   This  field  is  optional, if it is not specified no
notification will be issued.  This  command  could  also  be
used  to  notify  other management systems, such as progress
and defect tracking, in addition to notifying users.

77..22..11..  NNoottiiffiiccaattiioonn bbyy eemmaaiill

The aegis command is distributed with a set of shell scripts
to perform these notifications by email.  They are installed
into the _/_u_s_r_/_l_o_c_a_l_/_l_i_b_/_a_e_g_i_s  directory,  by  default;  the
actual  installed directory at your site is available as the
_$_{_D_A_T_a___D_I_R_e_c_t_o_r_y_} substitution.  The entries in the  project
attribute file look like this:















Page 130         (lib/en/user-guide/c5.0.so)    Peter Miller





Aegis                                             User Guide


     develop_end_notify_command =
       "$sh $datadir/de.sh $project $change";
     develop_end_undo_notify_command =
       "$sh $datadir/deu.sh $project $change";
     review_pass_notify_command =
       "$sh $datadir/rp.sh $project $change \
       $developer $reviewer";
     review_pass_undo_notify_command =
       "$sh $datadir/rpu.sh $project $change \
       $developer";
     review_fail_notify_command =
       "$sh $datadir/rf.sh $project $change \
       $developer $reviewer";
     integrate_pass_notify_command =
       "$sh $datadir/ip.sh $project $change \
       $developer $reviewer $integrator";
     integrate_fail_notify_command =
       "$sh $datadir/if.sh $project $change \
       $developer $reviewer $integrator";


Please  note:  the exit status of all these commands will be
ignored.

77..22..22..  NNoottiiffiiccaattiioonn bbyy UUSSEENNEETT

The aegis command is distributed with a set of shell scripts
to   perform   these  notifications  by  USENET.   They  are
installed  into  the  _/_u_s_r_/_l_o_c_a_l_/_l_i_b_/_a_e_g_i_s   directory,   by
default;  the  actual  installed  directory  at your site is
available  as  the  _$_{_D_A_T_a___D_I_R_e_c_t_o_r_y_}   substitution.    The
entries in the project attribute file look like this:

     develop_end_notify_command =
       "$sh $datadir/de.inews.sh $p $c alt.$p";
     develop_end_undo_notify_command =
       "$sh $datadir/deu.inews.sh $p $c alt.$p";
     review_pass_notify_command =
       "$sh $datadir/rp.inews.sh $p $c alt.$p";
     review_pass_undo_notify_command =
       "$sh $datadir/rpu.inews.sh $p $c alt.$p";
     review_fail_notify_command =
       "$sh $datadir/rf.inews.sh $p $c alt.$p";
     integrate_pass_notify_command =
       "$sh $datadir/ip.inews.sh $p $c alt.$p";
     integrate_fail_notify_command =
       "$sh $datadir/if.inews.sh $p $c alt.$p";


The  last  argument to each command is the newsgroup to post
the article in, you may want to use some other group.   Note
that  "$p"  is an abbreviation for "$project" and "$c" is an
abbreviation for "$change".




Peter Miller     (lib/en/user-guide/c5.0.so)        Page 131





User Guide                                             Aegis


77..33..  EExxeemmppttiioonn CCoonnttrroollss

The _d_e_v_e_l_o_p_e_r___m_a_y___r_e_v_i_e_w field is a boolean.  If this  field
is  true,  then a developer may review her own change.  This
is probably only a good idea for projects  of  less  than  3
people.  The idea is for as many people as possible to crit-
ically examine a change.

The _d_e_v_e_l_o_p_e_r___m_a_y___i_n_t_e_g_r_a_t_e field is  a  boolean.   If  this
field  is  true,  then  a  developer  may  integrate her own
change.  This is probably only a good idea for  projects  of
less  than 3 people.  The idea is for as many people as pos-
sible to critically examine a change.

The _r_e_v_i_e_w_e_r___m_a_y___i_n_t_e_g_r_a_t_e field  is  a  boolean.   If  this
field  is  true,  then a reviewer may integrate a change she
reviewed.  This is probably only a good idea for projects of
less  than 3 people.  The idea is for as many people as pos-
sible to critically examine a change.

The _d_e_v_e_l_o_p_e_r_s___m_a_y___c_r_e_a_t_e___c_h_a_n_g_e_s field is  a  boolean.   If
this  field  is  true then developers may create changes, in
addition to administrators.  This tends to be a very  useful
thing, since developers find most of the bugs.

The  _d_e_f_a_u_l_t___t_e_s_t___e_x_e_m_p_t_i_o_n  field is a boolean.  This field
contains what to do when a change is created  with  no  test
exemption  specified.  The default is "false", i.e. no test-
ing exemption, tests must be provided.

This kind of blanket exemption should only  be  set  when  a
project  has  absolutely no functionality available from the
command line; examples include X11  programs.   The  program
could  possibly be improved by providing access to the func-
tionality from the command line, thus allowing tests  to  be
written.

77..33..11..  OOnnee PPeerrssoonn PPrroojjeeccttss

The  entries in the project attributes file for a one person
project look like this:

     developer_may_review = true;
     developer_may_integrate = true;
     reviewer_may_integrate = true;
     developers_may_create_changes = true;


All of the staff roles (administrator,  developer,  reviewer
and integrator) are all set to be the same user.







Page 132         (lib/en/user-guide/c5.0.so)    Peter Miller





Aegis                                             User Guide


77..33..22..  TTwwoo PPeerrssoonn PPrroojjeeccttss

A  two person project has the opportunity for each to review
the other's work.

The entries in the project attributes file for a two  person
project look like this:

     developer_may_review = false;
     developer_may_integrate = true;
     reviewer_may_integrate = true;
     developers_may_create_changes = true;


All  of the staff roles (developer, reviewer and integrator)
are all set to allow both users.

77..33..33..  LLaarrggeerr PPrroojjeeccttss

Once you have 3 or more staff on a project, you  can  assign
all  of  the  roles to separate people.  The idea is for the
greatest number of eyes to see each change and detect  flaws
before they reach the baseline.

The  entries in the project attributes file for a three per-
son project look like this:

     developer_may_review = false;
     developer_may_integrate = false;
     reviewer_may_integrate = false;
     developers_may_create_changes = true;


For smaller teams, everyone may be a reviewer.  As the teams
get larger, the more experienced staff are often the review-
ers, rather than everyone.





















Peter Miller    (lib/en/user-guide/c11.0.so)        Page 133





User Guide                                             Aegis


88..  TTeessttiinngg

This chapter discusses testing, and using  Aegis  to  manage
your tests and testing.

88..11..  WWhhyy BBootthheerr??

Writing  tests is extra work, compared to the way many small
(and some not-so-small) software shops  operate.   For  this
reason, the testing requirement may  be turned off.

The  win  is  that  the  tests hang around forever, catching
minor and major slips before they become embarrassing  "fea-
tures"  in  a  released product.  Prevention is cheaper than
cure in this case, the tests save work down the track.

All of the "extra work" of writing tests is a long-term win,
where  old problems never again reappear.  All of the "extra
work" of reviewing changes means that another pair  of  eyes
sees the code and finds potential problems before they mani-
fest themselves in shipped product.  All of the "extra work"
of  integration  ensures that the baseline always works, and
is always self-consistent.  All of the "extra work" of  hav-
ing  a  baseline and separate development directories allows
multiple  parallel  development,  with  no   inter-developer
interference;  and the baseline always works, it is never in
an "in-between" state.  In each case, not doing this  "extra
work" is a false economy.

The  existence  of  these  tests, though, is what determines
which projects are most suited to Aegis and which  are  not.
It  should  be noted that suitability is a continuous scale,
not black-and-white.  With effort and resources, almost any-
thing fits.

88..11..11..  PPrroojjeeccttss ffoorr wwhhiicchh AAeeggiiss'' TTeessttiinngg iiss MMoosstt SSuuiittaabbllee

Projects most suited to supervision by  Aegis  are  straight
programs.   What  the non-systems-programmers out there call
"tools" and sometimes "applications".   These  are  programs
which  take  a pile of input, chew on it, and emit a pile of
output.  The tests can  then  compare  actual  outputs  with
expected outputs.

As  an  example, you could be writing a _s_e_d(1) look-alike, a
public domain clone of the  UNIX  sed  utility.   You  could
write  tests  which exercise every feature (insertion, dele-
tion, etc.)  and generate the expected output with the  real
UNIX  sed.   You  write the code, and run the tests; you can
immediately see if the output matches expectations.

This is a simple example.  More complex examples exist, such
as Aegis itself.  The Aegis program is used to supervise its
own development.  Tests consist of sequences of commands and



Page 134        (lib/en/user-guide/c11.1.so)    Peter Miller





Aegis                                             User Guide


expected results are tested for.

Other  types  of  software  have been developed using Aegis:
compilers and interpreters,  client-server  model  software,
magnetic  tape  utilities,  graphics software such as a ray-
tracer.  The range is vast, but it is not all types of soft-
ware.

88..11..22..  PPrroojjeeccttss ffoorr wwhhiicchh AAeeggiiss'' TTeessttiinngg iiss UUsseeffuull

For  many  years there have been full-screen applications on
text terminals.  In more recent times  there  is  increasing
use of graphical interfaces.

In  developing  these types of programs it is still possible
to use Aegis, but several options need to be explored.

88..11..22..11..  TTeessttiinngg VViiaa EEmmuullaattoorrss

There are screen emulators for both full-screen text and X11
available.   Using  these  emulators, it is possible to test
the user interface, and test via  the  user  interface.   As
yet, the author knows of no freely available emulators suit-
able for testing via Aegis.  If you find one, please let  me
know.

88..11..22..22..  LLiimmiitteedd TTeessttiinngg

You  may  choose to use Aegis simply for its ability to pro-
vide controlled access to a large source.  You still get the
history  and  change  mechanisms,  the  baseline  model, the
enforced review.  You simply don't test all changes, because
figuring  out  what is on the screen, and testing it against
expectations, is too hard.

If the program has a command line interface, in addition  to
the full-screen or GUI interface, the functionality accessi-
ble from the command line may be tested using Aegis.

It is possible that "limited  testing"  actually  means  "no
testing",  if  you have no functionality accessible from the
command line.

88..11..22..33..  TTeessttiinngg MMooddee

Another alternative is to provide hooks  into  your  program
allowing  you to substitute a file for user input, and to be
able to trigger the dump of a "screen image".  The simulated
user  input  can  then be fed to the program, and the screen
dump (in some terminal-independent  form)  can  be  compared
against expectations.

This  is  easier  for full-screen applications, than for X11
applications.  You need to judge the cost-benefit trade-off.



Peter Miller    (lib/en/user-guide/c11.1.so)        Page 135





User Guide                                             Aegis


Cost  of  development, cost of storage space for X11 images,
cost of _n_o_t testing.

88..11..22..44..  MMaannuuaall TTeessttss

The Aegis program provides a manual test facility.   It  was
originally  intended for programs which required some physi-
cal action from a user, such as "unplug Ethernet cable  now"
or  "mount  tape XG356B now".  It can also be used to have a
user confirm that some on-screen activity has happened.

The problem with manual tests is that they simply don't hap-
pen.   It  is  far  more  pleasant to say "run the automatic
tests" and go for a cup of coffee, than to  wait  while  the
computer  thinks  of mindless things to ask you to do.  This
is human nature: if it can be automated, it is  more  likely
to happen.

88..11..22..55..  UUnniitt TTeessttss

Many  folks think of testing as taking the final product and
testing it.  It is also possible to build  specialized  unit
tests,  which exercise specific portions of the code.  These
tests can then be administrated by Aegis, even if the  full-
blown GUI cannot be.

88..11..33..  PPrroojjeeccttss ffoorr wwhhiicchh AAeeggiiss'' TTeessttiinngg iiss LLeeaasstt UUsseeffuull

Another class of software is things  like  operating  system
kernels  and firmware; things which are "stand alone".  This
isolated nature makes it the most difficult to test: to test
it you want to provide physical input and watch the physical
output.  By its very nature, it is hard to put into a  shell
script, and thus hard to write an Aegis test for.

The  above  chapter  was  written  in 1991.  At this writing
(1999) there are projects like xLinux and operating  systems
like  VxWorks.   These are all embedded, and all have excel-
lent network and download support.  It is entirely  possible
(with  design  support!)  to  write  automatically  testable
embedded systems.

88..11..33..11..  OOppeerraattiinngg SSyysstteemmss

It is not impossible, just that few of us have the resources
to do it.  You need to have a test system and a testing sys-
tem: the test system has all of its input and  outputs  con-
nected  to  the  outputs  and  inputs of the testing system.
That is, the testing system controls  and  drives  the  test
system, and watches what happens.

For  example,  in  the olden days before everyone had PC and
graphics terminals, there were only serial interfaces avail-
able.   Many  operating system vendors tested their products



Page 136        (lib/en/user-guide/c11.1.so)    Peter Miller





Aegis                                             User Guide


by using computers connected to each serial line to simulate
"user  input".   The  system  can  be rebooted this way, and
using dual-ported disks allows different versions of a  ker-
nel to be tried, or other test conditions created.

For  software  houses which write kernels, or device drivers
for kernels, or some other kernel work, this  is  bad  news:
the  Aegis program is probably not for you.  It is possible,
but there may be more cost-effective development strategies.
Of  course,  you  could  always  use  the rest of Aegis, and
ignore the testing part.

However, Aegis has been used quite successfully  to  develop
Linux  kernel  modules.  With suitable _s_u_d_o(1) configuration
to permit access to _i_n_s_m_o_d(1) &co, developers can write test
scripts  which load device drivers, try them out, and unload
them again, all without universal _r_o_o_t access.

Also, the advent of modern  tools,  such  as  VMware,  which
allow  one operating system to "host" another, may also per-
mit straightforward testing of kernels  and  operating  sys-
tems.

88..11..33..22..  FFiirrmmwwaarree

Firmware  is  a  similar deal: you need some way to download
the code to be tested into the test system,  and  write-pro-
tect  it to simulate ROM, and have the necessary hardware to
drive the inputs and watch the outputs.

As you can see, this is generally not available  to  run-of-
the-mill   software  houses,  but  then  they  rarely  write
firmware, either.  Those that do write firmware usually have
the download capabilities, and some kind of remote operation
facility.

However, this omits the possibility of not only  cross  com-
piling  your  code for the target system, but also compiling
your code to run natively on the build system.  The firmware
(in  the  host incarnation) then falls into one of the cate-
gories above, and may be  readily  tested.   This  does  not
relieve  you  of also testing the firmware, but it increases
the probability that the firmware isn't  completely  useless
before you download it.

By using an object oriented language, such as C++, the poly-
morphism necessary to cope with multiple environments can be
elegantly  hidden behind a pure abstract base class.  Alter-
natively, by using a consistent API, you can accomplish  the
necessary sleight-of-hand at link time.

The  unit  test method mentioned earlier is also very useful
for firmware, even if the device  "as  a  whole"  cannot  be
tested.



Peter Miller    (lib/en/user-guide/c11.2.so)        Page 137





User Guide                                             Aegis


88..22..  WWrriittiinngg TTeessttss

This  section  describes  a number of general guidelines for
writing better tests, and some pitfalls to be avoided.

There are also a number of suggestions  for  portability  of
tests  in specific scripting languages; this will definitely
be important if you are writing software to publish  on  WWW
or for FTP.  Portability is often required _w_i_t_h_i_n an organi-
zation, also.  Examples include a change in  company  policy
from  one  386  UNIX  to  another (e.g. company doesn't like
Linux, now you must use AT&T's SVR4 offering), or the devel-
opment  team  use _g_c_c until the company finds out and forces
you to use the prototype-less  compiler  supplied  with  the
operating  system, or even that the software being developed
must run under both UNIX and Windows NT.

Note, also, that when using Aegis' heterogeneous build  sup-
port, portability will again feature prominently.

88..22..11..  CCoonnttrriibbuuttoorrss

I'd  like  to  thank  Steven  Knight <knight@baldmt.com> for
writing portions of this information.

If other readers have additional testing techniques, or  use
other scripting languages, contributions are welcome.

88..22..22..  GGeenneerraall GGuuiiddeelliinneess

This  section  lists  a number of general guidelines for all
aegis tests, regardless  of  implementation  language.   Use
this  section  to guide how you write tests if the scripting
language you choose is not specifically covered  in  greater
detail below.

88..22..22..11..  CChhooiiccee ooff SSccrriippttiinngg LLaanngguuaaggee

The aegis program uses the _t_e_s_t___c_o_m_m_a_n_d field of the project
_c_o_n_f_i_g file to specify how tests are executed.  The  default
value of the _t_e_s_t___c_o_m_m_a_n_d field:

     test_command = "$shell $file_name";

specifies that tests be Bourne shell scripts.  You may, how-
ever, change the value of _t_e_s_t___c_o_m_m_a_n_d to specify some other
scripting  language  interpreter,  which allows you to write
your test scripts in whatever scripting language  is  appro-
priate  for your project.  The Perl or Python scripting lan-
guages, for example, could be used to  create  test  scripts
that are portable to systems other than UNIX systems.

This  means  that if you can write it in your scripting lan-
guage of choice, you can test it.  This includes such things



Page 138        (lib/en/user-guide/c11.2.so)    Peter Miller





Aegis                                             User Guide


as  client-server  model interfaces, and multi-user synchro-
nization testing.

88..22..22..22..  NNoo EExxeeccuuttee PPeerrmmiissssiioonn

Under aegis, script files do  not  have  execute  permission
set,  so they should always be invoked by passing the script
file to the interpreter, not executing the test directly:

     sh _f_i_l_e_n_a_m_e
     perl _f_i_l_e_n_a_m_e


88..22..22..33..  NNoo CCoommmmaanndd--LLiinnee AArrgguummeennttss

Tests should not expect command line arguments.   Tests  are
not  passed  the  name  of the project nor the number of the
change.

88..22..22..44..  IIddeennttiiffyyiinngg tthhee SSccrriippttiinngg LLaanngguuaaggee

Even though aegis does not execute the test script directly,
it  is  a  good idea to put some indication of its scripting
language into the test script.  See the sections  below  for
suggested  "magic number" identification of scripts in vari-
ous languages.

88..22..22..55..  CCuurrrreenntt DDiirreeccttoorryy

Tests are always run  with  the  current  directory  set  to
either  the  development  directory of the change under test
when testing a change, or  the  integration  directory  when
integrating  a change, or the baseline when performing inde-
pendent tests.

A test must not make assumptions about  where  it  is  being
executed  from,  except to the extent that it is somewhere a
build has been performed.  A test must not assume  that  the
current  directory is writable, and must not try to write to
it, as this could damage the source code of a  change  under
development, potentially destroying weeks of work.

88..22..22..66..  CChheecckk EExxiitt SSttaattuuss aanndd RReettuurrnn VVaalluueess

A  test  script should check the exit status or return value
of every single command or function call, even  those  which
cannot  fail.   Checking  the exit status or return value of
every statement in the script ensures that  strange  permis-
sion  settings,  or disk space problems, will cause the test
to fail, rather than plow on and produce  spurious  results.
See  the sections below for specific suggestions on checking
exit status or return values in various scripting languages.





Peter Miller    (lib/en/user-guide/c11.2.so)        Page 139





User Guide                                             Aegis


88..22..22..77..  TTeemmppoorraarryy DDiirreeccttoorryy

Tests  should create a temporary subdirectory in the operat-
ing system's temporary directory  (typically  _/_t_m_p  on  UNIX
systems)  and then change its working directory (_c_d) to this
directory.  This isolates any  vandalism  that  the  program
under  test  may  indulge in, and serves as a place to write
temporary files.

At the end of the test, it is sufficient to change directory
out of the temporary subdirectory and then remove the entire
temporary subdirectory  hierarchy,  rather  than  track  and
remove all test files which may or may not be created.

Some  UNIX systems provide other temporary directories, such
as _/_v_a_r_/_t_m_p, which may provide a better location for a  tem-
porary  subdirectory  for  testing  (more  file system space
available, administrator preference,  etc.).   Test  scripts
wishing to accomodate alternate temporary directories should
use the TMPDIR environment variable (or some other  environ-
ment  variable  appropriate  to the operating system hosting
the tests) as the location for creating their temporary sub-
directory,  with  _/_t_m_p  as a reasonable default if TMPDIR is
not set.

88..22..22..88..  TTrraapp IInntteerrrruuppttss

Test scripts should catch appropriate interrupts (1 2 3  and
15  on UNIX systems) and cause the test to fail.  The inter-
rupt handler should perform any cleanup the  test  requires,
such as removing the temporary subdirectory.

88..22..22..99..  PPAAGGEERR

If the program under test invokes pagers on its output, a la
_m_o_r_e(1) et al, it should be coded to use the PAGER  environ-
ment  variable.   Tests  of  such programs should always set
PAGER to _c_a_t so that tests always behave the same, irrespec-
tive  of invocation method (either by aegis or from the com-
mand line).

88..22..22..1100..  AAuuxxiilliiaarryy FFiilleess

If a test requires extra files as input or output to a  com-
mand, it must construct them itself from in-line data.  (See
the sections below for more specific information  about  how
to use in-line data in various scripting languages to create
files.)

It is almost impossible to determine the location of an aux-
iliary  file,  if that auxiliary file is part of the project
source.  It could be in either the change under test or  the
baseline.




Page 140        (lib/en/user-guide/c11.2.so)    Peter Miller





Aegis                                             User Guide


88..22..22..1111..  NNeeww TTeesstt TTeemmppllaatteess

Regardless  of your choice of scripting language, it is pos-
sible to specify most of the repetitious items  above  in  a
_f_i_l_e  _t_e_m_p_l_a_t_e  used  every  time a user creates a new test.
See the _a_e_n_t(1) command for more information.

Having the machine do it for you means  that  you  are  more
likely to do it.

88..22..33..  BBoouurrnnee SShheellll

The  Bourne  shell  is  available on all flavors of the UNIX
operating system, which allows Bourne shell  scripts  to  be
written  portably  across those systems.  Here are some spe-
cific guidelines for writing aegis tests using Bourne  shell
scripts.


88..22..33..11..  MMaaggiicc NNuummbbeerr

Some  indication that the test is a Bourne shell script is a
good idea.  While many systems  accept  that  a  first  line
starting  with  a  colon is a Bourne shell "magic number", a
more widely understood "magic number" is

     #! /bin/sh

as the first line of the script file.

88..22..33..22..  CChheecckk EExxiitt SSttaattuuss

A Bourne shell test script should check the exit  status  of
every  single command, even those which cannot fail.  Do not
rely on, or use, the _s_e_t _-_e shell  option  (it  provides  no
ability to clean up on error).

Checking  the  exit  status involves testing the contents of
the $$??  shell variable.  Do not use an _i_f statement  wrapped
around  an  execution of the program under test as this will
miss core dumps and other terminations caused by signals.

88..22..33..33..  TTeemmppoorraarryy DDiirreeccttoorryy

Bourne shell test scripts should create a  temporary  subdi-
rectory  in  _/_t_m_p  (or the directory specified by the TMPDIR
environment variable) and then _c_d into this  directory.   At
the  end  of the test, or on interrupt, the script should _c_d
out of the temporary subdirectory and then _r_m _-_r_f it.

88..22..33..44..  TTrraapp IInntteerrrruuppttss

Use the _t_r_a_p statement to catch interrupts 1 2 3 and 15  and
cause the test to fail.  This should perform any cleanup the



Peter Miller    (lib/en/user-guide/c11.2.so)        Page 141





User Guide                                             Aegis


test requires, such as removing the temporary directory.

88..22..33..55..  AAuuxxiilliiaarryy FFiilleess

If a test requires extra files as input or output to a  com-
mand, it must construct them itself, using _h_e_r_e documents:

     cat <<EOF >file
     contents
     of the
     file
     EOF

See _s_h(1) for more information.

88..22..33..66..  [[ tteesstt ]]

You  should  always  use  the  _t_e_s_t command, rather than the
square bracket form, as many systems do not have the  square
bracket form, if you publish to USENET or for FTP.

88..22..33..77..  OOtthheerr BBoouurrnnee SShheellll PPoorrttaabbiilliittyy IIssssuueess

The  above  list  covers the most common Bourne shell issues
that are relevant to most aegis  tests.   The  documentation
for  the  GNU  autoconf  utility,  however,  contains a more
exhaustive list of Bourne shell portability issues.  If  you
want  (or  need) to make your tests as portable as possible,
see the documentation for GNU autoconf.

88..22..44..  PPeerrll

Perl is a popular open-source scripting  language  available
on  a  number  of operating systems.  Here are some specific
guidelines for writing aegis tests using Perl scripts.

88..22..44..11..  MMaaggiicc NNuummbbeerr

Some indication that the test is a Perl  script  is  a  good
idea.  Because Perl is not installed in the same location on
all UNIX systems, a first-line "magic number" such as:

     #! /usr/local/bin/perl

that hard-codes the Perl path name will not be  portable  if
you publish your tests.

If  the  _e_n_v(1) program is available, a more portable "magic
number" for Perl is:

     #! /usr/bin/env perl






Page 142        (lib/en/user-guide/c11.2.so)    Peter Miller





Aegis                                             User Guide


88..22..44..22..  CChheecckk RReettuurrnn VVaalluueess

A Perl test script should check the return value from  every
subroutine, even those which cannot fail.

A  Perl  test  script  should  also check the exit status of
every  command  it  executes.   Checking  the  exit   status
involves  testing the contents of the $$??  variable.  See the
Perl documentation on "Predefined Variables" for details.

88..22..44..33..  TTeemmppoorraarryy DDiirreeccttoorryy

Perl test scripts should create a temporary subdirectory  in
_/_t_m_p  (or  the directory specified by the $$EENNVV{{TTMMPPDDIIRR}} envi-
ronment variable) and then _c_h_d_i_r into  this  directory.   At
the  end  of  the  test,  or on interrupt, the script should
_c_h_d_i_r out of the temporary subdirectory and then  remove  it
and  its hierarchy.  A portable way to do this within a Perl
script:

     use File::Find;
     finddepth(sub { if (-d $_) {
                     rmdir($_)
             } else {
                     unlink($_)
             } },
             $dir);


88..22..44..44..  TTrraapp IInntteerrrruuppttss

Use Perl's _$_S_I_G hash to catch interrupts for HUP, INT,  QUIT
and  TERM  and  cause the test to fail.  This should perform
any cleanup the test requires, such as removing  the  tempo-
rary directory.  A very simple example:

     $SIG{HUP} =
     $SIG{INT} =
     $SIG{QUIT} =
     $SIG{TERM} =
             sub { &cleanup; exit(2) };


88..22..44..55..  AAuuxxiilliiaarryy FFiilleess

If  a test requires extra files as input or output to a com-
mand, it must construct them itself, using in-line data such
as _h_e_r_e documents See the Perl documentation for more infor-
mation.

88..22..44..66..  EExxiitt VVaalluueess

Aegis expects tests to exit with a status of 0 for  success,
1  for  failure,  and  2  for no result.  The following code



Peter Miller    (lib/en/user-guide/c11.2.so)        Page 143





User Guide                                             Aegis


fragment will map all failed (non-zero) exit  values  to  an
exit  status  of  1,  regardless  of what Perl module called
exit:

     END { $? = 1 if $? }

A more complete example could check conditions and  set  the
exit status to 2 to indicate NO RESULT.

88..22..44..77..  MMoodduulleess

Perl  supports  the ability to re-use modules of common rou-
tines, and to search several directories for modules.   This
makes it convenient to write modules to share code among the
tests in a project.

Any modules that are used by your test scripts  (other  than
the  standard modules included by Perl) should be checked in
to the project as source files.  Test  scripts  should  then
import the module(s) via the normal Perl mechanism:

     use MyTest;


When  a  test is run, the module file may actually be in the
baseline  directory,  not  the  development  or  integration
directories.   To  make  sure that the test invocation finds
the module, the _t_e_s_t___c_o_m_m_a_n_d field  in  the  project  _c_o_n_f_i_g
file should use the Perl --II option to search first the local
directory and then the baseline:

     test_command =
         "perl -I. -I${BaseLine} \
         ${File_Name}"

or, alternatively, if you had created your Perl test modules
in a subdirectory named aauuxx:

     test_command =
         "perl -I./aux -I${BaseLine}/aux \
         ${File_Name}"


For  details on the conventions involved in writing your own
modules, consult the Perl documentation or  other  reference
work.

_A_c_t_u_a_l_l_y_,  _y_o_u  _n_e_e_d _t_o _u_s_e _t_h_e _$_{_s_e_a_r_c_h___p_a_t_h_} _s_u_b_s_t_i_t_u_t_i_o_n_.
_I_'_l_l _h_a_v_e _t_o _f_i_x _t_h_i_s _o_n_e _d_a_y_.

88..22..44..88..  TThhee TTeesstt::::CCmmdd MMoodduullee

A Test::Cmd module is available on CPAN  (the  Comprehensive
Perl  Archive  Network)  that  makes  it  easy to write Perl



Page 144        (lib/en/user-guide/c11.2.so)    Peter Miller





Aegis                                             User Guide


scripts  that  conform  to  aegis  test  requirements.   The
Test::Cmd  module  supports most of the guidelines mentioned
above, including creating a temporary subdirectory, cleaning
up  the temporary subdirectory on exit or interrupt, writing
auxiliary files from in-line contents, and provides  methods
for  exiting on success, failure, or no result.  The follow-
ing example illustrates some of its capabilities:

     #! /usr/bin/env perl
     use Test::Cmd;
     $test = Test::Cmd->new(prog
             => 'program_under_test',
                     workdir => '');
     $ret = $test->write('aux_file', <<EOF);
     contents of file
     EOF
     $test->no_result(! $ret =>
             sub { print STDERR
             "Couldn't write file: $!\\n"});
     $test->run(args => 'aux_file');
     $test->fail($? != 0);
     $test->pass;


The various methods supplied by the Test::Cmd module have  a
number of options to control their behavior.

The  Test::Cmd  module manipulates file and path names using
the operating-system-independent File::Spec module,  so  the
Test::Cmd  module can be used to write tests that are porta-
ble to any operating system that runs Perl and  the  program
under test.

The Test::Cmd module is available on CPAN.  See the module's
documentation for details.

88..22..44..99..  TThhee TTeesstt aanndd TTeesstt::::HHaarrnneessss MMoodduulleess

Perl supplies two modules, Test and Test::Harness,  to  sup-
port  its own testing infrastructure.  Perl's tests use dif-
ferent conventions  than  aegis  tests;  specifically,  Perl
tests  do not use the exit status to indicate the success or
failure of the test, like aegis expects.  The  Test::Harness
module expects that Perl tests report the success or failure
of individual sub-tests on standard output, and always  exit
with  a status of 0 to indicate the script tested everything
it was supposed to.

This difference  makes  it  awkward  to  use  the  Test  and
Test::Harness  modules  for  aegis  tests.   In some circum-
stances, though, you may be forced to write tests using  the
Test  and  Test::Harness  modules--for  example,  if you use
aegis to develop a Perl module for  distribution--but  still
wish  to  have the tests conform to aegis conventions during



Peter Miller    (lib/en/user-guide/c11.2.so)        Page 145





User Guide                                             Aegis


development.

This can be done by writing each test to use an  environment
variable  to  control whether its exit status should conform
to aegis or Perl conventions.  This is easy when  using  the
Test module to write tests, as its _o_n_f_a_i_l method provides an
appropriate place to set the exit status to non-zero if  the
appropriate environment variable is set.  The following code
fragment at or near the beginning of each Perl  test  script
accomplishes this:

     use Test;
     BEGIN { plan tests => 3,
         onfail => sub {
             $? = 1 if $ENV{AEGIS_TEST}
             }
         }

(See  the  documentation for the Test module for information
about using it to write tests.)

There then needs to be a wrapper Perl script around the exe-
cution  of  the  tests to set the environment variable.  The
following script (called _m_y_t_e_s_t_._p_l for the sake of  example)
sets  the  AAEEGGIISS__TTEESSTT  environment  variable expected by the
previous code fragment:

     use Test::Harness;
     $ENV{AEGIS_TEST} = 1;
     open STDOUT, ">/dev/null" || exit (2);
     runtests(@ARGV);
     END { $? = 1 if $?;
         print STDERR $?
             ? "FAILED" : "PASSED",
             "\n"; }

It also makes its output more nearly conform to aegis' exam-
ples   by  redirecting  standard  output  to  //ddeevv//nnuullll  and
restricting its reporting of results to a simple  FFAAIILLEEDD  or
PASSED on standard error output.

The  last  piece of the puzzle is to modify the _t_e_s_t___c_o_m_m_a_n_d
field of the project  _c_o_n_f_i_g  file  to  have  the  _m_y_t_e_s_t_._p_l
script call the test script:

     test_command =
         "perl -I. -I${BaseLine} mytest.pl \
         ${File_Name}"


The  Test and Test::Harness modules are part of the standard
Perl distribution and do not need to be downloaded from any-
where.   Because these modules are part of the standard dis-
tribution, they can be used by test  scripts  without  being



Page 146        (lib/en/user-guide/c11.2.so)    Peter Miller





Aegis                                             User Guide


checked in to the project.

88..22..44..1100..  GGrraannuullaarriittyy BByy _S_t_e_v_e_n _K_n_i_g_h_t _<_k_n_i_g_h_t_@_b_a_l_d_m_t_._c_o_m_>

The  granularity  of  Perl and Aegis tests mesh very well at
the individual test file (.t) level.  Aegis  and  Test::Har-
ness  are  simply  different  harnesses that expect slightly
different conventions from the tests  they  execute:   Aegis
uses  the exit code to communicate an aggregate pass/fail/no
result status, Test::Harness examines the output from  tests
to decide if a failure occurred.

It's  actually  pretty  easy to accomodate both conventions.
You can do this as easily as setting the test_command  vari-
able  in  the project config file to something like the fol-
lowing:

     test_command =
             "perl -MTest::Harness -e 'runtests(\"$fn\"); \
             END {$$? = 1 if $$? }'";

In reality, you'll likely need to add variable expansions to
generate  -I or other Perl options for the full Aegis search
path.  The END block takes  care  of  mapping  any  non-zero
Test::Harness  exit  code  to  the '1' that Aegis expects to
indicate a failure.

The only thing you really lose  here  is  the  Test::Harness
aggregation of results and timing at the end of a multi-test
run.  This is more than offset by having Aegis  track  which
tests need to be run for a given change.

Alternatively,  you  can  execute the .t files directly, not
through Test::Harness::runtests.  This is easily accomodated
using  the  onfail method from the standard Perl Test module
in each test.  Here's a standard opening block for .t tests

     use Test;
     BEGIN { $| = 1; plan tests => 19,
             onfail => sub { $? = 1 if $ENV{AEGIS_TEST} }
     }
     END {print "not ok 1\n" unless $loaded;}
     use Test::Cmd;
     $loaded = 1;
     ok(1);

That's it  (modulo  specifying  the  appropriate  number  of
tests).   My  .t  tests  now  use  the proper exit status to
report a failure back to Aegis.  The  only  other  piece  is
configuring  the  project's  "test_command" value to set the
AEGIS_TEST environment variable.

You can also use an intermediate script that also  redirects
the tests's STDOUT to /dev/null, if you are used to and like



Peter Miller    (lib/en/user-guide/c11.2.so)        Page 147





User Guide                                             Aegis


the coarser PASSED/FAILED status.

88..22..55..  BBaattcchh TTeessttiinngg

The usual ``_t_e_s_t___c_o_m_m_a_n_d'' field of the project _c_o_n_f_i_g  file
runs  a  single  test  at a time.  When you have a multi-CPU
machine, or are able to distribute the testing load across a
range  of  machines,  it  is  often desirable to do so.  The
``_b_a_t_c_h___t_e_s_t___c_o_m_m_a_n_d'' of the project  config  file  is  for
this purpose.  See _a_e_p_c_o_n_f(5) for more information.















































Page 148         (lib/en/user-guide/c9.0.so)    Peter Miller





Aegis                                             User Guide


99..  BBrraanncchhiinngg

This  chapter describes the concept of branching implemented
by Aegis.  The process described in previous chapters  makes
changes to a project's master source.
                     -1--    --2-     -3--
                 ---------B-a-s-e-l-i-n-e----------


Branching  generalizes  this  change  model, by allowing the
baseline to be treated as a change, or the ability to  treat
a change as a baseline.
                  Branch 1 -1-.-1   -1-.-2
                 --------------------------
                      Trunk Baseline

Since  branchs  are  sometimes considered as a changes it is
useful to expand on the differences.  A  branch,  or  trunk,
baseline  may  have  children  which  are  either _c_h_a_n_g_e_s or
deeper _b_r_a_n_c_h_e_s_.  From this perspective  the  difference  is
that  nothing may be modified directly in a branch. A branch
is an integrated baseline with all  the  associated  protec-
tion.  To  modify a branch one must open a change under that
branch.

Looking upward from a change under a branch, its  _p_a_r_e_n_t  is
the  branch  baseline,  and its _g_r_a_n_dparent is the _p_a_r_e_n_t of
the branch. We will see this used later when we  talk  about
ending a branch.

A  significant  feature  of  Aegis branches is that, because
they are an  extension  of  the  _c_h_a_n_g_e  concept,  they  are
expected to end, and be integrated back into _t_h_e_i_r baseline,
or _p_a_r_e_n_t ,in time.

The most common case of this is in project releases.

A branch in the _b_e_i_n_g _d_e_v_e_l_o_p_e_d state may have changes  made
to  it,  and/or  deeper  branches.   This may recurse to any
level.   Once  a  branch  is  complete,  no  further  deeper
branches may be created from that branch.

99..11..  HHooww TToo UUssee BBrraanncchhiinngg

To  access a project branch, the project name has the branch
appended, separated by a dot  or  a  hyphen.   For  example:
branch 1 of project "aegis" is referred to as "aegis.1".  To
reference changes on this branch, use this compound  project
name wherever you would normally use a project name.

Traditional  2-level  project  release names are obtained by
using a further level of branching.  For example: by  creat-
ing  branch  0 of project "aegis.1", there would be a branch
accessed as project "aegis.1.0".



Peter Miller     (lib/en/user-guide/c9.0.so)        Page 149





User Guide                                             Aegis


By default, these two level of project branching are created
automatically  when  the _a_e_n_p_r(1) command is used.  You need
to use the --VVEERRSSiioonn option to make this deeper or shallower,
or have different numbering.

              +------------+------------------+
              |Command     | Branches Created |
              +------------+------------------+
              |aenpr foo   | foo,      foo.1, |
              |            | foo.1.0          |
              |aenpr   foo | foo,      foo.2, |
              |-vers 2.4.1 | foo.2.4,         |
              |            | foo.2.4.1        |
              |aenpr foo.7 | foo, foo.7       |
              |aegis  -npr | foo              |
              |foo -vers - |                  |
              +------------+------------------+
The last is a special case, to enable a project to  be  cre-
ated  with  no  default  branches (it's also hard to get the
empty string past the alias).

To add branching and release level management to an existing
project  on  uses the _a_e_n_b_r(1) command at any level.  Say we
already have foo.1.0, which represents version  1.0  of  our
software. One method of release level management would be to
integrate _f_o_o_._1_._0 into its _p_a_r_e_n_t _f_o_o_._1 and then do _a_e_n_b_r _-_p
_f_o_o_._1  would create _f_o_o_._1_._1 representing version 1.1.  Even-
tually we might want to make a  major  version  release  and
would  integrate _f_o_o_._1 into its _p_a_r_e_n_t _f_o_o and then do _a_e_n_b_r
_-_p _f_o_o, which would create _f_o_o_._2.  Then if we  do  _a_e_n_b_r  _-_p
_f_o_o_._2  we  create _f_o_o_._2_._0, for development of version 2.0 of
our software.


99..22..  TTrraannssiittiioonn UUssiinngg aaeennrrllss

To convert a project from the old-style to the new branching
style, use the _a_e_n_r_l_s(1) command.

If  you  give no second project name, the new name is gener-
ated by removing the numeric suffixes.  If you did not  give
a  -VERSion  option,  the  numeric  suffixes will be used to
determine the next version, by adding one  to  the  previous
minor  version  number.   The  new  project  is then created
rather like the _a_e_n_p_r(1) command.

The files of  the  old  project  are  copied  across  as  an
implicit  change  on the newly created branch within the new
project.  If the new project name already exists, and  is  a
new-style  project,  the  _a_e_n_r_l_s(1)  command will attempt to
make the appropriate numbered branches.  If the new  project
already exists and is an old-style project, or it exists and
the branch number(s) are already in use, _a_e_n_r_l_s(1) will emit
an error and fail.  The _a_e_n_r_l_s(1) command only works on old-



Page 150         (lib/en/user-guide/c9.0.so)    Peter Miller





Aegis                                             User Guide


style projects,  and  always  converts  them  to  new  style
projects.

Planning  you  branch  numbers is essential.  If you want to
use 3-level branch numbers (e.g. "aegis.2.3.1") at some time
in the future, then you must use 3-level version numbers all
the way  through  (e.g.  "aegis.2.3.0").   This  is  because
change  numbers and branch numbers come from the same common
pool of numbers.   Once  change  one  has  been  used  (e.g.
"aegis.2.3.C001"),  then  branch  one is no longer available
(e.g. "aegis.2.3.1.C042" conflicts).

99..33..  CCrroossss BBrraanncchh MMeerrggee

From time to time you will want to merge  the  changes  from
one  branch  into a change.  This may be done using a cross-
branch merge.  This is done by specifying the --BBRRaanncchh option
to the _a_e_g_i_s _-_d_i_f_f _-_m_e_r_g_e_-_o_n_l_y command.

The  most  common  cross  branch merge is when the project's
files are out-of-date.  Because it is not  possible  to  use
_a_e_g_i_s _-_d_i_f_f _-_m_e_r_g_e_-_o_n_l_y directly on the branch, this must be
in a change on the branch.  As a short-cut, the  branch  may
be specified using the _-_g_r_a_n_d_p_a_r_e_n_t option.

99..44..  MMuullttiippllee BBrraanncchh DDeevveellooppmmeenntt

It  is  very  common  for a bug fix to need to be applied to
more than one branch at once.  The change could  be  applied
to  the  common  ancestor  branch,  however  this may not be
effective in the branch immediately.  An alternative  is  to
use  the  _a_e_g_i_s _-_c_l_o_n_e command, which can be used to identi-
cally reproduce a change on another branch.

99..55..  HHiieerraarrcchhyy ooff PPrroojjeeccttss

It would be nice if there was some way to use one project as
a sort of "super change" to a "super project", so that large
teams (say 1000 people) could work as lots  of  small  teams
(say  100  people).  As a small team gets their chunk ready,
using the facilities provided to-date by  Aegis,  the  small
team's  baseline  is  treated  as a change to be made to the
large team baseline.

This idea can be extended quite naturally to  any  depth  of
layering.

After reading _T_r_a_n_s_a_c_t_i_o_n _O_r_i_e_n_t_e_d _C_o_n_f_i_g_u_r_a_t_i_o_n _M_a_n_a_g_e_m_e_n_t_:
_A _C_a_s_e _S_t_u_d_y Peter Fieler, Grace  Downey,  CMU/SEI-90-TR-23,
this is not a new idea.  It also provides some ideas for how
to do branching sensibly, and was influential in the  design
of Aegis' branching.





Peter Miller     (lib/en/user-guide/c9.1.so)        Page 151





User Guide                                             Aegis


99..55..11..  FFuunnddaammeennttaallss

Aegis  has everything you need to have a super project and a
number of sub-projects.  All you need to  do  is  create  an
active branch for each sub-project.  Each branch gets a sep-
arate baseline, _v_i_z

     % aaeennpprr ggiizzmmoo..00..11
     project "gizmo": created
     project "gizmo.0": created
     project "gizmo.0.1": created
     %


Now, for each of your desired sub-projects,  create  another
branch

     aenbr -p gizmo.0.1 1 # _f_o_r _t_h_e _f_o_o _p_r_o_j_e_c_t
     aenbr -p gizmo.0.1 2 # _f_o_r _t_h_e _b_a_r _p_r_o_j_e_c_t
     aenbr -p gizmo.0.1 3 # _f_o_r _t_h_e _b_a_z _p_r_o_j_e_c_t


Now,  the  guys  on  the _f_o_o project set their AEGIS_PROJECT
environment variable to to _g_i_z_m_o_._0_._1_._1,  the  _b_a_r  guys  use
_g_i_z_m_o_._0_._1_._2, and _b_a_z uses _g_i_z_m_o_._0_._1_._3.  From the developer's
point of view they are separate projects.   From  one  level
up, though, they are just part of a bigger project.

It helps if you design and implement the build system first.
You do this as a change set on  the  common  parent  branch.
Once  it  is  completed  each branch can inherit it from the
common parent.  This makes integration easier, when it comes
time to integrate the sub-projects together.

99..55..22..  IInnccrreemmeennttaall IInntteeggrraattiioonn

It  is  very common that not all of the sub-projects will be
ready to be integrated at the same time.  This is the normal
situation  with  Aegis branching, and is handled cleanly and
simply.

In Aegis each branch is literally a change, all the way down
into the internal data structures.  Just as each change gets
its own development directory,  each  branch  gets  its  own
baseline.   Just  as a development directory inherits every-
thing its  doesn't  have  from  the  baseline,  so  branches
inherit  everything _t_h_e_y don't have from their parent branch
(or ultimately from the trunk).  Just as  you  incrementally
integrate changes into a branch, you incrementally integrate
branches into their parent.

The branches only influence each other when they  are  inte-
grated,  just as changes only influence each other when they
are integrated.



Page 152         (lib/en/user-guide/c9.1.so)    Peter Miller





Aegis                                             User Guide


There are times when a branch being integrated into its par-
ent  is  found  to  be  inadequate.  Aegis provides a simple
mechanism to ``bounce'' a branch integration.  Recall  that,
for  Aegis,  branches  are the same as changes.  Just as you
``develop end'' a change (see _a_e_d_e(1) for more  information)
you  also _a_e_d_e a branch when development on it is completed.

Once  a  branch  has  develop-end  (stops  being  an  _a_c_t_i_v_e
branch),  it  is reviewed as a normal change, and integrated
as a normal change.  If integration failed,  it  returns  to
``being developed'' and becomes an active branch once again,
until the next _a_e_d_e.  As you can  see,  it  is  as  easy  to
bounce  a  branch  integration  as  it is to bounce a change
integration.

An unsuccessful branch  integration  leaves  the  repository
unchanged, just as an unsuccessful change integration leaves
it unchanged.


99..55..33..  SSuuppeerr--PPrroojjeecctt BBrraanncchhiinngg

In many real-world situations it is  very  important  to  be
able  to  branch  at  any  point  in the past history of the
super-project to fix (integration specific) bugs or to  cus-
tomize more the older states of the super-project.

You can create a branch at any time, on any active branch or
active branch ancestor.  You can populate that  branch  with
historical  versions  (from  any other branch, actually, not
just the ancestral line).  The method is a  little  fussy  -
you  can't  _a_e_c_p into a branch directly, you need to do this
via a change to that branch.  Files not changed by a  change
on  a  branch  are  inherited from the current (_i_._e_. active)
state of the parent branch.  See the section on  _I_n_s_u_l_a_t_i_o_n,
above.

99..55..44..  SSuuppeerr--PPrroojjeecctt TTeessttiinngg

Many  folks  see  Aegis' testing features as useful for unit
testing  individual  files  or  change  sets.    For   large
projects,  it  is  common  that a specific test tool will be
written.  However, even large scale integration  testing  is
possible using Aegis.

You can change the test command from being a shell script to
being anything to you want - see the _t_e_s_t___c_o_m_m_a_n_d  field  in
_a_e_p_c_o_n_f(5).  Or run the test tool from the shell script.  If
the integration tests can be automated, it  makes  sense  to
preserve  them in the repository - they are some of the most
valuable  regression  tests  for  developers,  because  they
describe  correct behavior outside the ``box'' the developer
usually works in.




Peter Miller     (lib/en/user-guide/c9.1.so)        Page 153





User Guide                                             Aegis


99..55..55..  TThhee NNeexxtt CCyyccllee

Once you have a fully-integrated product,  what  happens  on
the  next  cycle?   Well,  first  you  may  want  to  finish
_g_i_z_m_o_._0_._1 and integrate it into _g_i_z_m_o_._0, and then  _a_e_n_b_r  _-_p
_g_i_z_m_o_._0 _2

Then what?  Same deal as before, but anything not changed in
one of the sub-project  branches  gets  inherited  from  the
ancestor.

     aenbr -p gizmo.0.2 1 # _f_o_r _t_h_e _f_o_o _p_r_o_j_e_c_t
     aenbr -p gizmo.0.2 2 # _f_o_r _t_h_e _b_a_r _p_r_o_j_e_c_t
     aenbr -p gizmo.0.2 3 # _f_o_r _t_h_e _b_a_z _p_r_o_j_e_c_t


Most  folks  find  doing  the whole mega-project-build every
time tiresome - so don't.  Temporarily (via  a  change  set)
hack the build config to build only the bit you want - obvi-
ously a different hack on each sub-project's  branch.   Just
remember  to  un-hack it (via another change set) before you
integrate the sub-project.

99..55..66..  BBuugg FFiixxiinngg

The _a_e_c_l_o_n_e(1) command lets you clone a change set from  one
branch  to  another.  So if you have a bug fix that needs to
be done on each active branch you can  clone  it  (once  you
have  it  fixed  the  first  time).  You still have to build
review and integrate _n times (branches  often  differ   non-
trivially).  Providing it isn't already in use, you can even
ask for the same change number on each branch  -  handy  for
syncing with an external bug tracking system.

Alternatively, fix bugs in the common ancestor, and the sub-
projects will inherit the fix the next time  they  integrate
something  on  their  branch (assuming they aren't insulated
against it).

99..66..  CCoonnfflliicctt RReessoolluuttiioonn

A development directory becomes out of date, compared to the
project,  when another change is integrated which has a file
in common.  This  situation  is  detected  automatically  by
_a_e_d_e(1)  and you resolve it using _a_e_d(1), usually with some-
thing like the _-_-_m_e_r_g_e_-_o_n_l_y option.  Additionally,  you  can
see  if  you  have an out-of-date file from the _c_h_a_n_g_e _f_i_l_e_s
listing, because it will show you the current baseline  ver-
sion in parentheses if you are out-of-date.

Aegis  implements  branches  as very long changes, with sub-
changes.  A side effect of this is that a branch can  become
out-of-date  in  the  same  way  that a development director
becomes out of date.  When it  comes  time  to  _a_e_d_e(1)  the



Page 154         (lib/en/user-guide/c9.2.so)    Peter Miller





Aegis                                             User Guide


branch, you will be told if there are any out-of-date files.
Additionally, the _p_r_o_j_e_c_t _f_i_l_e_s listing  will  show  out  of
date  files  in  exactly  the  same way that the _c_h_a_n_g_e _f_i_l_e
listing does.

99..66..11..  CCrroossss BBrraanncchh MMeerrggee

However, unlike a simple change, if you attempt to  use  the
_a_e_d  _-_-_m_e_r_g_e_-_o_n_l_y  command  in the branch baseline, you will
get an error message!  How, then, do you resolve the  appar-
ent impasse?

The _a_e_d(1) command has a number of options designed for just
this purpose.

+o The _-_-_b_r_a_n_c_h option may be used to specify another  branch
  of the same project, as a source of the file to be differ-
  enced against.  This is almost what you need.

+o The _-_-_g_r_a_n_d_p_a_r_e_n_t option is a special case of the _-_-_b_r_a_n_c_h
  option, and it means the parent branch of project.

+o The  _-_-_t_r_u_n_k option is also a special case of the _-_-_b_r_a_n_c_h
  option, and it means the base branch from which the entire
  branch tree springs.

By  creating  a  new  change  on the out-of-date branch, and
copying in the out-of-date files, you have almost everything
required.   All  that  is  necessary  is to perform a cross-
branch merge against the project grandparent, and the neces-
sary  merging  will  be  performed.   IInn aaddddiittiioonn Aegis will
remember that it was a cross-branch merge, and once  _a_e_i_p_a_s_s
completes  successfully,  the branch will be up-to-date once
more.

[] Create a new change on the out-of-date branch

[] Use a simple _a_e_c_p command to copy the out-of-date  files.
   (Do _n_o_t use any _-_-_b_r_a_n_c_h or _-_-_d_e_l_t_a options.)

[] Use  the  ``_a_e_d  _-_-_m_e_r_g_e_-_o_n_l_y  _-_-_g_r_a_n_d_p_a_r_e_n_t'' command to
   perform the merge.
   At this point, if you use the  ``_a_e_l  _c_f''  command,  you
   will  notice that this file is tagged in the listing with
   the new branch edit origin, to be  used  during  _a_e_i_p_a_s_s.
   If it isn't, you have made a mistake.

[] As  usual,  use  your favourite editor to check the merge
   results, and resolve any conflicts.

[] Build and test as usual.

[] Complete the change as usual.




Peter Miller     (lib/en/user-guide/c9.2.so)        Page 155





User Guide                                             Aegis


[] Once _a_e_i_p_a_s_s is successful, the branch will be up-to-date
   (for the files in the change).

99..66..22..  IInnssuullaattiioonn

One of the stated benefits of using a branch is the insulat-
ing effects which branches can provide.  However,  when  you
have  multiple simultaneous active branches, that insulation
will inevitably lead to out-of-date branch files.  Now  that
_h_o_w to merge them has been described, _w_h_e_n should you merge?

In a simple change's development directory, there are  times
when  an  _a_e_i_p_a_s_s  will  result in all developers needing to
recompile.  Depending on what files you are working  on,  it
may  be  that  you  need  to merge some of your change files
immediately, or _a_e_c_p an earlier version of the  files  which
changed in the project.

Branches can also suffer from exactly the same problems, and
are mended by exactly the same alternatives.

99..66..22..11..  BBrraanncchh IInnssuullaatteedd AAggaaiinnsstt PPrroojjeecctt

If you created a branch to insulate the work being  done  on
the  branch from other activities in the project, it follows
that when such build problems occurred,  you  would  use  an
``_a_e_c_p _-_d_e_l_t_a_'_' _c_o_m_m_a_n_d _t_o _c_o_n_t_i_n_u_e _i_n_s_u_l_a_t_i_n_g_.

This  action  defers the labour of merging until towards the
end of the branch development, sometimes with a quite  visi-
ble schedule impact.

99..66..22..22..  PPrroojjeecctt IInnssuullaatteedd AAggaaiinnsstt BBrraanncchh

If  you  created  a branch to insulate the project from work
being done in the branch, it follows that  you  would  do  a
cross branch immediately.

This  action amortizes the labour of merging across the life
of the branch, often with a number of small delays and  less
schedule impact.

99..66..22..33..  MMiixx ''nn'' MMaattcchh

Of course, we usually have both these motives, and some more
besides, so the answer is usually ``it depends''.

99..77..  EEnnddiinngg AA BBrraanncchh

``OK, I  give  up.   I  do  not  understand  the  ending  of
branches.''

Usually,  you  end  development of a branch the same way you
end development of a simple change.  In this example, branch



Page 156         (lib/en/user-guide/c9.3.so)    Peter Miller





Aegis                                             User Guide


_e_x_a_m_p_l_e_._1_._4_2 will be ended:

     % aaeeddee --pp eexxaammppllee 11 --cc 4422
     aegis: project "example.1": change 42: file "_f_u_b_a_r" in
     the baseline has changed since the last 'aegis -DIFFer-
     ence' command, you need to do a merge
     %

Oops.  Something went wrong.  Don't panic!

I'm going to assume, for the purposes of explanation, that
there have been changes in one of the  ancestor branches,
and thus require a merge, just like file _f_u_b_a_r, above.

You need to bring file _f_u_b_a_r up-to-date.  How?  You do it in
a change set, like everything else.

At his point you need to do 5 things: (1) create a new
change on example.1.42, (2) copy _f_u_b_a_r into it, (3) merge
_f_u_b_a_r with branch "example.1" (4) end development of the
change and integrate it, and (5) now you can end exam-
ple.1.42

The -GrandParent option is a special case of the -BRanch
option.  You are actually doing a cross-branch merge, just
up-and-down rather than sideways.

     % aaeemm --ggpp _f_u_b_a_r
     %

And manually fix any conflicts... naturally.

At this point, have a look at the file listing, it will show
you something you have never seen before - it will show you
what it is _g_o_i_n_g _t_o set the branch's edit_number_origin to
for each file, at _a_e_i_p_a_s_s.

     % aaeell ccff
     Type   Action Edit        File Name
     ------ ------ -------     -----------
     source modify 1.3         _f_u_b_a_r
                   {cross 1.2}

Now finish the change as usual...  _a_e_b_, _a_e_d_, _a_e_d_e_, _a_e_r_p_a_s_s_,
_a_e_i_b_, _._._._, _a_e_i_p_a_s_s nothing special here.

One small tip: merge the files one at a time.  It makes
keeping track of where you are up to much easier.

Now you can end development of the branch, because all of
the files are up-to-date.

In some cases, Aegis has detected a logical conflict where
you, the human, know there is none.  Remember that the _a_e_m



Peter Miller     (lib/en/user-guide/c9.3.so)        Page 157





User Guide                                             Aegis


command saves the old version of the file with a ,B suffix
(`B' for backup).  If you have a file like this, just use

     % mmvv _f_u_b_a_r,,BB _f_u_b_a_r
     %

to discard everything from the ancestor branch, and use the
current branch.

















































Page 158         (lib/en/user-guide/c6.0.so)    Peter Miller





Aegis                                             User Guide


1100..  TTiippss aanndd TTrraappss

This chapter contains hints for how to use the aegis program
more efficiently and documents a number of pitfalls you may
encounter.

This chapter is at present very "ad hoc" with no particular
ordering.  Fortunately, it is, as yet, rather small.  The
final size of this chapter is expected to be quite large.

1100..11..  RReennaammiinngg IInncclluuddee FFiilleess

Renaming include files can be a disaster, either finding all
of the clients, or making sure the new copy is used rather
than the old copy still in the baseline.

Aegis provides some assistance.  When the _a_e_m_v(1) command is
used, a file in the development directory is created in the
_o_l_d location, filled with garbage.  Compiles will fail very
diagnostically, and you can change the reference in the
source file, probably after _a_e_c_p(1)ing it first.

If you are moving an include file from one directory to
another, but leaving the basename unchanged, create a link20
between the new and old names, but only in the development
directory (i.e. replacing the "garbage" file aegis created
for you).  Create the link after _a_e_m_v(1) has succeeded.
This insulates you from a number of nasty Catch-22 situa-
tions in writing the dependency maintenance tool's rules
file.

1100..22..  SSyymmbboolliicc LLiinnkkss

If you are on a flavor of UNIX which has symbolic links, it
is often useful to create a symbolic link from the develop-
ment directory to the baseline.  This can make browsing the
baseline very simple.

Assuming that the project and change defaults are appropri-
ate, the following command

     ln -s `aegis -cd -bl` bl

is all that is required to create a symbolic link called _b_l
pointing to the baseline.  Note that the _a_e_c_d alias is inap-
propriate in this case.

This can be done automatically for every change, by placing
the line

-----------
  20 A hard link uses fewer disk blocks.  Symbolic
links survive the subject file being  deleted  and
recreated.



Peter Miller     (lib/en/user-guide/c6.0.so)        Page 159





User Guide                                             Aegis


     develop_begin_command =
             "ln -s $baseline bl";

into the project _c_o_n_f_i_g file.

1100..33..  UUsseerr SSeettuupp

There are a number of things which users of aegis can do to
make it more useful, or more user friendly.  This section
describes just a few of them.

1100..33..11..  TThhee ..ccsshhrrcc oorr ..pprrooffiillee ffiilleess

The aliases for the various user commands used throughout
this manual are obtained by appending a line of the form

     . /usr/local/share/aegis/profile

to the _._p_r_o_f_i_l_e file in the user's home directory, if they
use the _s_h(1) shell or the _b_a_s_h(1) shell.

If the user uses the _c_s_h(1) shell, append a line of the form

     source /usr/local/share/aegis/cshrc

to the _._c_s_h_r_c file in the user's home directory.

These days, many systems also provide an _/_e_t_c_/_p_r_o_f_i_l_e_._d
directory, which has symbolic links to the start-up scripts
for various packages.  These are run automatically for all
users.  If your system has such a thing, arrange for sym-
bolic links

     ln -s /usr/local/share/aegis/profile \
             /etc/profile.d/aegis.sh
     ln -s /usr/local/share/aegis/cshrc \
             /etc/profile.d/aegis.csh

and you will not need to edit every user's _._c_s_h_r_c or _._p_r_o_-
_f_i_l_e file.

1100..33..22..  TThhee AAEEGGIISS__PPAATTHH eennvviirroonnmmeenntt vvaarriiaabbllee

If users wish to use aegis for their own projects, in addi-
tion to the "system" projects, the _A_E_G_I_S___P_A_T_H environment
variable forms a colon separated search path of aegis
"library" directories.  The _/_u_s_r_/_l_o_c_a_l_/_l_i_b_/_a_e_g_i_s directory
is always implicitly added to this list.

The user should not create this library directory, but let
aegis do this for itself (otherwise you will get an error
message).





Page 160         (lib/en/user-guide/c6.0.so)    Peter Miller





Aegis                                             User Guide


The _A_E_G_I_S___P_A_T_H environment variable should be set in the
_._c_s_h_r_c or _._p_r_o_f_i_l_e files in the user's home directory.  Typ-
ical setting is

     setenv AEGIS_PATH ~/lib/aegis

and this is the default used in the
_/_u_s_r_/_l_o_c_a_l_/_s_h_a_r_e_/_a_e_g_i_s_/_c_s_h_r_c file.

1100..33..33..  TThhee ..aaeeggiissrrcc ffiillee

The _._a_e_g_i_s_r_c file in the user's home directory contains a
number of useful fields.  See _a_e_u_c_o_n_f(5) for more informa-
tion.

1100..33..44..  TThhee ddeeffaauullttiinngg mmeecchhaanniissmm

In order for you to specify the minimum possible information
on the command line, aegis has been designed to work most of
it out itself.

The default project is the project which you are working on
changes for, if there is only one, otherwise it is gleaned
from the _._a_e_g_i_s_r_c file.  The command line overrides any
default.

The default change is the one you are working on within the
(default or specified) project, if there is only one.  The
command line overrides any default.

1100..44..  TThhee PPrroojjeecctt OOwwnneerr

For the greatest protection from accidental change, it is
best if the project is owned by a UNIX account which is none
of the staff.  This account is often named the same as the
project, or sometimes there is a single umbrella account for
all projects.

When an aegis project is created, the owner is the user cre-
ating the project, and the group is the user's default
group.  The creating user is installed as the project's
first administrator.

A new project administrator should be created - an actual
user account.  The UNIX password should then be disabled on
the project account - it will never be necessary to use it
again.21

The user nominated as project administrator many then assign
all of the other staff roles.  Aegis takes care of ensuring
-----------
  21 Unless bugs in aegis corrupt the database, in
which  case  repairs  can  be  accomplished as the
project account using a text editor.



Peter Miller     (lib/en/user-guide/c6.0.so)        Page 161





User Guide                                             Aegis


that the baseline is owned by the project account, not any
of the other staff, while development directories always
belong to the developer (but the group will always be the
project group, irrespective of the developer's default
group).

All of the staff working on a project should be members of
the project's group, to be able to browse the baseline, for
reviewers to be able to review changes.  This use of UNIX
groups means that projects may be as secure or open as
desired.

1100..55..  UUSSEENNEETT PPuubblliiccaattiioonn SSttaannddaarrddss

If you are writing software to publish on USENET, a number
of the source newsgroups have publication standards.  This
section describes ways of generating the following files,
required by many of the newsgroups' moderators:

MANIFEST       List of files
               in the distri-
               bution.
Makefile       How to build
               the distribu-
               tion.
CHANGES        What happened
               for this dis-
               tribution.
patchlevel.h   An identifica-
               tion of this
               distribution.


Each of these files may be generated from information known
to aegis, with the aid of some fairly simple shell scripts.

1100..55..11..  CCHHAANNGGEESS

Write this section.

Look in the _a_u_x_/_C_H_A_N_G_E_S_._s_h file included in the aegis dis-
tribution for an example of one way to do this.

1100..55..22..  MMAANNIIFFEESSTT

Write this section.

Look in the _a_u_x_/_M_A_N_I_F_E_S_T_._s_h and _a_u_x_/_M_A_N_I_F_E_S_T_._a_w_k files
included in the aegis distribution for an example of one way
to do this.







Page 162         (lib/en/user-guide/c6.0.so)    Peter Miller





Aegis                                             User Guide


1100..55..33..  MMaakkeeffiillee

Write this section.

Look in the _a_u_x_/_M_a_k_e_f_i_l_e_._s_h and _a_u_x_/_M_a_k_e_f_i_l_e_._a_w_k files
included in the aegis distribution for an example of one way
to do this.

1100..55..44..  ppaattcchhlleevveell..hh

Write this section.

Look in the _a_u_x_/_H_o_w_t_o_._c_o_o_k file included in the aegis dis-
tribution for an example of one way to do this.

1100..55..55..  BBuuiillddiinngg PPaattcchh FFiilleess

The _p_a_t_c_h program by Larry Wall is one of the enduring mar-
vels of USENET.  This section describes how to build input
files for this miracle program.

Write this section.

Look in the _a_u_x_/_p_a_t_c_h_e_s_._s_h file included in the aegis dis-
tribution for an example of one way to do this.
































Peter Miller     (lib/en/user-guide/c6.1.so)        Page 163





User Guide                                             Aegis


1100..66..  HHeetteerrooggeenneeoouuss DDeevveellooppmmeenntt

The aegis program has support for heterogeneous development.
It will enforce that each change be built and tested on each
of a list of architectures.  It determines which architec-
ture it is currently executing on by using the _u_n_a_m_e(2) sys-
tem call.

The _u_n_a_m_e(2) system call can yield uneven results, depending
on the operating systems vendor's interpretation of what it
should return22.  To cope with this, each required architec-
ture for a project is specified as a name and a pattern.

The name is used by aegis internally, and is also available
in the _$_{_A_R_C_H_i_t_e_c_t_u_r_e_} substitution (see _a_e_s_u_b(5) for more
information).

The patterns are simple shell file name patterns (see _s_h(1)
for more information) matched against the output of the
_u_n_a_m_e(2) system call.

The result of _u_n_a_m_e(2) has four fields of interest: _s_y_s_n_a_m_e,
_r_e_l_e_a_s_e, _v_e_r_s_i_o_n and _m_a_c_h_i_n_e.  These are stitched together
with hyphens to form an architecture _v_a_r_i_a_n_t to be matched
by the pattern.

For example, a system the author commonly uses is
"SunOS-4.1.3-8-sun4m" which matches the "SunOS-4.1*-*-sun4*"
pattern.  A solaris system, a very different beast, matches
the "SunOS-5.*-*-sun4*" pattern.  Sun's 386 version of
Solaris matches the "SunOS-5.*-*-i86pc" pattern.  A convex
system matches the "ConvexOS-*-10.*-convex" pattern.

1100..66..11..  PPrroojjeecctt _c_o_n_f_i_g FFiillee

To require a project to build and test on each of these
architectures, the _a_r_c_h_i_t_e_c_t_u_r_e field of the project _c_o_n_f_i_g
file is set.  See _a_e_p_c_o_n_f(5) for more details on this file.
The above examples of architectures could be represented as











-----------
  22 For example, SCO 3.2 returns the nodename  in
the  sysname  field,  when  it  should place "SCO"
there; Convex and Pyramid scramble it even  worse.



Page 164         (lib/en/user-guide/c6.1.so)    Peter Miller





Aegis                                             User Guide


     architecture =
     [
       {
         name = "sun4";
         pattern = "SunOS-4.1*-*-sun4*";
       },
       {
         name = "sun5";
         pattern = "SunOS-5.*-*-sun4*";
       },


       {
         name = "sun5pc";
         pattern = "SunOS-5.*-*-i86pc";
       },
       {
         name = "convex";
         pattern = "ConvexOS-*-10.*-*";
       }
     ];

This would require that all changes build and test on each
of the "sun4", "sun5", "sun5pc" and "convex" architectures.

It is also possible to have _o_p_t_i_o_n_a_l architectures.  This
may be used to recognise an environment, but not mandate
that it be built every time.

       {
         name = "solaris-8-sparc";
         pattern = "SunOS-5.8*-*-sun4*";
         mode = optional;
       },

However, once an architecture name appears in a change's
architecture list, it is mandatory for that change.

If the _a_r_c_h_i_t_e_c_t_u_r_e field does not appear in the project
_c_o_n_f_i_g file, it defaults to

     architecture =
     [
       {
         name = "unspecified";
         pattern = "*";
       }
     ];


Setting the architectures is usually done as part of the
first change of a project, but it also may be done to exist-
ing projects.  This information is kept in the project _c_o_n_-
_f_i_g file, rather than as a project attribute, because it



Peter Miller     (lib/en/user-guide/c6.1.so)        Page 165





User Guide                                             Aegis


requires that the DMT configuration file and the tests have
corresponding details (see below).

     The _l_i_b_/_c_o_n_f_i_g_._e_x_a_m_p_l_e_/_a_r_c_h_i_t_e_c_t_u_r_e file in the Aegis
distribution contains many architecture variations, so that
you may readily insert them into your project _c_o_n_f_i_g file.

1100..66..22..  CChhaannggee AAttttrriibbuuttee

The _a_r_c_h_i_t_e_c_t_u_r_e attribute is inherited by each new change.
A project administrator may subsequently edit the change
attributes to grant exemptions for specific architectures.
See _a_e_c_a(1) for how to do this.

A build must be successfully performed on each of the target
architectures.  Similarly, the tests must be performed suc-
cessfully on each.  These requirements are because there is
often conditional code present to cope with the vagaries of
each architecture, and this needs to be compiled and tested
in each case.

This multiple build and test requirement includes both
development and integration states of each change.

1100..66..33..  NNeettwwoorrkk FFiilleess

This method of heterogeneous development assumes that the
baseline and development directories are available as the
same pathname in all target architectures.  With software
such as NFS, this does not present a great problem, however
NFS locking must also work.

There is also an assumption that all the hosts remotely
mounting NFS file systems will agree on the time, because
aegis uses time stamps to record that various tasks have
been performed.  Software such as _t_i_m_e_d(8) is required23.

1100..66..44..  DDMMTT IImmpplliiccaattiioonnss

This method of heterogeneous development assumes that the
baseline will have a copy of all object files for all target
architectures _s_i_m_u_l_t_a_n_e_o_u_s_l_y.

This means that the configuration file for the DMT will need
to distinguish all the variations of the object files in
some way.  The easiest method is to have a separate object
tree for each architecture24.  To facilitate this, there is
an _$_{_A_R_C_H_i_t_e_c_t_u_r_e_} substitution available, which may then be
-----------
  23 Some sites manage by  running  _r_d_a_t_e(8)  from
_c_r_o_n(8) every 15 minutes.
  24 A tree the same  shape  as  the  source  tree
makes  navigation easier, and users need not think
of file names unique across all directories.



Page 166         (lib/en/user-guide/c6.1.so)    Peter Miller





Aegis                                             User Guide


passed to the DMT using the _b_u_i_l_d___c_o_m_m_a_n_d field of the
project _c_o_n_f_i_g file.

The architecture name used by aegis needs to be used by the
DMT, so that both aegis and the DMT can agree on which
architecture is currently targeted.

1100..66..44..11..  CCooookk EExxaammppllee

As and example of how to do this, the cook recipes from the
DMT chapter are modified as appropriate.  First, the
_b_u_i_l_d___c_o_m_m_a_n_d field of the project _c_o_n_f_i_g file is changed to
include the _$_{_A_R_C_H_i_t_e_c_t_u_r_e_} substitution:

     build_command =
       "cook -b ${s Howto.cook} \
       project=$p change=$c \
       version=$v arch='$arch' -nl";


Second, the C recipe must be changed to include the archi-
tecture in the path of the result:

     [arch]/%.o: %.c: [collect c_incl
       -eia [prepost "-I" ""
       [search_list]] [resolve %.c]]
     {
       if [not [exists [arch]]] then
         mkdir [arch]
           set clearstat;
       if [exists [target]] then
         rm [target]
           set clearstat;
       [cc] [cc_flags] [prepost "-I"
         "" [search_list]] -c
         [resolve %.c];
       mv %.o [target];
     }


Third, the link recipe must be changed to include the archi-
tecture in the name of the result:















Peter Miller     (lib/en/user-guide/c6.1.so)        Page 167





User Guide                                             Aegis


     [arch]/example: [object_files]
     {
       if [not [exists [arch]]] then
         mkdir [arch]
           set clearstat;
       if [exists [target]] then
         rm [target]
           set clearstat;
       [cc] -o [target] [resolve
         [object_files]] -ly -ll;
     }


The method used to determine the object_files variable is
the same as before, but the object file names now include
the architecture:

     object_files =
       [fromto %.y [arch]/%.o
         [match_mask %.y [source_files]]]
       [fromto %.l [arch]/%.o
         [match_mask %.l [source_files]]]
       [fromto %.c [arch]/%.o
         [match_mask %.c [source_files]]]
       ;


Note that the form of these recipes precludes performing a
build in each target architecture simultaneously, because
intermediate files in the recipes may clash.  However, aegis
prevents simultaneous build, for this and other reasons.

1100..66..55..  TTeesstt IImmpplliiccaattiioonnss

Tests will need to know in which directory the relevant
binary files reside.  The _t_e_s_t___c_o_m_m_a_n_d field of the project
_c_o_n_f_i_g file may be changed from the default

     test_command =
       "$shell $file_name";

to pass the architecture name to the test

     test_command =
       "$shell $file_name $arch";

This will make the architecture name available as $1 within
the shell script.  Tests should fail elegantly when the
architecture name is not given, or should assume a sensible
default.







Page 168         (lib/en/user-guide/c6.1.so)    Peter Miller





Aegis                                             User Guide


1100..66..66..  CCrroossss CCoommppiilliinngg

If you are cross compiling to a number of different target
architectures, you would not use aegis' heterogeneous devel-
opment support, since it depends on the _u_n_a_m_e(2) system
call, which would tell it nothing useful when cross compil-
ing.  In this case, simply write the DMT configuration file
to cross compile to all architectures in every build.

1100..66..77..  FFiillee VVeerrssiioonn bbyy AArrcchhiitteeccttuurree

There is no intention of ever providing the facility where a
project source file may have different versions depending on
the architecture, but all of these versions overload the
same file name25.

The same effect may be achieved by naming files by architec-
ture, and using the DMT to compile and link those files in
the appropriate architecture.

This has the advantage of making it clear that several vari-
ations of a file exist, one for each architecture, rather
than hiding several related but independent source files
behind the one file name.

1100..77..  RReemmiinnddeerrss

This section documents some scripts available for reminding
users of changes which require their attention.  These
scripts are installed into the _/_u_s_r_/_l_o_c_a_l_/_s_h_a_r_e_/_a_e_g_i_s_/_r_e_m_i_n_d
directory, and may be run by _c_r_o_n(8) at appropriate inter-
vals.  You will almost certainly want to customize them for
your site.

1100..77..11..  AAwwaaiittiinngg DDeevveellooppmmeenntt

The _/_u_s_r_/_l_o_c_a_l_/_s_h_a_r_e_/_a_e_g_i_s_/_r_e_m_i_n_d_/_a_w_t___d_v_l_p_._s_h script takes a
project name as argument.  It is placed in the project
leader's per-user crontab.  It is suggested that this script
be run weekly, at 8AM on Monday.  This script will send all
developers of the named project email if there are any
changes in the _a_w_a_i_t_i_n_g _d_e_v_e_l_o_p_m_e_n_t state in the named
project.  No mail is sent if there are no changes outstand-
ing.

1100..77..22..  BBeeiinngg DDeevveellooppeedd

The _/_u_s_r_/_l_o_c_a_l_/_s_h_a_r_e_/_a_e_g_i_s_/_r_e_m_i_n_d_/_b_n_g___d_v_l_p_d_._s_h script takes
no arguments.  It is placed in each user's per-user crontab.
It is suggested that this script be run weekly, at 8AM on
Monday.  This script takes no arguments, and sends email to
-----------
  25 Some other SCM  tools  provide  a  repository
with this facility.



Peter Miller     (lib/en/user-guide/c6.3.so)        Page 169





User Guide                                             Aegis


the user if they have any changes in the _b_e_i_n_g _d_e_v_e_l_o_p_e_d or
_b_e_i_n_g _i_n_t_e_g_r_a_t_e_d states.  No mail is sent if there are no
changes outstanding.

1100..77..33..  BBeeiinngg RReevviieewweedd

The _/_u_s_r_/_l_o_c_a_l_/_s_h_a_r_e_/_a_e_g_i_s_/_r_e_m_i_n_d_/_b_n_g___r_v_w_d_._s_h script takes a
project name as argument.  It is placed in the project
leader's per-user crontab.  It is suggested that this script
be run daily at 8AM.  This script will send all reviewers of
the named project email if there are any changes in the
_b_e_i_n_g _r_e_v_i_e_w_e_d state in the named project.  No mail is sent
if there are no changes outstanding.

1100..77..44..  AAwwaaiittiinngg IInntteeggrraattiioonn

The _/_u_s_r_/_l_o_c_a_l_/_s_h_a_r_e_/_a_e_g_i_s_/_r_e_m_i_n_d_/_a_w_t___i_n_t_g_r_t_n_._s_h script
takes a project name as argument.  It is placed in the
project leader's per-user crontab.  It is suggested that
this script be run daily at 8AM.  This script will send all
integrators of the named project email if there are any
changes in the _a_w_a_i_t_i_n_g _i_n_t_e_g_r_a_t_i_o_n state in the named
project.  No mail is sent if there are no changes outstand-
ing.

































Page 170        (lib/en/user-guide/c10.0.so)    Peter Miller





Aegis                                             User Guide


1111..  GGeeooggrraapphhiiccaallllyy DDiissttrriibbuutteedd DDeevveellooppmmeenntt

This chapter describes various methods of collaboratively
developing software using Aegis, where the collaborating
sites are separated by administrative domains or even large
physical distances.

While many Open Source projects on the Internet typify such
development, this chapter will also describe techniques
suitable for commercial enterprises who do not wish to com-
promise their intellectual property.

1111..11..  IInnttrroodduuccttiioonn

The core of the distribution method is the _a_e_d_i_s_t(1) com-
mand.  In its simplest form, the command

     aedist -send | aedist -receive

will clone a change set locally.  This may appear less than
useful (after all, the _a_e_c_l_o_n_e(1) command already exists)
until you consider situations such as

     aedist -send | _e_-_m_a_i_l | aedist -receive

where _e_-_m_a_i_l represents the sending, transport and receiving
of e-mail.  In this example, the change set would be repro-
duced on the e-mail recipient's system, rather than locally.
Similar mechanisms are also possible for web distribution.

1111..11..11..  RRiisskk RReedduuccttiioonn

Receiving change sets in the mail, however, comes with a
number of risks:

+o  You can't just commit it to your repository, because it
   may not even compile.

+o  Even if it does compile, you want to run some tests on it
   first, to make sure it is working and doesn't break any-
   thing.

+o  Finally, you would always check it out, to make sure it
   was appropriate, and didn't do more subtle damage to the
   source.

While these are normal concerns for distributing source over
the Internet, and also internally within companies, they are
the heart of the process employed by Aegis.  All of these
checks and balances are already present.  The receive side
simply creates a normal Aegis change, and applies the normal
Aegis process to it.





Peter Miller    (lib/en/user-guide/c10.0.so)        Page 171





User Guide                                             Aegis


+o  The change set format is unpacked into a private work
   area, not directly into the repository.  This is a normal
   Aegis function.

+o  The change set is then confirmed to build against the
   repository.  All implications flowing from the change are
   exercised.  Build inconsistencies will flag the change
   for attention by a human, and the change set will not be
   committed to the repository.  This is a normal Aegis
   function.

+o  The change set is tested.  If it came accompanied by
   tests, these are run.  Also, relevant tests  from the
   repository are run.  Test inconsistencies will flag the
   change for attention by a human, and the change set will
   not be committed to the repository.  This is a normal
   Aegis function.

+o  Once the change set satisfies these requirements, it must
   still be reviewed by a human before being committed, to
   validate the change set for suitability and completeness.
   This is a normal Aegis function.

1111..11..22..  WWhhaatt ttoo SSeenndd

While there are many risks involved in receiving change
sets, there also problems in figuring out what to send.

At the core of Aegis' design is a transaction.  Think of the
source files as rows in a database table, and each change-
set as a transaction against that table.  The build step
represents maintaining referential integrity of the data-
base, but also represents an input validation step, as does
the review.  And like databases, the transactions are all-
or-nothing affairs, it is not possible to commit ``half'' a
transaction.

As you can see, Aegis changes are already elegantly vali-
dated, recorded and tracked, and ideally suited to being
packaged and sent to remote repositories.

1111..11..33..  MMeetthhooddss aanndd TTooppoollooggiieess

In distributed systems such as described in this chapter,
there are two clear methods of distribution:

+o The ``push'' method has the change set producer automati-
  cally send the change-set to a registered list of inter-
  ested consumers.  This is supported by Aegis and _a_e_d_i_s_t.

+o The ``pull'' method has the change set producer make the
  change sets available for interested consumers to come and
  collect.  This is supported by Aegis and _a_e_d_i_s_t.




Page 172        (lib/en/user-guide/c10.0.so)    Peter Miller





Aegis                                             User Guide


These are two ends of a continuum, and it is possible and
common for a mix-and-match approach to be taken.

There are also many ways of arranging how distribution is
accomplished, and many of the distribution arrangements
(commonly called topologies, when you draw the graphs) are
supported by Aegis and _a_e_d_i_s_t:

+o The star topology has a central master repository, sur-
  rounded by contributing satellite repositories.  The
  satellites are almost always ``push'' model, however the
  central master could be either ``push'' or ``pull'' model.

+o The snowflake topology is like a hierarchical star topol-
  ogy, with contributors feeding staging posts, which even-
  tually feed the master repository.  Common for large Open
  Source Internet projects.  Towards the master repository
  is almost always ``push'' model, and away from the master
  is almost always ``pull'' model.

+o The network topology is your basic anarchic autonomous
  collective, with change sets flying about peer-to-peer
  with no particular structure.  Often done as a ``push''
  model through an e-mail mailing list.

All of these topologies, and any mixture you can dream up,
are supported by Aegis and _a_e_d_i_s_t.  The choice of the right
topology depends on your project and your team.

1111..11..44..  TThhee RReesstt ooff tthhiiss CChhaapptteerr

Aegis is the ideal medium for hosting distributed projects,
for all the above reasons, and the rest of this chapter
describes a number of different ways of doing this:

[] The second section will describe how to perform these
   actions manually, both send and receive, as this demon-
   strates the method efficiently, and represents a majority
   of the use made of the mechanism.

[] The third section will show how to automate e-mail dis-
   tribution and receipt.  Automated e-mail distribution is
   probably the next most common use.

[] The fourth section will show how to configure distribu-
   tion and receipt using World Wide Web servers and
   browsers.

[] The fifth section deals with security issues, such as
   validating messages and coping with duplicate storms.







Peter Miller    (lib/en/user-guide/c10.1.so)        Page 173





User Guide                                             Aegis


1111..22..  MMaannuuaall OOppeerraattiioonn

This section describes how to use _a_e_d_i_s_t manually, in order
to send and receive change sets.

1111..22..11..  MMaannuuaall SSeenndd

In order to send a change set to another site, it must be
packaged in a form which captures all of the change's
attributes and the contents of the change's files.  This
package must be compressed and encoded in a form which will
survive the various mail transport agents it must pass
through, and then given to the local mail transport agent.
This is done by a single command

     %% aedist -send -c _n_u_m_b_e_r | \
       mail joe.blow@example.com
     %%


All of the usual Aegis command line options are available,
so you could specify the project on the command line if you
needed to.

This command will send the sources from the development
directory, if the change is not yet completed.  This is use-
ful for collaboration between developers, but it isn't
reviewed and integrated, so beware.

It is more usual to send a change which has been completed.
In this case the version of the file which was committed is
sent.  If necessary, the history files will be consulted to
reconstruct this information.  See the ``_A_u_t_o_m_a_t_i_c _S_e_n_d''
section, below, for more discussion of this.

There are many options for customizing the e-mail message
sent to joe.blow@example.com, see _a_e_d_i_s_t(1) for more infor-
mation.

1111..22..22..  SSeennddiinngg BBaasseelliinneess

In order to send the entire contents of the repository to
someone, you use a very similar command:

     %% aedist -send -baseline | \
       mail joe.blow@example.com
     %%


This can be a very large change set, because it is all files
of the project.






Page 174        (lib/en/user-guide/c10.1.so)    Peter Miller





Aegis                                             User Guide


1111..22..33..  SSeennddiinngg BBrraanncchheess

There are times when remote developers are not interested in
a blow-by-blow update of your repository.  Instead they want
to have updates from time to time.  In order to send them
the current state of your active development branch, in this
example ``_e_x_a_m_p_l_e_._4_._2'', you would use a command of the form

     %% aedist -send -p example.4 -c 2 | \
       mail joe.blow@example.com
     %%

Notice how the correspondence between branches and change
sets is exploited.  The baseline of a branch is the develop-
ment directory of the ``super change'' is represents.

Branch change sets like this are smaller than whole base-
lines, because they include only the files altered by this
branch, rather then the state of every file in the project.

1111..22..44..  MMaannuuaall RReecceeiivvee

The simplest form of receiving a change set is to save it
from your e-mail program into a file, and then

     %% aedist -receive -file _f_i_l_e_n_a_m_e
     _._._._l_o_t_s _o_f _i_n_f_o_r_m_a_t_i_o_n_._._.
     %%

where _f_i_l_e_n_a_m_e is where you saved the e-mail message.  If
your e-mail program is able to write to a pipe, you can use
a simpler form.  This example uses the Rand Mail Handler's
_s_h_o_w(1) command:

     %% show | aedist -receive
     _._._._l_o_t_s _o_f _i_n_f_o_r_m_a_t_i_o_n_._._.
     %%


Each of these examples assumes that you have used the same
project name locally as that of the sender (it's stored in
the package).  If this isn't the case, you will need to use
the -project option to tell _a_e_d_i_s_t which project to apply
the change to.

The actions performed by _a_e_d_i_s_t on receive are not quite a
mirror of what it does on send.  In particular, send usually
extracts its information from the repository, but receive
ddooeess nnoott put the change set directly into the repository.

On receipt of a change set, _a_e_d_i_s_t creates a new change with
its own development directory, and unpacks the change set
into it, in much the same way as a change would normally be
performed by a developer.  (Indeed, the receiver must be an



Peter Miller    (lib/en/user-guide/c10.1.so)        Page 175





User Guide                                             Aegis


authorized developer.)

Once the change is unpacked, it goes through the usual
development cycle of build, difference and test.  If any
portion of this fails, _a_e_d_i_s_t will stop with a suitable
error message.  If all goes well, development of the change
will end, and it will be left in the _b_e_i_n_g _r_e_v_i_e_w_e_d state.

At this point, a local reviewer must examine the change, and
it proceeds through the change integration process as nor-
mal.

If there is a problem with the change, it can be dealt with
as you would with any other defective change - by developing
it some more.  Or you can email the sender telling them the
problem and use _a_e_d_b_u(1) and _a_e_n_c_u(1) to entirely discard
the change.

1111..22..55..  GGeettttiinngg SSttaarrtteedd

In order to receive a change, you must have a project to
receive it into.  Also, changes tend to be the _d_i_f_f_e_r_e_n_c_e
between an existing repository and what it is to become.
You need some way to get the starting point of the differ-
ences before you can apply any differences.  This section
describes one way of doing this.

You start by creating a normal Aegis project in the usual
way.  That is covered earlier in this User Guide.  It helps
greatly if you give your local project exactly the same name
as the remote project.  It doesn't need the same pathname
for the project directory, just the same project name.

Once you have this project created, request the remote
repository send you a ``baseline'' change, as described
above.  Once you have received this, and it is integrated
successfully, you are ready to receive and apply change
sets.  This is an inherently ``pull'' activity, as the
source may never have heard of you before.  The initial
baseline may arrive by e-mail, or floppy disk, or you may
retrieve it from the web, it all depends how the project is
being managed.

You will be warned about "potential trojan horse" files in
the baseline change set.  This is normal, because you are
receiving all project configurations file, build files and
test files.  All of these contain executable commands _t_h_a_t
_w_i_l_l _b_e _e_x_e_c_u_t_e_d.  Caveat emptor.  Make sure you trust the
source.

1111..33..  SSnneeaakkeerr NNeett

Another common method of transporting data, sometimes a
quite large amount of it, is to write it onto transportable



Page 176        (lib/en/user-guide/c10.1.so)    Peter Miller





Aegis                                             User Guide


media and carry it.

To write a change set onto a floppy, you would use commands
such as

     %% mount /mnt/floppy
     %% aedist -send -no-base64 \
       -o /mnt/floppy/_c_h_a_n_g_e_._s_e_t
     %% umount /mnt/floppy
     %%

The above command assumes the floppy is pre-formatted, and
that there is a user-permitting line in the _/_e_t_c_/_f_s_t_a_b file,
as is common for many Linux distributions.  The _c_h_a_n_g_e_._s_e_t
can be any filename you like, but is usually project-name
and change-number related.

It takes a very sizable change set to fail to fit on a
1.44MB floppy, because they are compressed (and change sets
exceeding 8MB of source are rare, even for huge projects).
The -no-base64 option is used to avoid the MIME base 64
encoding, which is necessary for e-mail, not not necessary
in this case.  The receive side will automatically figure
out there is no MIME base 64 encoding.

Reading the change set is just as simple, as it closely fol-
lows the other commands for receiving commands sets.

     %% mount /mnt/floppy
     %% aedist -rec -f /mnt/floppy/_c_h_a_n_g_e_._s_e_t
     _._._._l_o_t_s _o_f _o_u_t_p_u_t_._._.
     %% umount /mnt/floppy
     %%

This technique will work for any of the disks available
these days including floppies, Zip, Jaz, _e_t_c.

1111..44..  AAuuttoommaattiicc OOppeerraattiioonn

This section describes how to use _a_e_d_i_s_t to automatically
send change sets via e-mail.

1111..44..11..  SSeennddiinngg

Change sets can be sent automatically when a change passes
integration.  You do this by setting the _i_n_t_e_g_r_a_t_e___p_a_s_s___-
_n_o_t_i_f_y___c_o_m_m_a_n_d field of the project attributes.

In this example, the ``example'' project sends all integra-
tions to all the addresses on the example-developers mailing
list.  (The mailing list is maintained outside of Aegis,
_e_._g_. by Majordomo.)  The relevant attribute (edited by using
the _a_e_p_a(1) command) looks like this:




Peter Miller    (lib/en/user-guide/c10.2.so)        Page 177





User Guide                                             Aegis


     integrate_pass_notify_command =
       "aedist -p $project -c $change | \
       mail example-users";


Please note that project attributes are inherited by
branches when they are created.  If you don't want all
branches to broadcast all changes, you need to remember to
clear this project attribute _f_r_o_m _t_h_e _b_r_a_n_c_h once the branch
has been created.  Alternatively, use the $version substitu-
tion to decide who to send the change to.

1111..44..22..  RReecceeiivviinngg

_w_r_i_t_e _t_h_i_s _s_e_c_t_i_o_n

You need to set up an e-mail alias, with a wrapper around it
- you probably _d_o_n_'_t want "daemon" as a registered devel-
oper.

While _a_e_d_i_s_t(1) makes every attempt to spot potential trojan
attacks, you really, _r_e_a_l_l_y want PGP validation (or similar
industrial strength digital signatures) before you accept
this kind of input.

1111..55..  WWoorrlldd WWiiddee WWeebb

This section describes how to use _a_e_d_i_s_t to transport change
sets using the World Wide Web.  This requires configuration
of the web server to package and send the change sets, and
configuration of the browser to receive and unpack the
change sets.

1111..55..11..  SSeerrvveerr

_w_r_i_t_e _t_h_i_s _s_e_c_t_i_o_n

You have a CGI script which invokes _a_e_d_i_s_t(1).  There is no
need to encode base64 in this case, so use the appropriate
option.

1111..55..22..  BBrroowwsseerr

_w_r_i_t_e _t_h_i_s _s_e_c_t_i_o_n

You need to set the appropriate mailcap entry, so that
application/aegis-change-set is handled by _a_e_d_i_s_t _-_-_r_e_c_e_i_v_e.

1111..66..  SSeeccuurriittyy

This section deals with security issues.  Security isn't
just ``keep the bad guys out'', it actually covers _a_v_a_i_l_-
_a_b_i_l_i_t_y, _i_n_t_e_g_r_i_t_y and _c_o_n_f_i_d_e_n_t_i_a_l_i_t_y.




Page 178        (lib/en/user-guide/c10.4.so)    Peter Miller





Aegis                                             User Guide


Availability:
        refers to the system being available for use by
        authorised users.  Denial of service and crashes are
        examples of bad things in this area.

Integrity:
        refers to the system being in a known good state.
        Corrupted change sets and un-buildable repositories
        are examples of bad things in this area.

Confidentiality:
        refers to the system being available _o_n_l_y to autho-
        rised users.  For many Open Source projects, this
        isn't a large concern, but for corporate users of
        Aegis, non-disclosure of change-sets as they cross
        the Internet is a serious requirement.

As you can see, a strategy of ``keep the bad guys out'' is
necessary, but not sufficient, to satisfy security.

This section covers the above security issues, as applied to
the use of _a_e_d_i_s_t to move change sets around.

1111..66..11..  TTrroojjaann HHoorrsseess

``A Trojan horse is an apparently useful program containing
hidden functions that can exploit the privileges of the user
[running the program], with a resulting security threat.  A
Trojan horse does things that the program user did not
intend26.''

In order to forestall this threat, _a_e_d_i_s_t will cease devel-
opment of the change if it detects the potential for a Tro-
jan horse.  These include...

+o Changing the project _c_o_n_f_i_g file.  This file contains the
  build command and the difference commands, both of which
  would be run before a reviewer had a chance to confirm
  they were acceptable.

+o Changing any of the files named in the _t_r_o_j_a_n___h_o_r_s_e___s_u_s_-
  _p_e_c_t field of the project _c_o_n_f_i_g file.  This lets you
  cover things like the build tool's configuration file
  (_e_._g_. the Makefile or the cookbook), and any scripts or
  code generators which would be run by the build.

This isn't exhaustive protection, and it depends on keeping
the _t_r_o_j_a_n _h_o_r_s_e _s_u_s_p_e_c_t list up-to-date.  (It accepts pat-
terns, so it's not too onerous.)  For better protection, you
need to validate the sender and the message.

-----------
  26 Summers,  Rita  C.,  _S_e_c_u_r_e _C_o_m_p_u_t_i_n_g _T_h_r_e_a_t_s
_a_n_d _S_a_f_e_g_u_a_r_d_s, McGraw-Hill, 1997.



Peter Miller    (lib/en/user-guide/c10.4.so)        Page 179





User Guide                                             Aegis


1111..66..22..  PPGGPP

PGP can be used to validate that the source of a change set
distribution is really someone you trust.

_a_n_y_o_n_e _w_a_n_t _t_o _a_d_v_i_s_e _m_e _w_h_a_t _t_o _p_u_t _h_e_r_e_?

1111..66..33..  SSoorrcceerreerr''ss AApppprreennttiiccee

In a push system, with a central master server and a collec-
tion of contributors, all of which are using automatic send,
as described above, a potential explosion of redundant mes-
sages is possible.  Viz:

+o Contributor integrates a change, which is dispatched to
  the master server.

+o Maintainer integrates the change set into the master
  repository.

+o Master repository automatically dispatches the change set
  to all of the contributors.

+o Each of the contributors receives and integrates the
  change, each of which are dispatched to the master server.

+o The master server is inundated with change sets it already
  has.

+o If these change sets were to be integrated, the storm
  repeats, growing exponentially every time it goes around
  the loop.

To prevent this, _a_e_d_i_s_t does several things...

+o Before the change is built, an _a_e_c_p_u _-_-_u_n_c_h_a_n_g_e_d is run.
  If there is nothing left, the change is abandoned, because
  you already have it.  (This doesn't always work, because
  propagation delays may try to _r_e_v_e_r_s_e a subsequent local
  change.)

+o When a change set is sent, an RFC 822 style header is
  added to the description.  This includes From and Date.
  When a change set is received, a Received line is added.
  Too many Received lines causes the change set to be
  dropped - for a star topology the maximum is 2.  (This
  doesn't always work, because the description could be
  edited to rip it off again.)  (This doesn't always work,
  because the maintainer may edit it in some ways before
  comitting it, and forget to rip off (enough of) the
  header.)  (This doesn't always work, because hierarchical
  topologies will group change sets together.)  (This
  doesn't always work, because a baseline pull will group
  change sets together.)



Page 180        (lib/en/user-guide/c10.4.so)    Peter Miller





Aegis                                             User Guide


+o Set the description to indicate it was received by aedist?
  Use this to influence the decision to send it off again at
  integrate pass?  How?

1111..77..  PPaattcchheess

In the open source community, patches are common way of
sharing enhancements to software.  This was particularly
common before the World Wide Web, and usenet was the more
common medium of distribution.  Patches also have the advan-
tage of being fairly small and usually tansportable by email
with few problems.

1111..77..11..  SSeenndd

If you are participating in an open source project, and
using Aegis to manage your development, the _a_e_p_a_t_c_h _-_s_e_n_d
command may be used to construct a patch to send to the
other developers.

It is very similar in operation to the _a_e_d_i_s_t(1) command,
however it is intended for non-Aegis-using recipients.

To send a change to someone (a completed change, or one in
progress) simply use a command such as

     %% aepatch -send -c _n_u_m_b_e_r | \
       mail joe.blow@example.com
     %%

to send your change as a patch.  Note that it will be com-
pressed (using GNU Zip) and encoded (using MIME base 64),
which produces small files which are going to survive email
transport.

1111..77..22..  RReecceeiivvee

The simplest way of receiving a patch and turn it into a
change set is to save it from your e-mail program into a
file, and then

     %% aepatch -receive -file _f_i_l_e_n_a_m_e
     _._._._l_o_t_s _o_f _i_n_f_o_r_m_a_t_i_o_n_._._.
     %%

where _f_i_l_e_n_a_m_e is where you saved the e-mail message.  If
your e-mail program is able to write to a pipe, you can use
a simpler form.  This example uses the Rand Mail Handler's
_s_h_o_w(1) command:

     %% show | aepatch -receive
     _._._._l_o_t_s _o_f _i_n_f_o_r_m_a_t_i_o_n_._._.
     %%




Peter Miller    (lib/en/user-guide/c10.5.so)        Page 181





User Guide                                             Aegis


Each of these examples assumes that you have already set the
project name, either via _a_e_u_c_o_n_f(5) or _a_e___p(1), or you could
use the _-_p_r_o_j_e_c_t option.

The actions performed by _a_e_p_a_t_c_h on receive are not quite a
mirror of what it does on send.  In particular, send usually
extracts its information from the repository, but receive
ddooeess nnoott put the change set directly into the repository.

On receipt of a change set, _a_e_p_a_t_c_h creates a new change
with its own development directory, copies the files into
it, and applies the patch to the files.  The receiver must
be an authorized developer.

Once the patch is applied, it goes through the usual devel-
opment cycle of build, difference and test.  If any portion
of this fails, _a_e_p_a_t_c_h will stop with a suitable error mes-
sage.  If all goes well, development of the change will end,
and it will be left in the _b_e_i_n_g _r_e_v_i_e_w_e_d state.

At this point, a local reviewer must examine the change, and
it proceeds through the change integration process as nor-
mal.

If there is a problem with the change, it can be dealt with
as you would with any other defective change - by developing
it some more.  Or you can email the sender telling them the
problem and use _a_e_d_b_u(1) and _a_e_n_c_u(1) to entirely discard
the change.

1111..77..33..  LLiimmiittaattiioonnss

Despite a great similarity of command line operations and
operation, the _a_e_p_a_t_c_h command should nnoott be thought of as
an equivalent for the _a_e_d_i_s_t command, or a replacement for
it.

The information provided by _a_e_d_i_s_t _-_s_e_n_d is sufficiently
complete to recreate the change set at the remote end.  No
information is lost.  In contrast, the _a_e_p_a_t_c_h _-_s_e_n_d command
is limited to that information a patch file (see the
_p_a_t_c_h(1) command, from the GNU Diff utils).  There is no
guarantee that the _a_e_p_a_t_c_h _-_s_e_n_d output will be given to
_a_e_p_a_t_c_h _-_r_e_c_e_i_v_e; it must work with _p_a_t_c_h(1), and similar
tools.

Conversely, there is no guarantee that the input to _a_e_p_a_t_c_h
_-_r_e_c_e_i_v_e came from _a_e_p_a_t_c_h _-_s_e_n_d.  It can and must be able
to cope with the outout of a simple _d_i_f_f _-_r _-_N _-_c command,
with no additional information.

All this means, use _a_e_d_i_s_t wherever possible.  The _a_e_p_a_t_c_h
command is to simplify and streamline communication with
non-Aegis developers.



Page 182        (lib/en/user-guide/c12.0.so)    Peter Miller





Aegis                                             User Guide


1122..  FFuurrtthheerr RReeaaddiinngg

This chapter contains information about books, articles or
web sites relevant to some aspect of Aegis or using Aegis.
These references should not be taken as endorements.

If I've missed a good reference, it isn't personal, but I
can't and haven't read everything out there.  Email me the
information and I'll add it to this chapter (no advertising,
please).

1122..11..  SSooffttwwaarree CCoonnffiigguurraattiioonn MMaannaaggeemmeenntt

Eaton, D. (1995), Configuration Management Frequently Asked
Questions, http://www.daveeaton.com/scm/CMFAQ.html
     _T_h_i_s _i_s _a_n _e_s_s_e_n_t_i_a_l _f_i_r_s_t_-_s_t_o_p _f_o_r _i_n_f_o_r_m_a_t_i_o_n _a_b_o_u_t
     _S_o_f_t_w_a_r_e _C_o_n_f_i_g_u_r_a_t_i_o_n _M_a_n_a_g_e_m_e_n_t_.  _I_t _h_a_s _a_n _e_x_c_e_l_l_e_n_t
     _b_o_o_k _l_i_s_t_.

Pool, D., CM Today, http://www.cmtoday.com/
     _T_h_i_s _i_s _a _c_o_n_f_i_g_u_r_a_t_i_o_n _m_a_n_a_g_e_m_e_n_t _p_o_r_t_a_l _s_i_t_e_, _w_i_t_h
     _n_e_w_s _a_n_d _o_t_h_e_r _l_i_n_k_s_.

1122..22..  RReevviieewwiinngg

Baldwin, J. (1992), An Abbreviated C++ Code Inspection
Checklist, http://www2.ics.hawaii.edu/~johnson/FTR/Bib/Bald-
win92.html
     _T_h_i_s _w_e_b _p_a_g_e _t_a_l_k_s _a_b_o_u_t _C_+_+ _c_o_d_e _i_n_s_p_e_c_t_i_o_n_s _w_i_t_h
     _s_o_m_e _u_s_e_f_u_l _s_u_g_g_e_s_t_i_o_n_s _a_b_o_u_t _h_o_w _t_o _c_o_n_d_u_c_t _(_r_a_t_h_e_r
     _f_o_r_m_a_l_) _r_e_v_i_e_w_s _a_n_d _s_o_m_e _f_o_r _C_+_+ _c_o_n_s_t_r_u_c_t_s _t_o _w_a_t_c_h
     _o_u_t _f_o_r_.

























Peter Miller     (lib/en/user-guide/cA.0.so)        Page 183





User Guide                                             Aegis


1133..  AAppppeennddiixx AA:: NNeeww PPrroojjeecctt QQuuiicckk RReeffeerreennccee

For those of you too impatient to read a whole great big
document about how to use the aegis program, this appendix
gives a quick look at how to place a project under aegis.

The style here is an itemized list.  It does not try to be
exhaustive.  For exact details on how to use the various
aegis commands, you should see the manual pages, ditto for
the formats and contents of some files.

Probably the quickest start of all is to copy an already
existing project.  The project used in chapter 2 is com-
plete, assuming you use the author's "cook" dependency main-
tenance tool.  The entirety of this example may be found, if
slightly obfuscated, in the aegis source file
_t_e_s_t_/_0_0_/_t_0_0_1_1_a_._s_h distributed with aegis.

1133..11..  CCrreeaattee tthhee PPrroojjeecctt

The _a_e_n_p_r command is used to create a project.  You must
supply the name on the command line.  The name should be ten
characters or less, six characters or less if you want ver-
sion numbers included.

The user who creates the project is the owner of the
project, and is set as the administrator.  The default group
of the user who created the project is used as the project's
group.

You may want to have a user account which owns the project.
You must create the project as this user, and then use the
_a_e_n_a and _a_e_r_a commands to add an appropriate administrator,
and remove the owning user as an administrator.  After this,
the password for the owning user may be disabled, because
the aegis program will, at appropriate times, set file own-
ership to reflect project ownership or execute commands on
behalf of the project owner _a_s the project owner.

1133..11..11..  AAdddd tthhee SSttaaffff

The _a_e_n_d command is used to add developers.  The _a_e_n_r_v com-
mand is used to add reviewers.  The _a_e_n_i command is used to
add integrators.  These commands may only be performed by a
project administrator.

You will still have to do this, even if the person who cre-
ated the project will be among these people, or even be all
of these people.

1133..11..22..  PPrroojjeecctt AAttttrriibbuutteess

The _a_e_p_a command is used to change project attributes.
These attributes include the description of the project, and



Page 184         (lib/en/user-guide/cA.0.so)    Peter Miller





Aegis                                             User Guide


booleans controlling whether, for example, developers may
review their own work.

The project attributes file is described in the _a_e_p_a_t_t_r(5)
manual entry.

1133..22..  CCrreeaattee CChhaannggee OOnnee

The _a_e_n_c command is used to create a new change.  You will
need to construct a change attributes file with your
favorite text editor before running this command.

The change attributes file is described in the _a_e_c_a_t_t_r(5)
manual entry.

1133..33..  DDeevveelloopp CChhaannggee OOnnee

This is the most grueling step.  Indeed, the integration
step will probably reveal things you missed, and you may
return to the _b_e_i_n_g _d_e_v_e_l_o_p_e_d
 state several times.

One of the people you nominated as a developer will have to
use the _a_e_d_b command to commence development of the first
change.  The _a_e_c_d command can be used to change directory
into the just-created development directory.

Add files to the change.  The _a_e_n_f command is used to create
new files.  If you don't use _a_e_n_f then the aegis program has
no way of knowing whether that file lying there in the
development directory is significant to the project, or just
a shopping list of the groceries you forgot to buy yester-
day.

One particular new file which _m_u_s_t be created by this change
is the _c_o_n_f_i_g file.  This tells the aegis program what his-
tory mechanism you wish to use, what dependency maintenance
command to use, what file difference tools to use, and much
more.  The _a_e_p_c_o_n_f(5) manual entry describes this file.

If you are going to use the "cook" dependency maintenance
tool, another new file you will need to create in this
change is the "Howto.cook" file.  Some other tool will want
some other rules file.

You probably have a prototype or some other "seed" you have
sort-of working.  Create new files for each source file and
_t_h_e_n copy the files from wherever they are now into the
development directory.

Use the _a_e_b command to build the change.  It will need to
build cleanly before it can advance to the next step.





Peter Miller     (lib/en/user-guide/cA.0.so)        Page 185





User Guide                                             Aegis


Use the _a_e_d command to difference the change.  It will need
to difference cleanly before it can advance to the next
step.

Use the _a_e_n_t command to add new tests to the command.  It
will need to have tests before it can advance to the next
step.

Most existing projects don't have formal tests.  These tests
will form a regression test-bed, used to make sure that
future changes never compromise existing functionality.

Use the _a_e_t command to test the change.  It will need to
test cleanly before it can advance to the next step.

Once the change builds, differences and tests cleanly, use
the _a_e_d_e command to end development.

1133..44..  RReevviieeww TThhee CChhaannggee

One of the people nominated as reviewers will have to run
the _a_e_r_p_a_s_s command to say that the change passed review.

The aegis program does not mandate any particular review
mechanism: you could use a single peer to do the review, you
could use a panel, you could set the project so that devel-
opers may review their own work effectively eliminating the
review step.  In projects with as few as two people, it is
always beneficial for someone other than the developer to
review changes.  It is even beneficial for the developer
herself to review the next day.

Should a reviewer actually want to _s_e_e the change, the _a_e_c_d
command may be used to change directory to the development
directory of the change.  The difference files all end with
a "comma D" suffix, so the

     more `find . -name "*,D" -print | sort`

command may be used to search them out and see them.  This
is probably fairly useless for the first change, but is
vital for all subsequent changes.  There is a supplied alias
for this command, it is _a_e_d_m_o_r_e and there is a similar _a_e_d_-
_l_e_s_s alias if you prefer the _l_e_s_s(1) command.

There are some facts that a reviewer _k_n_o_w_s because otherwise
the change would not be in the "being reviewed" state: +o the
change compiles cleanly, +o the change passes all of its
tests.  Other information about the change may be obtained
using the "change_details" variation of the _a_e_l command.

The _a_e_r_f_a_i_l command may also be used by reviewers to fail
reviews and return a change to the developer for further
work; the reviewer must supply a reason for the change



Page 186         (lib/en/user-guide/cA.0.so)    Peter Miller





Aegis                                             User Guide


history to record for all time.  Similarly, the _a_e_d_e_u com-
mand may be used by the developer to resume development of a
change at any time before it is integrated; no stated reason
is required.

1133..55..  IInntteeggrraattee tthhee CChhaannggee

A person nominated as an project integrator then integrates
the change.  This involves making a copy of the integration
directory, applying the modifications described by the
change to this integration directory, then building and
testing all over again.

This re-build and re-test is to ensure that no special
aspect of the developers environment influenced the success
up to this point, such as a unique environment variable set-
ting.  The re-build also ensures that all of the files in
the baseline, remembering that this includes source files
and all other intermediate files required by the build
process, remain consistent with each other, that the base-
line is self-consistent.  The definition of the baseline is
that it passes its own tests, so the tests are run on the
baseline.

Use the _a_e_i_b command to begin integration.

The _a_e_b command is used to build the integration copy of the
change.

The _a_e_t command is used to test the integration copy of the
change.

On later changes, the integration may also require the _a_e_t
_-_b_l command to test the change against the baseline.  This
tests ensures that the test _f_a_i_l_s against the baseline.
This failure is to ensure that bug fixes are accompanied by
tests which reproduce the bug initially, and that the change
has fixed it.  New functionality, naturally, will not be
present in the old baseline, and so tests of new functional-
ity will also fail against the old baseline.

Later changes may also have the regression tests run, using
the _a_e_t _-_r_e_g command.  This can be a very time-consuming
step for projects with a long history, and thus a large col-
lection of tests.  The _a_e_t _-_s_u_g_g_e_s_t command can also be used
to run "representative" sets of existing tests, but a full
regression test run is recommended before a major release,
or, say, weekly if it will complete over the weekend.  This
command is also available to developers, so that they have
fewer surprises from irate integrators.

The integrator may use the _a_e_i_f_a_i_l command to return a
change to its developer for further work; a reason must be
supplied, and should include relevant excerpts from the



Peter Miller     (lib/en/user-guide/cA.0.so)        Page 187





User Guide                                             Aegis


build log in the case of a build failure (not the _w_h_o_l_e
log!), or a list of the tests which failed for test fail-
ures.

The _a_e_i_p_a_s_s command may be used to pass an integration.
When the change passes, the file histories are updated.  In
the case of the first change, the history is created, and
problems with the _c_o_n_f_i_g file's history commands will be
revealed at this point.  The integration won't pass, and
should be failed, so that the developer may effect repairs.
There are rarely problems at this point for subsequent
changes, except for disk space problems.

Once the history is successfully updated, aegis renames the
integration directory  as the baseline, and throws the old
baseline away.  The development directory is deleted at this
time, too.

1133..66..  WWhhaatt ttoo ddoo NNeexxtt

There, the first change is completed.  The whole cycle may
now be repeated, starting at "Create Change," for all subse-
quent changes, with very few differences.

It is recommended that you read the _C_h_a_n_g_e _D_e_v_e_l_o_p_m_e_n_t _C_y_c_l_e
 chapter for a full worked example of the first four changes
of an example project, including some of the twists which
occur in real-world use of aegis.

Remember, too, the definition:

     aaeeggiiss (ee.j.iz) _n_. a protection, a defence.

It is not always the case that aegis exists to make life
"easier" for the software engineers.  The goal is to have a
baseline which always "works", where "works" is defined as
passing all of its own tests.  Wherever possible, the aegis
program attempts to be as helpful and as unintrusive as pos-
sible, but when the "working" definition is threatened, the
aegis program intrudes as necessary.  (Example: you can't do
an integrate pass without the integration copy building suc-
cessfully.)

All of the "extra work" of writing tests is a long-term win,
where old problems never again reappear.  All of the "extra
work" of reviewing changes means that another pair of eyes
sees the code and finds potential problems before they mani-
fest themselves in shipped product.  All of the "extra work"
of integration ensures that the baseline always works, and
is always self-consistent.  All of the "extra work" of hav-
ing a baseline and separate development directories allows
multiple parallel development, with no inter-developer
interference; and the baseline always works, it is never in
an "in-between" state.  In each case, not doing this "extra



Page 188         (lib/en/user-guide/cA.0.so)    Peter Miller





Aegis                                             User Guide


work" is a false economy.
























































Peter Miller     (lib/en/user-guide/cB.0.so)        Page 189





User Guide                                             Aegis


1144..  AAppppeennddiixx BB:: GGlloossssaarryy

The following is an alphabetical list of terms used in this
document.

administrator
     Person responsible for administering a _p_r_o_j_e_c_t.

awaiting_development
     The state a change is in immediately after creation.

awaiting_integration
     The state a change is in after it has passed review and
     before it is integrated.

awaiting review
     An optional state a change is in after it is developed,
     but before someone has chosen to review it..

baseline
     The repository; where the project master source is
     kept.

being developed
     The state a change is in when it is being worked on.

being integrated
     The state a change is in when it is being integrated
     with the baseline.

being reviewed
     The state a change is in after it is developed.

change
     A collection of files to be applied as a single atomic
     alteration of the baseline.

change number
     Each _c_h_a_n_g_e has a unique number identifying it.

completed
     The state a change is in after it has been integrated
     with the baseline.

delta number
     Each time the _a_e_i_b(1) command is used to start inte-
     grating a _c_h_a_n_g_e into the _b_a_s_e_l_i_n_e a unique number is
     assigned.  This number is the delta number.  This
     allows ascending version numbers to be generated for
     the baseline, independent of change numbers, which are
     inevitably integrated in a different order to their
     creation.





Page 190         (lib/en/user-guide/cB.0.so)    Peter Miller





Aegis                                             User Guide


dependency maintenance tool
     A program or programs external to aegis which may be
     given a set of rules for how to efficiently take a set
     of source files and process them to produce the final
     product.

DMT
     Abbreviation of Dependency Maintenance Tool.

develop_begin
     The command issued to take a change from the _a_w_a_i_t_i_n_g
     _d_e_v_e_l_o_p_m_e_n_t state to the _b_e_i_n_g _d_e_v_e_l_o_p_e_d state.  The
     change will be assigned to the user who executed the
     command.

develop_begin_undo
     The command issued to take a change from the _b_e_i_n_g
     _d_e_v_e_l_o_p_e_d state to the _a_w_a_i_t_i_n_g _d_e_v_e_l_o_p_m_e_n_t state.  Any
     files associated with the change will be removed from
     the development directory and their changes lost.

develop_end
     The command issued to take a change from the _b_e_i_n_g
     _d_e_v_e_l_o_p_e_d state to the _b_e_i_n_g _r_e_v_i_e_w_e_d state, or option-
     ally to the _a_w_a_i_t_i_n_g _r_e_v_i_e_w_e_d state.  The change must
     be known to build and test successfully.

develop_end_undo
     The command issued to take a change from the _b_e_i_n_g
     _r_e_v_i_e_w_e_d state back to the _b_e_i_n_g _d_e_v_e_l_o_p_e_d state.  The
     command must be executed by the original developer.

developer
     A member of staff allowed to develop changes.

development directory
     Each change is given a unique development directory in
     which to edit files and build and test.

history tool
     A program to save and restore previous versions of a
     file, usually by storing edits between the versions for
     efficiency.

integrate_pass
     The command used to take a change from the _b_e_i_n_g _i_n_t_e_-
     _g_r_a_t_e_d state to the _c_o_m_p_l_e_t_e_d state.  The change must
     be known to build and test successfully.

integrate_begin
     The command used to take a change from the _a_w_a_i_t_i_n_g
     _i_n_t_e_g_r_a_t_i_o_n state to the _b_e_i_n_g _i_n_t_e_g_r_a_t_e_d state.





Peter Miller     (lib/en/user-guide/cB.0.so)        Page 191





User Guide                                             Aegis


integrate_begin_undo
     The command used to take a change from the _b_e_i_n_g _i_n_t_e_-
     _g_r_a_t_e_d state to the _a_w_a_i_t_i_n_g _i_n_t_e_g_r_a_t_i_o_n state.

integrate_fail
     The command used to take a change from the _b_e_i_n_g _i_n_t_e_-
     _g_r_a_t_e_d state back to the _b_e_i_n_g _d_e_v_e_l_o_p_e_d state.

integration
     The process of merging the _b_a_s_e_l_i_n_e with the _d_e_v_e_l_o_p_-
     _m_e_n_t _d_i_r_e_c_t_o_r_y to form a new baseline.  This includes
     building and testing the merged directory, before
     replacing the original _b_a_s_e_l_i_n_e with the new merged
     version.

integration directory
     The directory used during _i_n_t_e_g_r_a_t_i_o_n to merge the
     existing _b_a_s_e_l_i_n_e with a change's _d_e_v_e_l_o_p_m_e_n_t _d_i_r_e_c_-
     _t_o_r_y.

integrator
     A staff member who performs _i_n_t_e_g_r_a_t_i_o_n_s_.

new_change
     The command used to create new changes.

new_change_undo
     The command used to destroy changes.

review_begin
     The command used to take a change from the _a_w_a_i_t_i_n_g
     _r_e_v_i_e_w state to the _b_e_i_n_g _r_e_v_i_e_w_e_d state.

review_fail
     The command used to take a change from the _b_e_i_n_g
     _r_e_v_i_e_w_e_d state back to the _b_e_i_n_g _d_e_v_e_l_o_p_e_d state.

review_pass
     The command used to take a change from the _b_e_i_n_g
     _r_e_v_i_e_w_e_d state to the _a_w_a_i_t_i_n_g _i_n_t_e_g_r_a_t_i_o_n state.

reviewer
     A person who may review _c_h_a_n_g_e_s and either pass or fail
     them (_r_e_v_i_e_w___p_a_s_s or _r_e_v_i_e_w___f_a_i_l respectively).

state
     Each _c_h_a_n_g_e is in one of seven states: _a_w_a_i_t_i_n_g _d_e_v_e_l_-
     _o_p_m_e_n_t, _b_e_i_n_g _d_e_v_e_l_o_p_e_d, _a_w_a_i_t_i_n_g _r_e_v_i_e_w, _b_e_i_n_g
     _r_e_v_i_e_w_e_d, _a_w_a_i_t_i_n_g _i_n_t_e_g_r_a_t_i_o_n, _b_e_i_n_g _i_n_t_e_g_r_a_t_e_d or
     _c_o_m_p_l_e_t_e_d.

state transition
     The event resulting in a _c_h_a_n_g_e changing from one state
     to another.



Page 192         (lib/en/user-guide/cD.0.so)    Peter Miller





Aegis                                             User Guide


1155..  AAppppeennddiixx DD:: WWhhyy iiss AAeeggiiss SSeett--UUiidd--RRoooott??

The goal for aegis is to have a project that "works".  There
is a fairly long discussion about this earlier in this User
Guide.  One of the first things that must be done to ensure
that a project is not subject to mystery break downs, is to
make sure that the master source of the project cannot be in
any way altered in an unauthorized fashion.  Note this says
"cannot", a stronger statement than "should not".

Aegis is more complicated than, say, set-group-id RCS,
because of the flaw with set-group-id: the baseline is
writable by the entire development team, so if a developer
says "this development process stinks" he can always bypass
it, and write the baseline directly.  This is a _v_e_r_y common
source of project disasters.  To prevent this, you must have
the baseline read-only, and so the set-group-id trick does
not work.  (The idea here is that there is _n_o way to bypass
the QA portions of the process.  Sure, set-group-id will
prevent accidental edits on the baseline, if the developers
are not members of the group, but it does not prevent _d_e_l_i_b_-
_e_r_a_t_e checkin of unauthorized code.  Again, the emphasis is
on "cannot" rather than "should not".)

Also, using the set-group-id trick, you need multiple copies
of RCS, one for each project.  Aegis can handle many
projects, each with a different owner and group, with a sin-
gle set-uid-root executable.

Aegis has no internal model of security, it uses UNIX secu-
rity, and so becomes each user in turn, so UNIX can deter-
mine the permissions.

1155..11..  EExxaammpplleess

Here are a few examples of the uid changes in common aegis
functions.  Unix "permission denied" errors are not shown,
but it should be clear where they would occur.

new change (aenc):
     become invoking user and read (edit) the change
     attribute file, validate the attribute file, then
     become the project owner to write the change state file
     and the project state file.

develop begin (aedb):
     become the project owner and read the project state
     file and the change state file, to see if the change
     exists and is available for development, and if the
     invoking user is on the developer access control list.
     Become the invoking user, but set the default group to
     the project group, and make a development directory.
     Become the project owner again, and update the change
     state file to say who is developing it and where.



Peter Miller     (lib/en/user-guide/cD.0.so)        Page 193





User Guide                                             Aegis


build (aeb):
     become the project owner to read the project and change
     state files, check that the invoking user is the devel-
     oper of the change, and that the change is in the _b_e_i_n_g
     _d_e_v_e_l_o_p_e_d state.  Become the invoking user, but set the
     default group to the project group, to invoke the build
     command.  Become the project owner to update the change
     state to remember the build result (the exit status).

copy file into change (aecp):
     become the project owner to read the project and change
     state files.  Check that the invoking user is the
     developer and that the change is in the _b_e_i_n_g _d_e_v_e_l_o_p_e_d
     state, and that the file is not already in the change,
     and that the file exists in the baseline.  Become the
     invoking user, but set the default group to the project
     group, and copy the file from the baseline into the
     development directory.  Become the project owner, and
     update the change state file to remember that the file
     is included in the change.

integrate fail (aeifail):
     become the project owner to read the project and change
     state files.  Check that in invoking user is the inte-
     grator of the change, and that the change is in the
     _b_e_i_n_g _i_n_t_e_g_r_a_t_e_d state.  Become the integrator to col-
     lect the integrate fail comments, then become the
     project owner to delete the integration directory, then
     become the developer to make the development directory
     writable again.  Then become the project owner to write
     the change state file, to remember that the change is
     back in the _b_e_i_n_g _d_e_v_e_l_o_p_e_d state.

integrate pass (aeipass):
     become the project owner to read the project and change
     state files.  Check that in invoking user is the inte-
     grator of the change, and that the change is in the
     _b_e_i_n_g _i_n_t_e_g_r_a_t_e_d state.  Make the integration directory
     the new baseline directory and remove the old baseline
     directory.  Write the change and project states to
     reflect the new baseline and the change is in the _c_o_m_-
     _p_l_e_t_e_d state.  Then become the developer to remove the
     development directory.

All the mucking about with default groups is to ensure that
the reviewers, other members of the same group, have access
to the files when it comes time to review the change.  The
umask is also set (not shown) so that the desired level of
"other" access is enforced.

As can be seen, each of the uid change either (a) allows
UNIX to enforce appropriate security, or (b) uses UNIX secu-
rity to ensure that unauthorized tampering of project files
cannot occur.  Each project has an owner and a group:



Page 194         (lib/en/user-guide/cD.0.so)    Peter Miller





Aegis                                             User Guide


members of the development team obtain read-only access to
the project files by membership to the appropriate group, to
actually alter project files requires that the development
procedure embodied by aegis is carried out.  You could have
a single account (not a user's account, usually, for obvious
conflicts of interest) which owns all project sources, or
you could have one account per project.  You can have one
group per project, if you don't want your various projects
to be able to see each other's work, or you could have a
single group for all projects.

1155..22..  SSoouurrccee DDeettaaiillss

For implementation details, see the os_become* functions in
the _a_e_g_i_s_/_o_s_._c file.  The os_become_init function is called
very early in main, in the _a_e_g_i_s_/_m_a_i_n_._c file.  After that,
all accesses are bracketed by os_become and os_become_undo
function calls, sometimes indirectly as project_become* or
user_become*, etc, functions.  You need to actually become
each user, because root is not root over NFS, and thus chown
tricks do not work, and also because duplicating kernel per-
mission checking in aegis is a little non-portable.

Note, also, that most system calls go via the interface
described in the _a_e_g_i_s_/_g_l_u_e_._h file.  This isolates the sys-
tem calls for UNIX variants which do not have the seteuid
function, or do not have a correctly working one.  The code
in the _a_e_g_i_s_/_g_l_u_e_._c file spawns "proxy" process which uses
the setuid function to become the user and stay that way.
If the seteuid function is available, it is used instead,
making aegis more efficient.  This isolation, however, makes
it possible for a system administrator to audit the aegis
code (for trojans) with some degree of confidence.  System
calls should be confined to the _a_e_g_i_s_/_l_o_g_._c, _a_e_g_i_s_/_p_a_g_e_r_._c,
_a_e_g_i_s_/_o_s_._c and _a_e_g_i_s_/_g_l_u_e_._c files.  System calls anywhere
else are probably a Bad Thing.





















Peter Miller     (lib/en/user-guide/cI.0.so)        Page 195





User Guide                                             Aegis


1166..  AAppppeennddiixx II:: IInntteerrnnaattiioonnaalliizzaattiioonn aanndd LLooccaalliizzaattiioonn

The Aegis source code has been internationalized, which is
the process of modifying the original source code to permit
error messages and other text to be presented in a language
other than the author's native English.  This was a large
and often painful task, but it allows a degree of customiza-
tion of error messages and other behaviours which would not
have been otherwise possible.  (It also makes the job of
running a spell-checker over the error messages signifi-
cantly easier.)

Localization is the process of translating the error mes-
sages and other text into various different languages or
nationalities.  This appendix is primarily aimed at localiz-
ers of Aegis.

1166..11..  TThhee ````..ppoo'''' FFiilleess

The ``lib/en/LC_MESSAGES'' directory in the source tree con-
tains the various message files needed to localize Aegis.
You will find a number of ``.po'' files in this directory,
which translates ``programmer cryptic'' into English.  You
will see that each message has a comment attached, describ-
ing the message and the context in which it is used.  Many
messages also have ``substitutions'' described, which are
strings similar to shell variables which may be substituted
into the message - such as the file name for messages which
have something to do with a specific file.

The substitution mechanism is the same one as is used for
the various commands in the project _c_o_n_f_i_g file, and so all
of the substitutions described in _a_e_s_u_b(5) are available to
the translator.  Note frequent use of the _p_l_u_r_a_l substitu-
tion, which allows grammatically correct error messages to
be issued when faced with the singular/plural dichotomy.
Other substitutions include the login name of the executing
user, names of projects, number and state of changes, etc.

Ideally, the task for a translator is to take the _._p_o files
and translate the msgstr lines into the appropriate lan-
guage.  The job will, of course, not be that simple and so
references into the code have been included, so that you can
read the code should context be necessary to correctly
translate the message.

1166..22..  CChheecckkiinngg tthhee CCooddee

There are a number of keywords you need to have for the
_x_g_e_t_t_e_x_t program when extracting message strings.  The get-
text keyword is not used directly, because of the substitu-
tion mechanism wrapped around it.





Page 196         (lib/en/user-guide/cI.0.so)    Peter Miller





Aegis                                             User Guide


              i18n                error_intl
              io_comment_append   fatal_intl
              report_error        verbose_intl
              report_error        gram_error
              rpt_value_error


In general, the _e_t_c_/_H_o_w_t_o_._c_o_o_k file causes the messages to
be extracted into _i_1_8_n_-_t_m_p_/_*_._p_o for checking during the
build.

1166..33..  TTrraannssllaattoorrss WWeellccoommee

If _y_o_u are able to translate the error messages into another
language, please contact Peter Miller
<millerp@canb.auug.org.au> and he will tell you how it is
done.  (Actually, he'll point you to this part of the User
Guide.  :-)

To translate the error messages, look up the two-letter
abbreviation (http://www.w3.org/WAI/ER/IG/ert/iso639.htm) of
the language you are going to translate the error messages
to.  The rest of these instructions will call it _x_x.

In the source tree, you will see a directory called
_l_i_b_/_e_n_/_L_C___M_E_S_S_A_G_E_S which contains some .po files.  These are
the text form of the message catalogues.  You can view them
with a simple text editor.

Create a new directory for your translations, and copy the
English messages into it.

     mkdir lib/_x_x/LC_MESSAGES
     cp lib/en/LC_MESSAGES/*.po \
             lib/_x_x/LC_MESSAGES

Now you need to edit each of the lib/_x_x/LC_MESSAGES/*.po
files, replacing the msgstr strings with suitable transla-
tions.  Leave the msgid strings and the comments untrans-
lated.  These are text files, you can edit them with a sim-
ple text editor.  GNU Emacs has a PO mode to make this eas-
ier.

The GNU Gettext (http://www.gnu.org/directory/gettext.html)
sources have fairly good documentation
(http://www.gnu.org/manual/gettext/index.html) about this
process.

If you want to test your translations, you need to "compile"
the text into the binary form used by the gettext() system
call.  This is done using the _m_s_g_f_m_t(1) program from the GNU
Gettext package.  To see your new translations in action,
you create a /usr/local/lib/aegis/_x_x/LC_MESSAGES directory
and arrange for the _m_s_g_f_m_t(1) output to be placed in it.



Peter Miller     (lib/en/user-guide/cI.0.so)        Page 197





User Guide                                             Aegis


Some of the messages are hard to trigger, don't expect com-
plete test coverage.

There are almost 600 error messages.  If you average 1 mes-
sage every 2 minutes, this is approximately 20 hours work.
The German translation, for example, required around 12
hours.

When you are done translating, email the results to Peter
Miller <millerp@canb.auug.org.au> and they will be included
in the next release of Aegis.














































Page 198         (lib/en/user-guide/main.ms)    Peter Miller





Aegis                                             User Guide


.
























































Peter Miller     (lib/en/user-guide/main.ms)      Page cxcix





Aegis                                             User Guide


                     TTaabbllee ooff CCoonntteennttss


1. Introduction . . . . . . . . . . . . . . . . . . . . . . .   3
1.1. Year 2000 Status . . . . . . . . . . . . . . . . . . . .   3
1.2. What does aegis do?  . . . . . . . . . . . . . . . . . .   3
1.3. Why use aegis?   . . . . . . . . . . . . . . . . . . . .   4
1.4. How to use this manual . . . . . . . . . . . . . . . . .   5
1.5. GNU GPL  . . . . . . . . . . . . . . . . . . . . . . . .   6
2. How Aegis Works  . . . . . . . . . . . . . . . . . . . . .   7
2.1. The Model  . . . . . . . . . . . . . . . . . . . . . . .   7
2.1.1. The Baseline . . . . . . . . . . . . . . . . . . . . .   7
2.1.2. The Change Mechanism . . . . . . . . . . . . . . . . .  10
2.1.3. Change States  . . . . . . . . . . . . . . . . . . . .  10
2.1.3.1. Awaiting Development . . . . . . . . . . . . . . . .  11
2.1.3.2. Being Developed  . . . . . . . . . . . . . . . . . .  11
2.1.3.3. Being Reviewed . . . . . . . . . . . . . . . . . . .  12
2.1.3.4. Awaiting Integration . . . . . . . . . . . . . . . .  12
2.1.3.5. Being Integrated . . . . . . . . . . . . . . . . . .  13
2.1.3.6. Completed  . . . . . . . . . . . . . . . . . . . . .  13
2.1.4. The Software Engineers . . . . . . . . . . . . . . . .  14
2.1.4.1. Developer  . . . . . . . . . . . . . . . . . . . . .  14
2.1.4.2. Reviewer . . . . . . . . . . . . . . . . . . . . . .  14
2.1.4.3. Integrator . . . . . . . . . . . . . . . . . . . . .  15
2.1.4.4. Administrator  . . . . . . . . . . . . . . . . . . .  15
2.1.5. The Change Process . . . . . . . . . . . . . . . . . .  16
2.1.5.1. New Change . . . . . . . . . . . . . . . . . . . . .  16
2.1.5.2. New Change Undo  . . . . . . . . . . . . . . . . . .  16
2.1.5.3. Develop Begin  . . . . . . . . . . . . . . . . . . .  16
2.1.5.4. Develop Begin Undo . . . . . . . . . . . . . . . . .  18
2.1.5.5. Develop End  . . . . . . . . . . . . . . . . . . . .  18
2.1.5.6. Develop End Undo . . . . . . . . . . . . . . . . . .  19
2.1.5.7. Review Pass  . . . . . . . . . . . . . . . . . . . .  19
2.1.5.8. Review Pass Undo . . . . . . . . . . . . . . . . . .  20
2.1.5.9. Review Fail  . . . . . . . . . . . . . . . . . . . .  20
2.1.5.10. Integrate Begin . . . . . . . . . . . . . . . . . .  20
2.1.5.11. Integrate Begin Undo  . . . . . . . . . . . . . . .  20
2.1.5.12. Integrate Pass  . . . . . . . . . . . . . . . . . .  20
2.1.5.13. Integrate Fail  . . . . . . . . . . . . . . . . . .  21
2.2. Philosophy . . . . . . . . . . . . . . . . . . . . . . .  22
2.2.1. Development  . . . . . . . . . . . . . . . . . . . . .  22
2.2.2. Post Development . . . . . . . . . . . . . . . . . . .  22
2.2.3. Minimalism . . . . . . . . . . . . . . . . . . . . . .  22
2.2.4. Overlap  . . . . . . . . . . . . . . . . . . . . . . .  22
2.2.5. Design Goals . . . . . . . . . . . . . . . . . . . . .  23
2.3. Security . . . . . . . . . . . . . . . . . . . . . . . .  24
2.4. Scalability  . . . . . . . . . . . . . . . . . . . . . .  24
2.5. When (not) to use Aegis  . . . . . . . . . . . . . . . .  25
2.5.1. Building . . . . . . . . . . . . . . . . . . . . . . .  25
2.5.2. Testing  . . . . . . . . . . . . . . . . . . . . . . .  25
2.5.3. Reviewing  . . . . . . . . . . . . . . . . . . . . . .  26
2.6. Further Work . . . . . . . . . . . . . . . . . . . . . .  27
2.6.1. Code Coverage Tool . . . . . . . . . . . . . . . . . .  27
2.6.2. Virtual File System  . . . . . . . . . . . . . . . . .  27



Peter Miller     (lib/en/user-guide/main.ms)         Page mi





User Guide                                             Aegis


3. The Change Development Cycle . . . . . . . . . . . . . . .  29
3.1. The Developer  . . . . . . . . . . . . . . . . . . . . .  30
3.1.1. Before You Start . . . . . . . . . . . . . . . . . . .  30
3.1.2. The First Change . . . . . . . . . . . . . . . . . . .  30
3.1.3. The Second Change  . . . . . . . . . . . . . . . . . .  40
3.1.4. The Third and Fourth Changes . . . . . . . . . . . . .  47
3.1.5. Developer Command Summary  . . . . . . . . . . . . . .  64
3.2. The Reviewer . . . . . . . . . . . . . . . . . . . . . .  65
3.2.1. Before You Start . . . . . . . . . . . . . . . . . . .  65
3.2.2. The First Change . . . . . . . . . . . . . . . . . . .  65
3.2.3. The Second Change  . . . . . . . . . . . . . . . . . .  66
3.2.4. Reviewer Command Summary . . . . . . . . . . . . . . .  68
3.3. The Integrator . . . . . . . . . . . . . . . . . . . . .  69
3.3.1. Before You Start . . . . . . . . . . . . . . . . . . .  69
3.3.2. The First Change . . . . . . . . . . . . . . . . . . .  69
3.3.3. The Other Changes  . . . . . . . . . . . . . . . . . .  71
3.3.4. Integrator Command Summary . . . . . . . . . . . . . .  72
3.3.5. Minimum Integrations . . . . . . . . . . . . . . . . .  72
3.4. The Administrator  . . . . . . . . . . . . . . . . . . .  74
3.4.1. Before You Start . . . . . . . . . . . . . . . . . . .  74
3.4.2. The First Change . . . . . . . . . . . . . . . . . . .  74
3.4.3. The Second Change  . . . . . . . . . . . . . . . . . .  77
3.4.4. The Third Change . . . . . . . . . . . . . . . . . . .  77
3.4.5. The Fourth Change  . . . . . . . . . . . . . . . . . .  77
3.4.6. Administrator Command Summary  . . . . . . . . . . . .  78
3.5. What to do Next  . . . . . . . . . . . . . . . . . . . .  79
3.6. Common Questions . . . . . . . . . . . . . . . . . . . .  79
3.6.1. Insulation . . . . . . . . . . . . . . . . . . . . . .  79
3.6.1.1. Copy Read-Only . . . . . . . . . . . . . . . . . . .  80
3.6.1.2. Branches . . . . . . . . . . . . . . . . . . . . . .  80
3.6.1.3. Builds . . . . . . . . . . . . . . . . . . . . . . .  80
3.6.1.4. Mix-and-Match  . . . . . . . . . . . . . . . . . . .  80
3.6.1.5. Disadvantages  . . . . . . . . . . . . . . . . . . .  80
3.6.2. Partial Check-In . . . . . . . . . . . . . . . . . . .  81
3.6.3. Multiple Active Branches . . . . . . . . . . . . . . .  82
3.6.3.1. Cloning  . . . . . . . . . . . . . . . . . . . . . .  82
3.6.3.2. Ancestral  . . . . . . . . . . . . . . . . . . . . .  82
3.6.4. Collaboration  . . . . . . . . . . . . . . . . . . . .  82
3.6.4.1. Change Owner . . . . . . . . . . . . . . . . . . . .  82
3.6.4.2. Branch . . . . . . . . . . . . . . . . . . . . . . .  83
3.6.4.3. View Path Hacking  . . . . . . . . . . . . . . . . .  83
4. The History Tool . . . . . . . . . . . . . . . . . . . . .  84
4.1. Interfacing  . . . . . . . . . . . . . . . . . . . . . .  84
4.1.1. history_create_command . . . . . . . . . . . . . . . .  84
4.1.2. history_get_command  . . . . . . . . . . . . . . . . .  84
4.1.3. history_put_command  . . . . . . . . . . . . . . . . .  85
4.1.4. history_query_command  . . . . . . . . . . . . . . . .  85
4.1.5. history_content_limitation . . . . . . . . . . . . . .  85
4.1.6. history_tool_trashes_file  . . . . . . . . . . . . . .  86
4.1.7. Quoting Filenames  . . . . . . . . . . . . . . . . . .  86
4.2. Using SCCS . . . . . . . . . . . . . . . . . . . . . . .  87
4.2.1. history_create_command . . . . . . . . . . . . . . . .  87
4.2.2. history_get_command  . . . . . . . . . . . . . . . . .  87
4.2.3. history_put_command  . . . . . . . . . . . . . . . . .  88



Page mii         (lib/en/user-guide/main.ms)    Peter Miller





Aegis                                             User Guide


4.2.4. history_query_command  . . . . . . . . . . . . . . . .  88
4.2.5. Templates  . . . . . . . . . . . . . . . . . . . . . .  89
4.2.6. Binary Files . . . . . . . . . . . . . . . . . . . . .  89
4.3. Using RCS  . . . . . . . . . . . . . . . . . . . . . . .  90
4.3.1. history_create_command . . . . . . . . . . . . . . . .  90
4.3.2. history_get_command  . . . . . . . . . . . . . . . . .  91
4.3.3. history_put_command  . . . . . . . . . . . . . . . . .  91
4.3.4. history_query_command  . . . . . . . . . . . . . . . .  92
4.3.5. merge_command  . . . . . . . . . . . . . . . . . . . .  92
4.3.6. Referential Integrity  . . . . . . . . . . . . . . . .  93
4.3.7. Templates  . . . . . . . . . . . . . . . . . . . . . .  94
4.3.8. Binary Files . . . . . . . . . . . . . . . . . . . . .  94
4.3.9. history_put_trashes_files  . . . . . . . . . . . . . .  95
4.4. Using fhist  . . . . . . . . . . . . . . . . . . . . . .  96
4.4.1. history_create_command . . . . . . . . . . . . . . . .  96
4.4.2. history_get_command  . . . . . . . . . . . . . . . . .  96
4.4.3. history_put_command  . . . . . . . . . . . . . . . . .  97
4.4.4. history_query_command  . . . . . . . . . . . . . . . .  97
4.4.5. Templates  . . . . . . . . . . . . . . . . . . . . . .  98
4.4.6. Capabilities . . . . . . . . . . . . . . . . . . . . .  98
4.4.7. Binary Files . . . . . . . . . . . . . . . . . . . . .  98
4.5. Detecting File Corruption  . . . . . . . . . . . . . . .  99
4.5.1. General Method . . . . . . . . . . . . . . . . . . . .  99
4.5.2. Configuration Commands . . . . . . . . . . . . . . . . 100
4.5.3. Aegis' Database  . . . . . . . . . . . . . . . . . . . 100
5. The Dependency Maintenance Tool  . . . . . . . . . . . . . 101
5.1. Required Features  . . . . . . . . . . . . . . . . . . . 101
5.1.1. Search Lists . . . . . . . . . . . . . . . . . . . . . 101
5.1.2. Dynamic Include File Dependencies  . . . . . . . . . . 102
5.1.2.1. Static File  . . . . . . . . . . . . . . . . . . . . 102
5.1.2.2. Dynamic  . . . . . . . . . . . . . . . . . . . . . . 103
5.2. Using Cook . . . . . . . . . . . . . . . . . . . . . . . 104
5.2.1. Invoking Cook  . . . . . . . . . . . . . . . . . . . . 104
5.2.2. The Recipe File  . . . . . . . . . . . . . . . . . . . 104
5.2.3. The Recipe for C . . . . . . . . . . . . . . . . . . . 106
5.2.3.1. C Include Semantics  . . . . . . . . . . . . . . . . 107
5.2.4. The Recipe for Yacc  . . . . . . . . . . . . . . . . . 108
5.2.5. The Recipe for Lex . . . . . . . . . . . . . . . . . . 109
5.2.6. Recipes for Documents  . . . . . . . . . . . . . . . . 109
5.2.7. Templates  . . . . . . . . . . . . . . . . . . . . . . 110
5.3. Using Cake . . . . . . . . . . . . . . . . . . . . . . . 111
5.3.1. Invoking Cake  . . . . . . . . . . . . . . . . . . . . 111
5.3.2. The Rules File . . . . . . . . . . . . . . . . . . . . 111
5.3.3. The Rule for C . . . . . . . . . . . . . . . . . . . . 112
5.3.3.1. Include Directives . . . . . . . . . . . . . . . . . 113
5.3.4. The Rule for Yacc  . . . . . . . . . . . . . . . . . . 113
5.3.5. The Rule for Lex . . . . . . . . . . . . . . . . . . . 114
5.3.6. Rules for Documents  . . . . . . . . . . . . . . . . . 114
5.4. Using Make . . . . . . . . . . . . . . . . . . . . . . . 115
5.4.1. Invoking Make  . . . . . . . . . . . . . . . . . . . . 115
5.4.2. The Rule File  . . . . . . . . . . . . . . . . . . . . 116
5.4.3. The Rule for C . . . . . . . . . . . . . . . . . . . . 117
5.4.3.1. Include Directives . . . . . . . . . . . . . . . . . 118
5.4.4. The Rule for Yacc  . . . . . . . . . . . . . . . . . . 118



Peter Miller     (lib/en/user-guide/main.ms)       Page miii





User Guide                                             Aegis


5.4.5. The Rule for Lex . . . . . . . . . . . . . . . . . . . 119
5.4.6. Rules for Documents  . . . . . . . . . . . . . . . . . 119
5.4.7. Other Makes  . . . . . . . . . . . . . . . . . . . . . 120
5.4.8. Templates  . . . . . . . . . . . . . . . . . . . . . . 120
5.4.9. GNU Make VPATH Patch . . . . . . . . . . . . . . . . . 120
5.4.10. GNU Make's VPATH+ . . . . . . . . . . . . . . . . . . 120
5.5. Building Executable Scripts  . . . . . . . . . . . . . . 121
6. The Difference Tools . . . . . . . . . . . . . . . . . . . 123
6.1. Binary Files . . . . . . . . . . . . . . . . . . . . . . 123
6.2. Interfacing  . . . . . . . . . . . . . . . . . . . . . . 123
6.2.1. diff_command . . . . . . . . . . . . . . . . . . . . . 123
6.2.2. merge_command  . . . . . . . . . . . . . . . . . . . . 124
6.3. Using diff and merge . . . . . . . . . . . . . . . . . . 126
6.3.1. diff_command . . . . . . . . . . . . . . . . . . . . . 126
6.3.2. merge_command  . . . . . . . . . . . . . . . . . . . . 126
6.4. Using fhist  . . . . . . . . . . . . . . . . . . . . . . 127
6.4.1. diff_command . . . . . . . . . . . . . . . . . . . . . 127
6.4.2. merge_command  . . . . . . . . . . . . . . . . . . . . 127
7. The Project Attributes . . . . . . . . . . . . . . . . . . 129
7.1. Description and Access . . . . . . . . . . . . . . . . . 129
7.2. Notification Commands  . . . . . . . . . . . . . . . . . 129
7.2.1. Notification by email  . . . . . . . . . . . . . . . . 130
7.2.2. Notification by USENET . . . . . . . . . . . . . . . . 131
7.3. Exemption Controls . . . . . . . . . . . . . . . . . . . 132
7.3.1. One Person Projects  . . . . . . . . . . . . . . . . . 132
7.3.2. Two Person Projects  . . . . . . . . . . . . . . . . . 133
7.3.3. Larger Projects  . . . . . . . . . . . . . . . . . . . 133
8. Testing  . . . . . . . . . . . . . . . . . . . . . . . . . 134
8.1. Why Bother?  . . . . . . . . . . . . . . . . . . . . . . 134
8.1.1. Projects for which Aegis' Testing is Most Suitable
 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134
8.1.2. Projects for which Aegis' Testing is Useful  . . . . . 135
8.1.2.1. Testing Via Emulators  . . . . . . . . . . . . . . . 135
8.1.2.2. Limited Testing  . . . . . . . . . . . . . . . . . . 135
8.1.2.3. Testing Mode . . . . . . . . . . . . . . . . . . . . 135
8.1.2.4. Manual Tests . . . . . . . . . . . . . . . . . . . . 136
8.1.2.5. Unit Tests . . . . . . . . . . . . . . . . . . . . . 136
8.1.3. Projects for which Aegis' Testing is Least Useful
 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136
8.1.3.1. Operating Systems  . . . . . . . . . . . . . . . . . 136
8.1.3.2. Firmware . . . . . . . . . . . . . . . . . . . . . . 137
8.2. Writing Tests  . . . . . . . . . . . . . . . . . . . . . 138
8.2.1. Contributors . . . . . . . . . . . . . . . . . . . . . 138
8.2.2. General Guidelines . . . . . . . . . . . . . . . . . . 138
8.2.2.1. Choice of Scripting Language . . . . . . . . . . . . 138
8.2.2.2. No Execute Permission  . . . . . . . . . . . . . . . 139
8.2.2.3. No Command-Line Arguments  . . . . . . . . . . . . . 139
8.2.2.4. Identifying the Scripting Language . . . . . . . . . 139
8.2.2.5. Current Directory  . . . . . . . . . . . . . . . . . 139
8.2.2.6. Check Exit Status and Return Values  . . . . . . . . 139
8.2.2.7. Temporary Directory  . . . . . . . . . . . . . . . . 140
8.2.2.8. Trap Interrupts  . . . . . . . . . . . . . . . . . . 140
8.2.2.9. PAGER  . . . . . . . . . . . . . . . . . . . . . . . 140
8.2.2.10. Auxiliary Files . . . . . . . . . . . . . . . . . . 140



Page miv         (lib/en/user-guide/main.ms)    Peter Miller





Aegis                                             User Guide


8.2.2.11. New Test Templates  . . . . . . . . . . . . . . . . 141
8.2.3. Bourne Shell . . . . . . . . . . . . . . . . . . . . . 141
8.2.3.1. Magic Number . . . . . . . . . . . . . . . . . . . . 141
8.2.3.2. Check Exit Status  . . . . . . . . . . . . . . . . . 141
8.2.3.3. Temporary Directory  . . . . . . . . . . . . . . . . 141
8.2.3.4. Trap Interrupts  . . . . . . . . . . . . . . . . . . 141
8.2.3.5. Auxiliary Files  . . . . . . . . . . . . . . . . . . 142
8.2.3.6. [ test ] . . . . . . . . . . . . . . . . . . . . . . 142
8.2.3.7. Other Bourne Shell Portability Issues  . . . . . . . 142
8.2.4. Perl . . . . . . . . . . . . . . . . . . . . . . . . . 142
8.2.4.1. Magic Number . . . . . . . . . . . . . . . . . . . . 142
8.2.4.2. Check Return Values  . . . . . . . . . . . . . . . . 143
8.2.4.3. Temporary Directory  . . . . . . . . . . . . . . . . 143
8.2.4.4. Trap Interrupts  . . . . . . . . . . . . . . . . . . 143
8.2.4.5. Auxiliary Files  . . . . . . . . . . . . . . . . . . 143
8.2.4.6. Exit Values  . . . . . . . . . . . . . . . . . . . . 143
8.2.4.7. Modules  . . . . . . . . . . . . . . . . . . . . . . 144
8.2.4.8. The Test::Cmd Module . . . . . . . . . . . . . . . . 144
8.2.4.9. The Test and Test::Harness Modules . . . . . . . . . 145
8.2.4.10. Granularity . . . . . . . . . . . . . . . . . . . . 147
8.2.5. Batch Testing  . . . . . . . . . . . . . . . . . . . . 148
9. Branching  . . . . . . . . . . . . . . . . . . . . . . . . 149
9.1. How To Use Branching . . . . . . . . . . . . . . . . . . 149
9.2. Transition Using aenrls  . . . . . . . . . . . . . . . . 150
9.3. Cross Branch Merge . . . . . . . . . . . . . . . . . . . 151
9.4. Multiple Branch Development  . . . . . . . . . . . . . . 151
9.5. Hierarchy of Projects  . . . . . . . . . . . . . . . . . 151
9.5.1. Fundamentals . . . . . . . . . . . . . . . . . . . . . 152
9.5.2. Incremental Integration  . . . . . . . . . . . . . . . 152
9.5.3. Super-Project Branching  . . . . . . . . . . . . . . . 153
9.5.4. Super-Project Testing  . . . . . . . . . . . . . . . . 153
9.5.5. The Next Cycle . . . . . . . . . . . . . . . . . . . . 154
9.5.6. Bug Fixing . . . . . . . . . . . . . . . . . . . . . . 154
9.6. Conflict Resolution  . . . . . . . . . . . . . . . . . . 154
9.6.1. Cross Branch Merge . . . . . . . . . . . . . . . . . . 155
9.6.2. Insulation . . . . . . . . . . . . . . . . . . . . . . 156
9.6.2.1. Branch Insulated Against Project . . . . . . . . . . 156
9.6.2.2. Project Insulated Against Branch . . . . . . . . . . 156
9.6.2.3. Mix 'n' Match  . . . . . . . . . . . . . . . . . . . 156
9.7. Ending A Branch  . . . . . . . . . . . . . . . . . . . . 156
10. Tips and Traps  . . . . . . . . . . . . . . . . . . . . . 159
10.1. Renaming Include Files  . . . . . . . . . . . . . . . . 159
10.2. Symbolic Links  . . . . . . . . . . . . . . . . . . . . 159
10.3. User Setup  . . . . . . . . . . . . . . . . . . . . . . 160
10.3.1. The .cshrc or .profile files  . . . . . . . . . . . . 160
10.3.2. The AEGIS_PATH environment variable . . . . . . . . . 160
10.3.3. The .aegisrc file . . . . . . . . . . . . . . . . . . 161
10.3.4. The defaulting mechanism  . . . . . . . . . . . . . . 161
10.4. The Project Owner . . . . . . . . . . . . . . . . . . . 161
10.5. USENET Publication Standards  . . . . . . . . . . . . . 162
10.5.1. CHANGES . . . . . . . . . . . . . . . . . . . . . . . 162
10.5.2. MANIFEST  . . . . . . . . . . . . . . . . . . . . . . 162
10.5.3. Makefile  . . . . . . . . . . . . . . . . . . . . . . 163
10.5.4. patchlevel.h  . . . . . . . . . . . . . . . . . . . . 163



Peter Miller     (lib/en/user-guide/main.ms)         Page mv





User Guide                                             Aegis


10.5.5. Building Patch Files  . . . . . . . . . . . . . . . . 163
10.6. Heterogeneous Development . . . . . . . . . . . . . . . 164
10.6.1. Project _c_o_n_f_i_g File . . . . . . . . . . . . . . . . . 164
10.6.2. Change Attribute  . . . . . . . . . . . . . . . . . . 166
10.6.3. Network Files . . . . . . . . . . . . . . . . . . . . 166
10.6.4. DMT Implications  . . . . . . . . . . . . . . . . . . 166
10.6.4.1. Cook Example  . . . . . . . . . . . . . . . . . . . 167
10.6.5. Test Implications . . . . . . . . . . . . . . . . . . 168
10.6.6. Cross Compiling . . . . . . . . . . . . . . . . . . . 169
10.6.7. File Version by Architecture  . . . . . . . . . . . . 169
10.7. Reminders . . . . . . . . . . . . . . . . . . . . . . . 169
10.7.1. Awaiting Development  . . . . . . . . . . . . . . . . 169
10.7.2. Being Developed . . . . . . . . . . . . . . . . . . . 169
10.7.3. Being Reviewed  . . . . . . . . . . . . . . . . . . . 170
10.7.4. Awaiting Integration  . . . . . . . . . . . . . . . . 170
11. Geographically Distributed Development  . . . . . . . . . 171
11.1. Introduction  . . . . . . . . . . . . . . . . . . . . . 171
11.1.1. Risk Reduction  . . . . . . . . . . . . . . . . . . . 171
11.1.2. What to Send  . . . . . . . . . . . . . . . . . . . . 172
11.1.3. Methods and Topologies  . . . . . . . . . . . . . . . 172
11.1.4. The Rest of this Chapter  . . . . . . . . . . . . . . 173
11.2. Manual Operation  . . . . . . . . . . . . . . . . . . . 174
11.2.1. Manual Send . . . . . . . . . . . . . . . . . . . . . 174
11.2.2. Sending Baselines . . . . . . . . . . . . . . . . . . 174
11.2.3. Sending Branches  . . . . . . . . . . . . . . . . . . 175
11.2.4. Manual Receive  . . . . . . . . . . . . . . . . . . . 175
11.2.5. Getting Started . . . . . . . . . . . . . . . . . . . 176
11.3. Sneaker Net . . . . . . . . . . . . . . . . . . . . . . 176
11.4. Automatic Operation . . . . . . . . . . . . . . . . . . 177
11.4.1. Sending . . . . . . . . . . . . . . . . . . . . . . . 177
11.4.2. Receiving . . . . . . . . . . . . . . . . . . . . . . 178
11.5. World Wide Web  . . . . . . . . . . . . . . . . . . . . 178
11.5.1. Server  . . . . . . . . . . . . . . . . . . . . . . . 178
11.5.2. Browser . . . . . . . . . . . . . . . . . . . . . . . 178
11.6. Security  . . . . . . . . . . . . . . . . . . . . . . . 178
11.6.1. Trojan Horses . . . . . . . . . . . . . . . . . . . . 179
11.6.2. PGP . . . . . . . . . . . . . . . . . . . . . . . . . 180
11.6.3. Sorcerer's Apprentice . . . . . . . . . . . . . . . . 180
11.7. Patches . . . . . . . . . . . . . . . . . . . . . . . . 181
11.7.1. Send  . . . . . . . . . . . . . . . . . . . . . . . . 181
11.7.2. Receive . . . . . . . . . . . . . . . . . . . . . . . 181
11.7.3. Limitations . . . . . . . . . . . . . . . . . . . . . 182
12. Further Reading . . . . . . . . . . . . . . . . . . . . . 183
12.1. Software Configuration Management . . . . . . . . . . . 183
12.2. Reviewing . . . . . . . . . . . . . . . . . . . . . . . 183
13. Appendix A: New Project Quick Reference . . . . . . . . . 184
13.1. Create the Project  . . . . . . . . . . . . . . . . . . 184
13.1.1. Add the Staff . . . . . . . . . . . . . . . . . . . . 184
13.1.2. Project Attributes  . . . . . . . . . . . . . . . . . 184
13.2. Create Change One . . . . . . . . . . . . . . . . . . . 185
13.3. Develop Change One  . . . . . . . . . . . . . . . . . . 185
13.4. Review The Change . . . . . . . . . . . . . . . . . . . 186
13.5. Integrate the Change  . . . . . . . . . . . . . . . . . 187
13.6. What to do Next . . . . . . . . . . . . . . . . . . . . 188



Page mvi         (lib/en/user-guide/main.ms)    Peter Miller





Aegis                                             User Guide


14. Appendix B: Glossary  . . . . . . . . . . . . . . . . . . 190
15. Appendix D: Why is Aegis Set-Uid-Root?  . . . . . . . . . 193
15.1. Examples  . . . . . . . . . . . . . . . . . . . . . . . 193
15.2. Source Details  . . . . . . . . . . . . . . . . . . . . 195
16. Appendix I: Internationalization and Localization . . . . 196
16.1. The ``.po'' Files . . . . . . . . . . . . . . . . . . . 196
16.2. Checking the Code . . . . . . . . . . . . . . . . . . . 196
16.3. Translators Welcome . . . . . . . . . . . . . . . . . . 197

















































Peter Miller                 ()                    Page mvii


