





.













                           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 3.28
and was prepared 30 August 2001.






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 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


11..  IInnttrroodduuccttiioonn

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 RCS).  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).

11..11..  YYeeaarr 22000000 SSttaattuuss

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.

11..22..  WWhhaatt ddooeess aaeeggiiss ddoo??

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.

11..33..  WWhhyy uussee aaeeggiiss??

So why should you use the aegis program?  The aegis  program
uses  a particular model of the development of software pro-
jects.  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


11..44..  HHooww ttoo uussee tthhiiss mmaannuuaall

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.

11..55..  GGNNUU GGPPLL

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


22..  HHooww AAeeggiiss WWoorrkkss

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.

22..11..  TThhee MMooddeell

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

22..11..11..  TThhee BBaasseelliinnee

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.
You will not be able to have binary files in  your  baseline
if the history tool of your choice can't cope with them.
-----------
  1 "Unfortunately,"  because many real-world pro-
jects 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  pro-
ject,  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  manda-
tory 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 base-
line may result in the baseline ceasing to work2.

The  model may be summarised 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





                 developmentdevelopment
                  directory directory




                       integrator
                              integrate
                            |      pass
                  integrate |
                      begin |
                            |
                      integration
                       directory




         FFiigguurree 11:: 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
database 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.

22..11..22..  TThhee CChhaannggee MMeecchhaanniissmm

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.

22..11..33..  CChhaannggee SSttaatteess

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.

22..11..33..11..  AAwwaaiittiinngg DDeevveellooppmmeenntt

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.

22..11..33..22..  BBeeiinngg DDeevveellooppeedd

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.

22..11..33..33..  BBeeiinngg RReevviieewweedd

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  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.

22..11..33..44..  AAwwaaiittiinngg IInntteeggrraattiioonn

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
change would break another, in these  cases  the  integrator



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





Aegis                                             User Guide


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.

22..11..33..55..  BBeeiinngg IInntteeggrraatteedd

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.

22..11..33..66..  CCoommpplleetteedd

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
may never leave it, unlike all other states.



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





User Guide                                             Aegis


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

22..11..44..  TThhee SSooffttwwaarree EEnnggiinneeeerrss

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.

22..11..44..11..  DDeevveellooppeerr

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).

22..11..44..22..  RReevviieewweerr

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
each and every edit, to each and every file, can be  pointed
out to the reviewer.



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





Aegis                                             User Guide


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.

22..11..44..33..  IInntteeggrraattoorr

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 defence 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.

22..11..44..44..  AAddmmiinniissttrraattoorr

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.

+o  Add  or  remove  staff.  The four roles described in this
section may be assigned to, or removed from,  specific  UNIX



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





User Guide                                             Aegis


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.

22..11..55..  TThhee CChhaannggee PPrroocceessss

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.

22..11..55..11..  NNeeww CChhaannggee

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.

22..11..55..22..  NNeeww CChhaannggee UUnnddoo

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.

22..11..55..33..  DDeevveelloopp BBeeggiinn

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  |devreelvoipew
                     end      |end fail
                     undo     |
                develop    being
                end       reviewed integrate
                undo          |         fail
                              |revrieevwiew
                              |passpass
                              |    undo
                          awaiting
                        integration
                              |
                  integrate   |integrate
                  begin       |begin
                  undo        |
                           being
                         integrated
                              |
                              |integrate
                              |pass
                              |

                         completed


          FFiigguurree 22:: 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
database 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
file 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.

22..11..55..44..  DDeevveelloopp BBeeggiinn UUnnddoo

It is possible to return a change from the  being  developed
state  to the awaiting development state if it has no source
files and has no tests.  This is usually desired if a devel-
oper selected the wrong change by mistake.

22..11..55..55..  DDeevveelloopp EEnndd

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  basleine 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.

22..11..55..66..  DDeevveelloopp EEnndd UUnnddoo

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.

22..11..55..77..  RReevviieeww PPaassss

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.

22..11..55..88..  RReevviieeww PPaassss UUnnddoo

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
must be supplied.  The change will be returned to the  _b_e_i_n_g
_r_e_v_i_e_w_e_d state.



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





User Guide                                             Aegis


22..11..55..99..  RReevviieeww FFaaiill

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.

22..11..55..1100..  IInntteeggrraattee BBeeggiinn

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 hard links, is controlled by the project con-
figuration 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.

22..11..55..1111..  IInntteeggrraattee BBeeggiinn UUnnddoo

This  command  is used to return a change to the integration
queue, with out 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.

22..11..55..1122..  IInntteeggrraattee PPaassss

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.

22..11..55..1133..  IInntteeggrraattee FFaaiill

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



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





Aegis                                             User Guide


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.  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


22..22..  PPhhiilloossoopphhyy

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   pro-
ject  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.)

22..22..11..  DDeevveellooppmmeenntt

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.

22..22..22..  PPoosstt DDeevveellooppmmeenntt

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.

22..22..33..  MMiinniimmaalliissmm

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.

22..22..44..  OOvveerrllaapp

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.

22..22..55..  DDeessiiggnn GGooaallss

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


22..33..  SSeeccuurriittyy

Access to project data is controlled by the UNIX group mech-
anism.   The group may be selected as suitable for your pro-
ject, 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.

22..44..  SSccaallaabbiilliittyy

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


22..55..  WWhheenn ((nnoott)) ttoo uussee AAeeggiiss

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.

22..55..11..  BBuuiillddiinngg

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.

22..55..22..  TTeessttiinngg

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


22..55..33..  RReevviieewwiinngg

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


22..66..  FFuurrtthheerr WWoorrkk

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.

22..66..11..  CCooddee CCoovveerraaggee TTooooll

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.

NNoottee:: 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.

22..66..22..  VViirrttuuaall FFiillee SSyysstteemm

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


33..  TThhee CChhaannggee DDeevveellooppmmeenntt CCyyccllee

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


33..11..  TThhee DDeevveellooppeerr

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 as modi-
fications of existing code, similar to bug-fixing  activity.

33..11..11..  BBeeffoorree YYoouu SSttaarrtt

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.

33..11..22..  TThhee FFiirrsstt CChhaannggee

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% aaeeddbb --ll --pp eexxaammppllee..11..00
     Project "example.1.0"
     List of Changes


     Change  State           Description
     ------- -------         -------------
       10    awaiting_       Create initial skeleton.
             development
     pat% aaeeddbb eexxaammppllee..11..00 1100
     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% aaeeccdd
     aegis: project "example.1.0": change 10: /u/pat/example.1.0.C010
     pat%

-----------
  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


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% aaeennff ccoonnffiigg HHoowwttoo..ccooookk ggrraamm..yy lleexx..ll mmaaiinn..cc
     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);
     }


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


-----------
  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


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


     %%


     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; }






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





Aegis                                             User Guide


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.

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.


















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





User Guide                                             Aegis


     pat% aaeebb
     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% eexxaammppllee
     11 ++ 22
     3
     ^^DD
     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% aaeeddee
     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
down and inevitably miss  obscure  but  important  edits  to
large or complex files.












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





Aegis                                             User Guide


     pat% aaeedd
     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% mmoorree ``ffiinndd .. --nnaammee ""**,,DD"" --pprriinntt || ssoorrtt``
     _._._._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% aaeeddee
     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
times that a project works12.  Making this a precondition to
-----------
  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.
  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



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





User Guide                                             Aegis


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% aaeenntt
     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


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




-----------
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


     #
     # 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:

+o  It  is  a Bourne shell script.  All test files are Bourne
     shell  scripts  because  they  are the most portable.13
-----------
  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



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





User Guide                                             Aegis


     (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.

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-
-----------
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


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% aaeebb &&&& aaeett ;; vvii aaeeggiiss..lloogg
     ...
     pat% !!!!
     ...
     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% aaeett
     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% aaeeddee
     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
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



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% aaeebb
     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% aaeett
     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% aaeedd
     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% aaeeddee
     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.

33..11..33..  TThhee SSeeccoonndd CChhaannggee

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% aaeeddbb --ll --pp eexxaammppllee..11..00
     Project "example.1.0"
     List of Changes





-----------
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% aaeeddbb --cc 1111 --pp eexxaammppllee..11..00
     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% aaeeccdd
     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% aaeell ccdd
     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% aaeeccpp mmaaiinn..cc
     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% aaeenntt
     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% aaeebb
     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% aaeett
     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% aaeedd
     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% aaeeddmmoorree
     _._._._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% aaeeddee
     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% aaeett --bbll
     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% aaeett --rreegg
     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% aaeeddee
     aegis: sh /usr/local/lib/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.

33..11..44..  TThhee TThhiirrdd aanndd FFoouurrtthh CChhaannggeess

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% aaeeddbb --ll
     Project "example.1.0"
     List of Changes

     Change  State           Description
     ------- -------         -------------
       12    awaiting_       add powers
             development
       13    awaiting_       add variables
             development
     sam% aaeeddbb 1122
     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% aaeeccdd
     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% aaeeccpp ggrraamm..yy
     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% aaeedd
     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% aaeeddmmoorree
     _._._._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% aaeenntt
     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% aaeebb
     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% aaeett
     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% aaeett --bbll
     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% aaeett --rreegg
     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% aaeeddbb --ll
     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% aaeeddbb 44
     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% aaeeccdd
     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% aaeell ccdd
     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% aaeeccpp ggrraamm..yy
     aegis: project "example.1.0": change 13: file "gram.y" copied
     pat% aaeennff vvaarr..cc
     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% vvii ggrraamm..yy
     _._._._e_d_i_t _t_h_e _f_i_l_e_._._.
     pat% aaeedd
     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% aaeebb
     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.

     :
     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% aaeedd
     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% aaeett
     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% aaeett --bbll
     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% aaeett --rreegg
     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% aaeeddee
     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% aaeeddee
     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% aaeemm
     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% aaeebb
     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% aaeett
     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% aaeett --bbll
     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% aaeett --rreegg
     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% aaeeddee
     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% aaeedd
     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% aaeeddee
     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


33..11..55..  DDeevveellooppeerr CCoommmmaanndd SSuummmmaarryy

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


33..22..  TThhee RReevviieewweerr

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 "command D" files is avail-
able 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.

33..22..11..  BBeeffoorree YYoouu SSttaarrtt

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.

33..22..22..  TThhee FFiirrsstt CChhaannggee

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

     robyn% aaeerrppaassss --ll --pp eexxaammppllee..11..00

     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% aaeeccdd --pp eexxaammppllee..11..00 --cc 1100
     aegis: project "example": change 1: /u/pat/example.1.0.C010
     robyn% aaeeddmmoorree
     _._._._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% aaeerrppaassss --pp eexxaammppllee..11..00 1100
     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.

33..22..33..  TThhee SSeeccoonndd CChhaannggee

Most reviews have the same pattern as the first.

     robyn% aaeerrppaassss --ll --pp eexxaammppllee..11..00

     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% aaeeccdd --pp eexxaammppllee..11..00 --cc 1111
     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% aaeell ccdd --pp eexxaammppllee..11..00 --cc 1111

     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_integrated' 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% aaeeddmmoorree
     _._._._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% aaeerrppaassss --pp eexxaammppllee..11..00 1111
     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.

33..22..44..  RReevviieewweerr CCoommmmaanndd SSuummmmaarryy

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


33..33..  TThhee IInntteeggrraattoorr

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.

33..33..11..  BBeeffoorree YYoouu SSttaarrtt

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.

33..33..22..  TThhee FFiirrsstt CChhaannggee

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% aaeeiibb --ll --pp eexxaammppllee..11..00

     Project "example.1.0"
     List of Changes

     Change  State           Description
     ------- -------         -------------
       10    awaiting_       Place under Aegis
             integration
     isa% aaeeiibb eexxaammppllee..11..00 1100
     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% aaeebb
     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% aaeett
     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% aaeeiippaassss
     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
             '/^head:/ {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.

33..33..33..  TThhee OOtthheerr CChhaannggeess

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


33..33..44..  IInntteeggrraattoorr CCoommmmaanndd SSuummmmaarryy

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.






























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





Aegis                                             User Guide


33..44..  TThhee AAddmmiinniissttrraattoorr

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 pro-
jects,  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

33..44..11..  BBeeffoorree YYoouu SSttaarrtt

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.

33..44..22..  TThhee FFiirrsstt CChhaannggee

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% aaeennpprr eexxaammppllee --ddiirr //pprroojjeeccttss//eexxaammppllee --vveerrssiioonn --
     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 --EEddiitt option of the aaeeppaa command.  This will  invoke  an
editor  (_v_i(1)  by  default) to edit the project attributes.
Alex edits them to look like this:







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





User Guide                                             Aegis


     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% aaeeppaa --eeddiitt --pp eexxaammppllee
     _._._._e_d_i_t _a_s _a_b_o_v_e_._._.
     aegis: project "example.1.0": attributes changed
     alex% aaeell pp
     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% aaeenndd ppaatt jjaann ssaamm --pp eexxaammppllee
     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% aaeennrrvv rroobbyynn jjaann --pp eexxaammppllee
     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% aaeennii iissaa --pp eexxaammppllee
     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% aaeeggiiss --nnbbrr eexxaammppllee 11
     aegis: project "example.1": created
     alex% aaeeggiiss --nnbbrr eexxaammppllee..11 00
     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



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





Aegis                                             User Guide


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

     alex% aaeell pp
     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 --EEddiitt option of the aaeenncc 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% aaeenncc --eeddiitt --pp eexxaammppllee..11..00
     _._._._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 bused 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.





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





User Guide                                             Aegis


33..44..33..  TThhee SSeeccoonndd CChhaannggee

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% aaeenncc --eeddiitt --pp eexxaammppllee..11..00
     _._._._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.

33..44..44..  TThhee TThhiirrdd CChhaannggee

Other features are required for the calculator, and also for
this example.  The second 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% aaeenncc --eeddiitt --pp eexxaammppllee..11..00
     _._._._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.

33..44..55..  TThhee FFoouurrtthh CChhaannggee

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






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





Aegis                                             User Guide


     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% aaeenncc --eeddiitt --pp eexxaammppllee..11..00
     _._._._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.

33..44..66..  AAddmmiinniissttrraattoorr CCoommmmaanndd SSuummmmaarryy

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.









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





User Guide                                             Aegis


33..55..  WWhhaatt ttoo ddoo NNeexxtt

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.  This idea 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 num-
ber 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:

     % aaeeddbb --hheellpp
     _._._._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.

33..66..  CCoommmmoonn QQuueessttiioonnss

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

33..66..11..  IInnssuullaattiioonn

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  a 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.




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





Aegis                                             User Guide


33..66..11..11..  CCooppyy RReeaadd--OOnnllyy

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.

33..66..11..22..  BBrraanncchheess

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.

33..66..11..33..  BBuuiillddss

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!

33..66..11..44..  MMiixx--aanndd--MMaattcchh

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.

33..66..11..55..  DDiissaaddvvaannttaaggeess

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.





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





User Guide                                             Aegis


However,  it  also means that if there are integration prob-
lems 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 lit-
erature,  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.

33..66..22..  PPaarrttiiaall CChheecckk--IInn

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.

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.

The  original  change  will  then need to be merged with the
baseline,  because  the  bug  fix  change  will  have   been



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





Aegis                                             User Guide


integrated  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 base-
line.

33..66..33..  MMuullttiippllee AAccttiivvee BBrraanncchheess

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.

33..66..33..11..  CClloonniinngg

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.

33..66..33..22..  AAnncceessttrraall

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).

33..66..44..  CCoollllaabboorraattiioonn

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.

33..66..44..11..  CChhaannggee OOwwnneerr

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




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





User Guide                                             Aegis


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

33..66..44..22..  BBrraanncchh

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.

33..66..44..33..  VViieeww PPaatthh HHaacckkiinngg

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.



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





Aegis                                             User Guide


44..  TThhee HHiissttoorryy TTooooll

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.

44..11..  IInntteerrffaacciinngg

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

44..11..11..  hhiissttoorryy__ccrreeaattee__ccoommmmaanndd

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.

44..11..22..  hhiissttoorryy__ggeett__ccoommmmaanndd

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_get_command.

${Output}
     absolute path of destination file





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





User Guide                                             Aegis


In  addition,  all  substitutions  described in _a_e_s_u_b(5) are
available.

44..11..33..  hhiissttoorryy__ppuutt__ccoommmmaanndd

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.

44..11..44..  hhiissttoorryy__qquueerryy__ccoommmmaanndd

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.

44..11..55..   hhiissttoorryy__ccoonntteenntt__lliimmiittaattiioonn TThhiiss ffiieelldd ddeessccrriibbeess tthhee
ccoonntteenntt ssttyyllee wwhhiicchh tthhee hhiissttoorryy ttooooll iiss ccaappaabbllee  ooff  wwoorrkkiinngg
wwiitthh..

ascii_text
     The history tool can only cope with files which contain
     printable  ASCII  characters,  plus  space,   tab   and
     newline.    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.  This is the default.

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
a problem, the file is encoded in  either  the  MIME  quoted



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





Aegis                                             User Guide


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).

44..11..66..  hhiissttoorryy__ttooooll__ttrraasshheess__ffiillee MMaannyy hhiissttoorryy  ttoooollss  ((ee..gg..
RRCCSS))  ccaann mmooddiiffyy tthhee ccoonntteennttss ooff tthhee ffiillee wwhheenn iitt iiss ccoommmmiitt--
tteedd..  WWhhiillee tthheerree aarree uussuuaallllyy ooppttiioonnss ttoo ttuurrnn tthhiiss ooffff,, tthheeyy
aarree  sseellddoomm uusseedd..  TThhee pprroobblleemm iiss:: iiff tthhee ccoommmmiitt cchhaannggeess tthhee
ffiillee,, tthhee ssoouurrccee iinn tthhee rreeppoossiittoorryy nnooww nnoo lloonnggeerr mmaattcchheess tthhee
oobbjjeecctt  ffiillee  iinn  tthhee rreeppoossiittoorryy -- _i_._e_. tthhee hhiissttoorryy ttooooll hhaass
ccoommpprroommiisseedd tthhee rreeffeerreennttiiaall iinntteeggrriittyy ooff tthhee rreeppoossiittoorryy..

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.

44..11..77..  QQuuoottiinngg FFiilleennaammeess

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.



















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





User Guide                                             Aegis


44..22..  UUssiinngg SSCCCCSS

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,  these  command  need  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 insultaes some of the weirdness the SCCS carries
on with, and make sht eommands below comprehensible.

44..22..11..  hhiissttoorryy__ccrreeaattee__ccoommmmaanndd

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.

44..22..22..  hhiissttoorryy__ggeett__ccoommmmaanndd

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




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





Aegis                                             User Guide


${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";


44..22..33..  hhiissttoorryy__ppuutt__ccoommmmaanndd

This  command  is  used to add a new "top-most" entry to the
history file.  This command is always executed as  the  pro-
ject 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-pit \
         -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.

44..22..44..  hhiissttoorryy__qquueerryy__ccoommmmaanndd

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:




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





User Guide                                             Aegis


${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.

44..22..55..  TTeemmppllaatteess

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 --yy  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.

44..22..66..  BBiinnaarryy FFiilleess SSCCCCSS iiss  uunnaabbllee  ttoo  ccooppee  wwiitthh  bbiinnaarryy
ffiilleess..   HHoowweevveerr,,  AAeeggiiss  wwiillll ttrraannssppaarreennttllyy eennccooddee aallll ssuucchh
ffiilleess,, iiff yyoouu  lleeaavvee  tthhee  _h_i_s_t_o_r_y___c_o_n_t_e_n_t___l_i_m_i_t_a_t_i_o_n  ffiieelldd
uunnsseett..






















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





Aegis                                             User Guide


44..33..  UUssiinngg RRCCSS

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.

44..33..11..  hhiissttoorryy__ccrreeaattee__ccoommmmaanndd

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.





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





User Guide                                             Aegis


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.

44..33..22..  hhiissttoorryy__ggeett__ccoommmmaanndd

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.

44..33..33..  hhiissttoorryy__ppuutt__ccoommmmaanndd

This command is used to add a new "top-most"  entry  to  the
history  file.   This command is always executed as the pro-
ject 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";





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





Aegis                                             User Guide


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.

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.

44..33..44..  hhiissttoorryy__qquueerryy__ccoommmmaanndd

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 '/^head:/ {print $$2}'";


44..33..55..  mmeerrggee__ccoommmmaanndd

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
also available:

${ORiginal}
     The absolute path name of a file containing the version



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





User Guide                                             Aegis


     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.)

WWaarrnniinngg::  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.

44..33..66..   RReeffeerreennttiiaall IInntteeggrriittyy MMaannyy hhiissttoorryy ttoooollss ((iinncclluuddiinngg
RRCCSS)) ccaann mmooddiiffyy tthhee ccoonntteennttss ooff tthhee ffiillee wwhheenn iitt iiss  ccoommmmiitt--
tteedd..  WWhhiillee tthheerree aarree uussuuaallllyy ooppttiioonnss ttoo ttuurrnn tthhiiss ooffff,, tthheeyy
aarree sseellddoomm uusseedd..  TThhee pprroobblleemm iiss:: iiff tthhee ccoommmmiitt cchhaannggeess  tthhee
ffiillee,, tthhee ssoouurrccee iinn tthhee rreeppoossiittoorryy nnooww nnoo lloonnggeerr mmaattcchheess tthhee
oobbjjeecctt ffiillee iinn tthhee rreeppoossiittoorryy -- _i_._e_. tthhee  hhiissttoorryy  ttooooll  hhaass
ccoommpprroommiisseedd tthhee rreeffeerreennttiiaall iinntteeggrriittyy ooff tthhee rreeppoossiittoorryy..




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





Aegis                                             User Guide


     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.

44..33..77..  TTeemmppllaatteess

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 --mm  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.

44..33..88..  BBiinnaarryy FFiilleess RRCCSS ((vveerrssiioonn 55..66 aanndd llaatteerr)) iiss aabbllee  ttoo
ccooppee  wwiitthh  bbiinnaarryy ffiilleess..  IItt ddooeess ssoo bbyy ssaavviinngg aa wwhhoollee ccooppyy
ooff tthhee ffiillee aatt eeaacchh cchheecckk--iinn..

     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.

44..33..99..  hhiissttoorryy__ppuutt__ttrraasshheess__ffiilleess IIff yyoouu uussee  RRCCSS  kkeeyywwoorrddss,,
ssuucchh  aass  $$id$$ oorr $$log$$,, tthhiiss wwiillll rreessuulltt iinn tthhee ffiillee iinn tthhee
bbaasseelliinnee bbeeiinngg cchhaannggeedd bbyy RRCCSS aatt iinntteeggrraattee  ppaassss..   TThhiiss  iiss
_a_f_t_e_r  tthhee  bbuuiilldd..   TThhee  rreessuulltt iiss tthhaatt tthhee ssoouurrccee ffiilleess nnoo
lloonnggeerr mmaattcchh tthhee oobbjjeecctt ffiilleess..  OOooppss..

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.



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





User Guide                                             Aegis


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.













































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





Aegis                                             User Guide


44..44..  UUssiinngg ffhhiisstt

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.

44..44..11..  hhiissttoorryy__ccrreeaattee__ccoommmmaanndd

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.

44..44..22..  hhiissttoorryy__ggeett__ccoommmmaanndd

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





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





User Guide                                             Aegis


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.

44..44..33..  hhiissttoorryy__ppuutt__ccoommmmaanndd

This command is used to add a new "top-most"  entry  to  the
history  file.   This command is always executed as the pro-
ject 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.


44..44..44..  hhiissttoorryy__qquueerryy__ccoommmmaanndd

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:







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





Aegis                                             User Guide


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


44..44..55..  TTeemmppllaatteess

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.

44..44..66..  CCaappaabbiilliittiieess

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.

44..44..77..  BBiinnaarryy FFiilleess

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.   is
unable to cope with binary files.

     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  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 set
for international text.  In some cases, Aegis' encoding will
be  more efficient that fhist's.  And you have the advantage
of being able to change your mind later.




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





User Guide                                             Aegis


44..55..  DDeetteeccttiinngg FFiillee CCoorrrruuppttiioonn

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.

44..55..11..  GGeenneerraall MMeetthhoodd

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 pro-
   ject 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 - yesterday's.




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





Aegis                                             User Guide


44..55..22..  CCoonnffiigguurraattiioonn CCoommmmaannddss

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_.

44..55..33..  AAeeggiiss'' DDaattaabbaassee

In  addition  to  your  history  files,  Aegis  maintains  a
database 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.







Peter Miller     (lib/en/user-guide/c4.0.so)         Page 99





User Guide                                             Aegis


55..  TThhee DDeeppeennddeennccyy MMaaiinntteennaannccee TTooooll

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.

55..11..  RReeqquuiirreedd FFeeaattuurreess

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.

55..11..11..  SSeeaarrcchh LLiissttss

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.)



Page 100         (lib/en/user-guide/c4.1.so)    Peter Miller





Aegis                                             User Guide


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.

55..11..22..  DDyynnaammiicc IInncclluuddee FFiillee DDeeppeennddeenncciieess

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 re 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.

55..11..22..11..  SSttaattiicc FFiillee

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




Peter Miller     (lib/en/user-guide/c4.1.so)        Page 101





User Guide                                             Aegis


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.

55..11..22..22..  DDyynnaammiicc

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.



Page 102         (lib/en/user-guide/c4.2.so)    Peter Miller





Aegis                                             User Guide


55..22..  UUssiinngg CCooookk

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.

55..22..11..  IInnvvookkiinngg CCooookk

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 files must be  removed  first,  otherwise  the  baseline
would cease to be self-consistent.

55..22..22..  TThhee RReecciippee FFiillee

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.



Peter Miller     (lib/en/user-guide/c4.2.so)        Page 103





User Guide                                             Aegis


     project_files =
       [collect aegis -l pf -terse
         -p [project] -c [change]];
     change_files =
       [collect aegis -l cf -terse
         -p [project] -c [change]];
     source_files =
       [sort [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;
     }





Page 104         (lib/en/user-guide/c4.2.so)    Peter Miller





Aegis                                             User Guide


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.

55..22..33..  TThhee RReecciippee ffoorr CC

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:






Peter Miller     (lib/en/user-guide/c4.2.so)        Page 105





User Guide                                             Aegis


     %.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.

55..22..33..11..  CC IInncclluuddee SSeemmaannttiiccss

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.



Page 106         (lib/en/user-guide/c4.2.so)    Peter Miller





Aegis                                             User Guide


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.

55..22..44..  TThhee RReecciippee ffoorr YYaacccc

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.






Peter Miller     (lib/en/user-guide/c4.2.so)        Page 107





User Guide                                             Aegis


55..22..55..  TThhee RReecciippee ffoorr LLeexx

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.

55..22..66..  RReecciippeess ffoorr DDooccuummeennttss

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












Page 108         (lib/en/user-guide/c4.2.so)    Peter Miller





Aegis                                             User Guide


     %.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];
     }


55..22..77..  TTeemmppllaatteess

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.






































Peter Miller     (lib/en/user-guide/c4.3.so)        Page 109





User Guide                                             Aegis


55..33..  UUssiinngg CCaakkee

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
archives 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.

55..33..11..  IInnvvookkiinngg CCaakkee

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 files 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.

55..33..22..  TThhee RRuulleess FFiillee

The  file  containing  the  rules  is called _C_a_k_e_f_i_l_e and is
given to cake on the command line.



Page 110         (lib/en/user-guide/c4.3.so)    Peter Miller





Aegis                                             User Guide


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.

55..33..33..  TThhee RRuullee ffoorr CC

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.





Peter Miller     (lib/en/user-guide/c4.3.so)        Page 111





User Guide                                             Aegis


     %.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 exists, 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.

55..33..33..11..  IInncclluuddee DDiirreeccttiivveess

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.

55..33..44..  TThhee RRuullee ffoorr YYaacccc

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



Page 112         (lib/en/user-guide/c4.3.so)    Peter Miller





Aegis                                             User Guide


with the example.

Cake's ability to cope  with  transitive  dependencies  will
pick up the generated _._c file and construct the necessary _._o
file.

55..33..55..  TThhee RRuullee ffoorr LLeexx

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.

55..33..66..  RRuulleess ffoorr DDooccuummeennttss

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








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





User Guide                                             Aegis


55..44..  UUssiinngg MMaakkee

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.

55..44..11..  IInnvvookkiinngg MMaakkee

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.



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





Aegis                                             User Guide


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.

55..44..22..  TThhee RRuullee FFiillee

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




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





User Guide                                             Aegis


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.

55..44..33..  TThhee RRuullee ffoorr CC

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  (because the integrator will not have write



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





Aegis                                             User Guide


permission on the integration directory).

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.

55..44..33..11..  IInncclluuddee DDiirreeccttiivveess

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.

55..44..44..  TThhee RRuullee ffoorr YYaacccc

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:









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





User Guide                                             Aegis


     .PRECIOUS: \
       $(patsubst %.y,%.c,$(filter \
         %.y,$(source_files)))     \
       $(patsubst %.y,%.h,$(filter \
         %.y,$(source_files)))


55..44..55..  TThhee RRuullee ffoorr LLeexx

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)))


55..44..66..  RRuulleess ffoorr DDooccuummeennttss

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






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





Aegis                                             User Guide


     %.cat: %.man
       rm $*.cat
       groff -Tascii -s -t -man $*.man \
         > $*.cat


55..44..77..  OOtthheerr MMaakkeess

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.

55..44..88..  TTeemmppllaatteess

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.

55..44..99..  GGNNUU MMaakkee VVPPAATTHH PPaattcchh

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.





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





User Guide                                             Aegis


55..44..1100..  GGNNUU MMaakkee''ss VVAAPPTTHH++ IInn tthheeoorryy,, uussiinngg GGNNUU MMaakkee 33..7766 oorr
llaatteerr ((oorr aa ssuuiittaabbllee ppaattcchheedd eeaarrlliieerr vveerrssiioonn)) iiss ssiimmiillaarr  ttoo
uussiinngg CCooookk..  TThhee pprroojjeecctt _c_o_n_f_i_g ffiillee nnooww rreeqquuiirreess

     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.













































Page 120         (lib/en/user-guide/c8.0.so)    Peter Miller





Aegis                                             User Guide


66..  TThhee DDiiffffeerreennccee TToooollss

This chapter describes the difference commands in  the  pro-
ject 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.

66..11..  IInntteerrffaacciinngg

The build commands are accessed from two fields of the  pro-
ject configuration file (_c_o_n_f_i_g).

66..11..11..  ddiiffff__ccoommmmaanndd

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:

${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
-----------
  19 Or this is logically the case.



Peter Miller     (lib/en/user-guide/c8.1.so)        Page 121





User Guide                                             Aegis


difference files must be produced in addition to these extra
tests.

66..11..22..  mmeerrggee__ccoommmmaanndd

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
means something is wrong.





















Page 122         (lib/en/user-guide/c8.2.so)    Peter Miller





Aegis                                             User Guide


66..22..  UUssiinngg ddiiffff aanndd mmeerrggee

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.

66..22..11..  ddiiffff__ccoommmmaanndd

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 --ee 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.

66..22..22..  mmeerrggee__ccoommmmaanndd

The entry in the _c_o_n_f_i_g file looks like this:

     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.
+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







Peter Miller     (lib/en/user-guide/c8.3.so)        Page 123





User Guide                                             Aegis


standard output, which are redirected into the $output file.

66..33..  UUssiinngg ffhhiisstt

The ffhhiisstt 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.

66..33..11..  ddiiffff__ccoommmmaanndd

The entry in the _c_o_n_f_i_g file looks like this:

     diff_command =
       "fcomp -w $original $input \
        -o $output";


The  --ww  option  produces an output of the entire file, with
insertions an 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.

66..33..22..  mmeerrggee__ccoommmmaanndd

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
the output.  For more information, see the _f_m_e_r_g_e(1)  manual
entry.

















Page 124         (lib/en/user-guide/c5.0.so)    Peter Miller





Aegis                                             User Guide


77..  TThhee PPrroojjeecctt AAttttrriibbuutteess

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.

77..11..  DDeessccrriippttiioonn aanndd AAcccceessss

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.

77..22..  NNoottiiffiiccaattiioonn CCoommmmaannddss

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 125





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.

77..22..11..  NNoottiiffiiccaattiioonn bbyy eemmaaiill

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 126         (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.

77..22..22..  NNoottiiffiiccaattiioonn bbyy UUSSEENNEETT

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 127





User Guide                                             Aegis


77..33..  EExxeemmppttiioonn CCoonnttrroollss

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.  This
field is true if developers may created 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.

77..33..11..  OOnnee PPeerrssoonn PPrroojjeeccttss

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 128         (lib/en/user-guide/c5.0.so)    Peter Miller





Aegis                                             User Guide


77..33..22..  TTwwoo PPeerrssoonn PPrroojjeeccttss

A two person project has the opportunity for each to  review
the other's work.

The  entries in the project attributes file for a one 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.

77..33..33..  LLaarrggeerr PPrroojjeeccttss

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 one  person
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 developer.  As the
teams get larger, the more experienced staff are  often  the
reviewers, rather than everyone.





















Peter Miller    (lib/en/user-guide/c11.0.so)        Page 129





User Guide                                             Aegis


88..  TTeessttiinngg

This  chapter  discusses  testing, and using Aegis to manage
your tests and testing.

88..11..  WWhhyy BBootthheerr??

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
sights the code and finds  potential  problems  before  they
manifest  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
having  a  baseline  and  separate  development  directories
allows  multiple  parallel development, with no inter-devel-
oper 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.

88..11..11..  PPrroojjeeccttss ffoorr wwhhiicchh AAeeggiiss'' TTeessttiinngg iiss MMoosstt SSuuiittaabbllee

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 130        (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.

88..11..22..  PPrroojjeeccttss ffoorr wwhhiicchh AAeeggiiss'' TTeessttiinngg iiss UUsseeffuull

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.

88..11..22..11..  TTeessttiinngg VViiaa EEmmuullaattoorrss

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 on no freely available emulators suit-
able  for testing via Aegis.  If you find one, please let me
know.

88..11..22..22..  LLiimmiitteedd TTeessttiinngg

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.

88..11..22..33..  TTeessttiinngg MMooddee

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 131





User Guide                                             Aegis


Cost of development, cost of storage space for  X11  images,
cost of _n_o_t testing.

88..11..22..44..  MMaannuuaall TTeessttss

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.

88..11..22..55..  UUnniitt TTeessttss MMaannyy ffoollkkss tthhiinnkk ooff tteessttiinngg  aass  ttaakkiinngg
tthhee  ffiinnaall  pprroodduucctt  aanndd tteessttiinngg iitt..  IItt iiss aallssoo ppoossssiibbllee ttoo
bbuuiilldd ssppeecciiaalliizzeedd uunniitt tteessttss,, wwhhiicchh eexxeerrcciissee  ssppeecciiffiicc  ppoorr--
ttiioonnss ooff tthhee ccooddee..  TThheessee tteessttss ccaann tthheenn bbee aaddmmiinniissttrraatteedd bbyy
AAeeggiiss,, eevveenn iiff tthhee ffuullll--bblloowwnn GGUUII ccaannnnoott bbee..

88..11..33..  PPrroojjeeccttss ffoorr wwhhiicchh AAeeggiiss'' TTeessttiinngg iiss LLeeaasstt UUsseeffuull

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.

88..11..33..11..  OOppeerraattiinngg SSyysstteemmss

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
by using computers connected to each serial line to simulate
"user input".  The system can  be  rebooted  this  way,  and



Page 132        (lib/en/user-guide/c11.1.so)    Peter Miller





Aegis                                             User Guide


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.

88..11..33..22..  FFiirrmmwwaarree

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  on  natively  on the build system.  The
firmware (in the host incarnation) then falls  into  one  of
the  categories 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 133





User Guide                                             Aegis


88..22..  WWrriittiinngg TTeessttss

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.

88..22..11..  CCoonnttrriibbuuttoorrss

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.

88..22..22..  GGeenneerraall GGuuiiddeelliinneess

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.

88..22..22..11..  CChhooiiccee ooff SSccrriippttiinngg LLaanngguuaaggee

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 134        (lib/en/user-guide/c11.2.so)    Peter Miller





Aegis                                             User Guide


as client-server model interfaces, and  multi-user  synchro-
nization testing.

88..22..22..22..  NNoo EExxeeccuuttee PPeerrmmiissssiioonn

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


88..22..22..33..  NNoo CCoommmmaanndd--LLiinnee AArrgguummeennttss

Tests  should  not expect command line arguments.  Tests are
not passed the name of the project nor  the  number  of  the
change.

88..22..22..44..  IIddeennttiiffyyiinngg tthhee SSccrriippttiinngg LLaanngguuaaggee

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.

88..22..22..55..  CCuurrrreenntt DDiirreeccttoorryy

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.

88..22..22..66..  CChheecckk EExxiitt SSttaattuuss aanndd RReettuurrnn VVaalluueess

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 135





User Guide                                             Aegis


88..22..22..77..  TTeemmppoorraarryy DDiirreeccttoorryy

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.

88..22..22..88..  TTrraapp IInntteerrrruuppttss

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.

88..22..22..99..  PPAAGGEERR

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).

88..22..22..1100..  AAuuxxiilliiaarryy FFiilleess

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 136        (lib/en/user-guide/c11.2.so)    Peter Miller





Aegis                                             User Guide


88..22..22..1111..  NNeeww TTeesstt TTeemmppllaatteess

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.

88..22..33..  BBoouurrnnee SShheellll

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.


88..22..33..11..  MMaaggiicc NNuummbbeerr

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.

88..22..33..22..  CChheecckk EExxiitt SSttaattuuss

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.

88..22..33..33..  TTeemmppoorraarryy DDiirreeccttoorryy

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.

88..22..33..44..  TTrraapp IInntteerrrruuppttss

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 137





User Guide                                             Aegis


test requires, such as removing the temporary directory.

88..22..33..55..  AAuuxxiilliiaarryy FFiilleess

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.

88..22..33..66..  [[ tteesstt ]]

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.

88..22..33..77..  OOtthheerr BBoouurrnnee SShheellll PPoorrttaabbiilliittyy IIssssuueess

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.

88..22..44..  PPeerrll

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.

88..22..44..11..  MMaaggiicc NNuummbbeerr

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 138        (lib/en/user-guide/c11.2.so)    Peter Miller





Aegis                                             User Guide


88..22..44..22..  CChheecckk RReettuurrnn VVaalluueess

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.

88..22..44..33..  TTeemmppoorraarryy DDiirreeccttoorryy

Perl  test scripts should create a temporary subdirectory in
_/_t_m_p (or the directory specified by the  $$EENNVV{{TTMMPPDDIIRR}}  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);


88..22..44..44..  TTrraapp IInntteerrrruuppttss

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) };


88..22..44..55..  AAuuxxiilliiaarryy FFiilleess

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.

88..22..44..66..  EExxiitt VVaalluueess

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 139





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.

88..22..44..77..  MMoodduulleess

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 --II 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 aauuxx:

     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_.

88..22..44..88..  TThhee TTeesstt::::CCmmdd MMoodduullee

A  Test::Cmd  module is available on CPAN (the Comprehensive
Perl Archive Network) that  makes  it  easy  to  write  Perl



Page 140        (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
portable to any operating system that runs Perl and the pro-
gram under test.

The Test::Cmd module is available on CPAN.  See the module's
documentation for details.

88..22..44..99..  TThhee TTeesstt aanndd TTeesstt::::HHaarrnneessss MMoodduulleess

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 141





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 AAEEGGIISS__TTEESSTT 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  //ddeevv//nnuullll   and
restricting  its  reporting of results to a simple FFAAIILLEEDD 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 142        (lib/en/user-guide/c11.2.so)    Peter Miller





Aegis                                             User Guide


checked in to the project.

88..22..44..1100..  GGrraannuullaarriittyy BByy _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 143





User Guide                                             Aegis


the coarser PASSED/FAILED status.

88..22..55..  BBaattcchh TTeessttiinngg

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 144         (lib/en/user-guide/c9.0.so)    Peter Miller





Aegis                                             User Guide


99..  BBrraanncchhiinngg

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
                 --------------------------
                         Baseline

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
in time.

The commonest 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, deeper branches.  This  may  recurse  to  any  level.
Once a branch is complete, no further deeper branches may be
created from that branch.

99..11..  HHooww TToo UUssee BBrraanncchhiinngg

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 a "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".

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 --VVEERRSSiioonn option to make this deeper or shallower,
or have different numbering.












Peter Miller     (lib/en/user-guide/c9.0.so)        Page 145





User Guide                                             Aegis


              +------------+------------------+
              |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).

99..22..  TTrraannssiittiioonn UUssiinngg aaeennrrllss

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
then  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-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 time 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).

99..33..  CCrroossss BBrraanncchh MMeerrggee

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 --BBRRaanncchh option
to the _a_e_g_i_s _-_d_i_f_f _-_m_e_r_g_e_-_o_n_l_y command.



Page 146         (lib/en/user-guide/c9.0.so)    Peter Miller





Aegis                                             User Guide


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.

99..44..  MMuullttiippllee BBrraanncchh DDeevveellooppmmeenntt

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.

99..55..  HHiieerraarrcchhyy ooff PPrroojjeeccttss

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.

99..55..11..  FFuunnddaammeennttaallss

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

     % aaeennpprr ggiizzmmoo..00..11
     project "gizmo": created
     project "gizmo.0": created
     project "gizmo.0.1": created
     %


Now,  for  each of your desired sub-projects, create another
branch







Peter Miller     (lib/en/user-guide/c9.1.so)        Page 147





User Guide                                             Aegis


     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.

99..55..22..  IInnccrreemmeennttaall IInntteeggrraattiioonn

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.

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  and  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.





Page 148         (lib/en/user-guide/c9.1.so)    Peter Miller





Aegis                                             User Guide


An  unsuccessful  branch  integration  leaves the repository
unchanged, just as an unsuccessful change integration leaves
it unchanged.


99..55..33..  SSuuppeerr--PPrroojjeecctt BBrraanncchhiinngg

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.

99..55..44..  SSuuppeerr--PPrroojjeecctt TTeessttiinngg

Many folks see Aegis' testing features as  useful  for  unit
testing  individual  files  or  change sets.  For large pro-
jects, it is common that a specific test tool will be  writ-
ten.   However, even large scale integration testing is pos-
sible 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.

99..55..55..  TThhee NNeexxtt CCyyccllee

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




Peter Miller     (lib/en/user-guide/c9.1.so)        Page 149





User Guide                                             Aegis


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.

99..55..66..  BBuugg FFiixxiinngg

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).

99..66..  CCoonnfflliicctt RReessoolluuttiioonn

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  to to _a_e_d_e(1) the
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.

99..66..11..  CCrroossss BBrraanncchh MMeerrggee

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.





Page 150         (lib/en/user-guide/c9.2.so)    Peter Miller





Aegis                                             User Guide


+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.   IInn  aaddddiittiioonn  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.

[] Once _a_e_i_p_a_s_s is successful, the branch will be up-to-date
   (for the files in the change).

99..66..22..  IInnssuullaattiioonn

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 describes, _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



Peter Miller     (lib/en/user-guide/c9.2.so)        Page 151





User Guide                                             Aegis


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.

99..66..22..11..  BBrraanncchh IInnssuullaatteedd AAggaaiinnsstt PPrroojjeecctt

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.

99..66..22..22..  PPrroojjeecctt IInnssuullaatteedd AAggaaiinnsstt BBrraanncchh

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.

99..66..22..33..  MMiixx ''nn'' MMaattcchh

Of course, we usually have both these motives, and some more
besides, so the answer is usually ``it depends''.


























Page 152         (lib/en/user-guide/c6.0.so)    Peter Miller





Aegis                                             User Guide


1100..  TTiippss aanndd TTrraappss

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.

1100..11..  RReennaammiinngg IInncclluuddee FFiilleess

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.

1100..22..  SSyymmbboolliicc LLiinnkkss

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 153





User Guide                                             Aegis


     develop_begin_command =
             "ln -s $baseline bl";

into the project _c_o_n_f_i_g file.

1100..33..  UUsseerr SSeettuupp

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.

1100..33..11..  TThhee ..ccsshhrrcc oorr ..pprrooffiillee ffiilleess

The  aliases  for  the various user commands used throughout
this manual are obtained by appending a line of the form

     source /usr/local/lib/aegis/cshrc

to the _._c_s_h_r_c file in the user's home directory.

1100..33..22..  TThhee AAEEGGIISS__PPAATTHH eennvviirroonnmmeenntt vvaarriiaabbllee

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).

The _A_E_G_I_S___P_A_T_H environment variable should  be  set  in  the
_._c_s_h_r_c  file  in the user's home directory.  Typical setting
is

     setenv AEGIS_PATH ~/lib/aegis

and  this  is  the  default  used  in  the  _/_u_s_r_/_l_o_c_a_l_/_l_i_b_/_-
_a_e_g_i_s_/_c_s_h_r_c file.

1100..33..33..  TThhee ..aaeeggiissrrcc ffiillee

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.

1100..33..44..  TThhee ddeeffaauullttiinngg mmeecchhaanniissmm

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.





Page 154         (lib/en/user-guide/c6.0.so)    Peter Miller





Aegis                                             User Guide


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.

1100..44..  TThhee PPrroojjeecctt OOwwnneerr

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
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.

1100..55..  UUSSEENNEETT PPuubblliiccaattiioonn SSttaannddaarrddss

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:



-----------
  21 Unless bugs in aegis corrupt the database, in
which case repairs can be accomplished as the pro-
ject account using a text editor.



Peter Miller     (lib/en/user-guide/c6.0.so)        Page 155





User Guide                                             Aegis


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.

1100..55..11..  CCHHAANNGGEESS

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.

1100..55..22..  MMAANNIIFFEESSTT

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.

1100..55..33..  MMaakkeeffiillee

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.

1100..55..44..  ppaattcchhlleevveell..hh

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.

1100..55..55..  BBuuiillddiinngg PPaattcchh FFiilleess

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.





Page 156         (lib/en/user-guide/c6.0.so)    Peter Miller





Aegis                                             User Guide


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 157





User Guide                                             Aegis


1100..66..  HHeetteerrooggeenneeoouuss DDeevveellooppmmeenntt

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.

1100..66..11..  PPrroojjeecctt _c_o_n_f_i_g FFiillee

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 158         (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.

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
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.

1100..66..22..  CChhaannggee AAttttrriibbuuttee

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.



Peter Miller     (lib/en/user-guide/c6.1.so)        Page 159





User Guide                                             Aegis


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.

1100..66..33..  NNeettwwoorrkk FFiilleess

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.

1100..66..44..  DDMMTT IImmpplliiccaattiioonnss

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
passed  to the DMT using the _b_u_i_l_d___c_o_m_m_a_n_d field of the pro-
ject _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.

1100..66..44..11..  CCooookk EExxaammppllee

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:

-----------
  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 160         (lib/en/user-guide/c6.1.so)    Peter Miller





Aegis                                             User Guide


     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:

     [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:












Peter Miller     (lib/en/user-guide/c6.1.so)        Page 161





User Guide                                             Aegis


     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.

1100..66..55..  TTeesstt IImmpplliiccaattiioonnss

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.

1100..66..66..  CCrroossss CCoommppiilliinngg

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.

1100..66..77..  FFiillee VVeerrssiioonn bbyy AArrcchhiitteeccttuurree

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.


-----------
  25 Some  other  SCM  tools  provide a repository
with this facility.



Page 162         (lib/en/user-guide/c6.1.so)    Peter Miller





Aegis                                             User Guide


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.

1100..77..  RReemmiinnddeerrss

This  section documents some scripts available for reminding
users of  changes  which  require  their  attention.   These
scripts   are  installed  into  the  _/_u_s_r_/_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.

1100..77..11..  AAwwaaiittiinngg DDeevveellooppmmeenntt

The _/_u_s_r_/_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  pro-
ject 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 devel-
opers 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 outstanding.

1100..77..22..  BBeeiinngg DDeevveellooppeedd

The  _/_u_s_r_/_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
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.

1100..77..33..  BBeeiinngg RReevviieewweedd

The _/_u_s_r_/_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  pro-
ject 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.

1100..77..44..  AAwwaaiittiinngg IInntteeggrraattiioonn

The _/_u_s_r_/_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



Peter Miller     (lib/en/user-guide/c6.3.so)        Page 163





User Guide                                             Aegis


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 outstanding.






















































Page 164        (lib/en/user-guide/c10.0.so)    Peter Miller





Aegis                                             User Guide


1111..  GGeeooggrraapphhiiccaallllyy DDiissttrriibbuutteedd DDeevveellooppmmeenntt

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.

1111..11..  IInnttrroodduuccttiioonn

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.

1111..11..11..  RRiisskk RReedduuccttiioonn

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 165





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.

1111..11..22..  WWhhaatt ttoo SSeenndd

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
database,  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.

1111..11..33..  MMeetthhooddss aanndd TTooppoollooggiieess

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 166        (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
(common 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.

1111..11..44..  TThhee RReesstt ooff tthhiiss CChhaapptteerr

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 167





User Guide                                             Aegis


1111..22..  MMaannuuaall OOppeerraattiioonn

This  section describes how to use _a_e_d_i_s_t manually, in order
to send and receive change sets.

1111..22..11..  MMaannuuaall SSeenndd

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
set to joe.blow@example.com, see _a_e_d_i_s_t(1) for more informa-
tion.

1111..22..22..  SSeennddiinngg BBaasseelliinneess

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 168        (lib/en/user-guide/c10.1.so)    Peter Miller





Aegis                                             User Guide


1111..22..33..  SSeennddiinngg BBrraanncchheess

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.

1111..22..44..  MMaannuuaall RReecceeiivvee

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
ddooeess nnoott 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 169





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.

1111..22..55..  GGeettttiinngg SSttaarrtteedd

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.

1111..33..  SSnneeaakkeerr NNeett

Another common method of transporting data, sometimes  quite
large  amount of it, is to write it onto transportable media



Page 170        (lib/en/user-guide/c10.1.so)    Peter Miller





Aegis                                             User Guide


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.

1111..44..  AAuuttoommaattiicc OOppeerraattiioonn

This  section  describes  how to use _a_e_d_i_s_t to automatically
send change sets via e-mail.

1111..44..11..  SSeennddiinngg

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 171





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.

1111..44..22..  RReecceeiivviinngg

_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.

1111..55..  WWoorrlldd WWiiddee WWeebb

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.

1111..55..11..  SSeerrvveerr

_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  the  base64  in  this case, so use the appropriate
option.

1111..55..22..  BBrroowwsseerr

_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.

1111..66..  SSeeccuurriittyy

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 172        (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.

1111..66..11..  TTrroojjaann HHoorrsseess

``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 saw them 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 173





User Guide                                             Aegis


1111..66..22..  PPGGPP

_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_?

1111..66..33..  SSoorrcceerreerr''ss AApppprreennttiiccee

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 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.)

+o Set the description to indicate it was received by aedist?
  Use this to influence the decision to send it off again at



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





Aegis                                             User Guide


  integrate pass?  How?

1111..77..  PPaattcchheess

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.

1111..77..11..  SSeenndd

If  you  are  participating  in  an open source project, and
using Aegis to manage your  development,  the  _a_e_d_i_s_t  _-_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 you 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.

1111..77..22..  RReecceeiivvee

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

     %% 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_._._.
     %%






Peter Miller    (lib/en/user-guide/c10.5.so)        Page 175





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
ddooeess nnoott put the change set directly into the repository.

On  receipt  of  a change set, _a_e_p_a_t_r_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.

1111..77..33..  LLiimmiittaattiioonnss

Despite a great similarity of command  line  operations  and
operation,  the  _a_e_p_a_t_c_h command should nnoott 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_P_;  _i_t _m_u_s_t _w_o_r_k _w_i_t_h _p_a_t_c_h_(_1_)_, _a_n_d _s_i_m_i_l_a_r
_t_o_o_l_s_.

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 176        (lib/en/user-guide/c12.0.so)    Peter Miller





Aegis                                             User Guide


1122..  FFuurrtthheerr RReeaaddiinngg

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.  AEmail me  the
information and I'll add it to this chapter (no advertising,
please).

1122..11..  SSooffttwwaarree CCoonnffiigguurraattiioonn MMaannaaggeemmeenntt

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_.

1122..22..  RReevviieewwiinngg

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 177





User Guide                                             Aegis


1133..  AAppppeennddiixx AA:: NNeeww PPrroojjeecctt QQuuiicckk RReeffeerreennccee

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.

1133..11..  CCrreeaattee tthhee PPrroojjeecctt

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  pro-
ject, 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.

1133..11..11..  AAdddd tthhee SSttaaffff

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.

1133..11..22..  PPrroojjeecctt AAttttrriibbuutteess

The  _a_e_p_a  command  is  used  to  change project attributes.
These attributes include the description of the project, and



Page 178         (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.

1133..22..  CCrreeaattee CChhaannggee OOnnee

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.

1133..33..  DDeevveelloopp CChhaannggee OOnnee

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 change 1.
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 179





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.  At this point, the
mode of the files will be changed to read  only,  preventing
accidental modification of the files.

1133..44..  RReevviieeww TThhee CChhaannggee

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 and 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.

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



Page 180         (lib/en/user-guide/cA.0.so)    Peter Miller





Aegis                                             User Guide


work;  the reviewer must supply a reason for the change his-
tory to record for all time.  Similarly, the  _a_e_d_e_u  command
may  be  used  by  the  developer to resume development of a
change at any time before it is integrated; no stated reason
is required.

1133..55..  IInntteeggrraattee tthhee CChhaannggee

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  pro-
cess,  ensures  that  all of these files are consistent with
each other, that the baseline is self-consistent.  The defi-
nition  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 command can also be used  to  run
"representative"  sets of existing tests, but a full regres-
sion test run is recommended before  a  major  release,  or,
say, weekly if it will complete over the weekend.  This com-
mand 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



Peter Miller     (lib/en/user-guide/cA.0.so)        Page 181





User Guide                                             Aegis


supplied,  and  should  include  relevant  excerpts from the
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.

1133..66..  WWhhaatt ttoo ddoo NNeexxtt

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:

     aaeeggiiss (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
sights the code and finds  potential  problems  before  they
manifest  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
having  a  baseline  and  separate  development  directories
allows  multiple  parallel development, with no inter-devel-
oper interference; and the  baseline  always  works,  it  is



Page 182         (lib/en/user-guide/cA.0.so)    Peter Miller





Aegis                                             User Guide


never  in  an  "in-between"  state.  In each case, not doing
this "extra work" is a false economy.























































Peter Miller     (lib/en/user-guide/cB.0.so)        Page 183





User Guide                                             Aegis


1144..  AAppppeennddiixx BB:: GGlloossssaarryy

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.

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.

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.



Page 184         (lib/en/user-guide/cB.0.so)    Peter Miller





Aegis                                             User Guide


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.  The
     change must have no files associated with it.

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.  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.

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.





Peter Miller     (lib/en/user-guide/cB.0.so)        Page 185





User Guide                                             Aegis


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_ns.

new_change
     The command used to create new changes.

new_change_undo
     The command used to destroy changes.

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 six 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, _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 186         (lib/en/user-guide/cD.0.so)    Peter Miller





Aegis                                             User Guide


1155..  AAppppeennddiixx DD:: WWhhyy iiss AAeeggiiss SSeett--UUiidd--RRoooott??

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 pro-
jects, each with a different owner and group, with a  single
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.

1155..11..  EExxaammpplleess

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 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 187





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 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.  Become the integrator to col-
     lect the integrate fail comments, then become the  pro-
     ject  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.

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:  mem-
bers  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.




Page 188         (lib/en/user-guide/cD.0.so)    Peter Miller





Aegis                                             User Guide


1155..22..  SSoouurrccee DDeettaaiillss

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 189





User Guide                                             Aegis


1166..  AAppppeennddiixx II:: IInntteerrnnaattiioonnaalliizzaattiioonn aanndd LLooccaalliizzaattiioonn

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.

1166..11..  TThhee ````ppoo//eenn..ppoo'''' FFiillee

The ``po'' directory in the source tree contains the various
message  files  needed  to  localize Aegis.  You will find a
``en.po'' file in this directory, it translates ``programmer
cryptic''  into English.  You will see that each message has
a comment attached, describing the message and  the  context
in  which  it  is used.  Many messages also have ``substitu-
tions'' described, which are strings similar to shell  vari-
ables  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.  Of frequent use is the _p_l_u_r_a_l substitution,
which  allows  grammatically  correct  error  messages to be
issued when faced with the singular/plural dictotomy.  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 _e_n_._p_o file
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 has been included, so that you can
read the code  should  context  be  necessary  to  correctly
translate the message.

1166..22..  CChheecckkiinngg tthhee CCooddee

There are a number of keywords you need to have the _x_g_e_t_t_e_x_t
program when extracting message strings.  The  gettext  key-
word is not used directly, because of the substitution mech-
anism wrapped around it.





Page 190         (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 _a_u_x_/_H_o_w_t_o_._c_o_o_k file causes the  messages  to
be  extracted  into  _p_o_/_m_e_s_s_a_g_e_s_._p_o  for checking during the
build.

Assuming the author has  located  all  such  instances,  the
translator  need  only  translate the _p_o_/_e_n_._p_o file, and the
author will add the file to the project on receipt  of  your
translation.










































Peter Miller     (lib/en/user-guide/main.ms)        Page 191





User Guide                                             Aegis


.
























































Page cxcii       (lib/en/user-guide/main.ms)    Peter Miller





Aegis                                             User Guide


                     TTaabbllee ooff CCoonntteennttss


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 . . . . . . . . . . . . . . . . . .  19
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  . . . . . . . . . . . . . . . . . .  20
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.4. The Administrator  . . . . . . . . . . . . . . . . . . .  73
3.4.1. Before You Start . . . . . . . . . . . . . . . . . . .  73
3.4.2. The First Change . . . . . . . . . . . . . . . . . . .  73
3.4.3. The Second Change  . . . . . . . . . . . . . . . . . .  76
3.4.4. The Third Change . . . . . . . . . . . . . . . . . . .  76
3.4.5. The Fourth Change  . . . . . . . . . . . . . . . . . .  76
3.4.6. Administrator Command Summary  . . . . . . . . . . . .  77
3.5. What to do Next  . . . . . . . . . . . . . . . . . . . .  78
3.6. Common Questions . . . . . . . . . . . . . . . . . . . .  78
3.6.1. Insulation . . . . . . . . . . . . . . . . . . . . . .  78
3.6.1.1. Copy Read-Only . . . . . . . . . . . . . . . . . . .  79
3.6.1.2. Branches . . . . . . . . . . . . . . . . . . . . . .  79
3.6.1.3. Builds . . . . . . . . . . . . . . . . . . . . . . .  79
3.6.1.4. Mix-and-Match  . . . . . . . . . . . . . . . . . . .  79
3.6.1.5. Disadvantages  . . . . . . . . . . . . . . . . . . .  79
3.6.2. Partial Check-In . . . . . . . . . . . . . . . . . . .  80
3.6.3. Multiple Active Branches . . . . . . . . . . . . . . .  81
3.6.3.1. Cloning  . . . . . . . . . . . . . . . . . . . . . .  81
3.6.3.2. Ancestral  . . . . . . . . . . . . . . . . . . . . .  81
3.6.4. Collaboration  . . . . . . . . . . . . . . . . . . . .  81
3.6.4.1. Change Owner . . . . . . . . . . . . . . . . . . . .  81
3.6.4.2. Branch . . . . . . . . . . . . . . . . . . . . . . .  82
3.6.4.3. View Path Hacking  . . . . . . . . . . . . . . . . .  82
4. The History Tool . . . . . . . . . . . . . . . . . . . . .  83
4.1. Interfacing  . . . . . . . . . . . . . . . . . . . . . .  83
4.1.1. history_create_command . . . . . . . . . . . . . . . .  83
4.1.2. history_get_command  . . . . . . . . . . . . . . . . .  83
4.1.3. history_put_command  . . . . . . . . . . . . . . . . .  84
4.1.4. history_query_command  . . . . . . . . . . . . . . . .  84
4.1.5. history_content_limitation . . . . . . . . . . . . . .  84
4.1.6. history_tool_trashes_file  . . . . . . . . . . . . . .  85
4.1.7. Quoting Filenames  . . . . . . . . . . . . . . . . . .  85
4.2. Using SCCS . . . . . . . . . . . . . . . . . . . . . . .  86
4.2.1. history_create_command . . . . . . . . . . . . . . . .  86
4.2.2. history_get_command  . . . . . . . . . . . . . . . . .  86
4.2.3. history_put_command  . . . . . . . . . . . . . . . . .  87
4.2.4. history_query_command  . . . . . . . . . . . . . . . .  87



Page mii         (lib/en/user-guide/main.ms)    Peter Miller





Aegis                                             User Guide


4.2.5. Templates  . . . . . . . . . . . . . . . . . . . . . .  88
4.2.6. Binary Files . . . . . . . . . . . . . . . . . . . . .  88
4.3. Using RCS  . . . . . . . . . . . . . . . . . . . . . . .  89
4.3.1. history_create_command . . . . . . . . . . . . . . . .  89
4.3.2. history_get_command  . . . . . . . . . . . . . . . . .  90
4.3.3. history_put_command  . . . . . . . . . . . . . . . . .  90
4.3.4. history_query_command  . . . . . . . . . . . . . . . .  91
4.3.5. merge_command  . . . . . . . . . . . . . . . . . . . .  91
4.3.6. Referential Integrity  . . . . . . . . . . . . . . . .  92
4.3.7. Templates  . . . . . . . . . . . . . . . . . . . . . .  93
4.3.8. Binary Files . . . . . . . . . . . . . . . . . . . . .  93
4.3.9. history_put_trashes_files  . . . . . . . . . . . . . .  93
4.4. Using fhist  . . . . . . . . . . . . . . . . . . . . . .  95
4.4.1. history_create_command . . . . . . . . . . . . . . . .  95
4.4.2. history_get_command  . . . . . . . . . . . . . . . . .  95
4.4.3. history_put_command  . . . . . . . . . . . . . . . . .  96
4.4.4. history_query_command  . . . . . . . . . . . . . . . .  96
4.4.5. Templates  . . . . . . . . . . . . . . . . . . . . . .  97
4.4.6. Capabilities . . . . . . . . . . . . . . . . . . . . .  97
4.4.7. Binary Files . . . . . . . . . . . . . . . . . . . . .  97
4.5. Detecting File Corruption  . . . . . . . . . . . . . . .  98
4.5.1. General Method . . . . . . . . . . . . . . . . . . . .  98
4.5.2. Configuration Commands . . . . . . . . . . . . . . . .  99
4.5.3. Aegis' Database  . . . . . . . . . . . . . . . . . . .  99
5. The Dependency Maintenance Tool  . . . . . . . . . . . . . 100
5.1. Required Features  . . . . . . . . . . . . . . . . . . . 100
5.1.1. Search Lists . . . . . . . . . . . . . . . . . . . . . 100
5.1.2. Dynamic Include File Dependencies  . . . . . . . . . . 101
5.1.2.1. Static File  . . . . . . . . . . . . . . . . . . . . 101
5.1.2.2. Dynamic  . . . . . . . . . . . . . . . . . . . . . . 102
5.2. Using Cook . . . . . . . . . . . . . . . . . . . . . . . 103
5.2.1. Invoking Cook  . . . . . . . . . . . . . . . . . . . . 103
5.2.2. The Recipe File  . . . . . . . . . . . . . . . . . . . 103
5.2.3. The Recipe for C . . . . . . . . . . . . . . . . . . . 105
5.2.3.1. C Include Semantics  . . . . . . . . . . . . . . . . 106
5.2.4. The Recipe for Yacc  . . . . . . . . . . . . . . . . . 107
5.2.5. The Recipe for Lex . . . . . . . . . . . . . . . . . . 108
5.2.6. Recipes for Documents  . . . . . . . . . . . . . . . . 108
5.2.7. Templates  . . . . . . . . . . . . . . . . . . . . . . 109
5.3. Using Cake . . . . . . . . . . . . . . . . . . . . . . . 110
5.3.1. Invoking Cake  . . . . . . . . . . . . . . . . . . . . 110
5.3.2. The Rules File . . . . . . . . . . . . . . . . . . . . 110
5.3.3. The Rule for C . . . . . . . . . . . . . . . . . . . . 111
5.3.3.1. Include Directives . . . . . . . . . . . . . . . . . 112
5.3.4. The Rule for Yacc  . . . . . . . . . . . . . . . . . . 112
5.3.5. The Rule for Lex . . . . . . . . . . . . . . . . . . . 113
5.3.6. Rules for Documents  . . . . . . . . . . . . . . . . . 113
5.4. Using Make . . . . . . . . . . . . . . . . . . . . . . . 114
5.4.1. Invoking Make  . . . . . . . . . . . . . . . . . . . . 114
5.4.2. The Rule File  . . . . . . . . . . . . . . . . . . . . 115
5.4.3. The Rule for C . . . . . . . . . . . . . . . . . . . . 116
5.4.3.1. Include Directives . . . . . . . . . . . . . . . . . 117
5.4.4. The Rule for Yacc  . . . . . . . . . . . . . . . . . . 117
5.4.5. The Rule for Lex . . . . . . . . . . . . . . . . . . . 118



Peter Miller     (lib/en/user-guide/main.ms)       Page miii





User Guide                                             Aegis


5.4.6. Rules for Documents  . . . . . . . . . . . . . . . . . 118
5.4.7. Other Makes  . . . . . . . . . . . . . . . . . . . . . 119
5.4.8. Templates  . . . . . . . . . . . . . . . . . . . . . . 119
5.4.9. GNU Make VPATH Patch . . . . . . . . . . . . . . . . . 119
5.4.10. GNU Make's VAPTH+ . . . . . . . . . . . . . . . . . . 120
6. The Difference Tools . . . . . . . . . . . . . . . . . . . 121
6.1. Interfacing  . . . . . . . . . . . . . . . . . . . . . . 121
6.1.1. diff_command . . . . . . . . . . . . . . . . . . . . . 121
6.1.2. merge_command  . . . . . . . . . . . . . . . . . . . . 122
6.2. Using diff and merge . . . . . . . . . . . . . . . . . . 123
6.2.1. diff_command . . . . . . . . . . . . . . . . . . . . . 123
6.2.2. merge_command  . . . . . . . . . . . . . . . . . . . . 123
6.3. Using fhist  . . . . . . . . . . . . . . . . . . . . . . 124
6.3.1. diff_command . . . . . . . . . . . . . . . . . . . . . 124
6.3.2. merge_command  . . . . . . . . . . . . . . . . . . . . 124
7. The Project Attributes . . . . . . . . . . . . . . . . . . 125
7.1. Description and Access . . . . . . . . . . . . . . . . . 125
7.2. Notification Commands  . . . . . . . . . . . . . . . . . 125
7.2.1. Notification by email  . . . . . . . . . . . . . . . . 126
7.2.2. Notification by USENET . . . . . . . . . . . . . . . . 127
7.3. Exemption Controls . . . . . . . . . . . . . . . . . . . 128
7.3.1. One Person Projects  . . . . . . . . . . . . . . . . . 128
7.3.2. Two Person Projects  . . . . . . . . . . . . . . . . . 129
7.3.3. Larger Projects  . . . . . . . . . . . . . . . . . . . 129
8. Testing  . . . . . . . . . . . . . . . . . . . . . . . . . 130
8.1. Why Bother?  . . . . . . . . . . . . . . . . . . . . . . 130
8.1.1. Projects for which Aegis' Testing is Most Suitable
 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130
8.1.2. Projects for which Aegis' Testing is Useful  . . . . . 131
8.1.2.1. Testing Via Emulators  . . . . . . . . . . . . . . . 131
8.1.2.2. Limited Testing  . . . . . . . . . . . . . . . . . . 131
8.1.2.3. Testing Mode . . . . . . . . . . . . . . . . . . . . 131
8.1.2.4. Manual Tests . . . . . . . . . . . . . . . . . . . . 132
8.1.2.5. Unit Tests . . . . . . . . . . . . . . . . . . . . . 132
8.1.3. Projects for which Aegis' Testing is Least Useful
 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132
8.1.3.1. Operating Systems  . . . . . . . . . . . . . . . . . 132
8.1.3.2. Firmware . . . . . . . . . . . . . . . . . . . . . . 133
8.2. Writing Tests  . . . . . . . . . . . . . . . . . . . . . 134
8.2.1. Contributors . . . . . . . . . . . . . . . . . . . . . 134
8.2.2. General Guidelines . . . . . . . . . . . . . . . . . . 134
8.2.2.1. Choice of Scripting Language . . . . . . . . . . . . 134
8.2.2.2. No Execute Permission  . . . . . . . . . . . . . . . 135
8.2.2.3. No Command-Line Arguments  . . . . . . . . . . . . . 135
8.2.2.4. Identifying the Scripting Language . . . . . . . . . 135
8.2.2.5. Current Directory  . . . . . . . . . . . . . . . . . 135
8.2.2.6. Check Exit Status and Return Values  . . . . . . . . 135
8.2.2.7. Temporary Directory  . . . . . . . . . . . . . . . . 136
8.2.2.8. Trap Interrupts  . . . . . . . . . . . . . . . . . . 136
8.2.2.9. PAGER  . . . . . . . . . . . . . . . . . . . . . . . 136
8.2.2.10. Auxiliary Files . . . . . . . . . . . . . . . . . . 136
8.2.2.11. New Test Templates  . . . . . . . . . . . . . . . . 137
8.2.3. Bourne Shell . . . . . . . . . . . . . . . . . . . . . 137
8.2.3.1. Magic Number . . . . . . . . . . . . . . . . . . . . 137



Page miv         (lib/en/user-guide/main.ms)    Peter Miller





Aegis                                             User Guide


8.2.3.2. Check Exit Status  . . . . . . . . . . . . . . . . . 137
8.2.3.3. Temporary Directory  . . . . . . . . . . . . . . . . 137
8.2.3.4. Trap Interrupts  . . . . . . . . . . . . . . . . . . 137
8.2.3.5. Auxiliary Files  . . . . . . . . . . . . . . . . . . 138
8.2.3.6. [ test ] . . . . . . . . . . . . . . . . . . . . . . 138
8.2.3.7. Other Bourne Shell Portability Issues  . . . . . . . 138
8.2.4. Perl . . . . . . . . . . . . . . . . . . . . . . . . . 138
8.2.4.1. Magic Number . . . . . . . . . . . . . . . . . . . . 138
8.2.4.2. Check Return Values  . . . . . . . . . . . . . . . . 139
8.2.4.3. Temporary Directory  . . . . . . . . . . . . . . . . 139
8.2.4.4. Trap Interrupts  . . . . . . . . . . . . . . . . . . 139
8.2.4.5. Auxiliary Files  . . . . . . . . . . . . . . . . . . 139
8.2.4.6. Exit Values  . . . . . . . . . . . . . . . . . . . . 139
8.2.4.7. Modules  . . . . . . . . . . . . . . . . . . . . . . 140
8.2.4.8. The Test::Cmd Module . . . . . . . . . . . . . . . . 140
8.2.4.9. The Test and Test::Harness Modules . . . . . . . . . 141
8.2.4.10. Granularity . . . . . . . . . . . . . . . . . . . . 143
8.2.5. Batch Testing  . . . . . . . . . . . . . . . . . . . . 144
9. Branching  . . . . . . . . . . . . . . . . . . . . . . . . 145
9.1. How To Use Branching . . . . . . . . . . . . . . . . . . 145
9.2. Transition Using aenrls  . . . . . . . . . . . . . . . . 146
9.3. Cross Branch Merge . . . . . . . . . . . . . . . . . . . 146
9.4. Multiple Branch Development  . . . . . . . . . . . . . . 147
9.5. Hierarchy of Projects  . . . . . . . . . . . . . . . . . 147
9.5.1. Fundamentals . . . . . . . . . . . . . . . . . . . . . 147
9.5.2. Incremental Integration  . . . . . . . . . . . . . . . 148
9.5.3. Super-Project Branching  . . . . . . . . . . . . . . . 149
9.5.4. Super-Project Testing  . . . . . . . . . . . . . . . . 149
9.5.5. The Next Cycle . . . . . . . . . . . . . . . . . . . . 149
9.5.6. Bug Fixing . . . . . . . . . . . . . . . . . . . . . . 150
9.6. Conflict Resolution  . . . . . . . . . . . . . . . . . . 150
9.6.1. Cross Branch Merge . . . . . . . . . . . . . . . . . . 150
9.6.2. Insulation . . . . . . . . . . . . . . . . . . . . . . 151
9.6.2.1. Branch Insulated Against Project . . . . . . . . . . 152
9.6.2.2. Project Insulated Against Branch . . . . . . . . . . 152
9.6.2.3. Mix 'n' Match  . . . . . . . . . . . . . . . . . . . 152
10. Tips and Traps  . . . . . . . . . . . . . . . . . . . . . 153
10.1. Renaming Include Files  . . . . . . . . . . . . . . . . 153
10.2. Symbolic Links  . . . . . . . . . . . . . . . . . . . . 153
10.3. User Setup  . . . . . . . . . . . . . . . . . . . . . . 154
10.3.1. The .cshrc or .profile files  . . . . . . . . . . . . 154
10.3.2. The AEGIS_PATH environment variable . . . . . . . . . 154
10.3.3. The .aegisrc file . . . . . . . . . . . . . . . . . . 154
10.3.4. The defaulting mechanism  . . . . . . . . . . . . . . 154
10.4. The Project Owner . . . . . . . . . . . . . . . . . . . 155
10.5. USENET Publication Standards  . . . . . . . . . . . . . 155
10.5.1. CHANGES . . . . . . . . . . . . . . . . . . . . . . . 156
10.5.2. MANIFEST  . . . . . . . . . . . . . . . . . . . . . . 156
10.5.3. Makefile  . . . . . . . . . . . . . . . . . . . . . . 156
10.5.4. patchlevel.h  . . . . . . . . . . . . . . . . . . . . 156
10.5.5. Building Patch Files  . . . . . . . . . . . . . . . . 156
10.6. Heterogeneous Development . . . . . . . . . . . . . . . 158
10.6.1. Project _c_o_n_f_i_g File . . . . . . . . . . . . . . . . . 158
10.6.2. Change Attribute  . . . . . . . . . . . . . . . . . . 159



Peter Miller     (lib/en/user-guide/main.ms)         Page mv





User Guide                                             Aegis


10.6.3. Network Files . . . . . . . . . . . . . . . . . . . . 160
10.6.4. DMT Implications  . . . . . . . . . . . . . . . . . . 160
10.6.4.1. Cook Example  . . . . . . . . . . . . . . . . . . . 160
10.6.5. Test Implications . . . . . . . . . . . . . . . . . . 162
10.6.6. Cross Compiling . . . . . . . . . . . . . . . . . . . 162
10.6.7. File Version by Architecture  . . . . . . . . . . . . 162
10.7. Reminders . . . . . . . . . . . . . . . . . . . . . . . 163
10.7.1. Awaiting Development  . . . . . . . . . . . . . . . . 163
10.7.2. Being Developed . . . . . . . . . . . . . . . . . . . 163
10.7.3. Being Reviewed  . . . . . . . . . . . . . . . . . . . 163
10.7.4. Awaiting Integration  . . . . . . . . . . . . . . . . 163
11. Geographically Distributed Development  . . . . . . . . . 165
11.1. Introduction  . . . . . . . . . . . . . . . . . . . . . 165
11.1.1. Risk Reduction  . . . . . . . . . . . . . . . . . . . 165
11.1.2. What to Send  . . . . . . . . . . . . . . . . . . . . 166
11.1.3. Methods and Topologies  . . . . . . . . . . . . . . . 166
11.1.4. The Rest of this Chapter  . . . . . . . . . . . . . . 167
11.2. Manual Operation  . . . . . . . . . . . . . . . . . . . 168
11.2.1. Manual Send . . . . . . . . . . . . . . . . . . . . . 168
11.2.2. Sending Baselines . . . . . . . . . . . . . . . . . . 168
11.2.3. Sending Branches  . . . . . . . . . . . . . . . . . . 169
11.2.4. Manual Receive  . . . . . . . . . . . . . . . . . . . 169
11.2.5. Getting Started . . . . . . . . . . . . . . . . . . . 170
11.3. Sneaker Net . . . . . . . . . . . . . . . . . . . . . . 170
11.4. Automatic Operation . . . . . . . . . . . . . . . . . . 171
11.4.1. Sending . . . . . . . . . . . . . . . . . . . . . . . 171
11.4.2. Receiving . . . . . . . . . . . . . . . . . . . . . . 172
11.5. World Wide Web  . . . . . . . . . . . . . . . . . . . . 172
11.5.1. Server  . . . . . . . . . . . . . . . . . . . . . . . 172
11.5.2. Browser . . . . . . . . . . . . . . . . . . . . . . . 172
11.6. Security  . . . . . . . . . . . . . . . . . . . . . . . 172
11.6.1. Trojan Horses . . . . . . . . . . . . . . . . . . . . 173
11.6.2. PGP . . . . . . . . . . . . . . . . . . . . . . . . . 174
11.6.3. Sorcerer's Apprentice . . . . . . . . . . . . . . . . 174
11.7. Patches . . . . . . . . . . . . . . . . . . . . . . . . 175
11.7.1. Send  . . . . . . . . . . . . . . . . . . . . . . . . 175
11.7.2. Receive . . . . . . . . . . . . . . . . . . . . . . . 175
11.7.3. Limitations . . . . . . . . . . . . . . . . . . . . . 176
12. Further Reading . . . . . . . . . . . . . . . . . . . . . 177
12.1. Software Configuration Management . . . . . . . . . . . 177
12.2. Reviewing . . . . . . . . . . . . . . . . . . . . . . . 177
13. Appendix A: New Project Quick Reference . . . . . . . . . 178
13.1. Create the Project  . . . . . . . . . . . . . . . . . . 178
13.1.1. Add the Staff . . . . . . . . . . . . . . . . . . . . 178
13.1.2. Project Attributes  . . . . . . . . . . . . . . . . . 178
13.2. Create Change One . . . . . . . . . . . . . . . . . . . 179
13.3. Develop Change One  . . . . . . . . . . . . . . . . . . 179
13.4. Review The Change . . . . . . . . . . . . . . . . . . . 180
13.5. Integrate the Change  . . . . . . . . . . . . . . . . . 181
13.6. What to do Next . . . . . . . . . . . . . . . . . . . . 182
14. Appendix B: Glossary  . . . . . . . . . . . . . . . . . . 184
15. Appendix D: Why is Aegis Set-Uid-Root?  . . . . . . . . . 187
15.1. Examples  . . . . . . . . . . . . . . . . . . . . . . . 187
15.2. Source Details  . . . . . . . . . . . . . . . . . . . . 189



Page mvi         (lib/en/user-guide/main.ms)    Peter Miller





Aegis                                             User Guide


16. Appendix I: Internationalization and Localization . . . . 190
16.1. The ``po/en.po'' File . . . . . . . . . . . . . . . . . 190
16.2. Checking the Code . . . . . . . . . . . . . . . . . . . 190






















































Peter Miller                 ()                    Page mvii


