





.













                           Aegis

                A Project Change Supervisor




                         User Guide







                        Peter Miller

                  _m_i_l_l_e_r_p_@_c_a_n_b_._a_u_u_g_._o_r_g_._a_u































User Guide                                             Aegis


.






                        DEDICATIONS

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

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






This document describes Aegis version 4.24.2
and was prepared 17 April 2025.






This  document  describing  the Aegis program, and the Aegis
program itself, are
Copyright (C) 1991, 1992,  1993,  1994,  1995,  1996,  1997,
1998,  1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
2008, 2009 Peter Miller

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 3 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,   see
<http://www.gnu.org/licenses/>.





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





Aegis                                             User Guide


11..  IInnttrroodduuccttiioonn

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

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

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

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

11..11..  YYeeaarr 22000000 SSttaattuuss

Aegis does not suffer from Year 2000 problems.

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

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

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

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

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





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





User Guide                                             Aegis


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

11..33..  WWhhyy uussee aaeeggiiss??

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

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

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

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













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





Aegis                                             User Guide


11..44..  HHooww ttoo uussee tthhiiss mmaannuuaall

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

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

This manual is broken into a number of sections.

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

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

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

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

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

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

Chapter 8
     describes managing tests and testing with Aegis.

Chapter 9
     describes the branching mechanism used in Aegis.

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



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





User Guide                                             Aegis


     supervision of the aegis program.

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

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

Appendix B
     is a glossary of terms.

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

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

11..55..  GGNNUU GGPPLL

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

























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





Aegis                                             User Guide


22..  HHooww AAeeggiiss WWoorrkkss

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

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

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

22..11..  TThhee MMooddeell

The model of the software development process used by  Aegis
evolved and grew with time in a commercial software develop-
ment environment, and it has continued to be used and devel-
oped.

The model described here is generic, and can be adapted in a
variety of ways.  These will be described  at  the  relevant
points in the text.

22..11..11..  TThhee BBaasseelliinnee

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

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

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

The structure of the baseline is dictated by the  nature  of
each  project.   The  Aegis  program attempts to make as few
arbitrary rules as possible.  There is one mandatory file in
the  your  project  baseline.   The mandatory file is called
_a_e_g_i_s_._c_o_n_f  by  default,  and   contains   the   per-project



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





User Guide                                             Aegis


configuration  information.   The  name  of this file may be
changed if you want to call it something different.  It  ios
also  common  (though  not  mandatory,  and  the name may be
changed) to have a directory called _t_e_s_t which contains  all
of the test scripts.  The contents and structure of the _t_e_s_t
directory (or whatever you call it) are controlled by a test
filename  pattern  you  supply  to Aegis.  Tests are treated
just like any other source file, and are subject to the same
process.

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

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

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

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

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



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





Aegis                                             User Guide






                        baseline





                 developmentdevelopment
                  directory directory




                       integrator
                              integrate
                            |      pass
                  integrate |
                      begin |

                      integration
                       directory




         FFiigguurree 11:: Flow of Files through the Model


development builds can take object files from  the  baseline
rather than rebuild them within the development directory.

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

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

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




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





User Guide                                             Aegis


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

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

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

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

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

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

22..11..33..  CChhaannggee SSttaatteess

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

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



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





Aegis                                             User Guide


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

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

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

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

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

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

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

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
-----------
  3 It  is possible for these testing requirements
to be waived on either a per-project or per-change
basis.   How is described in a later section.  The
power to waive this requirement is  not  automati-
cally  granted  to  developers,  as experience has
shown that it is usually abused.



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





User Guide                                             Aegis


without losing the edits made by the developer.

22..11..33..33..  AAwwaaiittiinngg RReevviieeww

The  default configuration for an Aegis project does not use
this  state,  because  for  small-ish  projects  it  can  be
tedious.   For larger projects, however, it assists in coor-
dinating reviewers when you use email  notification  that  a
review is required to several potential reviewers.

To  enable  this state, you need to change the _d_e_v_e_l_o_p___e_n_d___-
_a_c_t_i_o_n field of the project  attributes.   See  _a_e_p_a(1)  for
more information, or _t_k_a_e_p_a(1) for a GUI interface.

It  is  also  possible,  by  a different setting of the same
project attribute, to skip the code review step  altogether.
This can be of benefit to one-person projects where indepen-
dent code review would be impossible.

The rest of this description will assume the _a_w_a_i_t_i_n_g _r_e_v_i_e_w
state is not being used, but code reviews _a_r_e being used, to
simplify matters.  Once you are more  familiar  with  Aegis,
enabling the use of the _a_w_a_i_t_i_n_g _r_e_v_i_e_w state will be simple
and will behave intuitively.

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

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

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

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

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

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

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



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





Aegis                                             User Guide


maybe  two).   The  Aegis program has no way of knowing that
the user passing a review has actually looked at, and under-
stood, the code.

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

22..11..33..44..11..  CCuussttoommiizziinngg CCooddee RReevviieeww PPoolliiccyy

It  is  possible  to  require  more  than one reviewer for a
change.  By setting the _r_e_v_i_e_w___p_o_l_i_c_y___c_o_m_m_a_n_d of the project
configuration  file,  you  can pass a shell script (or other
command) the relevant change details, and  the  exit  status
will  be  used  to  determine  of the change advances to the
_a_w_a_i_t_i_n_g _i_n_t_e_g_r_a_t_i_o_n  state,  or  requires  additional  code
reviewers first.

Because  it is a program, it is possible to implement almost
any policy you can think of, including particular  reviewers
for  particular  areas of code, or that there must be 3 dif-
ferent reviewers, _e_t_c.

22..11..33..55..  AAwwaaiittiinngg IInntteeggrraattiioonn

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

The  issue  of  one integration at a time is a philosophical
one: all of the changes in the queue are physically indepen-
dent;  because  of the _D_e_v_e_l_o_p _E_n_d locking rules they do not
have intersecting sets of files.  The problem comes when one
change  would  break  another, in these cases the integrator
needs to know which to bounce and which  to  accept.   Inte-
grating  one  change  at a time greatly simplifies this, and
enforces the "only change one thing at a time" maxim,  occa-
sionally at the expense of integrator throughput.

22..11..33..66..  BBeeiinngg IInntteeggrraatteedd

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

The additional compilation has two purposes: it ensures that
the successful compile performed by the developer was not  a



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





User Guide                                             Aegis


fluke of the developer's environment, and it also allows the
baseline to be the closure of the sources files.   That  is,
all  of the implications flowing from the source files, such
as object files and linked programs or libraries.  It is not
possible  for  Aegis  to  know  which files these are in the
development directory, because Aegis is decoupled  from  the
build mechanism (this will discussed later).

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

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

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

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

22..11..33..77..  CCoommpplleetteedd

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

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

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

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

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

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



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





Aegis                                             User Guide


file of a project.

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

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

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

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

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

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

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

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




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





User Guide                                             Aegis


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

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

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

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

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

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

The project administrator has the following duties:

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

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

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

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

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

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




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





Aegis                                             User Guide


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

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

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

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

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

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

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

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

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

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

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

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

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



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





User Guide                                             Aegis


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


                           being
                         developed

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


                         completed


          FFiigguurree 22:: Change States and Transitions


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



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





Aegis                                             User Guide


UNIX  shell  scripts  - anything that can be done in a shell
script can be tested.

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

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

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

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

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

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

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.



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





User Guide                                             Aegis


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

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

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

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

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

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

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

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

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

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

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

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

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



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





Aegis                                             User Guide


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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




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





User Guide                                             Aegis


22..22..  PPhhiilloossoopphhyy

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

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

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

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

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

22..22..11..  DDeevveellooppmmeenntt

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

22..22..22..  PPoosstt DDeevveellooppmmeenntt

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

22..22..33..  MMiinniimmaalliissmm

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

22..22..44..  OOvveerrllaapp

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



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





Aegis                                             User Guide


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

22..22..55..  DDeessiiggnn GGooaallss

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

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

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

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

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
































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





User Guide                                             Aegis


22..33..  SSeeccuurriittyy

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

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

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

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

22..44..  SSccaallaabbiilliittyy

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

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

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











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





Aegis                                             User Guide


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

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

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

+o Each change set is applied atomically.

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

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

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

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

22..55..11..  BBuuiillddiinngg

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

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

22..55..22..  TTeessttiinngg

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







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





User Guide                                             Aegis


22..55..33..  RReevviieewwiinngg

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














































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





Aegis                                             User Guide


22..66..  FFuurrtthheerr WWoorrkk

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

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

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

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

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

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

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

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

There  is  almost  sufficient  information in the Aegis data
base to create a virtual file system, overlaying the  devel-
opment directory atop the baseline4.  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
path5.   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  with6.  Many graphical tools, such as bubble chart
-----------
  4 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.
  5 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.
  6 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 configuration file has greatly reduced the  need
for  this functionality.  However, it does not provide copy-
on-write semantics, nor automatic _a_e_c_p functionality;  which
a virtual file system could do.





































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





Aegis                                             User Guide


33..  TThhee CChhaannggee DDeevveellooppmmeenntt CCyyccllee

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

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

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

There are six hypothetical users in the example: the  devel-
opers are Pat, Jan and Sam; the reviewers are Robyn and Jan;
the integrator is  Isa;  and  the  administrator  is  Alex7.
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.






















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



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





User Guide                                             Aegis


33..11..  TThhee DDeevveellooppeerr

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

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

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

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

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

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

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













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



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





Aegis                                             User Guide


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


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

Five files will be created by this change.

     pat% aaeennff aaeeggiiss..ccoonnff HHoowwttoo..ccooookk ggrraamm..yy lleexx..ll mmaaiinn..cc
     aegis: project "example.1.0": change 10: file "Howto.cook" added
     aegis: project "example.1.0": change 10: file "aegis.conf" 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 _a_e_g_i_s_._c_o_n_f 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);
     }

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



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





User Guide                                             Aegis


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


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

     %token  DOUBLE
     %token  NAME


     %union
     {
             int     lv_int;
             double  lv_double;
     }


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


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


     %%




















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





Aegis                                             User Guide


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


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

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


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



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





User Guide                                             Aegis


The  files are processed, compiled and linked together using
the _a_e_b command; this is known as _b_u_i_l_d_i_n_g a  change.   This
is  done through Aegis so that Aegis can know the success or
failure of the build.  (Build success is a precondition  for
a  change  to  leave  the _b_e_i_n_g _d_e_v_e_l_o_p_e_d state.)  The build
command is in the _a_e_g_i_s_._c_o_n_f file so vaguely described  ear-
lier.  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  ear-
lier.  This file describes the commands and dependencies for
the various processing, compiling and linking.

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


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

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


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

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


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

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



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





Aegis                                             User Guide


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

     pat% aaeedd
     aegis: set +e; diff -c /dev/null /u/pat/example.1.0.C010/Howto.cook >
             /u/pat/example.1.0.C010/Howto.cook,D; test $? -eq 0 -o $? -eq 1
     aegis: set +e; diff -c /dev/null /u/pat/example.1.0.C010/aegis.conf >
             /u/pat/example.1.0.C010/aegis.conf,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 pedanticism10.

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

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

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

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

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


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

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



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





User Guide                                             Aegis


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

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


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

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


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


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






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



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





Aegis                                             User Guide


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


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


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


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


     #
     # this much worked
     #
     pass


There are several things to notice about this test file:




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





User Guide                                             Aegis


+o  It  is  a Bourne shell script.  All test files are Bourne
     shell  scripts  because  they  are the most portable.12
     (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.
-----------
  12 Portable for Aegis'  point  of  view:  Bourne
shell  is  the  most  widely  available shell.  Of
course, if you are  writing  code  to  publish  on
USENET  or  for FTP, portability of the tests will
be important from the developer's  point  of  view
also.



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





Aegis                                             User Guide


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

This efficiency is especially evident when using  commands13
such as

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


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

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

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


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

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


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



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





User Guide                                             Aegis


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

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


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

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

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

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

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



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





Aegis                                             User Guide


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


The first on the list is chosen.

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


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

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


     NAME
             Project "example.1.0", Change 11.


     SUMMARY
             file names on command line


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


     CAUSE
             This change was caused by internal_bug.


     STATE
             This change is in 'being_developed' state.







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





User Guide                                             Aegis


     FILES
             Change has no files.


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


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

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


This file is now extended to look like this:

     #include <stdio.h>


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


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













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





Aegis                                             User Guide


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


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


             yyparse();
             exit(0);
     }


A new test is also required,

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

which is edited to look like this:

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










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





User Guide                                             Aegis


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


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


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


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


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





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





Aegis                                             User Guide


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


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


     #
     # this much worked
     #
     pass


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

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






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





User Guide                                             Aegis


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

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

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

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


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

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

Running the regression tests is also a good idea

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


Now Aegis will be satisfied







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





Aegis                                             User Guide


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


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

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

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

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

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

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


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

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


The grammar file is changed to look like this:









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





User Guide                                             Aegis


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


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


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


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


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


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



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





Aegis                                             User Guide


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

The difference file looks like this

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


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


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


These are the differences Sam expected to see.

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



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





User Guide                                             Aegis


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


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

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


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


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


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


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




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





Aegis                                             User Guide


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


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


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


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


     # it probably worked
     pass


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

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


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

     #include <_f_i_l_e_n_a_m_e>

directives, rather then the double quote form.

     Now the change is tested.






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





User Guide                                             Aegis


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


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

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


Running the regression tests is also a good idea.

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


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

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





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





Aegis                                             User Guide


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

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


With such a wide choice, Pat selected change 13.

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


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

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


     NAME
             Project "example.1.0", Change 13.


     SUMMARY
             add variables


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


     CAUSE
             This change was caused by internal_enhancement.


     STATE
             This change is in 'being_developed' state.







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





User Guide                                             Aegis


     FILES
             This change has no files.


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


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

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


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

Pat now edits the grammar file.

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


The difference file looks like this

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


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

     static double memory[26];






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





Aegis                                             User Guide


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


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


Little remains except to build the change.

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


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

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










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





User Guide                                             Aegis


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


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


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


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


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


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


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


     # it probably worked
     pass





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





Aegis                                             User Guide


The new files are then differenced:

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


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

The change is tested.

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


The change is tested against the baseline.

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


And the regression tests







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





User Guide                                             Aegis


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


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

All is finished for this change,

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


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

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

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


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














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





Aegis                                             User Guide


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


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

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


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


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







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





User Guide                                             Aegis


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


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

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

Sam now rebuilds:




















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





Aegis                                             User Guide


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


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

All that remains is to test the change again.

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

And test against the baseline,





















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





User Guide                                             Aegis


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


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

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

All done, or are we?

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

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






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





Aegis                                             User Guide


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

This time everything will run smoothly,

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

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

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




































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





User Guide                                             Aegis


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

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

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


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




















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





Aegis                                             User Guide


33..22..  TThhee RReevviieewweerr

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

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

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

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

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

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

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

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

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

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

     Project "example.1.0"
     List of Changes

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

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

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

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



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





User Guide                                             Aegis


prefer the _l_e_s_s(1) command.

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

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

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

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

Most reviews have the same pattern as the first.

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

     Project "example.1.0"
     List of Changes

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


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

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


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

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

     Project "example.1.0", Change 11
     Change Details


     NAME
             Project "example.1.0", Change 11.


     SUMMARY
             file names on command line






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





Aegis                                             User Guide


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


     CAUSE
             This change was caused by internal_bug.


     STATE
             This change is in 'being_reviewed' state.


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


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


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

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


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

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


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

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



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





User Guide                                             Aegis


_a_e_r_f_a_i_l(1) manual entry.

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

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


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


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
































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





Aegis                                             User Guide


33..33..  TThhee IInntteeggrraattoorr

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

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

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

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

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

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

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

     Project "example.1.0"
     List of Changes

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


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










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





User Guide                                             Aegis


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


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

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

The change is now re-tested:

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

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










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





Aegis                                             User Guide


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


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

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

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

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

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

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











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





User Guide                                             Aegis


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

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


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


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

33..33..55..  MMiinniimmuumm IInntteeggrraattiioonnss

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

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

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

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



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





Aegis                                             User Guide


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

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











































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





User Guide                                             Aegis


33..44..  TThhee AAddmmiinniissttrraattoorr

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

These responsibilities include:

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

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

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

All of these things will be examined

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

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

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

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

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


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







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





Aegis                                             User Guide


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

The project attributes are set as follows:

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

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

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

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

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

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

The next role we need to fill is an integrator.

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

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

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

This is for versioning; see the _B_r_a_n_c_h_i_n_g chapter  for  more



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





User Guide                                             Aegis


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

     alex% aaeell pp
     List of Projects

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

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

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

The change is created as follows:

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

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

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

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





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





Aegis                                             User Guide


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

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

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


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

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

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

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

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

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


The change is created as follows:

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

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

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

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






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





User Guide                                             Aegis


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


The change is created as follows:

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

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

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

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


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


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









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





Aegis                                             User Guide


33..55..  WWhhaatt ttoo ddoo NNeexxtt

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

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

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


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

33..66..  CCoommmmoonn QQuueessttiioonnss

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

33..66..11..  IInnssuullaattiioonn

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

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




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





User Guide                                             Aegis


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

It is possible to select the degree of insulation.  By using
"aecp ." at the top of a development directory, the complete
project source tree will be copied, thus completely insulat-
ing you.  Mind you, it comes  at  the  cost  of  a  complete
build.

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

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

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

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

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

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

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

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

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





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





Aegis                                             User Guide


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

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

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

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

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

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

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

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





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





User Guide                                             Aegis


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

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

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

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

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

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

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

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

33..66..44..  CCoollllaabboorraattiioonn

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

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

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

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



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





Aegis                                             User Guide


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

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

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

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

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

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
























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



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





User Guide                                             Aegis


44..  TThhee HHiissttoorryy TTooooll

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

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

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

44..11..  HHiissttoorryy FFiillee NNaammeess

In  order  to track project source file renames and yet pre-
serve a continuous history, the name of each source file and
the  name of each corresponding history file have nothing in
common.  The history file will have the same name  (both  on
the  local repository and any remote repository it is in) no
matter how many times the source file is renamed.

Each source file is assigned universally  unique  identifier
(UUID) when it is first created.  This attribute, unlike the
source file's name, is immutable and thus  is  suitable  for
use when forming the name of the history file.

44..22..  IInntteerrffaacciinngg

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

44..22..11..  hhiissttoorryy__ccrreeaattee__ccoommmmaanndd

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

${Input}
     absolute path of source file

${History}
     absolute path of history file

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

This command should be identical to the  _h_i_s_t_o_r_y___p_u_t___c_o_m_m_a_n_d
otherwise  mysterious  things  can  happen when branches are



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





Aegis                                             User Guide


ended.

44..22..22..  hhiissttoorryy__ggeett__ccoommmmaanndd

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

${History}
     absolute path of history file

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

${Output}
     absolute path of destination file

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

44..22..33..  hhiissttoorryy__ppuutt__ccoommmmaanndd

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

${Input}
     absolute path of source file

${History}
     absolute path of history file

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

This command should be  identical  to  the  _h_i_s_t_o_r_y___c_r_e_a_t_e___-
_c_o_m_m_a_n_d otherwise mysterious things can happen when branches
are ended.

44..22..44..  hhiissttoorryy__qquueerryy__ccoommmmaanndd

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

${History}
     absolute path of history file

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






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





User Guide                                             Aegis


44..22..55..  hhiissttoorryy__ccoonntteenntt__lliimmiittaattiioonn

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

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

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

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

When a file is added to the history (by either the _h_i_s_t_o_r_y___-
_c_r_e_a_t_e___c_o_m_m_a_n_d or the _h_i_s_t_o_r_y___p_u_t___c_o_m_m_a_n_d field) it is exam-
ined  for  conformance  to  this  limitation.  If there is a
problem, the file is  encoded  in  either  the  MIME  quoted
printable  or  the  MIME  Base  64  encoding (see RFC 1521),
whichever is smaller, before  being  given  to  the  history
tool.  The file in the baseline is unchanged.

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

44..22..66..  hhiissttoorryy__ttooooll__ttrraasshheess__ffiillee

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

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






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





Aegis                                             User Guide


44..22..77..  QQuuoottiinngg FFiilleennaammeess

The  default  setting is for Aegis to reject filenames which
contain shell special characters.  This ensures  that  file-
names  may be substituted into the commands without worrying
about whether this is safe.  If you set the _s_h_e_l_l___s_a_f_e___f_i_l_e_-
_n_a_m_e_s  field  of  the  project _a_e_g_i_s_._c_o_n_f file to false, you
will need to surround filenames with the  ${quote  _f_i_l_e_n_a_m_e}
substitution.  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.

44..22..88..  TTeemmppllaatteess

The  source  distribution  contains  numerous  configuration
examples  in a directory called _l_i_b_/_c_o_n_f_i_g_._e_x_a_m_p_l_e_/ which is
installed   into   _/_u_s_r_/_p_k_g_/_s_h_a_r_e_/_a_e_g_i_s_/_c_o_n_f_i_g_._e_x_a_m_p_l_e_/   by
default.   In  the  interests of accuracy, it may be best to
copy configurations from there, rather  than  copy-type  the
ones below.




































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





User Guide                                             Aegis


44..33..  UUssiinngg aaeessvvtt

The _a_e_s_v_t(1) command is distributed with Aegis.  It supports
binary files, has versy small history files,  and  has  good
end-to-end  behaviour.   The  entries  for  the commands are
listed below.

44..33..11..  hhiissttoorryy__ccrreeaattee__ccoommmmaanndd

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

The following substitutions are available:

${Input}
     absolute path of the source file

${History}
     absolute path of the history file

The entry in the _a_e_g_i_s_._c_o_n_f file looks like this:

     history_create_command =
       "aesvt -checkin "
       "-history $history "
       "-f $input"
       ;


44..33..22..  hhiissttoorryy__ppuutt__ccoommmmaanndd

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

44..33..33..  hhiissttoorryy__ggeett__ccoommmmaanndd

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

The following substitutions are available:

${History}
     absolute path of the history file

${Edit}
     edit number, as given by history_query_command

${Output}
     absolute path of the destination file

The entry in the _a_e_g_i_s_._c_o_n_f file looks like this:




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





Aegis                                             User Guide


     history_get_command =
       "aesvt -checkout "
       "-history $history "
       "-edit $edit "
       "-o $output"
       ;


44..33..44..  hhiissttoorryy__qquueerryy__ccoommmmaanndd

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

The following substitutions are available:

${History}
     absolute path of the history file

The entry in the _a_e_g_i_s_._c_o_n_f file looks like this:

     history_query_command =
       "aesvt -query "
       "-history $history"
       ;


44..33..55..  TTeemmppllaatteess

The _l_i_b_/_c_o_n_f_i_g_._e_x_a_m_p_l_e_/_a_e_s_v_t file in the Aegis  distribution
(installed  as  _/_u_s_r_/_p_k_g_/_s_h_a_r_e_/_a_e_g_i_s_/_c_o_n_f_i_g_._e_x_a_m_p_l_e_/_a_e_s_v_t by
default) contains all of the above commands, so that you may
readily insert them into your project configuration 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  store  meta-date  with  each
version.    For   example:  "Description=${quote  ($version)
${change description}}" inserts the version number  and  the
brief  description  into  the  file's  log.  This means that
using the _a_e_s_v_t _-_l_i_s_t option will provide quite useful  sum-
maries.






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





User Guide                                             Aegis


44..33..66..  BBiinnaarryy FFiilleess

The _a_e_s_v_t(1) command is able to cope with binary files.  Set

     history_content_limitation =
         binary_capable;

so that Aegis knows that no encoding is required.

















































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





Aegis                                             User Guide


44..44..  UUssiinngg SSCCCCSS

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

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

44..44..11..  hhiissttoorryy__ccrreeaattee__ccoommmmaanndd

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

The following substitutions are available:

${Input}
     absolute path of the source file

${History}
     absolute path of the history file

The entry in the _a_e_g_i_s_._c_o_n_f file looks like this:

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


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

44..44..22..  hhiissttoorryy__ggeett__ccoommmmaanndd

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

The following substitutions are available:

${History}
     absolute path of the history file





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





User Guide                                             Aegis


${Edit}
     edit number, as given by history_query_command

${Output}
     absolute path of the destination file

The entry in the _a_e_g_i_s_._c_o_n_f file looks like this:

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


44..44..33..  hhiissttoorryy__ppuutt__ccoommmmaanndd

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

The following substitutions are available:

${Input}
     absolute path of source file

${History}
     absolute path of history file

The entry in the _a_e_g_i_s_._c_o_n_f file looks like this:

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


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

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

44..44..44..  hhiissttoorryy__qquueerryy__ccoommmmaanndd

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

The following substitutions are available:





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





Aegis                                             User Guide


${History}
     absolute path of the history file

The entry in the _a_e_g_i_s_._c_o_n_f file looks like this:

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


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

44..44..55..  TTeemmppllaatteess

The _l_i_b_/_c_o_n_f_i_g_._e_x_a_m_p_l_e_/_s_c_c_s file in the  Aegis  distribution
contains   all   of   the   above   commands  (installed  as
_/_u_s_r_/_p_k_g_/_s_h_a_r_e_/_a_e_g_i_s_/_e_x_a_m_p_l_e_._c_o_n_f_i_g_/_s_c_c_s by default) so that
you  may readily insert them into your project configuration
file (called _a_e_g_i_s_._c_o_n_f by default, see _a_e_p_c_o_n_f_(_5_)  _f_o_r  _h_o_w
_t_o _c_a_l_l _i_t _s_o_m_e_t_h_i_n_g _e_l_s_e_)_.

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

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

44..44..66..  BBiinnaarryy FFiilleess

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


















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





User Guide                                             Aegis


44..55..  UUssiinngg RRCCSS

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

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

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

44..55..11..  hhiissttoorryy__ccrreeaattee__ccoommmmaanndd

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

The following substitutions are available:

${Input}
     absolute path of the source file

${History}
     absolute path of the history file

The entry in the _a_e_g_i_s_._c_o_n_f file looks like this:

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


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





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





Aegis                                             User Guide


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

44..55..22..  hhiissttoorryy__ggeett__ccoommmmaanndd

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

The following substitutions are available:

${History}
     absolute path of the history file

${Edit}
     edit number, as given by history_query_command

${Output}
     absolute path of the destination file

The entry in the _a_e_g_i_s_._c_o_n_f file looks like this:

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


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

44..55..33..  hhiissttoorryy__ppuutt__ccoommmmaanndd

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

The following substitutions are available:

${Input}
     absolute path of source file

${History}
     absolute path of history file

The entry in the _a_e_g_i_s_._c_o_n_f file looks like this:

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





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





User Guide                                             Aegis


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

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

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

44..55..44..  hhiissttoorryy__qquueerryy__ccoommmmaanndd

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

The following substitutions are available:

${History}
     absolute path of the history file

The entry in the _a_e_g_i_s_._c_o_n_f file looks like this:

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


44..55..55..  mmeerrggee__ccoommmmaanndd

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

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



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





Aegis                                             User Guide


also available:

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

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

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

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

The entry in the _a_e_g_i_s_._c_o_n_f 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 versions
of Aegis, this was necessary, however this is no longer  the
case.)

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

44..55..66..  RReeffeerreennttiiaall IInntteeggrriittyy

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



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





User Guide                                             Aegis


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

     history_put_trashes_file = warn;

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

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

44..55..77..  TTeemmppllaatteess

The _l_i_b_/_c_o_n_f_i_g_._e_x_a_m_p_l_e_/_r_c_s file in  the  Aegis  distribution
(installed   as  _/_u_s_r_/_p_k_g_/_s_h_a_r_e_/_a_e_g_i_s_/_c_o_n_f_i_g_._e_x_a_m_p_l_e_/_r_c_s  by
default) contains all of the above commands, so that you may
readily insert them into your project configuration file.

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

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

44..55..88..  BBiinnaarryy FFiilleess

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

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

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

     history_content_limitation =
         binary_capable;

so that Aegis knows that no encoding is desired.





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





Aegis                                             User Guide


44..55..99..  hhiissttoorryy__ppuutt__ttrraasshheess__ffiilleess

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

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

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

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

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

     history_tool_trashes_file = warning;

to cause Aegis to warn you, rather than fail.
































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





User Guide                                             Aegis


44..66..  UUssiinngg ffhhiisstt

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

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

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

44..66..11..  hhiissttoorryy__ccrreeaattee__ccoommmmaanndd

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

The following substitutions are available:

${Input}
     absolute path of the source file

${History}
     absolute path of the history file

The entry in the _a_e_g_i_s_._c_o_n_f file looks like this:

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

Note that the source file is left in the baseline.

44..66..22..  hhiissttoorryy__ggeett__ccoommmmaanndd

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

The following substitutions are available:

${History}
     absolute path of the history file

${Edit}
     edit number, as given by history_query_command

${Output}
     absolute path of the destination file





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





Aegis                                             User Guide


The entry in the _a_e_g_i_s_._c_o_n_f file looks like this:

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


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

44..66..33..  hhiissttoorryy__ppuutt__ccoommmmaanndd

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

The following substitutions are available:

${Input}
     absolute path of source file

${History}
     absolute path of history file

The entry in the _a_e_g_i_s_._c_o_n_f file looks like this:

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


Note that the source file is left in the baseline.


44..66..44..  hhiissttoorryy__qquueerryy__ccoommmmaanndd

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

The following substitutions are available:

${History}
     absolute path of the history file

The entry in the _a_e_g_i_s_._c_o_n_f file looks like this:







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





User Guide                                             Aegis


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


44..66..55..  TTeemmppllaatteess

The _l_i_b_/_c_o_n_f_i_g_._e_x_a_m_p_l_e_/_f_h_i_s_t file in the Aegis  distribution
(installed  as  _/_u_s_r_/_p_k_g_/_s_h_a_r_e_/_a_e_g_i_s_/_c_o_n_f_i_g_._e_x_a_m_p_l_e_/_f_h_i_s_t by
default) contains all of the above commands, so that you may
readily insert them into your project configuration file.

44..66..66..  CCaappaabbiilliittiieess

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

     history_content_limitation =
         international_text;

in the project _a_e_g_i_s_._c_o_n_f file.

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

44..66..77..  BBiinnaarryy FFiilleess

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

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

     history_content_limitation =
         binary_capable;


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



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





Aegis                                             User Guide


being able to change your mind later.
























































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





User Guide                                             Aegis


44..77..  DDeetteeccttiinngg HHiissttoorryy FFiillee CCoorrrruuppttiioonn

When you have files which exist for long  periods  of  time,
particularly  files  such as the ones typically used by his-
tory tools, which are generally appended to, without modifi-
cation  of the bulk of the file, there is a very real possi-
bility that a block of the file could become corrupted  over
the years.16 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 or  _a_e_s_v_t(1),
they already have checksums in their files.

44..77..11..  GGeenneerraall MMeetthhoodd

In general, you need to do three things:

1. You  need to create some kind of checksum of your history
   file each time you modify it.  Something  like  _m_d_5_s_u_m(1)
   from the GNU Fileutils would be good.  Store the checksum
   in a file next to the history file.  This would  be  done
   in  the  _h_i_s_t_o_r_y___c_r_e_a_t_e___c_o_m_m_a_n_d  and  _h_i_s_t_o_r_y___p_u_t___c_o_m_m_a_n_d
   fields of the project _a_e_g_i_s_._c_o_n_f 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 _a_e_g_i_s_._c_o_n_f 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.
-----------
  16 See  also  Saltzer, J.H. _e_t _a_l (1981) _E_n_d_-_t_o_-
_e_n_d     _a_r_g_u_m_e_n_t_s      _i_n      _s_y_s_t_e_m      _d_e_s_i_g_n,
http://web.mit.edu/Saltzer/www/publications/-
endtoend/endtoend.pdf



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





Aegis                                             User Guide


   Email  failures  to  the  system  administrator  and  the
   project  administrators.   By doing this nightly, you not
   only avoid backing-up corrupted files,  you  will  always
   know on which backup tape the good copy resides - yester-
   day's.

44..77..22..  CCoonnffiigguurraattiioonn CCoommmmaannddss

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

history_create_command
  You need to test if the history file and its checksum 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 checksum 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  checksum 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,  immediately
  after  one  of the _h_i_s_t_o_r_y___c_r_e_a_t_e___c_o_m_m_a_n_d or _h_i_s_t_o_r_y___p_u_t___-
  _c_o_m_m_a_n_d commands.  It is up to you whether you  think  you
  need  to add a guard as for the _h_i_s_t_o_r_y___g_e_t___c_o_m_m_a_n_d _f_i_e_l_d_.

44..77..33..  AAnn AAlltteerrnnaattiivvee

Rather than run _m_d_5_s_u_m(1) on the history files each time you
modify them, you could use _g_z_i_p(1) to obtain some minor com-
pression, but it also provides and Adler32 checksum  of  the
file.  For files with long histories, this can be tedious to
unpack every time you need to extract an  old  version,  but
such  operations  are frequently I/O bound, and so there may
be no perceived slowness by the user..







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





User Guide                                             Aegis


44..77..44..  AAeeggiiss'' DDaattaabbaassee

In addition to your history files, Aegis maintains  a  data-
base  of  file meta-data.  In order to add a checksum to the
various file making  up  the  database,  turn  on  the  _c_o_m_-
_p_r_e_s_s_e_d___d_a_t_a_b_a_s_e  project  attribute.   In  addition to com-
pressing the database (a minor  savings)  it  also  adds  an
Adler32 checksum.

You can check this in the _c_r_o_n(1) job by using _g_z_c_a_t(1) sent
to _/_d_e_v_/_n_u_l_l.














































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





Aegis                                             User Guide


55..  TThhee DDeeppeennddeennccyy MMaaiinntteennaannccee TTooooll

Aegis can place heavy demands on the dependency  maintenance
tool, so it is important that you select an appropriate one.
This chapter talks about what features a dependency  mainte-
nance  tool  requires,  and gives examples of how to use the
various alternatives.

55..11..  RReeqquuiirreedd FFeeaattuurreess

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.
Something like PROLOG is probably ideal.

Aegis is capable of supporting a wide variety of development
directory   styles.   The  different  development  directory
styles place different demands on the dependency maintenance
tool.  Development directory styles will be described in the
next section, but here is a quick summary:

copy of all sources:
     This is what CVS does, and what many other VC tool  do.
     Because  you  have a complete copy of all source files,
     the dependency maintenance tool only needs to be  aware
     of one directory tree.

copy of everything:
     This  is  a  small optimization of the previous case to
     cut down the time required for that first build,because
     the  derived  files  from  the integration build can be
     reused.

link all sources
     The is an optimization of the "copy all sources"  case,
     because  linking  a  file  is significantly faster than
     making a copy of a file.   The  dependency  maintenance
     tool only needs to be aware of one directory tree.

link everything
     This  is  an  optimization  of the previous case, again
     reusing  derived  files  from  the  integration  build,
     except  that  you  need  to ensure that your dependency
     maintenance tool is configured to  remove  the  derived
     file  outputs  of  each  rule  before creating them, to
     avoid corrupting the baseline  or  getting  "permission
     denied" error.

view path
     This is the most efficient development directory style,
     and it scales much better than any of  the  above,  but



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





User Guide                                             Aegis


     the  dependency  maintenance  tool must be able to cope
     with a hierarchy of parallel  source  directory  trees.
     These  trees  for  a "view path", a list of directories
     that programs search below to find the files of  inter-
     est.   The vpath statements of GNU Make are almost, but
     not quite, capable of being used in this way.

55..11..11..  VViieeww PPaatthhss

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 _d_e_v_e_l_o_p_m_e_n_t___d_i_r_e_c_t_o_r_y___s_t_y_l_e_._s_o_u_r_c_e___f_i_l_e___s_y_m_l_i_n_k field of
the  project  configuration  file  may be set to _t_r_u_e, which
tells Aegis to maintain symbolic links  in  the  development
directory for all source files in the baseline which are not
present in the development directory.  (See  _a_e_p_c_o_n_f(5)  and
_a_e_b(1)  for more information.)  This incurs a certain amount
of overhead when Aegis maintains these links, but a  similar
amount  of  work  is done within DMTs which have search path
functionality.

55..11..22..  DDyynnaammiicc IInncclluuddee FFiillee DDeeppeennddeenncciieess

Include file dependencies  are  very  important,  because  a
change  may alter an include file, and all of the sources in
the baseline which use that include file must be recompiled.

Consider   the  example  given  earlier:  the  include  file
describing the interface definition of a function is  copied
into a change and edited, and so is the source file defining
the function.  It is essential that all source files in  the
baseline  which include that file are recompiled, which will
usually result in suitable diagnostic errors if any  of  the
clients  of  the altered function have yet to be included in
the change.

There are two ways of handling include file dependencies:




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





Aegis                                             User Guide


+o They can be kept in a file, and the file can be maintained
by  suitable  programs (maintaining it manually never works,
that's just human nature).

+o They can be determined by the DMT when it is scanning  the
rules to determine what needs updating.

55..11..22..11..  SSttaattiicc FFiillee

Keeping  include  dependencies  in  a  file  has a number of
advantages:

+o Most existing DMTs have the ability to include other rules
files,  so  that  when performing a development build from a
baseline rules file, it could include a dependencies file in
the development directory.

+o  Reading  a  file  is much faster than scanning all of the
source files.

Keeping include dependencies in a file has a number of  dis-
advantages:

+o The file is independent of the DMT, it is either generated
before the DMT is invoked, in which case it may do more work
than  is  necessary,  or it may be invoked after the DMT (or
after the DMT has scanned its rules), in which case  it  may
well be out-of-date when the DMT needs it.

For example, the use of _g_c_c _-_M produces "dot d" files, which
may be merged to construct  such  an  includable  dependency
file.   This  happens after the DMT has read and applied the
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.


-----------
  17 See the _U_s_i_n_g _M_a_k_e section for how  GNU  Make
may  be  used.  It effectively combines both meth-
ods: keeping _._d  files  and  dynamically  updating
them.   Because  it  combines both methods, it has
some of the advantages and disadvantages of  both.



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





User Guide                                             Aegis


55..11..22..22..  DDyynnaammiicc

In  order for a DMT to be suitable for use with Aegis, it is
essential that rules for the DMT may be specified in such  a
way  that  include  file dependencies are determined "on the
fly" when the DMT is determining if a given rule is applica-
ble, and before the rule is applied.

This  method suffers from the problem being rather slow; but
this is amenable to some caching and the losses  of  perfor-
mance are not as bad as could be imagined.

This  method  has the advantage of correctness in all cases,
where a static file may at times be out-of-date.

55..22..  DDeevveellooppmmeenntt DDiirreeccttoorryy SSttyyllee

The project configuration file, usually  called  _a_e_g_i_s_._c_o_n_f,
contains  a  field  called _d_e_v_e_l_o_p_m_e_n_t___d_i_r_e_c_t_o_r_y___s_t_y_l_e which
controls how the project sources are presented to the DMT.

See _a_e_p_c_o_n_f(5) for a complete description of this field.

There is a corresponding _i_n_t_e_g_r_a_t_i_o_n___d_i_r_e_c_t_o_r_y___s_t_y_l_e  field,
which  defaults  to  the  same  value  as  the _d_e_v_e_l_o_p_m_e_n_t___-
_d_i_r_e_c_t_o_r_y___s_t_y_l_e.  It is usually a very bad idea if these two
are different.

55..22..11..  VViieeww PPaatthh

By  not  setting _d_e_v_e_l_o_p_m_e_n_t___d_i_r_e_c_t_o_r_y___s_t_y_l_e at all the only
source files present in the development directory are source
files being create and/or modified.

By  using information provided by the _$_s_e_a_r_c_h___p_a_t_h substitu-
tion, the build can access the unchanged source files in the
branch  baseline  and  deeper  branch  baselines.  The great
thing about this approach is that there  are  also  "precom-
piled"  object  files  on the viewpath, so if an object file
does not need to be compiled (there are no  soure  files  in
the  development directory that have anything to do with it)
then the build can simply link the unchanged object files in
the baseline without recompiling.

This build method scales the best, and is the Aegis default.

The difficulties of finding a DMT which is capable of coping
with  a  view path means that this is not the only work area
style.  All other methods scale less well than a view  path;
some scale _m_u_c_h less well.







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





Aegis                                             User Guide


55..22..22..  LLiinnkk tthhee BBaasseelliinnee

The  first  two  sub-fields of interest in the _d_e_v_e_l_o_p_m_e_n_t___-
_d_i_r_e_c_t_o_r_y___s_t_y_l_e  are  _s_o_u_r_c_e___f_i_l_e___l_i_n_k   and   _s_o_u_r_c_e___f_i_l_e___-
_s_y_m_l_i_n_k.

_s_o_u_r_c_e___f_i_l_e___l_i_n_k  _=  _t_r_u_e_;  This field is true if hard links
     are to be used for project source files (which are  not
     part  of  the  change) so that the work area has a com-
     plete set of source files.

_s_o_u_r_c_e___f_i_l_e___s_y_m_l_i_n_k _= _t_r_u_e_; This field is true  if  symbolic
     links  are  to  be used for project source files (which
     are not part of the change) so that the work area has a
     complete set of source files.

By using these settings, all source files are present in the
development directory.  They  will  be  read-only.   As  you
decide  to  modify files in the change set, the _a_e_c_p command
will remove the link and replace it with a  read-write  copy
of the file.

You  need  both these sub-fields set, because hard links are
not allowed to cross file system boundaries.  Aegis will use
hard links in preference to soft links when it can.

Maintaining  the  hard links can be time consuming for large
projects, and add quite a  noticeable  delay  before  builds
start  doing  anything.   But see the _-_a_s_s_u_m_e_-_s_y_m_b_o_l_i_c_-_l_i_n_k_s
option of the _a_e_b(1) command; use it sparingly.

The biggest penalty with this method  is  that  the  initial
build  for a change set for a large project can be _v_e_r_y time
consuming.  Recall that the baseline has  a  complete  "pre-
build"  already  available.  To take advantage of these pre-
built derived files, there are a few more sub-fields:

_d_e_r_i_v_e_d___f_i_l_e___c_o_p_y _= _t_r_u_e_; This field is true if  copies  are
     to  be  used  for non-source files which are present in
     the project baseline but which are not present  in  the
     work  area, so that the work area has a complete set of
     derived files.

_d_e_r_i_v_e_d___a_t___s_t_a_r_t___o_n_l_y _= _t_r_u_e_; This settign causes the  above
     fields controling the appearance of derived files to be
     acted upon only when the development directory is  cre-
     ated (at _a_e_d_b(1) time).

Copying files can be very time consuming and also eats a lot
of disk space.  If you are prepared  to  change  your  build
slightly, it is possible to use the following fields:

_d_e_r_i_v_e_d___f_i_l_e___l_i_n_k  _=  _t_r_u_e_; This field is true if hard links
     are to be used for non-source files which  are  present



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





User Guide                                             Aegis


     in  the  project  baseline but which are not present in
     the work area, so that the work area has a complete set
     of derived files.

_d_e_r_i_v_e_d___f_i_l_e___s_y_m_l_i_n_k  _= _t_r_u_e_; This field is true if symbolic
     links are to be used for  non-source  files  which  are
     present  in  the  project  baseline  but  which are not
     present in the work area, so that the work area  has  a
     complete set of derived files.

Just as for source files, hard links will be used in prefer-
ence to symbolic links if possible.

Note that _e_v_e_r_y rule in your Makefile (or whatever your  DMT
uses) mmuusstt remove its outputs before doing enything else, to
break the links to the files in the baseline, otherwise  you
will  corrupt the baseline.  Aegis tries very hard to ensure
that the baseline files (and thus the links) are  read-only,
so  that  you  get  an error from the build if you forget to
break a link.

This development directory  style  is  called  "arch  style"
after  Tom Lord's _a_r_c_h (tla) which does something very simi-
lar.

If you are placing an existing project under Aegis,  do  the
above three things one step at a time.  First get the source
files available and integrate that.  In a second change  set
get  derived file copies working.  In a third change set (if
you do it at all) change the  build  and  use  derived  file
links.

55..22..33..  CCooppyy AAllll SSoouurrcceess

The  sub-fields  of  interest in the _d_e_v_e_l_o_p_m_e_n_t___d_i_r_e_c_t_o_r_y___-
_s_t_y_l_e is _s_o_u_r_c_e___f_i_l_e___c_o_p_y.

_s_o_u_r_c_e___f_i_l_e___c_o_p_y _= _t_r_u_e_; This field says copies  are  to  be
     used  for  project  source files (which are not part of
     the change) so that the work area has a complete set of
     source  files.   File modification time attributes will
     be preserved.

By using this setting, all source files are present  in  the
development  directory.   They  will  be  read-only.  As you
decide to modify files in the change set, the  _a_e_c_p  command
will  remove  the file and replace it with a read-write copy
of the file.

Maintaining the copies  can  be  time  consuming  for  large
projects,  and  add  quite  a noticeable delay before builds
start doing anything.  But  see  the  _-_a_s_s_u_m_e_-_s_y_m_b_o_l_i_c_-_l_i_n_k_s
option  of  the  _a_e_b(1)  command;  use it sparingly (yes, it
applies to copies as well).



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





Aegis                                             User Guide


The biggest penalty with this method  is  that  the  initial
build  for a change set for a large project can be _v_e_r_y time
consuming.  Recall that the baseline has  a  complete  "pre-
build"  already  available.  To take advantage of these pre-
built derived files, there are a few more sub-fields:

_d_e_r_i_v_e_d___f_i_l_e___c_o_p_y _= _t_r_u_e_; This says copies are  to  be  used
     for  non-source  files which are present in the project
     baseline but which are not present in the work area, so
     that the work area has a complete set of derived files.

_d_e_r_i_v_e_d___a_t___s_t_a_r_t___o_n_l_y _= _t_r_u_e_; This setting causes the  above
     fields  controlling  the appearance of derived files to
     be acted upon only when the  development  directory  is
     created (at _a_e_d_b(1) time).

This development directory style is called "CVS style" after
GNU CVS which does something very similar.

55..22..44..  OObbssoolleettee FFeeaattuurreess

There are several fields in the _a_e_g_i_s_._c_o_n_f  file  which  are
obsolete.  Aegis will automatically transfer these to create
a _d_e_v_e_l_o_p_m_e_n_t___d_i_r_e_c_t_o_r_y___s_t_y_l_e if you haven't specified  one.

_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_:  This  is  like  setting  both
     _d_e_v_e_l_o_p_m_e_n_t___d_i_r_e_c_t_o_r_y___s_t_y_l_e_._s_o_u_r_c_e___f_i_l_e___s_y_m_l_i_n_k     and
     _d_e_v_e_l_o_p_m_e_n_t___d_i_r_e_c_t_o_r_y___s_t_y_l_e_._d_e_r_i_v_e_d___f_i_l_e___s_y_m_l_i_n_k at the
     same time.

_r_e_m_o_v_e___s_y_m_l_i_n_k_s___a_f_t_e_r___b_u_i_l_d_:  This  is  like   setting   the
_d_e_v_e_l_o_p_m_e_n_t___d_i_r_e_c_t_o_r_y___s_t_y_l_e_._d_u_r_i_n_g___b_u_i_l_d___o_n_l_y field.

_c_r_e_a_t_e___s_y_m_l_i_n_k_s___b_e_f_o_r_e___i_n_t_e_g_r_a_t_i_o_n___b_u_i_l_d_:  This is like set-
     ting   both   _i_n_t_e_g_r_a_t_i_o_n___d_i_r_e_c_t_o_r_y___s_t_y_l_e_._s_o_u_r_c_e___f_i_l_e___-
     _s_y_m_l_i_n_k           and           _i_n_t_e_g_r_a_t_i_o_n___d_i_r_e_c_t_o_r_y___-
     _s_t_y_l_e_._d_e_r_i_v_e_d___f_i_l_e___s_y_m_l_i_n_k at the same time.

_r_e_m_o_v_e___s_y_m_l_i_n_k_s___a_f_t_e_r___i_n_t_e_g_r_a_t_i_o_n___b_u_i_l_d_: This is  like  set-
ting    the    _i_n_t_e_g_r_a_t_i_o_n___d_i_r_e_c_t_o_r_y___s_t_y_l_e_._d_u_r_i_n_g___b_u_i_l_d___o_n_l_y
field.

Aegis will print a warning if you use any of these fields.














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





User Guide                                             Aegis


55..33..  UUssiinngg CCooookk

The _C_o_o_k program is the only  dependency  maintenance  tool,
known to the author, which is sufficiently capable to supply
Aegis'  needs.18  Tools  such  as  _c_a_k_e  and  _G_N_U  _M_a_k_e  are
described  later.   They  need  a special tweak to make them
work.

This  section  describes  appropriate   contents   for   the
_H_o_w_t_o_._c_o_o_k file, input to the _c_o_o_k(1) program.  It also dis-
cusses the  _b_u_i_l_d___c_o_m_m_a_n_d  and  _i_n_t_e_g_r_a_t_e___b_u_i_l_d___c_o_m_m_a_n_d  and
_l_i_n_k___b_a_s_e_l_i_n_e  and  _c_h_a_n_g_e___f_i_l_e___c_o_m_m_a_n_d  and  _p_r_o_j_e_c_t___f_i_l_e___-
_c_o_m_m_a_n_d and _l_i_n_k___i_n_t_e_g_r_a_t_i_o_n___d_i_r_e_c_t_o_r_y fields of the config-
uration  file.   See  _a_e_p_c_o_n_f(5)  for more information about
this file.

55..33..11..  IInnvvookkiinngg CCooookk

The _b_u_i_l_d___c_o_m_m_a_n_d field of the configuration file is used to
invoke  the relevant build command.  In this case, it is set
as follows

     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 configuration file:

     link_integration_directory = true;


The  links  must  be  removed  first, otherwise the baseline
would cease to be self-consistent.

55..33..22..  TThhee RReecciippee FFiillee

The file containing the recipes is called _H_o_w_t_o_._c_o_o_k and  is
given to Cook on the command line.

The  following  items  are preamble to the rest of the file;
they ask Aegis for the  source  files  of  the  project  and
change  so that Cook can determine what needs to be compiled
-----------
  18 The version in use when writing this  section
was  1.5.  All versions from 1.3 onwards are known
to work with the recipes described here.



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





Aegis                                             User Guide


and linked.

     project_files =
       [collect_lines aelpf
         -p [project] -c [change]];
     change_files =
       [collect_lines aelcf
         -p [project] -c [change]];
     source_files =
       [stringset [project_files]
         [change_files]];


This example continues the one from chapter 3, and thus  has
a single executable to be linked from all the object files

     object_files =
       [fromto %.y %.o [match_mask %.y
         [source_files]]]
       [fromto %.l %.o [match_mask %.l
         [source_files]]]
       [fromto %.c %.o [match_mask %.c
         [source_files]]]
       ;


It is necessary to determine if this is a development build,
and  thus  has  the  baseline  for  additional   ingredients
searches, or an integration build, which does not.  The ver-
sion supplied  by  Aegis  will  tell  us  this  information,
because  it  will  be  _m_a_j_o_r_._m_i_n_o_r_.C_c_h_a_n_g_e  for  development
builds and _m_a_j_o_r_._m_i_n_o_r_.D_d_e_l_t_a for integration builds.

     if [match_mask %1C%2 [version]] then
     {
       baseline = [collect aegis -cd -bl
         -p [project]];
       search_list = . [baseline];
     }


The _s_e_a_r_c_h___l_i_s_t variable in Cook is the list of  directories
to  search for dependencies; it defaults to only the current
directory.  The _r_e_s_o_l_v_e builtin function of Cook may be used
to  ask  Cook  for  the  name  of  the file actually used to
resolve dependencies, so that recipe  bodies  may  reference
the appropriate file:










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





User Guide                                             Aegis


     example: [object_files]
     {
       [cc] -o example
         [resolve [object_files]]
         -ly -ll;
     }


This  recipe says that to Cook the example program, you need
the object files determined  earlier,  and  them  link  them
together.   Object  files which were up to date in the base-
line are used wherever possible, but files which were out of
date are constructed in the current directory and those will
be linked.

55..33..33..  TThhee RReecciippee ffoorr CC

Next we need to tell Cook how to manage C sources.   On  the
surface, this is a simple recipe:

     %.o: %.c
     {
       rm %.o;
       [cc] [cc_flags] -c %.c;
     }


Unfortunately  it  has  forgotten  about finding the include
file dependencies.  The  Cook  package  includes  a  program
called  _c___i_n_c_l  which  is used to find them.  The recipe now
becomes

     %.o: %.c: [collect c_incl -eia %.c]
     {
       rm %.o;
       [cc] [cc_flags] -c %.c;
     }


The file may not always be present to be removed (causing  a
fatal  error),  and  it is irritating to execute a redundant
command, so the remove is mangled to look like this:

     %.o: %.c: [collect c_incl -eia %.c]
     {
       if [exists %.o] then
         rm %.o
           set clearstat;
       [cc] [cc_flags] -c %.c;
     }


The "set clearstat" clause tells Cook that the command  will
invalidate  parts  of  its  _s_t_a_t  cache,  and to look at the



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





Aegis                                             User Guide


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

     %.o: %.c: [collect c_incl -eia
       [prepost "-I" "" [search_list]]
         %.c]
     {
      if [exists %.o] then
         rm %.o
           set clearstat;
       [cc] [cc_flags] [prepost "-I" ""
         [search_list]] -c %.c;
     }


See the _C_o_o_k _R_e_f_e_r_e_n_c_e _M_a_n_u_a_l for a description of the  _p_r_e_-
_p_o_s_t builtin function, and other Cook details.

There  is  one last change that must be made to this recipe,
it must use the resolve function to reference the  appropri-
ate file once Cook has found it on the search list:

     %.o: %.c: [collect c_incl -eia
       [prepost "-I" "" [search_list]]
         [resolve %.c]]
     {
       if [exists %.o] then
         rm %.o
           set clearstat;
       [cc] [cc_flags] [prepost "-I" ""
         [search_list]] -c [resolve %.c];
     }


Only use this last recipe for C sources, the others are only
shown so that the derivation of the recipe is  clear;  while
it  is  very  similar  to the original, it looks daunting at
first.

55..33..33..11..  CC IInncclluuddee SSeemmaannttiiccss

The semantics of C include directives make the

     #include "_f_i_l_e_n_a_m_e"

directive dangerous in a project developed  with  the  Aegis
program and Cook.

Depending  on  the  age of your compiler, whether it is AT&T
traditional C or newer ANSI C, this form of  directive  will
search  first  in  the  current directory and then along the



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





User Guide                                             Aegis


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.

The  second  case is bad news.  If the source file is in the
baseline and the include file is in the  change,  you  don't
want  the  source  file to use the include file in the base-
line.

Always use the

     #include <_f_i_l_e_n_a_m_e>

form of the include directive, and set  the  include  search
path explicitly on the command line used by Cook.

Cook  is able to dynamically adapt to include file dependen-
cies, because they are  not  static.   The  presence  of  an
include  file in a change means that any file which includes
this include file, whether that source file is in the  base-
line  or  in  the  change,  must  have  a  dependency on the
change's include file.  Potentially, files in  the  baseline
will  need  to  be recompiled, and the object file stored in
the change, not the baseline.  Subsequent linking  needs  to
pick  up  the  object file in the change, not from the base-
line.

55..33..44..  TThhee RReecciippee ffoorr YYaacccc

Having explained the complexities  of  the  recipes  in  the
above  section  about  C,  the recipe for yacc will be given
without delay:

     %.c %.h: %.y
     {
       if [exists %.c] then
         rm %.c
           set clearstat;
       if [exists %.h] then
         rm %.h
           set clearstat;
       [yacc] [yacc_flags] -d
         [resolve %.y];
       mv y.tab.c %.c;
       mv y.tab.h %.h;
     }


This  recipe could be jazzed up to  cope  with  the  listing
file,  too,  if  that was desired, but this is sufficient to
work with the example.



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





Aegis                                             User Guide


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

55..33..55..  TThhee RReecciippee ffoorr LLeexx

The recipe for lex is vary similar to the recipe for yacc.

     %.c: %.l
     {
       if [exists %.c] then
         rm %.c
           set clearstat;
       [lex] [lex_flags] -d [resolve %.l];
       mv lex.yy.c %.c;
     }


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

55..33..66..  RReecciippeess ffoorr DDooccuummeennttss

You can format documents, such as  user  guides  and  manual
entries  with Aegis and Cook, and the recipes are similar to
the ones above.

     %.ps: %.ms: [collect c_incl -r -eia
       [prepost "-I" "" [search_list]]
       [resolve %.ms]]
     {
       if [exists %.ps] then
         rm %.ps
           set clearstat;
       roffpp [prepost "-I" ""
         [search_list]] [resolve %.ms]
         | groff -p -t -ms
         > [target];
     }


This recipe says to run the document through groff, with the
_p_i_c(1)  and  _t_b_l(1) filters, use the _m_s(7) macro package, to
produce PostScript output.  The _r_o_f_f_p_p  program  comes  with
Cook,  and  is  like _s_o_e_l_i_m(1) but it accepts include search
path options on the command line.

Manual entries may be handled in a similar way








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





User Guide                                             Aegis


     %.cat: %.man: [collect c_incl -r -eia
       [prepost "-I" "" [search_list]]
       [resolve %.man]]
     {
       if [exists %.cat] then
         rm %.cat
           set clearstat;
       roffpp [prepost "-I" ""
         [search_list]] [resolve %.man]
         | groff -Tascii -t -man
         > [target];
     }


55..33..77..  TTeemmppllaatteess

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






































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





Aegis                                             User Guide


55..44..  UUssiinngg CCaakkee

This section describes how to use  _c_a_k_e  as  the  dependency
maintenance  tool.   The  _c_a_k_e  package was published in the
_c_o_m_p_._s_o_u_r_c_e_s_._u_n_i_x USENET newsgroup volume 12, around  Febru-
ary  1988,  and  is thus easily accessible from the many ar-
chives around the internet.

     It does not have a search path of any  form,  not  even
something like _V_P_A_T_H.  It does, however, have facilities for
dynamic include file dependencies.

55..44..11..  IInnvvookkiinngg CCaakkee

The _b_u_i_l_d___c_o_m_m_a_n_d field of the configuration file is used to
invoke  the relevant build command.  In this case, it is set
as follows

     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 configuration file:

     link_integration_directory = true;


The  links  must  be  removed  first, otherwise the baseline
would be corrupted by integration builds.

Another field to be set in this file is

     development_directory_style =
     {
         source_file_symlink = 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.






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





User Guide                                             Aegis


55..44..22..  TThhee RRuulleess FFiillee

The file containing the rules  is  called  _C_a_k_e_f_i_l_e  and  is
given to cake on the command line.

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 \
       [[aelpf -p PROJECT \
         -c CHANGE]];
     #define change_files \
       [[aelcf -p PROJECT \
        -c CHANGE]];
     #define source_files \
       project_files change_files

     #define CC     gcc
     #define CFLAGS -O


This example parallels the one from chapter 3, and thus  has
a single executable to be linked from all the object files

     #define object_files \
       [[sub -i X.c %.o source_files]] \
       [[sub -i X.y %.o source_files]] \
       [[sub -i X.l %.o source_files]]


Constructing the program is straightforward

     example: object_files
       rm -f example
       CC -o example object_files


This  rule  says  that to construct the example program, you
need the object files determined earlier, and them link them
together.   Object  files which were up to date in the base-
line are used wherever possible, but files which were out of
date are constructed in the current directory and those will
be linked.

55..44..33..  TThhee RRuullee ffoorr CC

Next we need to tell cake how to manage C sources.   On  the
surface, this is a simple rule:

     %.o: %.c
       CC CFLAGS -c %.c




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





Aegis                                             User Guide


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.

     %.o!: %.c
       rm -f %.o
       CC CFLAGS -c %.c

The _-_f option to the _r_m command is because the file does not
always exist.

Unfortunately this  rule  omits  finding  the  include  file
dependencies.   The  cake  package includes a program called
_c_c_i_n_c_l which is used to find them.  The rule now becomes

     %.o!: %.c* [[ccincl %.c]]
       rm -f %.o
       CC CFLAGS -c %.c

This rule is a little quirky about include  files  which  do
not  yet  exist, but must be constructed by some other rule.
You may want to use _g_c_c _-_M_M  instead,  which  is  almost  as
quirky  when  used  with cake.  Another alternative, used by
the author with far more success, is to use the _c___i_n_c_l  pro-
gram from the _c_o_o_k package, mentioned in an earlier section.
The _g_c_c _-_M_M understands C include semantics  perfectly,  the
_c___i_n_c_l  command  caches its results and thus goes faster, so
you will need to figure which you most want.

55..44..33..11..  IInncclluuddee DDiirreeccttiivveess

Unlike _c_o_o_k described in an earlier section, using  _c_a_k_e  as
described here allows you to continue using the

     #include "_f_i_l_e_n_a_m_e"

form of the include directive.  This is because the develop-
ment directory appears, to the compiler, to  be  a  complete
copy of the baseline.

55..44..44..  TThhee RRuullee ffoorr YYaacccc

Having  explained the complexities of the rules in the above
section about C, the rule for yacc  will  be  given  without
delay:












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





User Guide                                             Aegis


     #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
with the example.

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

55..44..55..  TThhee RRuullee ffoorr LLeexx

The rule for lex is vary similar to the rule for yacc.

     #define LEX lex
     #define LFLAGS

     %.c!: %.l  if exist %.l
       rm -f %.c
       LEX LFLAGS %.l
       mv lex.yy.c %.c


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

55..44..66..  RRuulleess ffoorr DDooccuummeennttss

You  can  format  documents,  such as user guides and manual
entries with Aegis and cake, and the rules  are  similar  to
the ones above.

     %.ps!: %.ms* [[soincl %.ms]]
       rm -f %.ps
       groff -s -p -t -ms %.ms > %.ps


This  rule  says to run the document through groff, with the
_s_o_e_l_i_m(1) and _p_i_c(1) and _t_b_l(1) filters, use the _m_s(7) macro
package, to produce PostScript output.

This  suffers  from  many of the problems with include files
which need to be generated, as does the C rule, above.   You
may want to use _c___i_n_c_l _-_r from the _c_o_o_k package, rather than
the _s_o_i_n_c_l supplied by the _c_a_k_e package.



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





Aegis                                             User Guide


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 125





User Guide                                             Aegis


55..55..  UUssiinngg MMaakkee

The _m_a_k_e(1) program exists in many  forms,  usually  one  is
available with each UNIX version.  The one used in the writ-
ing of this section is _G_N_U _M_a_k_e _3_._7_0, available by anonymous
FTP from your nearest GNU archive site.  GNU Make was chosen
because it was the most powerful,  it  is  widely  available
(usually for little or no cost) and discussion of the alter-
natives (SunOS make, BSD 4.3 make, etc), would not  be  uni-
versally  applicable.  "Plain vanilla" make (with no transi-
tive closure, no pattern rules, no functions) is not  suffi-
ciently  capable  to  satisfy  the  demands  placed on it by
Aegis.

With the  introduction  of  the  _d_e_v_e_l_o_p_m_e_n_t___d_i_r_e_c_t_o_r_y___s_t_y_l_e
field  of  the project configuration file, any project which
is currently using a "plain vanilla" make  may  continue  to
use it, and still manage the project using 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   _d_e_v_e_l_o_p_m_e_n_t___d_i_r_e_c_t_o_r_y___s_t_y_l_e_._s_o_u_r_c_e___f_i_l_e___s_y_m_l_i_n_k
field  of  the  project configuration file is set to _t_r_u_e so
that Aegis will arrange for the development directory to  be
full  of  symbolic  links,  making it appear that the entire
project source is in each change's development directory.

55..55..11..  IInnvvookkiinngg MMaakkee

The _b_u_i_l_d___c_o_m_m_a_n_d field of the project configuration 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 configuration file:




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





Aegis                                             User Guide


     link_integration_directory = true;


The  files  must  be  removed  first, otherwise the baseline
would be corrupted by integration builds (or even by  devel-
oper  builds,  if  your aren't using a separate user for the
project owner).

NNoottee:: if you are migrating an existing project  ddoo  nnoott  sseett
tthhiiss  ffiieelldd;  only  set it _a_f_t_e_r you have changed _a_l_l of the
Make rules.  If in doubt, ddoonn''tt set this field.

Another field to be set in this file is

     development_directory_style =
     {
         source_file_symlink = true;
     };

which tells Aegis to maintain  symbolic  links  between  the
development directory and the baseline for source files (but
not derived files).  See _a_e_p_c_o_n_f(5) for more information.

55..55..22..  TThhee RRuullee FFiillee

The file containing the rules  is  called  _M_a_k_e_f_i_l_e  and  is
given to make on the command line.

The  following  items  are preamble to the rest of the file;
they ask Aegis for the  source  files  of  the  project  and
change  so that make can determine what needs to be compiled
and linked.

     project_files := \
       $(shell aelpf -p $(project) \
         -c $(change))
     change_files := \
       $(shell aelcf -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









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





User Guide                                             Aegis


     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


This rule says that to make the example  program,  you  need
the  object  files  determined  earlier,  and them link them
together.  Object files which were up to date in  the  base-
line are used wherever possible, but files which were out of
date are constructed in the current directory and those will
be linked.

55..55..33..  TThhee RRuullee ffoorr CC

Next  we  need to tell make how to manage C sources.  On the
surface, this is a simple rule:

     %.o: %.c
       $(CC) $(CFLAGS) -c $*.c

This example matches the built-in rule for most _m_a_k_es.   But
it forgets to remove the target before constructing it.

     %.o: %.c
       rm -f $*.o
       $(CC) $(CFLAGS) -c $*.c

The target may not yet exist, hence the _-_f option.

Something missing from this rule is finding the include file
dependencies.  The GNU Make User Guide  describes  a  method
for  obtaining  include  file dependencies.  A set of depen-
dency files are constructed, one per _._c file.

     %.d: %.c
       rm -f %.d
       $(CC) $(CFLAGS) -MM $*.c \
       | sed 's/^\(.*\).o :/\1.o \1.d :/' \
       > $*.d

These dependency files are then included into  the  _M_a_k_e_f_i_l_e



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





Aegis                                             User Guide


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.

The  _-_M_M  option  to  the $(CC) command means that this rule
requires the _g_c_c program in order to work correctly.  It may
be  possible  to  use _c___i_n_c_l(1) from cook, or _c_c_i_n_c_l(1) from
cake to build the dependency lists instead; but  they  don't
understand  the  conditional  preprocessing  as  well as _g_c_c
does.

This method also suffers when heterogeneous  development  is
performed.  If you include different files, depending on the
environment being compiled  within,  the  _._d  files  may  be
incorrect, and GNU Make has no way of knowing this.

55..55..33..11..  IInncclluuddee DDiirreeccttiivveess

Unlike  _c_o_o_k described in an earlier section, using GNU Make
as described here allows you to continue using the

     #include "_f_i_l_e_n_a_m_e"

form of the include directive.  This is because the develop-
ment  directory  appears,  to the compiler, to be a complete
copy of the baseline.

55..55..44..  TThhee RRuullee ffoorr YYaacccc

Having explained the complexities of the rules in the  above
section  about  C,  the  rule for yacc will be given without
delay:

     %.c %.h: %.y
       rm -f $*.c $*.h y.tab.c y.tab.h
       $(YACC) $(YFLAGS) -d $*.y
       mv y.tab.c $*.c
       mv y.tab.h $*.h




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





User Guide                                             Aegis


This  rule could be jazzed up to cope with the listing file,
too,  if  that  was  desired, but this is sufficient to work
with the example.

GNU Make's ability to cope with transitive closure will pick
up  the  generated  _._c  file  and construct the necessary _._o
file.

To prevent GNU Make throwing away the transitive files,  and
thus slowing things down in some cases, make them precious:

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


55..55..55..  TThhee RRuullee ffoorr LLeexx

The rule for lex is vary similar to the rule for yacc.

     %.c: %.l
       rm -f $*.c lex.yy.c
       $(LEX) $(LFLAGS) $*.l
       mv lex.yy.c $*.c


GNU Make's ability to cope with transitive closure will pick
up the generated _._c file  and  construct  the  necessary  _._o
file.

To  prevent GNU Make throwing away the transitive files, and
thus slowing things down in some cases, make them precious:

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


55..55..66..  RRuulleess ffoorr DDooccuummeennttss

You can format documents, such as  user  guides  and  manual
entries  with  Aegis and GNU Make, and the rules are similar
to the ones above.

     %.ps: %.ms
       rm -f $*.ps
       groff -p -t -ms $*.ms > $*.ps


This rule says to run the document through groff,  with  the
_p_i_c(1)  and  _t_b_l(1) filters, use the _m_s(7) macro package, to
produce PostScript output.



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





Aegis                                             User Guide


This omits include file dependencies.  If this is  important
to  you,  the  _c___i_n_c_l  program from _c_o_o_k can be used to find
them.  Filtering its output can then produce  the  necessary
dependency  files  to  be included, rather like the C rules,
above.

Manual entries may be handled in a similar way

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


55..55..77..  OOtthheerr MMaakkeess

All of the above discussion assumes that GNU  Make  and  GCC
are used.  If you do not want to do this, or may not do this
because of internal company politics, it is possible to per-
form all of the automated features manually.

This  may,  however,  rapidly  become spectacularly tedious.
For example: if a user needs to copy the _M_a_k_e_f_i_l_e into their
change  for  any  reason,  they  will need to constantly use
_a_e_d(1) to "catch up" with integrations into the baseline.

Reviewers are also  affected:  they  must  check  that  each
change  to  the _M_a_k_e_f_i_l_e accurately reflects the object list
and the dependencies of each source file.

55..55..88..  TTeemmppllaatteess

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

55..55..99..  GGNNUU MMaakkee VVPPAATTHH PPaattcchh

Version 3.76 and later of GNU Make include  this  patch,  so
you don't need to read this section unless you have GNU Make
3.75 or earlier.

There is a patch available for GNU  Make  3.75  and  earlier
which gives it improved VPATH semantics.  At the time it was
not maintained by the same person who maintained  GNU  Make.
Since  then,  the  maintaier changed, and the patch has been
incorporated.

The patch is the  work  of  Paul  D.  Smith  <psmith@BayNet-
works.com> and may be fetched By Anonymous FTP from

Host:   ftp.wellfleet.com
Dir:    /netman/psmith/gmake




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





User Guide                                             Aegis


File:   vpath+.README
File:   vpath+.patch._v_e_r_s_i_o_n

The version numbers track the GNU Make version numbers.

For  a  description of the VPATH problem, and how this patch
addresses it, see the README file referenced.

55..55..1100..  GGNNUU MMaakkee''ss VVPPAATTHH++

In theory, using GNU Make  3.76  or  later  (or  a  suitable
patched  earlier  version)  is  similar  to using Cook.  The
project configuration file now requires

     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 132         (lib/en/user-guide/c4.5.so)    Peter Miller





Aegis                                             User Guide


55..66..  BBuuiillddiinngg EExxeeccuuttaabbllee SSccrriippttss

Aegis  treats  source  files  as,  well, source files.  This
means that it forgets any executable  bits  (and  any  other
mode  bits)  you may set on the file.  Usually, this isn't a
problem - except for scripts.

So, just how _d_o you get Aegis  to  give  you  an  executable
script?   Well,  you  add  a  build rule.  However, since it
can't depend on itself, it  needs  to  depend  on  something
else.

Using a Cook example, we could write

     bin/%: script/%.sh
     {
         /* copy the script */
         cp script/%.sh bin/%;
         /* make it executable */
         chmod a+rx bin/%;
         /* syntax check */
         bash -n bin/%;
     }

There  is a small amout of value-added here: we did a syntax
check along the way, which catches all sorts of problems.

The same technique also works for Perl

     bin/%: script/%.pl
     {
         cp script/%.pl bin/%;
         chmod a+rx bin/%;
         perl -cw bin/%;
     }


The same technique also works for TCL

     bin/%: script/%.tcl
     {
         cp script/%.rcl bin/%;
         chmod a+rx bin/%;
         procheck -nologo bin/%;
     }

The _p_r_o_c_h_e_c_k(1) command is part of the TclPro package.

Many tools have a similar options.

You can also combine  this  with  GNU  Autoconf  to  produce
architecture  specific  shell scripts from architecture neu-
tral sources.




Peter Miller     (lib/en/user-guide/c4.7.so)        Page 133





User Guide                                             Aegis


55..77..  GGNNUU AAuuttooccoonnff

If your  projects  uses  GNU  Make,  GNU  Autoconf  and  GNU
Automake,  here  is a quick and simple method to import your
project into Aegis and have it running fairly quickly.

55..77..11..  TThhee SSoouurrcceess

Once you have create and Aegis project to, your first change
set  should  simply contain all of the source files, without
removing or adding anything.  The only additonal file is the
Aegis  project configuration file, usually called _a_e_g_i_s_._c_o_n_f
and usually located in the top-level directory.

Follow the directions in the section, above, on  _u_s_i_n_g  _M_a_k_e
for how to fill out this file.

Note  that  if  you are working from a tarball, they usually
contain several _d_e_r_i_v_e_d file.  That is, files which are  not
primary  sourec  files,  but  are instead derived from other
files.  This is a convenience for the end-user  but  a  nui-
sance  at  this  point.   Exanple of derived files in source
tarballs include configure, Makefile.in,  config.h.in,  _e_t_c.
You will need to exclude them form the first change set.

In  this  first change set, you don't even try to build any-
thing.

     build_command = "exit 0";

Which will allow the Aegis process to complete.

55..77..22..  BBuuiillddiinngg

You actually get your project to buld in the  second  change
set.  Once you have started development, you will see all of
the source files in the development  directory  (well,  sym-
links to them).

In order to get you build to work, you have to bootstrap the
Makefile.  Using the usual GNU tool chain, this file is gen-
erated  from  Makefile.in  which  is  in turn generated from
Makefile.am, and this is not presently  in  the  development
directory.

This  is  done  by creating a new primary source file called
makefile at the top level

     $ aaeennff mmaakkeeffiillee
     $

and setting its contents to be





Page 134         (lib/en/user-guide/c4.7.so)    Peter Miller





Aegis                                             User Guide


     include Makefile

     ifndef srcdir

     bogus-default-target: Makefile
             $(MAKE) $(MAKEFLAGS) $(MAKECMDGOALS)


     Makefile: configure Makefile.in config.h.in
             rm -f config.cache
             ./configure


     configure: configure.ac
             autoconf


     config.h.in: configure.ac
             autoheader


     Makefile.in: Makefile.am
             automake

     endif

This works because _m_a_k_e(1) looks for makefile  before  Make-
file,  but  also because our bootstrapping makefile includes
the real Makefile if it exists, and the  real  file's  rules
will  take  precedence.   At this point, GNU Make has a very
useful feature: it will rebuild include files which are out-
of-date  before  it does anything else.  In oue new develop-
ment directory, this will  result  in  the  necessary  files
being automagically generated and then acted upon.

Things  that  can go wrong: many projects include files such
as _i_n_s_t_a_l_l_-_s_h and _m_i_s_s_i_n_g and _m_k_i_n_s_t_a_l_l_d_i_r_s in the  directi-
bution.   You  will need to include rules for these files in
the conditonal part of your bootstrapping makefile rules.

     AUTOMAKE_DIR=/usr/share/automake-1.7

     install-sh: $(AUTOMAKE_DIR)/install-sh
             cp $^ $@

     missing: $(AUTOMAKE_DIR)/missing
             cp $^ $@

     mkinstalldirs: $(AUTOMAKE_DIR)/mkinstalldirs
             cp $^ $@

You will have to tell the _c_o_n_f_i_g_u_r_e rule that it depends  on
these files as well.




Peter Miller     (lib/en/user-guide/c4.7.so)        Page 135





User Guide                                             Aegis


Other  things that can go wrong: some projects use different
rules for constructing the config.h file.  You  should  read
the  generated  Makefile.in file for how, and duplicate into
the bootstrapping makefile file.  You may also need  a  rule
for  the  aclocal.m4  file,  and  tell the _c_o_n_f_i_g_u_r_e rule it
depends on it.

There   is   a   template   makefile   installed   in    the
_/_u_s_r_/_p_k_g_/_s_h_a_r_e_/_a_e_g_i_s_/_c_o_n_f_i_g_._e_x_a_m_p_l_e directory.

Now  you can set the build command field of the project con-
figuration file:

     build_command =
             "make "
             "project=$project "
             "change=$change "
             "version=$version";

Aegis watches the eist status  of  the  build  command.   Be
aware  that  many  build  systems  which  use recursive make
report false positives, because the exist status of the sub-
make is often ignored by the top-level Makefile.  This means
that Aegis may think your project compiles when, in fact, it
does not.

If,  while  trying  to  get  it  to build, you discover more
derived files which should not be primary source files, sim-
ply  use  the  _a_e_r_m(1)  command.  The _a_e_c_l_e_a_n(1) command may
come in handly, too.

Once this second change set builds,  integrate  it  via  the
usual Aegis process.

55..77..33..  TTeessiinngg

If  the project you are importing has tests, they are proba-
bly executed by saying

     $ mmaakkee cchheecckk
     _l_o_t_s _o_f _o_u_t_p_u_t
     $

or something similar.  Aegis expects each test to  be  in  a
separate  shell  script.   Usually  this is simple enough to
arrange.  See the chapter on _T_e_s_t_i_n_g for some hints.

55..77..44..  AAnn OOppttiimmiizzaattiioonn

The first build in a new development directory can be  quite
time  consuming.   It  is  possible  to short-ciruit this by
using the pre-built object files in  the  baseline.   To  do
this, use the following setting in the project configuration
file:



Page 136         (lib/en/user-guide/c4.7.so)    Peter Miller





Aegis                                             User Guide


     development_directory_style =
     {
         source_file_symlink = true;
         derived_file_copy = true;
         derived_at_start_only = true;
     };

This causes Aegis to copy all of the derived file into  your
development  directory  at  _a_e_d_b time.  This is usually much
faster than compiling and linking all over again.

55..77..55..  SSiiggnneedd--ooffff--bbyy

It is possible to get the  Aegis  process  to  automatically
append  Signed-off-by  lines to the change description.  Set
the following field in the project configuration file:

     signed_off_by = true;

Only open source projects should use this field.   The  OSDL
definition  of the Developer's Certificate of Origin 1.0 can
be  found  at  http://www.osdl.org/newsroom/press_releases/-
2004/2004_05_24_dco.html and is defined to mean:

"By making a contribution to this project, I certify that:

(a)  The  contribution was created in whole or in part by me
and I have the right to submit  it  under  the  open  source
license indicated in the file; or

(b)  The  contribution  is based upon previous work that, to
the best of my knowledge, is covered  under  an  appropriate
open  source license and I have the right under that license
to submit that work with modifications, whether  created  in
whole  or  in part by me, under the same open source license
(unless I am permitted to submit under a different license),
as indicated in the file; or

(c)  The  contribution  was  provided directly to me by some
other person who certified (a), (b) or (c) and  I  have  not
modified it."

55..77..66..  IImmppoorrttiinngg tthhee NNeexxtt UUppssttrreeaamm TTaarrbbaallll

If  you are using Aegis to track your local changes, but the
master  sourecs  are  elsewhere,  you  will  need  to  track
upstream changes when they are released.

It  is tempting to use the _a_e_t_a_r(1) command, but it will not
be able to detect derived files which have been added to the
tarball.   You  will  need  to uppack the tarball and remove
them manually.





Peter Miller     (lib/en/user-guide/c4.7.so)        Page 137





User Guide                                             Aegis


Create a change set in the usual way, and _a_e_c_d(1)  into  it.
Copy  the  entire  project into your change set, because you
don't yet know what the tarball will want to change (and  it
will include unchanged files).

     $ aaeeccdd
     $ aaeeccpp ..
     $

(Yes,  that dot is part of the command.)  Now you can unpack
the tarball.  You need to strip off  the  leading  directory
somehow  (most  polite  projects  use a prefix).  The author
uses the _t_a_r_d_y(1) command, like this:

     $ zzccaatt _p_r_o_j_e_c_t_-_x_._y..ttaarr..ggzz || \\
       ttaarrddyy --rrpp _p_r_o_j_e_c_t_-_x_._y --nnooww || \\
       ttaarr xxff --
     $$

It pays to change that the tarball is the shape  you  expect
_b_e_f_o_r_e running this command.

At this point you have to once again remove all of the files
which are in the tarball, but which are not  primary  source
files, such as _c_o_n_f_i_g_u_r_e and _M_a_k_e_f_i_l_e_._i_n and the like.

     $ rrmm --ff ccoonnffiigguurree MMaakkeeffiillee..iinn ccoonnffiigg..hh..iinn _e_t_c
     $ rrmm --ff aaeeggiiss..lloogg
     $

It  is  useful  if  you  place  the _r_m(1) command in a shell
script, and tell Aegis it is a source file, because you will
have to do this every time.

Now  you can have Aegis add any new files by using the foll-
woing command:

     $ aaeennff ..
     $

(Yes, that dot is part of the command.)  Note that if  there
are  no new files, this command will give you an error, this
is expected.

You will have to work out moved and removed files for  your-
self, and use the _a_e_m_v(1) and _a_e_r_m(1) commands.

At  this  point  you  should remove all the files which were
present in the tarball but which  dod  not  actually  change
from  the  change  set.   The  follwoing  command  does this
quickly and simply:






Page 138         (lib/en/user-guide/c4.7.so)    Peter Miller





Aegis                                             User Guide


     $ aaeeccppuu --uunncchhaannggeedd
     $

You change set now contains the minimum set of  differences.
Go ahead and complete it using the usual Aegis process.

55..77..77..  IImmppoorrttiinngg tthhee NNeexxtt UUppssttrreeaamm PPaattcchh

In  contrast  to  tarballs, patches tend to be far easier to
cope with.  In general, all that is necessary is to use  the
_a_e_p_a_t_c_h(1) command, something like this:

     $ aaeeppaattcchh --rreecceeiivvee --ffiillee _p_r_o_j_e_c_t_-_x_._y..ddiiffff
     $

which  will  create  a change set, check-out only those file
the  patch  alters,  and  copes  with  creates  and  removes
automagically.

There  are two problems with this method.  The largest prob-
lem is patches whicg contains  diff  for  derived  fiels  as
well.  This is unfortunately _v_e_r_y common.

The  simplest  way of coping with this is to add the _a_e_p_a_t_c_h
_-_t_r_o_j_a_n option, which will leave the  change  in  the  _b_e_i_n_g
_d_e_v_e_l_o_p_e_d  state,  where  you  can  examine  it  and use the
_a_e_n_f_u(1) command for any derived files it insisted on creat-
ing as primary source files.

The second problem is much simpler: if a patch only contains
new files, Aegis can't work out how much of the leading path
it  should  ignore  on the filenames in the patch.  You will
need to use the _a_e_p_a_t_c_h _-_r_e_m_o_v_e_-_p_r_e_f_i_x option in this  case.

55..88..  NNoo BBuuiilldd RReeqquuiirreedd

For  some projects, particularly web sites and those written
exclusively in interpreted languages, it may not  be  neces-
sary to ever actually build your project.

For  this  kind of project you add the following line to the
project configuration file:

     build_command = "exit 0";

For a project  configured  in  this  way,  the  _a_e_d_e(1)  and
_a_e_i_p_a_s_s(1)  commands  will  not  check that a build has been
performed.

55..88..11..  WWhhyy TThhiiss MMaayy NNoott BBee SSuucchh AA GGoooodd IIddeeaa

It  isn't  always desirable to configure a project this way,
even when it may initialy appear to be a good idea.




Peter Miller     (lib/en/user-guide/c4.8.so)        Page 139





User Guide                                             Aegis


Web sites:
     You can use the build stage to  check  the  HTML  files
     against  the relevant standards and DTDs.  You can also
     check that all of you (internal) links are  valid,  and
     don't  point  to  non-existant pages or anchors.  Some-
     times, if you have the space, you  can  resolve  server
     side includes, to make it faster for Apache, by serving
     static pages.

Interpreted Languages:
     A whole lot of simple errors, such  as  syntax  errors,
     can  be  caught  by a static check of the source files.
     For example, the perl -c option can syntax  check  your
     Perl  files  without  executing them.  See also the GNU
     awk -lint option, the Python built-in  compile()  func-
     tion,  and  the  php -l (lower case L) option.  You can
     also check that all include files  referenced  actually
     exist.

Documentation:
     Many  systems  allow documentation to be extracted from
     the source files, and turned into  HTML  or  PDF  files
     (_e_._g_.  Doxygen).   This  is  a  sensable thing to do at
     build time.

































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





Aegis                                             User Guide


66..  TThhee DDiiffffeerreennccee TToooollss

This  chapter  describes  the  difference  commands  in  the
project configuration file.  Usually these commands are used
by the _a_e_g_i_s _-_D_I_F_F_e_r_e_n_c_e command  when  differencing  files,
but they may be used to accomplish some other things.

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

66..11..  BBiinnaarryy FFiilleess

Aegis doesn't  particularly  care  whether  your  files  are
binary  or  text.   However, your difference and merge tools
certainly will.  In general, you need  format-specific  dif-
ference and merge tools for each of the file formats used in
your project.  Unfortunately, most vendors of software which
make  use  of proprietary file formats do not supply differ-
ence and merge tools.

The simplest compromise is to treat all files as text,  with
manual repairs for binary files.

A  more elegant solution is to use a shell script invoked by
the _d_i_f_f___c_o_m_m_a_n_d in the project _a_e_g_i_s_._c_o_n_f file.  This shell
script  examines  the file to determine the file format, and
then runs the appropriate difference tool.  Similar  consid-
erations apply to the _m_e_r_g_e___c_o_m_m_a_n_d field.

Please note that this support is not present in Aegis itself
because (a) it  would  cause  code  bloat,  and  (b)  it  is
entirely  possible  to  do  with  a shell script launched by
_d_i_f_f___c_o_m_m_a_n_d.

66..22..  IInntteerrffaacciinngg

The diff command is configured by a  field  of  the  project
configuration file (_a_e_g_i_s_._c_o_n_f).

66..22..11..  ddiiffff__ccoommmmaanndd

This command is used by _a_e_d(1) to produce a difference list-
ing when file in the development  directory  was  originally
copied from the current version in the baseline19.
-----------
  19 Or this is logically the case.



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





User Guide                                             Aegis


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 dif-
ference  files  must  be produced in addition to these extra
tests.

66..22..22..  mmeerrggee__ccoommmmaanndd

This command is used by _a_e_d(1) to produce a difference list-
ing  when  file  in the development directory is out of date
compared to the current version in the baseline.

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

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

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

${Input}
     The absolute path name of the  edited  version  of  the
     file.   Usually  in  the  development directory.  Aegis
     usually moves the source file aside, so that the output
     can replace the source file.

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



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





Aegis                                             User Guide


     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.

66..33..  WWhheenn NNoo DDiiffff iiss RReeqquuiirreedd

It is possible to configure a project to omit the diff  step
as unnecessary, by the following setting:

     diff_command = "exit 0";

This  disables  all  generation,  checking and validation of
difference files for each change  source  file.   The  merge
functions  of  the  _a_e_d_i_f_f(1) command are unaffected by this
setting.








































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





User Guide                                             Aegis


66..44..  UUssiinngg ddiiffff aanndd mmeerrggee

These two tools are available with most  flavours  of  UNIX,
but  often in a very limited form.  One severe limitation is
the _d_i_f_f_3(1) command, which often can  only  cope  with  200
lines  of  differences.   The best alternative is to use GNU
diff, which has context differences  available,  and  a  far
more robust _d_i_f_f_3(1) implementation.

See   the   earlier  _I_n_t_e_r_f_a_c_i_n_g  section  for  substitution
details.

66..44..11..  ddiiffff__ccoommmmaanndd

The entry in the configuration file looks like this:

     diff_command =
       "set +e; diff -c $original "
       "$input > $output; test $? -le 1";


This needs a little explanation:
+o This command is always executed with the shell's --ee option
enabled,  causing the shell to exit on the first error.  The
"set +e" turns this off.
+o The _d_i_f_f(1) command exits with a status of 0 if the  files
are  identical, and a status of 1 if they differ.  Any other
status means something horrible happened.  The  "test"  com-
mand  is  used  to  change  this  to  the  exit status aegis
expects.

The --cc option says to  produce  a  context  diff.   You  may
choose  to  use the --uu option, to produce uni-diffs, if your
_d_i_f_f command supports it.

You may also wish to consider ignoring white space  in  com-
parisons,  as these tend to be cosmetic changes and not very
interesting to code reviewers.  The --bb option  of  GNU  Diff
will ignore changes to the amount of white space, and the --ww
option will ignore white space altogether.

Binary files will often cause modern versions of GNU Diff to
exit  with an exit status of 2, which is probably reasonable
most of the time.  If your project  contains  binary  files,
you  may want to treat all files as text files.  Use the GNU
Diff --aa option in this case.

A useful alternative, available with more recent versions of
GNU  Diff,  is  the  --UU option.  This is a more compact form
than the --cc option, and is able to give the  whole  file  as
context.






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





Aegis                                             User Guide


     diff_command =
       "set +e; diff -U999999 $original "
       "$input > $output; test $? -le 1";


The  exit  status  must  once again be taylored, however the
output will be the whole source for  context,  with  changes
marked  by  `+' and `-' in the left margin.  This, reviewers
need only search for /^[-+]/ in order to see all  edit  made
to the file.

66..44..22..  mmeerrggee__ccoommmmaanndd

Note:  The  _m_e_r_g_e(1)  command is better than this use of the
_d_i_f_f_3(1) command.  See the RCS chapter for more details.

The entry in the configuration 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.  You may want the  --aa  option,
to treat all files as ACSII.
+o  The  _s_e_d(1)  command  is  used  to remove the "write" and
"quit" commands from the generated edit script.
+o The _e_d(1) command is used  to  apply  the  generated  edit
script to the $MostRecent file, and print the results on the
standard output, which are redirected into the $output file.

66..55..  UUssiinngg ffhhiisstt

The ffhhiisstt program by David I. Bell also comes with two other
utilities, _f_c_o_m_p and _f_m_e_r_g_e, which use the same minimal dif-
ference algorithm.

See   the   earlier  _I_n_t_e_r_f_a_c_i_n_g  section  for  substitution
details.

66..55..11..  ddiiffff__ccoommmmaanndd

The entry in the configuration file looks like this:

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





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





User Guide                                             Aegis


The --ww option produces an output of the  entire  file,  with
insertions and deletions marked by "change bars" in the left
margin.  This is superior to context difference, as it shows
the entire file as context.

For more information, see the _f_c_o_m_p(1) manual entry.

66..55..22..  mmeerrggee__ccoommmmaanndd

The entry in the configuration 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 146         (lib/en/user-guide/c5.0.so)    Peter Miller





Aegis                                             User Guide


77..  TThhee PPrroojjeecctt AAttttrriibbuutteess

The project attributes are  manipulated  using  the  _a_e_p_a(1)
command.   This  command  reads a project attributes file to
set the project attributes.  This file can be thought of  as
having  several  sections,  each of which will be covered by
this chapter.  You should see the  _a_e_p_a_t_t_r(5)  manual  entry
for more details.

77..11..  DDeessccrriippttiioonn aanndd AAcccceessss

The  _d_e_s_c_r_i_p_t_i_o_n field is a string which contains a descrip-
tion of  the  project.   Large  amounts  of  prose  are  not
required; a single line is sufficient.

The  _d_e_f_a_u_l_t___d_e_v_e_l_o_p_m_e_n_t___d_i_r_e_c_t_o_r_y_P  _f_i_e_l_d _i_s _a _s_t_r_i_n_g _w_h_i_c_h
_c_o_n_t_a_i_n_s _t_h_e _p_a_t_h_n_a_m_e _o_f  _w_h_e_r_e  _t_o  _p_l_a_c_e  _n_e_w  _d_e_v_e_l_o_p_m_e_n_t
_d_i_r_e_c_t_o_r_i_e_s_.   _T_h_e _p_a_t_h_n_a_m_e _m_u_s_t _b_e _a_b_s_o_l_u_t_e_.  _T_h_i_s _f_i_e_l_d _i_s
_o_n_l_y _c_o_n_s_u_l_t_e_d _i_f _t_h_e _u_c_o_n_f_(_5_) _f_i_e_l_d _o_f _t_h_e _s_a_m_e _n_a_m_e _i_s _n_o_t
_s_e_t_.  _D_e_f_a_u_l_t_s _t_o _$_H_O_M_E_.

The  _u_m_a_s_k field is an integer which is set to the file per-
mission mode mask.  See _u_m_a_s_k(2) for more information.  This
value  will always be OR'ed with 022, because aegis is para-
noid.

77..22..  NNoottiiffiiccaattiioonn CCoommmmaannddss

The _d_e_v_e_l_o_p___e_n_d___n_o_t_i_f_y___c_o_m_m_a_n_d field is a string which  con-
tains  a command to be used to notify that a change requires
reviewing.  All of the substitutions described  in  _a_e_s_u_b(5)
are  available.  This field is optional, if it is not speci-
fied no notification will be  issued.   This  command  could
also  be  used  to  notify other management systems, such as
progress and  defect  tracking,  in  addition  to  notifying
users.

The  _d_e_v_e_l_o_p___e_n_d___u_n_d_o___n_o_t_i_f_y___c_o_m_m_a_n_d  field is a string con-
taining a command used to notify  that  a  change  has  been
withdrawn  from  review for further development.  All of the
substitutions described in  _a_e_s_u_b(5)  are  available.   This
field  is  optional,  if it is not specified no notification
will be issued.  This command could also be used  to  notify
other management systems, such as progress and defect track-
ing, in addition to notifying users.

The _r_e_v_i_e_w___p_a_s_s___n_o_t_i_f_y___c_o_m_m_a_n_d field is a string  containing
the  command  to  notify that the review has passed.  All of
the substitutions described in _a_e_s_u_b(5) are available.  This
field  is  optional,  if it is not specified no notification
will be issued.  This command could also be used  to  notify
other management systems, such as progress and defect track-
ing, in addition to notifying users.




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





User Guide                                             Aegis


The _r_e_v_i_e_w___p_a_s_s___u_n_d_o___n_o_t_i_f_y___c_o_m_m_a_n_d field is a  string  con-
taining  the  command  to  notify that a review pass has has
been rescinded.   All  of  the  substitutions  described  in
_a_e_s_u_b(5)   are  available.   This  field  is  optional,  and
defaults to  the  _d_e_v_e_l_o_p___e_n_d___n_o_t_i_f_y___c_o_m_m_a_n_d  field  if  not
specified.  If neither is specified, no notification will be
issued.  This command could also be  used  to  notify  other
management systems, such as progress and defect tracking, in
addition to notifying users.

The _r_e_v_i_e_w___f_a_i_l___n_o_t_i_f_y___c_o_m_m_a_n_d field is a string  containing
the  command  to  notify that the review has failed.  All of
the substitutions described in _a_e_s_u_b(5) are available.  This
field  is  optional,  if it is not specified no notification
will be issued.  This command could also be used  to  notify
other management systems, such as progress and defect track-
ing, in addition to notifying users.

The _i_n_t_e_g_r_a_t_e___p_a_s_s___n_o_t_i_f_y___c_o_m_m_a_n_d field is a string contain-
ing  the  command to notify that the integration has passed.
All of the substitutions described in  _a_e_s_u_b(5)  are  avail-
able.   This  field  is  optional, if it is not specified no
notification will be issued.  This  command  could  also  be
used  to  notify  other management systems, such as progress
and defect tracking, in addition to notifying users.

The _i_n_t_e_g_r_a_t_e___f_a_i_l___n_o_t_i_f_y___c_o_m_m_a_n_d field is a string contain-
ing  the  command to notify that the integration has failed.
All of the substitutions described in  _a_e_s_u_b(5)  are  avail-
able.   This  field  is  optional, if it is not specified no
notification will be issued.  This  command  could  also  be
used  to  notify  other management systems, such as progress
and defect tracking, in addition to notifying users.

77..22..11..  NNoottiiffiiccaattiioonn bbyy eemmaaiill

The aegis command is distributed with a set of shell scripts
to perform these notifications by email.  They are installed
into  the  _/_u_s_r_/_p_k_g_/_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 148         (lib/en/user-guide/c5.0.so)    Peter Miller





Aegis                                             User Guide


     develop_end_notify_command =
       "$sh $datadir/de.sh $project $change";
     develop_end_undo_notify_command =
       "$sh $datadir/deu.sh $project $change";
     review_pass_notify_command =
       "$sh $datadir/rp.sh $project $change \
       $developer $reviewer";
     review_pass_undo_notify_command =
       "$sh $datadir/rpu.sh $project $change \
       $developer";
     review_fail_notify_command =
       "$sh $datadir/rf.sh $project $change \
       $developer $reviewer";
     integrate_pass_notify_command =
       "$sh $datadir/ip.sh $project $change \
       $developer $reviewer $integrator";
     integrate_fail_notify_command =
       "$sh $datadir/if.sh $project $change \
       $developer $reviewer $integrator";


Please  note:  the exit status of all these commands will be
ignored.

77..22..22..  NNoottiiffiiccaattiioonn bbyy UUSSEENNEETT

The aegis command is distributed with a set of shell scripts
to   perform   these  notifications  by  USENET.   They  are
installed into the _/_u_s_r_/_p_k_g_/_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 149





User Guide                                             Aegis


77..33..  EExxeemmppttiioonn CCoonnttrroollss

The _d_e_v_e_l_o_p_e_r___m_a_y___r_e_v_i_e_w field is a boolean.  If this  field
is  true,  then a developer may review her own change.  This
is probably only a good idea for projects  of  less  than  3
people.  The idea is for as many people as possible to crit-
ically examine a change.

The _d_e_v_e_l_o_p_e_r___m_a_y___i_n_t_e_g_r_a_t_e field is  a  boolean.   If  this
field  is  true,  then  a  developer  may  integrate her own
change.  This is probably only a good idea for  projects  of
less  than 3 people.  The idea is for as many people as pos-
sible to critically examine a change.

The _r_e_v_i_e_w_e_r___m_a_y___i_n_t_e_g_r_a_t_e field  is  a  boolean.   If  this
field  is  true,  then a reviewer may integrate a change she
reviewed.  This is probably only a good idea for projects of
less  than 3 people.  The idea is for as many people as pos-
sible to critically examine a change.

The _d_e_v_e_l_o_p_e_r_s___m_a_y___c_r_e_a_t_e___c_h_a_n_g_e_s field is  a  boolean.   If
this  field  is  true then developers may create changes, in
addition to administrators.  This tends to be a very  useful
thing, since developers find most of the bugs.

The  _d_e_f_a_u_l_t___t_e_s_t___e_x_e_m_p_t_i_o_n  field is a boolean.  This field
contains what to do when a change is created  with  no  test
exemption  specified.  The default is "false", i.e. no test-
ing exemption, tests must be provided.

This kind of blanket exemption should only  be  set  when  a
project  has  absolutely no functionality available from the
command line; examples include X11  programs.   The  program
could  possibly be improved by providing access to the func-
tionality from the command line, thus allowing tests  to  be
written.

77..33..11..  OOnnee PPeerrssoonn PPrroojjeeccttss

The  entries in the project attributes file for a one person
project look like this:

     developer_may_review = true;
     developer_may_integrate = true;
     reviewer_may_integrate = true;
     developers_may_create_changes = true;


All of the staff roles (administrator,  developer,  reviewer
and integrator) are all set to be the same user.







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





Aegis                                             User Guide


77..33..22..  TTwwoo PPeerrssoonn PPrroojjeeccttss

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

The entries in the project attributes file for a two  person
project look like this:

     developer_may_review = false;
     developer_may_integrate = true;
     reviewer_may_integrate = true;
     developers_may_create_changes = true;


All  of the staff roles (developer, reviewer and integrator)
are all set to allow both users.

77..33..33..  LLaarrggeerr PPrroojjeeccttss

Once you have 3 or more staff on a project, you  can  assign
all  of  the  roles to separate people.  The idea is for the
greatest number of eyes to see each change and detect  flaws
before they reach the baseline.

The  entries in the project attributes file for a three per-
son project look like this:

     developer_may_review = false;
     developer_may_integrate = false;
     reviewer_may_integrate = false;
     developers_may_create_changes = true;


For smaller teams, everyone may be a reviewer.  As the teams
get larger, the more experienced staff are often the review-
ers, rather than everyone.

77..33..44..  RRSSSS FFeeeeddss

Aegis has the ability to publish RSS 2.0  items  to  an  RSS
channel  when changesets transition to a new state.  This is
an optional feature that must be enabled and configured  via
the project-specific attributes.

Project administrators can configure each change of state to
cause an RSS item to be added to a  specified  RSS  channel.
Each  transition  is  individually controlled, allowing each
transition to be recorded in separate channels, or all tran-
sitions in the same channel, or some combination thereof.

Generating  RSS  items  for  particular state transitions is
enabled by the _r_s_s_:_f_e_e_d_f_i_l_e_n_a_m_e  project-specific  attibute.
The format of this attribute is:




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





User Guide                                             Aegis


     name = "rss:feedfilename-<filename>";
     value = "<state> [<state> <state>]";

The  _n_a_m_e  part of this attribute includes a _f_i_l_e_n_a_m_e_, which
is the name of the RSS feed file (channel) to which the item
is to be added.  The _v_a_l_u_e part of the attribute is a space-
separated list of states that will cause an RSS item  to  be
added to the specified file.  For example,

     name = "rss:feedfilename-foo.xml";
     value = "awaiting_review
              awaiting_integration";

will  cause  items  to be added to the channel stored in the
file "foo.xml" when a changeset transitions _i_n_t_o the  await-
ing_review and awaiting_integration states.

The channel description can be specified using the _r_s_s_:_f_e_e_d_-
_d_e_s_c_r_i_p_t_i_o_n attribute.  The format of this attribute is:

     name = "rss:feeddescription-<filenane>";
     value = "<Some description>";

For example,

     name = "rss:feeddescription-foo.xml";
     value = "This is a description";

will cause the <description> sub-element  of  the  <channel>
element  stored  in the file foo.xml to have the value "_T_h_i_s
_i_s _a _d_e_s_c_r_i_p_t_i_o_n".  If  this  attribute  is  not  used,  the
default description is: "_F_e_e_d _o_f _c_h_a_n_g_e_s _i_n _s_t_a_t_e_._._."

The  channel  title can be specified using the _r_s_s_:_f_e_e_d_t_i_t_l_e
attribute.  The format of this attribute is:

     name = "rss:feedtitle-<filename>";
     value = <Some title>;

For example,

     name = "rss:feedtitle-foo.xml";
     value = "This is a title";

will cause the <title> sub-element of the <channel>  element
stored  in  the file foo.xml to have the value "Project ...:
This is a title" The title will always start with  the  word
"Project"  and  the project name.  If this attribute is sup-
plied, this default title is appended  with  the  test  pro-
vided.

The channel language can be specified using the _r_s_s_:_f_e_e_d_l_a_n_-
_g_u_a_g_e attribute.  The format of this attribute is:




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





Aegis                                             User Guide


     name = "rss:feedlanguage-_f_i_l_e_n_a_m_e";
     value = "_l_a_n_g_u_a_g_e";

For example,

     name = "rss:feedlanguage-foo.xml";
     value = "en-AU";

will cause the <language> sub-element of the <channel>  ele-
ment  stored  in the file foo.xml to have the value _e_n_-_A_U If
not specified, the default value of the language sub-element
is "en-US".

77..33..44..11..  SSeerrvviinngg RRSSSS CChhaannnneellss

aeget  is able to serve up RSS channels, with an appropriate
URL.  An example URL is

     http://somehost/cgi-bin/aeget/proj.1.0/?rss+foo.xml

The key aspect of the URL shown is the "_?_r_s_s_+_f_o_o_._x_m_l"  modi-
fier.   "_f_o_o_._x_m_l" should obviously be replaced with the name
of your RSS channel feed (that is,  the  filename  specified
with  the "_r_s_s_:_f_e_e_d_f_i_l_e_n_a_m_e" project-specified attribute(s).

In order to read the RSS  channels,  it  is  recommended  to
point  your RSS aggregator of choice to the appropriate URL.
In order to make determining the URL easy, aeget  will  also
place  "RSS" icons next to the individual state links on the
main project web page (_"_p_r_o_j_._1_._0_/_?_m_e_n_u_") if there is an  RSS
channel configured to include that changeset state.

77..33..44..22..  LLiinnkkss iinn RRSSSS CChhaannnneellss

Links  within  RSS feed files are stored using a placeholder
("@@SCRIPTNAME@@") instead of the serving  script  in  URLs.
This  is done because the code that knows about hte URL of a
particular installation is encapsulated within aeget.

The placeholder is replaced with the  real  scriptname  when
the file is served by aeget.
















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





User Guide                                             Aegis


88..  TTeessttiinngg

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

88..11..  WWhhyy BBootthheerr??

Writing tests is extra work, compared to the way many  small
(and  some  not-so-small)  software shops operate.  For this
reason, the testing requirement may  be turned off.

The win is that the  tests  hang  around  forever,  catching
minor  and major slips before they become embarrassing "fea-
tures" in a released product.  Prevention  is  cheaper  than
cure in this case, the tests save work down the track.

All of the "extra work" of writing tests is a long-term win,
where old problems never again reappear.  All of the  "extra
work"  of  reviewing changes means that another pair of eyes
sees the code and finds potential problems before they mani-
fest themselves in shipped product.  All of the "extra work"
of integration ensures that the baseline always  works,  and
is  always self-consistent.  All of the "extra work" of hav-
ing a baseline and separate development  directories  allows
multiple   parallel  development,  with  no  inter-developer
interference; and the baseline always works, it is never  in
an  "in-between" state.  In each case, not doing this "extra
work" is a false economy.

The existence of these tests,  though,  is  what  determines
which  projects  are most suited to Aegis and which are not.
It should be noted that suitability is a  continuous  scale,
not black-and-white.  With effort and resources, almost any-
thing fits.

88..11..11..  PPrroojjeeccttss ffoorr wwhhiicchh AAeeggiiss'' TTeessttiinngg iiss MMoosstt SSuuiittaabbllee

Projects  most  suited  to supervision by Aegis are straight
programs.  What the non-systems-programmers out  there  call
"tools"  and  sometimes  "applications".  These are programs
which take a pile of input, chew on it, and emit a  pile  of
output.   The  tests  can  then  compare actual outputs with
expected outputs.

As an example, you could be writing a _s_e_d(1)  look-alike,  a
public  domain  clone  of  the  UNIX sed utility.  You could
write tests which exercise every feature  (insertion,  dele-
tion,  etc.)  and generate the expected output with the real
UNIX sed.  You write the code, and run the  tests;  you  can
immediately see if the output matches expectations.

This is a simple example.  More complex examples exist, such
as Aegis itself.  The Aegis program is used to supervise its
own development.  Tests consist of sequences of commands and



Page 154        (lib/en/user-guide/c11.1.so)    Peter Miller





Aegis                                             User Guide


expected results are tested for.

Other types of software have  been  developed  using  Aegis:
compilers  and  interpreters,  client-server model software,
magnetic tape utilities, graphics software such  as  a  ray-
tracer.  The range is vast, but it is not all types of soft-
ware.

88..11..22..  PPrroojjeeccttss ffoorr wwhhiicchh AAeeggiiss'' TTeessttiinngg iiss UUsseeffuull

For  many  years there have been full-screen applications on
text terminals.  In more recent times  there  is  increasing
use of graphical interfaces.

In  developing  these types of programs it is still possible
to use Aegis, but several options need to be explored.

88..11..22..11..  TTeessttiinngg VViiaa EEmmuullaattoorrss

There are screen emulators for both full-screen text and X11
available.   Using  these  emulators, it is possible to test
the user interface, and test via  the  user  interface.   As
yet, the author knows of no freely available emulators suit-
able for testing via Aegis.  If you find one, please let  me
know.

88..11..22..22..  LLiimmiitteedd TTeessttiinngg

You  may  choose to use Aegis simply for its ability to pro-
vide controlled access to a large source.  You still get the
history  and  change  mechanisms,  the  baseline  model, the
enforced review.  You simply don't test all changes, because
figuring  out  what is on the screen, and testing it against
expectations, is too hard.

If the program has a command line interface, in addition  to
the full-screen or GUI interface, the functionality accessi-
ble from the command line may be tested using Aegis.

It is possible that "limited  testing"  actually  means  "no
testing",  if  you have no functionality accessible from the
command line.

88..11..22..33..  TTeessttiinngg MMooddee

Another alternative is to provide hooks  into  your  program
allowing  you to substitute a file for user input, and to be
able to trigger the dump of a "screen image".  The simulated
user  input  can  then be fed to the program, and the screen
dump (in some terminal-independent  form)  can  be  compared
against expectations.

This  is  easier  for full-screen applications, than for X11
applications.  You need to judge the cost-benefit trade-off.



Peter Miller    (lib/en/user-guide/c11.1.so)        Page 155





User Guide                                             Aegis


Cost  of  development, cost of storage space for X11 images,
cost of _n_o_t testing.

88..11..22..44..  MMaannuuaall TTeessttss

The Aegis program provides a manual test facility.   It  was
originally  intended for programs which required some physi-
cal action from a user, such as "unplug Ethernet cable  now"
or  "mount  tape XG356B now".  It can also be used to have a
user confirm that some on-screen activity has happened.

The problem with manual tests is that they simply don't hap-
pen.   It  is  far  more  pleasant to say "run the automatic
tests" and go for a cup of coffee, than to  wait  while  the
computer  thinks  of mindless things to ask you to do.  This
is human nature: if it can be automated, it is  more  likely
to happen.

88..11..22..55..  UUnniitt TTeessttss

Many  folks think of testing as taking the final product and
testing it.  It is also possible to build  specialized  unit
tests,  which exercise specific portions of the code.  These
tests can then be administrated by Aegis, even if the  full-
blown GUI cannot be.

88..11..33..  PPrroojjeeccttss ffoorr wwhhiicchh AAeeggiiss'' TTeessttiinngg iiss LLeeaasstt UUsseeffuull

Another class of software is things  like  operating  system
kernels  and firmware; things which are "stand alone".  This
isolated nature makes it the most difficult to test: to test
it you want to provide physical input and watch the physical
output.  By its very nature, it is hard to put into a  shell
script, and thus hard to write an Aegis test for.

The  above  chapter  was  written  in 1991.  At this writing
(1999) there are projects like xLinux and operating  systems
like  VxWorks.   These are all embedded, and all have excel-
lent network and download support.  It is entirely  possible
(with  design  support!)  to  write  automatically  testable
embedded systems.

88..11..33..11..  OOppeerraattiinngg SSyysstteemmss

It is not impossible, just that few of us have the resources
to do it.  You need to have a test system and a testing sys-
tem: the test system has all of its input and  outputs  con-
nected  to  the  outputs  and  inputs of the testing system.
That is, the testing system controls  and  drives  the  test
system, and watches what happens.

For  example,  in  the olden days before everyone had PC and
graphics terminals, there were only serial interfaces avail-
able.   Many  operating system vendors tested their products



Page 156        (lib/en/user-guide/c11.1.so)    Peter Miller





Aegis                                             User Guide


by using computers connected to each serial line to simulate
"user  input".   The  system  can  be rebooted this way, and
using dual-ported disks allows different versions of a  ker-
nel to be tried, or other test conditions created.

For  software  houses which write kernels, or device drivers
for kernels, or some other kernel work, this  is  bad  news:
the  Aegis program is probably not for you.  It is possible,
but there may be more cost-effective development strategies.
Of  course,  you  could  always  use  the rest of Aegis, and
ignore the testing part.

However, Aegis has been used quite successfully  to  develop
Linux  kernel  modules.  With suitable _s_u_d_o(1) configuration
to permit access to _i_n_s_m_o_d(1) &co, developers can write test
scripts  which load device drivers, try them out, and unload
them again, all without universal _r_o_o_t access.

Also, the advent of modern  tools,  such  as  VMware,  which
allow  one operating system to "host" another, may also per-
mit straightforward testing of kernels  and  operating  sys-
tems.

88..11..33..22..  FFiirrmmwwaarree

Firmware  is  a  similar deal: you need some way to download
the code to be tested into the test system,  and  write-pro-
tect  it to simulate ROM, and have the necessary hardware to
drive the inputs and watch the outputs.

As you can see, this is generally not available  to  run-of-
the-mill   software  houses,  but  then  they  rarely  write
firmware, either.  Those that do write firmware usually have
the download capabilities, and some kind of remote operation
facility.

However, this omits the possibility of not only  cross  com-
piling  your  code for the target system, but also compiling
your code to run natively on the build system.  The firmware
(in  the  host incarnation) then falls into one of the cate-
gories above, and may be  readily  tested.   This  does  not
relieve  you  of also testing the firmware, but it increases
the probability that the firmware isn't  completely  useless
before you download it.

By using an object oriented language, such as C++, the poly-
morphism necessary to cope with multiple environments can be
elegantly  hidden behind a pure abstract base class.  Alter-
natively, by using a consistent API, you can accomplish  the
necessary sleight-of-hand at link time.

The  unit  test method mentioned earlier is also very useful
for firmware, even if the device  "as  a  whole"  cannot  be
tested.



Peter Miller    (lib/en/user-guide/c11.2.so)        Page 157





User Guide                                             Aegis


88..22..  WWrriittiinngg TTeessttss

This  section  describes  a number of general guidelines for
writing better tests, and some pitfalls to be avoided.

There are also a number of suggestions  for  portability  of
tests  in specific scripting languages; this will definitely
be important if you are writing software to publish  on  WWW
or for FTP.  Portability is often required _w_i_t_h_i_n an organi-
zation, also.  Examples include a change in  company  policy
from  one  386  UNIX  to  another (e.g. company doesn't like
Linux, now you must use AT&T's SVR4 offering), or the devel-
opment  team  use _g_c_c until the company finds out and forces
you to use the prototype-less  compiler  supplied  with  the
operating  system, or even that the software being developed
must run under both UNIX and Windows NT.

Note, also, that when using Aegis' heterogeneous build  sup-
port, portability will again feature prominently.

88..22..11..  CCoonnttrriibbuuttoorrss

I'd  like  to  thank  Steven  Knight <knight@baldmt.com> for
writing portions of this information.

If other readers have additional testing techniques, or  use
other scripting languages, contributions are welcome.

88..22..22..  GGeenneerraall GGuuiiddeelliinneess

This  section  lists  a number of general guidelines for all
aegis tests, regardless  of  implementation  language.   Use
this  section  to guide how you write tests if the scripting
language you choose is not specifically covered  in  greater
detail below.

88..22..22..11..  CChhooiiccee ooff SSccrriippttiinngg LLaanngguuaaggee

The aegis program uses the _t_e_s_t___c_o_m_m_a_n_d field of the project
_a_e_g_i_s_._c_o_n_f 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 158        (lib/en/user-guide/c11.2.so)    Peter Miller





Aegis                                             User Guide


as  client-server  model interfaces, and multi-user synchro-
nization testing.

88..22..22..22..  NNoo EExxeeccuuttee PPeerrmmiissssiioonn

Under aegis, script files do  not  have  execute  permission
set,  so they should always be invoked by passing the script
file to the interpreter, not executing the test directly:

     sh _f_i_l_e_n_a_m_e
     perl _f_i_l_e_n_a_m_e


88..22..22..33..  NNoo CCoommmmaanndd--LLiinnee AArrgguummeennttss

Tests should not expect command line arguments.   Tests  are
not  passed  the  name  of the project nor the number of the
change.

88..22..22..44..  IIddeennttiiffyyiinngg tthhee SSccrriippttiinngg LLaanngguuaaggee

Even though aegis does not execute the test script directly,
it  is  a  good idea to put some indication of its scripting
language into the test script.  See the sections  below  for
suggested  "magic number" identification of scripts in vari-
ous languages.

88..22..22..55..  CCuurrrreenntt DDiirreeccttoorryy

Tests are always run  with  the  current  directory  set  to
either  the  development  directory of the change under test
when testing a change, or  the  integration  directory  when
integrating  a change, or the baseline when performing inde-
pendent tests.

A test must not make assumptions about  where  it  is  being
executed  from,  except to the extent that it is somewhere a
build has been performed.  A test must not assume  that  the
current  directory is writable, and must not try to write to
it, as this could damage the source code of a  change  under
development, potentially destroying weeks of work.

88..22..22..66..  CChheecckk EExxiitt SSttaattuuss aanndd RReettuurrnn VVaalluueess

A  test  script should check the exit status or return value
of every single command or function call, even  those  which
cannot  fail.   Checking  the exit status or return value of
every statement in the script ensures that  strange  permis-
sion  settings,  or disk space problems, will cause the test
to fail, rather than plow on and produce  spurious  results.
See  the sections below for specific suggestions on checking
exit status or return values in various scripting languages.





Peter Miller    (lib/en/user-guide/c11.2.so)        Page 159





User Guide                                             Aegis


88..22..22..77..  TTeemmppoorraarryy DDiirreeccttoorryy

Tests  should create a temporary subdirectory in the operat-
ing system's temporary directory  (typically  _/_t_m_p  on  UNIX
systems)  and then change its working directory (_c_d) to this
directory.  This isolates any  vandalism  that  the  program
under  test  may  indulge in, and serves as a place to write
temporary files.

At the end of the test, it is sufficient to change directory
out of the temporary subdirectory and then remove the entire
temporary subdirectory  hierarchy,  rather  than  track  and
remove all test files which may or may not be created.

Some  UNIX systems provide other temporary directories, such
as _/_v_a_r_/_t_m_p, which may provide a better location for a  tem-
porary  subdirectory  for  testing  (more  file system space
available, administrator preference,  etc.).   Test  scripts
wishing to accomodate alternate temporary directories should
use the TMPDIR environment variable (or some other  environ-
ment  variable  appropriate  to the operating system hosting
the tests) as the location for creating their temporary sub-
directory,  with  _/_t_m_p  as a reasonable default if TMPDIR is
not set.

88..22..22..88..  TTrraapp IInntteerrrruuppttss

Test scripts should catch appropriate interrupts (1 2 3  and
15  on UNIX systems) and cause the test to fail.  The inter-
rupt handler should perform any cleanup the  test  requires,
such as removing the temporary subdirectory.

88..22..22..99..  PPAAGGEERR

If the program under test invokes pagers on its output, a la
_m_o_r_e(1) et al, it should be coded to use the PAGER  environ-
ment  variable.   Tests  of  such programs should always set
PAGER to _c_a_t so that tests always behave the same, irrespec-
tive  of invocation method (either by aegis or from the com-
mand line).

88..22..22..1100..  AAuuxxiilliiaarryy FFiilleess

If a test requires extra files as input or output to a  com-
mand, it must construct them itself from in-line data.  (See
the sections below for more specific information  about  how
to use in-line data in various scripting languages to create
files.)

It is almost impossible to determine the location of an aux-
iliary  file,  if that auxiliary file is part of the project
source.  It could be in either the change under test or  the
baseline.




Page 160        (lib/en/user-guide/c11.2.so)    Peter Miller





Aegis                                             User Guide


88..22..22..1111..  NNeeww TTeesstt TTeemmppllaatteess

Regardless  of your choice of scripting language, it is pos-
sible to specify most of the repetitious items  above  in  a
_f_i_l_e  _t_e_m_p_l_a_t_e  used  every  time a user creates a new test.
See the _a_e_n_t(1) command for more information.

Having the machine do it for you means  that  you  are  more
likely to do it.

88..22..33..  BBoouurrnnee SShheellll

The  Bourne  shell  is  available on all flavors of the UNIX
operating system, which allows Bourne shell  scripts  to  be
written  portably  across those systems.  Here are some spe-
cific guidelines for writing aegis tests using Bourne  shell
scripts.


88..22..33..11..  MMaaggiicc NNuummbbeerr

Some  indication that the test is a Bourne shell script is a
good idea.  While many systems  accept  that  a  first  line
starting  with  a  colon is a Bourne shell "magic number", a
more widely understood "magic number" is

     #! /bin/sh

as the first line of the script file.

88..22..33..22..  CChheecckk EExxiitt SSttaattuuss

A Bourne shell test script should check the exit  status  of
every  single command, even those which cannot fail.  Do not
rely on, or use, the _s_e_t _-_e shell  option  (it  provides  no
ability to clean up on error).

Checking  the  exit  status involves testing the contents of
the $$??  shell variable.  Do not use an _i_f statement  wrapped
around  an  execution of the program under test as this will
miss core dumps and other terminations caused by signals.

88..22..33..33..  TTeemmppoorraarryy DDiirreeccttoorryy

Bourne shell test scripts should create a  temporary  subdi-
rectory  in  _/_t_m_p  (or the directory specified by the TMPDIR
environment variable) and then _c_d into this  directory.   At
the  end  of the test, or on interrupt, the script should _c_d
out of the temporary subdirectory and then _r_m _-_r_f it.

88..22..33..44..  TTrraapp IInntteerrrruuppttss

Use the _t_r_a_p statement to catch interrupts 1 2 3 and 15  and
cause the test to fail.  This should perform any cleanup the



Peter Miller    (lib/en/user-guide/c11.2.so)        Page 161





User Guide                                             Aegis


test requires, such as removing the temporary directory.

88..22..33..55..  AAuuxxiilliiaarryy FFiilleess

If a test requires extra files as input or output to a  com-
mand, it must construct them itself, using _h_e_r_e documents:

     cat <<EOF >file
     contents
     of the
     file
     EOF

See _s_h(1) for more information.

88..22..33..66..  [[ tteesstt ]]

You  should  always  use  the  _t_e_s_t command, rather than the
square bracket form, as many systems do not have the  square
bracket form, if you publish to USENET or for FTP.

88..22..33..77..  OOtthheerr BBoouurrnnee SShheellll PPoorrttaabbiilliittyy IIssssuueess

The  above  list  covers the most common Bourne shell issues
that are relevant to most aegis  tests.   The  documentation
for  the  GNU  autoconf  utility,  however,  contains a more
exhaustive list of Bourne shell portability issues.  If  you
want  (or  need) to make your tests as portable as possible,
see the documentation for GNU autoconf.

88..22..44..  PPeerrll

Perl is a popular open-source scripting  language  available
on  a  number  of operating systems.  Here are some specific
guidelines for writing aegis tests using Perl scripts.

88..22..44..11..  MMaaggiicc NNuummbbeerr

Some indication that the test is a Perl  script  is  a  good
idea.  Because Perl is not installed in the same location on
all UNIX systems, a first-line "magic number" such as:

     #! /usr/local/bin/perl

that hard-codes the Perl path name will not be  portable  if
you publish your tests.

If  the  _e_n_v(1) program is available, a more portable "magic
number" for Perl is:

     #! /usr/bin/env perl






Page 162        (lib/en/user-guide/c11.2.so)    Peter Miller





Aegis                                             User Guide


88..22..44..22..  CChheecckk RReettuurrnn VVaalluueess

A Perl test script should check the return value from  every
subroutine, even those which cannot fail.

A  Perl  test  script  should  also check the exit status of
every  command  it  executes.   Checking  the  exit   status
involves  testing the contents of the $$??  variable.  See the
Perl documentation on "Predefined Variables" for details.

88..22..44..33..  TTeemmppoorraarryy DDiirreeccttoorryy

Perl test scripts should create a temporary subdirectory  in
_/_t_m_p  (or  the directory specified by the $$EENNVV{{TTMMPPDDIIRR}} envi-
ronment variable) and then _c_h_d_i_r into  this  directory.   At
the  end  of  the  test,  or on interrupt, the script should
_c_h_d_i_r out of the temporary subdirectory and then  remove  it
and  its hierarchy.  A portable way to do this within a Perl
script:

     use File::Find;
     finddepth(sub { if (-d $_) {
                     rmdir($_)
             } else {
                     unlink($_)
             } },
             $dir);


88..22..44..44..  TTrraapp IInntteerrrruuppttss

Use Perl's _$_S_I_G hash to catch interrupts for HUP, INT,  QUIT
and  TERM  and  cause the test to fail.  This should perform
any cleanup the test requires, such as removing  the  tempo-
rary directory.  A very simple example:

     $SIG{HUP} =
     $SIG{INT} =
     $SIG{QUIT} =
     $SIG{TERM} =
             sub { &cleanup; exit(2) };


88..22..44..55..  AAuuxxiilliiaarryy FFiilleess

If  a test requires extra files as input or output to a com-
mand, it must construct them itself, using in-line data such
as _h_e_r_e documents See the Perl documentation for more infor-
mation.

88..22..44..66..  EExxiitt VVaalluueess

Aegis expects tests to exit with a status of 0 for  success,
1  for  failure,  and  2  for no result.  The following code



Peter Miller    (lib/en/user-guide/c11.2.so)        Page 163





User Guide                                             Aegis


fragment will map all failed (non-zero) exit  values  to  an
exit  status  of  1,  regardless  of what Perl module called
exit:

     END { $? = 1 if $? }

A more complete example could check conditions and  set  the
exit status to 2 to indicate NO RESULT.

88..22..44..77..  MMoodduulleess

Perl  supports  the ability to re-use modules of common rou-
tines, and to search several directories for modules.   This
makes it convenient to write modules to share code among the
tests in a project.

Any modules that are used by your test scripts  (other  than
the  standard modules included by Perl) should be checked in
to the project as source files.  Test  scripts  should  then
import the module(s) via the normal Perl mechanism:

     use MyTest;


When  a  test is run, the module file may actually be in the
baseline  directory,  not  the  development  or  integration
directories.   To  make  sure that the test invocation finds
the module, the _t_e_s_t___c_o_m_m_a_n_d field in the project _a_e_g_i_s_._c_o_n_f
file should use the Perl --II option to search first the local
directory and then the baseline:

     test_command =
         "perl -I. -I${BaseLine} \
         ${File_Name}"

or, alternatively, if you had created your Perl test modules
in a subdirectory named aauuxx:

     test_command =
         "perl -I./aux -I${BaseLine}/aux \
         ${File_Name}"


For  details on the conventions involved in writing your own
modules, consult the Perl documentation or  other  reference
work.

_A_c_t_u_a_l_l_y_,  _y_o_u  _n_e_e_d _t_o _u_s_e _t_h_e _$_{_s_e_a_r_c_h___p_a_t_h_} _s_u_b_s_t_i_t_u_t_i_o_n_.
_I_'_l_l _h_a_v_e _t_o _f_i_x _t_h_i_s _o_n_e _d_a_y_.

88..22..44..88..  TThhee TTeesstt::::CCmmdd MMoodduullee

A Test::Cmd module is available on CPAN  (the  Comprehensive
Perl  Archive  Network)  that  makes  it  easy to write Perl



Page 164        (lib/en/user-guide/c11.2.so)    Peter Miller





Aegis                                             User Guide


scripts  that  conform  to  aegis  test  requirements.   The
Test::Cmd  module  supports most of the guidelines mentioned
above, including creating a temporary subdirectory, cleaning
up  the temporary subdirectory on exit or interrupt, writing
auxiliary files from in-line contents, and provides  methods
for  exiting on success, failure, or no result.  The follow-
ing example illustrates some of its capabilities:

     #! /usr/bin/env perl
     use Test::Cmd;
     $test = Test::Cmd->new(prog
             => 'program_under_test',
                     workdir => '');
     $ret = $test->write('aux_file', <<EOF);
     contents of file
     EOF
     $test->no_result(! $ret =>
             sub { print STDERR
             "Couldn't write file: $!\\n"});
     $test->run(args => 'aux_file');
     $test->fail($? != 0);
     $test->pass;


The various methods supplied by the Test::Cmd module have  a
number of options to control their behavior.

The  Test::Cmd  module manipulates file and path names using
the operating-system-independent File::Spec module,  so  the
Test::Cmd  module can be used to write tests that are porta-
ble to any operating system that runs Perl and  the  program
under test.

The Test::Cmd module is available on CPAN.  See the module's
documentation for details.

88..22..44..99..  TThhee TTeesstt aanndd TTeesstt::::HHaarrnneessss MMoodduulleess

Perl supplies two modules, Test and Test::Harness,  to  sup-
port  its own testing infrastructure.  Perl's tests use dif-
ferent conventions  than  aegis  tests;  specifically,  Perl
tests  do not use the exit status to indicate the success or
failure of the test, like aegis expects.  The  Test::Harness
module expects that Perl tests report the success or failure
of individual sub-tests on standard output, and always  exit
with  a status of 0 to indicate the script tested everything
it was supposed to.

This difference  makes  it  awkward  to  use  the  Test  and
Test::Harness  modules  for  aegis  tests.   In some circum-
stances, though, you may be forced to write tests using  the
Test  and  Test::Harness  modules--for  example,  if you use
aegis to develop a Perl module for  distribution--but  still
wish  to  have the tests conform to aegis conventions during



Peter Miller    (lib/en/user-guide/c11.2.so)        Page 165





User Guide                                             Aegis


development.

This can be done by writing each test to use an  environment
variable  to  control whether its exit status should conform
to aegis or Perl conventions.  This is easy when  using  the
Test module to write tests, as its _o_n_f_a_i_l method provides an
appropriate place to set the exit status to non-zero if  the
appropriate environment variable is set.  The following code
fragment at or near the beginning of each Perl  test  script
accomplishes this:

     use Test;
     BEGIN { plan tests => 3,
         onfail => sub {
             $? = 1 if $ENV{AEGIS_TEST}
             }
         }

(See  the  documentation for the Test module for information
about using it to write tests.)

There then needs to be a wrapper Perl script around the exe-
cution  of  the  tests to set the environment variable.  The
following script (called _m_y_t_e_s_t_._p_l for the sake of  example)
sets  the  AAEEGGIISS__TTEESSTT  environment  variable expected by the
previous code fragment:

     use Test::Harness;
     $ENV{AEGIS_TEST} = 1;
     open STDOUT, ">/dev/null" || exit (2);
     runtests(@ARGV);
     END { $? = 1 if $?;
         print STDERR $?
             ? "FAILED" : "PASSED",
             "\n"; }

It also makes its output more nearly conform to aegis' exam-
ples   by  redirecting  standard  output  to  //ddeevv//nnuullll  and
restricting its reporting of results to a simple  FFAAIILLEEDD  or
PASSED on standard error output.

The  last  piece of the puzzle is to modify the _t_e_s_t___c_o_m_m_a_n_d
field of the project _a_e_g_i_s_._c_o_n_f 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 166        (lib/en/user-guide/c11.2.so)    Peter Miller





Aegis                                             User Guide


checked in to the project.

88..22..44..1100..  GGrraannuullaarriittyy BByy _S_t_e_v_e_n _K_n_i_g_h_t _<_k_n_i_g_h_t_@_b_a_l_d_m_t_._c_o_m_>

The  granularity  of  Perl and Aegis tests mesh very well at
the individual test file (.t) level.  Aegis  and  Test::Har-
ness  are  simply  different  harnesses that expect slightly
different conventions from the tests  they  execute:   Aegis
uses  the exit code to communicate an aggregate pass/fail/no
result status, Test::Harness examines the output from  tests
to decide if a failure occurred.

It's  actually  pretty  easy to accomodate both conventions.
You can do this as easily as setting the test_command  vari-
able in the project configuration file to something like the
following:

     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 167





User Guide                                             Aegis


the coarser PASSED/FAILED status.

88..22..55..  BBaattcchh TTeessttiinngg

The usual "_t_e_s_t___c_o_m_m_a_n_d" field  of  the  project  _a_e_g_i_s_._c_o_n_f
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  configuration  file
is for this purpose.  See _a_e_p_c_o_n_f(5) for more information.















































Page 168         (lib/en/user-guide/c9.0.so)    Peter Miller





Aegis                                             User Guide


99..  BBrraanncchhiinngg

This  chapter describes the concept of branching implemented
by Aegis.  The process described in previous chapters  makes
changes to a project's master source.
                     -1--    --2-     -3--
                 ---------B-a-s-e-l-i-n-e----------


Branching  generalizes  this  change  model, by allowing the
baseline to be treated as a change, or the ability to  treat
a change as a baseline.
                  Branch 1 -1-.-1   -1-.-2
                 --------------------------
                      Trunk Baseline

Since  branchs  are  sometimes considered as a changes it is
useful to expand on the differences.  A  branch,  or  trunk,
baseline  may  have  children  which  are  either _c_h_a_n_g_e_s or
deeper _b_r_a_n_c_h_e_s_.  From this perspective  the  difference  is
that  nothing may be modified directly in a branch. A branch
is an integrated baseline with all  the  associated  protec-
tion.  To  modify a branch one must open a change under that
branch.

Looking upward from a change under a branch, its  _p_a_r_e_n_t  is
the  branch  baseline,  and its _g_r_a_n_dparent is the _p_a_r_e_n_t of
the branch. We will see this used later when we  talk  about
ending a branch.

A  significant  feature  of  Aegis branches is that, because
they are an  extension  of  the  _c_h_a_n_g_e  concept,  they  are
expected to end, and be integrated back into _t_h_e_i_r baseline,
or _p_a_r_e_n_t ,in time.

The most common case of this is in project releases.

A branch in the _b_e_i_n_g _d_e_v_e_l_o_p_e_d state may have changes  made
to  it,  and/or  deeper  branches.   This may recurse to any
level.   Once  a  branch  is  complete,  no  further  deeper
branches may be created from that branch.

99..11..  HHooww TToo UUssee BBrraanncchhiinngg

To  access a project branch, the project name has the branch
appended, separated by a dot  or  a  hyphen.   For  example:
branch 1 of project "aegis" is referred to as "aegis.1".  To
reference changes on this branch, use this compound  project
name wherever you would normally use a project name.

Traditional  2-level  project  release names are obtained by
using a further level of branching.  For example: by  creat-
ing  branch  0 of project "aegis.1", there would be a branch
accessed as project "aegis.1.0".



Peter Miller     (lib/en/user-guide/c9.0.so)        Page 169





User Guide                                             Aegis


By default, these two level of project branching are created
automatically  when  the _a_e_n_p_r(1) command is used.  You need
to use the --VVEERRSSiioonn option to make this deeper or shallower,
or have different numbering.

              +------------+------------------+
              |Command     | Branches Created |
              +------------+------------------+
              |aenpr foo   | foo,      foo.1, |
              |            | foo.1.0          |
              |aenpr   foo | foo,      foo.2, |
              |-vers 2.4.1 | foo.2.4,         |
              |            | foo.2.4.1        |
              |aenpr foo.7 | foo, foo.7       |
              |aegis  -npr | foo              |
              |foo -vers - |                  |
              +------------+------------------+
The last is a special case, to enable a project to  be  cre-
ated  with  no  default  branches (it's also hard to get the
empty string past the alias).

To add branching and release level management to an existing
project  on  uses the _a_e_n_b_r(1) command at any level.  Say we
already have foo.1.0, which represents version  1.0  of  our
software. One method of release level management would be to
integrate _f_o_o_._1_._0 into its _p_a_r_e_n_t _f_o_o_._1 and then do _a_e_n_b_r _-_p
_f_o_o_._1  would create _f_o_o_._1_._1 representing version 1.1.  Even-
tually we might want to make a  major  version  release  and
would  integrate _f_o_o_._1 into its _p_a_r_e_n_t _f_o_o and then do _a_e_n_b_r
_-_p _f_o_o, which would create _f_o_o_._2.  Then if we  do  _a_e_n_b_r  _-_p
_f_o_o_._2  we  create _f_o_o_._2_._0, for development of version 2.0 of
our software.


99..22..  TTrraannssiittiioonn UUssiinngg aaeennrrllss

To convert a project from the old-style to the new branching
style, use the _a_e_n_r_l_s(1) command.

If  you  give no second project name, the new name is gener-
ated by removing the numeric suffixes.  If you did not  give
a  -VERSion  option,  the  numeric  suffixes will be used to
determine the next version, by adding one  to  the  previous
minor  version  number.   The  new  project  is then created
rather like the _a_e_n_p_r(1) command.

The files of  the  old  project  are  copied  across  as  an
implicit  change  on the newly created branch within the new
project.  If the new project name already exists, and  is  a
new-style  project,  the  _a_e_n_r_l_s(1)  command will attempt to
make the appropriate numbered branches.  If the new  project
already exists and is an old-style project, or it exists and
the branch number(s) are already in use, _a_e_n_r_l_s(1) will emit
an error and fail.  The _a_e_n_r_l_s(1) command only works on old-



Page 170         (lib/en/user-guide/c9.0.so)    Peter Miller





Aegis                                             User Guide


style projects,  and  always  converts  them  to  new  style
projects.

Planning  you  branch  numbers is essential.  If you want to
use 3-level branch numbers (e.g. "aegis.2.3.1") at some time
in the future, then you must use 3-level version numbers all
the way  through  (e.g.  "aegis.2.3.0").   This  is  because
change  numbers and branch numbers come from the same common
pool of numbers.   Once  change  one  has  been  used  (e.g.
"aegis.2.3.C001"),  then  branch  one is no longer available
(e.g. "aegis.2.3.1.C042" conflicts).

99..33..  CCrroossss BBrraanncchh MMeerrggee

From time to time you will want to merge  the  changes  from
one  branch  into a change.  This may be done using a cross-
branch merge.  This is done by specifying the --BBRRaanncchh option
to the _a_e_g_i_s _-_d_i_f_f _-_m_e_r_g_e_-_o_n_l_y command.

The  most  common  cross  branch merge is when the project's
files are out-of-date.  Because it is not  possible  to  use
_a_e_g_i_s _-_d_i_f_f _-_m_e_r_g_e_-_o_n_l_y directly on the branch, this must be
in a change on the branch.  As a short-cut, the  branch  may
be specified using the _-_g_r_a_n_d_p_a_r_e_n_t option.

99..44..  MMuullttiippllee BBrraanncchh DDeevveellooppmmeenntt

It  is  very  common  for a bug fix to need to be applied to
more than one branch at once.  The change could  be  applied
to  the  common  ancestor  branch,  however  this may not be
effective in the branch immediately.  An alternative  is  to
use  the  _a_e_g_i_s _-_c_l_o_n_e command, which can be used to identi-
cally reproduce a change on another branch.

99..55..  HHiieerraarrcchhyy ooff PPrroojjeeccttss

It would be nice if there was some way to use one project as
a sort of "super change" to a "super project", so that large
teams (say 1000 people) could work as lots  of  small  teams
(say  100  people).  As a small team gets their chunk ready,
using the facilities provided to-date by  Aegis,  the  small
team's  baseline  is  treated  as a change to be made to the
large team baseline.

This idea can be extended quite naturally to  any  depth  of
layering.

After reading _T_r_a_n_s_a_c_t_i_o_n _O_r_i_e_n_t_e_d _C_o_n_f_i_g_u_r_a_t_i_o_n _M_a_n_a_g_e_m_e_n_t_:
_A _C_a_s_e _S_t_u_d_y Peter Fieler, Grace  Downey,  CMU/SEI-90-TR-23,
this is not a new idea.  It also provides some ideas for how
to do branching sensibly, and was influential in the  design
of Aegis' branching.





Peter Miller     (lib/en/user-guide/c9.1.so)        Page 171





User Guide                                             Aegis


99..55..11..  FFuunnddaammeennttaallss

Aegis  has everything you need to have a super project and a
number of sub-projects.  All you need to  do  is  create  an
active branch for each sub-project.  Each branch gets a sep-
arate baseline, _v_i_z

     % aaeennpprr ggiizzmmoo..00..11
     project "gizmo": created
     project "gizmo.0": created
     project "gizmo.0.1": created
     %


Now, for each of your desired sub-projects,  create  another
branch

     aenbr -p gizmo.0.1 1 # _f_o_r _t_h_e _f_o_o _p_r_o_j_e_c_t
     aenbr -p gizmo.0.1 2 # _f_o_r _t_h_e _b_a_r _p_r_o_j_e_c_t
     aenbr -p gizmo.0.1 3 # _f_o_r _t_h_e _b_a_z _p_r_o_j_e_c_t


Now,  the  guys  on  the _f_o_o project set their AEGIS_PROJECT
environment variable to to _g_i_z_m_o_._0_._1_._1,  the  _b_a_r  guys  use
_g_i_z_m_o_._0_._1_._2, and _b_a_z uses _g_i_z_m_o_._0_._1_._3.  From the developer's
point of view they are separate projects.   From  one  level
up, though, they are just part of a bigger project.

It helps if you design and implement the build system first.
You do this as a change set on  the  common  parent  branch.
Once  it  is  completed  each branch can inherit it from the
common parent.  This makes integration easier, when it comes
time to integrate the sub-projects together.

99..55..22..  IInnccrreemmeennttaall IInntteeggrraattiioonn

It  is  very common that not all of the sub-projects will be
ready to be integrated at the same time.  This is the normal
situation  with  Aegis branching, and is handled cleanly and
simply.

In Aegis each branch is literally a change, all the way down
into the internal data structures.  Just as each change gets
its own development directory,  each  branch  gets  its  own
baseline.   Just  as a development directory inherits every-
thing its  doesn't  have  from  the  baseline,  so  branches
inherit  everything _t_h_e_y don't have from their parent branch
(or ultimately from the trunk).  Just as  you  incrementally
integrate changes into a branch, you incrementally integrate
branches into their parent.

The branches only influence each other when they  are  inte-
grated,  just as changes only influence each other when they
are integrated.



Page 172         (lib/en/user-guide/c9.1.so)    Peter Miller





Aegis                                             User Guide


There are times when a branch being integrated into its par-
ent  is  found  to  be  inadequate.  Aegis provides a simple
mechanism to "bounce" a branch  integration.   Recall  that,
for  Aegis,  branches  are the same as changes.  Just as you
"develop end" a change (see _a_e_d_e(1)  for  more  information)
you  also _a_e_d_e a branch when development on it is completed.

Once  a  branch  has  develop-end  (stops  being  an  _a_c_t_i_v_e
branch),  it  is reviewed as a normal change, and integrated
as a normal change.  If integration failed,  it  returns  to
"being  developed"  and becomes an active branch once again,
until the next _a_e_d_e.  As you can  see,  it  is  as  easy  to
bounce  a  branch  integration  as  it is to bounce a change
integration.

An unsuccessful branch  integration  leaves  the  repository
unchanged, just as an unsuccessful change integration leaves
it unchanged.


99..55..33..  SSuuppeerr--PPrroojjeecctt BBrraanncchhiinngg

In many real-world situations it is  very  important  to  be
able  to  branch  at  any  point  in the past history of the
super-project to fix (integration specific) bugs or to  cus-
tomize more the older states of the super-project.

You can create a branch at any time, on any active branch or
active branch ancestor.  You can populate that  branch  with
historical  versions  (from  any other branch, actually, not
just the ancestral line).  The method is a  little  fussy  -
you  can't  _a_e_c_p into a branch directly, you need to do this
via a change to that branch.  Files not changed by a  change
on  a  branch  are  inherited from the current (_i_._e_. active)
state of the parent branch.  See the section on  _I_n_s_u_l_a_t_i_o_n,
above.

99..55..44..  SSuuppeerr--PPrroojjeecctt TTeessttiinngg

Many  folks  see  Aegis' testing features as useful for unit
testing  individual  files  or  change  sets.    For   large
projects,  it  is  common  that a specific test tool will be
written.  However, even large scale integration  testing  is
possible using Aegis.

You can change the test command from being a shell script to
being anything to you want - see the _t_e_s_t___c_o_m_m_a_n_d  field  in
_a_e_p_c_o_n_f(5).  Or run the test tool from the shell script.  If
the integration tests can be automated, it  makes  sense  to
preserve  them in the repository - they are some of the most
valuable  regression  tests  for  developers,  because  they
describe  correct  behavior  outside the "box" the developer
usually works in.




Peter Miller     (lib/en/user-guide/c9.1.so)        Page 173





User Guide                                             Aegis


99..55..55..  TThhee NNeexxtt CCyyccllee

Once you have a fully-integrated product,  what  happens  on
the  next  cycle?   Well,  first  you  may  want  to  finish
_g_i_z_m_o_._0_._1 and integrate it into _g_i_z_m_o_._0, and then  _a_e_n_b_r  _-_p
_g_i_z_m_o_._0 _2

Then what?  Same deal as before, but anything not changed in
one of the sub-project  branches  gets  inherited  from  the
ancestor.

     aenbr -p gizmo.0.2 1 # _f_o_r _t_h_e _f_o_o _p_r_o_j_e_c_t
     aenbr -p gizmo.0.2 2 # _f_o_r _t_h_e _b_a_r _p_r_o_j_e_c_t
     aenbr -p gizmo.0.2 3 # _f_o_r _t_h_e _b_a_z _p_r_o_j_e_c_t


Most  folks  find  doing  the whole mega-project-build every
time tiresome - so don't.  Temporarily (via  a  change  set)
hack  the build configuration to build only the bit you want
- obviously a different hack on each  sub-project's  branch.
Just  remember to un-hack it (via another change set) before
you integrate the sub-project.

99..55..66..  BBuugg FFiixxiinngg

The _a_e_c_l_o_n_e(1) command lets you clone a change set from  one
branch  to  another.  So if you have a bug fix that needs to
be done on each active branch you can  clone  it  (once  you
have  it  fixed  the  first  time).  You still have to build
review and integrate _n times (branches  often  differ   non-
trivially).  Providing it isn't already in use, you can even
ask for the same change number on each branch  -  handy  for
syncing with an external bug tracking system.

Alternatively, fix bugs in the common ancestor, and the sub-
projects will inherit the fix the next time  they  integrate
something  on  their  branch (assuming they aren't insulated
against it).

99..66..  CCoonnfflliicctt RReessoolluuttiioonn

A development directory becomes out of date, compared to the
project,  when another change is integrated which has a file
in common.  This  situation  is  detected  automatically  by
_a_e_d_e(1)  and you resolve it using _a_e_d(1), usually with some-
thing like the _-_-_m_e_r_g_e_-_o_n_l_y option.  Additionally,  you  can
see  if  you  have an out-of-date file from the _c_h_a_n_g_e _f_i_l_e_s
listing, because it will show you the current baseline  ver-
sion in parentheses if you are out-of-date.

Aegis  implements  branches  as very long changes, with sub-
changes.  A side effect of this is that a branch can  become
out-of-date  in  the  same  way  that a development director
becomes out of date.  When it  comes  time  to  _a_e_d_e(1)  the



Page 174         (lib/en/user-guide/c9.2.so)    Peter Miller





Aegis                                             User Guide


branch, you will be told if there are any out-of-date files.
Additionally, the _p_r_o_j_e_c_t _f_i_l_e_s listing  will  show  out  of
date  files  in  exactly  the  same way that the _c_h_a_n_g_e _f_i_l_e
listing does.

99..66..11..  CCrroossss BBrraanncchh MMeerrggee

However, unlike a simple change, if you attempt to  use  the
_a_e_d  _-_-_m_e_r_g_e_-_o_n_l_y  command  in the branch baseline, you will
get an error message!  How, then, do you resolve the  appar-
ent impasse?

The _a_e_d(1) command has a number of options designed for just
this purpose.

+o The _-_-_b_r_a_n_c_h option may be used to specify another  branch
  of the same project, as a source of the file to be differ-
  enced against.  This is almost what you need.

+o The _-_-_g_r_a_n_d_p_a_r_e_n_t option is a special case of the _-_-_b_r_a_n_c_h
  option, and it means the parent branch of project.

+o The  _-_-_t_r_u_n_k option is also a special case of the _-_-_b_r_a_n_c_h
  option, and it means the base branch from which the entire
  branch tree springs.

By  creating  a  new  change  on the out-of-date branch, and
copying in the out-of-date files, you have almost everything
required.   All  that  is  necessary  is to perform a cross-
branch merge against the project grandparent, and the neces-
sary  merging  will  be  performed.   IInn aaddddiittiioonn Aegis will
remember that it was a cross-branch merge, and once  _a_e_i_p_a_s_s
completes  successfully,  the branch will be up-to-date once
more.

[] Create a new change on the out-of-date branch

[] Use a simple _a_e_c_p command to copy the out-of-date  files.
   (Do _n_o_t use any _-_-_b_r_a_n_c_h or _-_-_d_e_l_t_a options.)

[] Use  the "_a_e_d _-_-_m_e_r_g_e_-_o_n_l_y _-_-_g_r_a_n_d_p_a_r_e_n_t" command to per-
   form the merge.
   At this point, if you use the "_a_e_l _c_f" command, you  will
   notice  that  this file is tagged in the listing with the
   new branch edit origin, to be used during _a_e_i_p_a_s_s.  If it
   isn't, you have made a mistake.

[] As  usual,  use  your favourite editor to check the merge
   results, and resolve any conflicts.

[] Build and test as usual.

[] Complete the change as usual.




Peter Miller     (lib/en/user-guide/c9.2.so)        Page 175





User Guide                                             Aegis


[] Once _a_e_i_p_a_s_s is successful, the branch will be up-to-date
   (for the files in the change).

99..66..22..  IInnssuullaattiioonn

One of the stated benefits of using a branch is the insulat-
ing effects which branches can provide.  However,  when  you
have  multiple simultaneous active branches, that insulation
will inevitably lead to out-of-date branch files.  Now  that
_h_o_w to merge them has been described, _w_h_e_n should you merge?

In a simple change's development directory, there are  times
when  an  _a_e_i_p_a_s_s  will  result in all developers needing to
recompile.  Depending on what files you are working  on,  it
may  be  that  you  need  to merge some of your change files
immediately, or _a_e_c_p an earlier version of the  files  which
changed in the project.

Branches can also suffer from exactly the same problems, and
are mended by exactly the same alternatives.

99..66..22..11..  BBrraanncchh IInnssuullaatteedd AAggaaiinnsstt PPrroojjeecctt

If you created a branch to insulate the work being  done  on
the  branch from other activities in the project, it follows
that when such build problems occurred,  you  would  use  an
"_a_e_c_p _-_d_e_l_t_a_" _c_o_m_m_a_n_d _t_o _c_o_n_t_i_n_u_e _i_n_s_u_l_a_t_i_n_g_.

This  action  defers the labour of merging until towards the
end of the branch development, sometimes with a quite  visi-
ble schedule impact.

99..66..22..22..  PPrroojjeecctt IInnssuullaatteedd AAggaaiinnsstt BBrraanncchh

If  you  created  a branch to insulate the project from work
being done in the branch, it follows that  you  would  do  a
cross branch immediately.

This  action amortizes the labour of merging across the life
of the branch, often with a number of small delays and  less
schedule impact.

99..66..22..33..  MMiixx ''nn'' MMaattcchh

Of course, we usually have both these motives, and some more
besides, so the answer is usually "it depends".

99..77..  EEnnddiinngg AA BBrraanncchh

"OK,  I  give  up.   I  do  not  understand  the  ending  of
branches."

Usually,  you  end  development of a branch the same way you
end development of a simple change.  In this example, branch



Page 176         (lib/en/user-guide/c9.3.so)    Peter Miller





Aegis                                             User Guide


_e_x_a_m_p_l_e_._1_._4_2 will be ended:

     % aaeeddee --pp eexxaammppllee 11 --cc 4422
     aegis: project "example.1": change 42: file "_f_u_b_a_r" in
     the baseline has changed since the last 'aegis -DIFFer-
     ence' command, you need to do a merge
     %

Oops.  Something went wrong.  Don't panic!

I'm going to assume, for the purposes of explanation, that
there have been changes in one of the  ancestor branches,
and thus require a merge, just like file _f_u_b_a_r, above.

You need to bring file _f_u_b_a_r up-to-date.  How?  You do it in
a change set, like everything else.

At his point you need to do 5 things: (1) create a new
change on example.1.42, (2) copy _f_u_b_a_r into it, (3) merge
_f_u_b_a_r with branch "example.1" (4) end development of the
change and integrate it, and (5) now you can end exam-
ple.1.42

The -GrandParent option is a special case of the -BRanch
option.  You are actually doing a cross-branch merge, just
up-and-down rather than sideways.

     % aaeemm --ggpp _f_u_b_a_r
     %

And manually fix any conflicts... naturally.

At this point, have a look at the file listing, it will show
you something you have never seen before - it will show you
what it is _g_o_i_n_g _t_o set the branch's edit_number_origin to
for each file, at _a_e_i_p_a_s_s.

     % aaeell ccff
     Type   Action Edit        File Name
     ------ ------ -------     -----------
     source modify 1.3         _f_u_b_a_r
                   {cross 1.2}

Now finish the change as usual...  _a_e_b_, _a_e_d_, _a_e_d_e_, _a_e_r_p_a_s_s_,
_a_e_i_b_, _._._._, _a_e_i_p_a_s_s nothing special here.

One small tip: merge the files one at a time.  It makes
keeping track of where you are up to much easier.

Now you can end development of the branch, because all of
the files are up-to-date.

In some cases, Aegis has detected a logical conflict where
you, the human, know there is none.  Remember that the _a_e_m



Peter Miller     (lib/en/user-guide/c9.3.so)        Page 177





User Guide                                             Aegis


command saves the old version of the file with a ,B suffix
(`B' for backup).  If you have a file like this, just use

     % mmvv _f_u_b_a_r,,BB _f_u_b_a_r
     %

to discard everything from the ancestor branch, and use the
current branch.

















































Page 178         (lib/en/user-guide/c6.0.so)    Peter Miller





Aegis                                             User Guide


1100..  TTiippss aanndd TTrraappss

This chapter contains hints for how to use the aegis program
more efficiently and documents a number of pitfalls you may
encounter.

This chapter is at present very "ad hoc" with no particular
ordering.  Fortunately, it is, as yet, rather small.  The
final size of this chapter is expected to be quite large.

1100..11..  RReennaammiinngg IInncclluuddee FFiilleess

Renaming include files can be a disaster, either finding all
of the clients, or making sure the new copy is used rather
than the old copy still in the baseline.

Aegis provides some assistance.  When the _a_e_m_v(1) command is
used, a file in the development directory is created in the
_o_l_d location, filled with garbage.  Compiles will fail very
diagnostically, and you can change the reference in the
source file, probably after _a_e_c_p(1)ing it first.

If you are moving an include file from one directory to
another, but leaving the basename unchanged, create a link20
between the new and old names, but only in the development
directory (i.e. replacing the "garbage" file aegis created
for you).  Create the link after _a_e_m_v(1) has succeeded.
This insulates you from a number of nasty Catch-22 situa-
tions in writing the dependency maintenance tool's rules
file.

1100..22..  SSyymmbboolliicc LLiinnkkss

If you are on a flavor of UNIX which has symbolic links, it
is often useful to create a symbolic link from the develop-
ment directory to the baseline.  This can make browsing the
baseline very simple.

Assuming that the project and change defaults are appropri-
ate, the following command

     ln -s `aegis -cd -bl` bl

is all that is required to create a symbolic link called _b_l
pointing to the baseline.  Note that the _a_e_c_d alias is inap-
propriate in this case.

This can be done automatically for every change, by placing
the line

-----------
  20 A hard link uses fewer disk blocks.  Symbolic
links survive the subject file being  deleted  and
recreated.



Peter Miller     (lib/en/user-guide/c6.0.so)        Page 179





User Guide                                             Aegis


     develop_begin_command =
             "ln -s $baseline bl";

into the project configuration file.

1100..33..  UUsseerr SSeettuupp

There are a number of things which users of aegis can do to
make it more useful, or more user friendly.  This section
describes just a few of them.

1100..33..11..  TThhee ..ccsshhrrcc oorr ..pprrooffiillee ffiilleess

The aliases for the various user commands used throughout
this manual are obtained by appending a line of the form

     . /usr/pkg/share/aegis/profile

to the _._p_r_o_f_i_l_e file in the user's home directory, if they
use the _s_h(1) shell or the _b_a_s_h(1) shell.

If the user uses the _c_s_h(1) shell, append a line of the form

     source /usr/pkg/share/aegis/cshrc

to the _._c_s_h_r_c file in the user's home directory.

These days, many systems also provide an _/_e_t_c_/_p_r_o_f_i_l_e_._d
directory, which has symbolic links to the start-up scripts
for various packages.  These are run automatically for all
users.  If your system has such a thing, arrange for sym-
bolic links

     ln -s /usr/pkg/share/aegis/profile \
             /etc/profile.d/aegis.sh
     ln -s /usr/pkg/share/aegis/cshrc \
             /etc/profile.d/aegis.csh

and you will not need to edit every user's _._c_s_h_r_c or _._p_r_o_-
_f_i_l_e file.

1100..33..22..  TThhee AAEEGGIISS__PPAATTHH eennvviirroonnmmeenntt vvaarriiaabbllee

If users wish to use aegis for their own projects, in addi-
tion to the "system" projects, the _A_E_G_I_S___P_A_T_H environment
variable forms a colon separated search path of aegis
"library" directories.  The _/_u_s_r_/_p_k_g_/_l_i_b_/_a_e_g_i_s directory is
always implicitly added to this list.

The user should not create this library directory, but let
aegis do this for itself (otherwise you will get an error
message).





Page 180         (lib/en/user-guide/c6.0.so)    Peter Miller





Aegis                                             User Guide


The _A_E_G_I_S___P_A_T_H environment variable should be set in the
_._c_s_h_r_c or _._p_r_o_f_i_l_e files in the user's home directory.  Typ-
ical setting is

     setenv AEGIS_PATH ~/lib/aegis

and this is the default used in the
_/_u_s_r_/_p_k_g_/_s_h_a_r_e_/_a_e_g_i_s_/_c_s_h_r_c file.

1100..33..33..  TThhee ..aaeeggiissrrcc ffiillee

The _._a_e_g_i_s_r_c file in the user's home directory contains a
number of useful fields.  See _a_e_u_c_o_n_f(5) for more informa-
tion.

1100..33..44..  TThhee ddeeffaauullttiinngg mmeecchhaanniissmm

In order for you to specify the minimum possible information
on the command line, aegis has been designed to work most of
it out itself.

The default project is the project which you are working on
changes for, if there is only one, otherwise it is gleaned
from the _._a_e_g_i_s_r_c file.  The command line overrides any
default.

The default change is the one you are working on within the
(default or specified) project, if there is only one.  The
command line overrides any default.

1100..44..  TThhee PPrroojjeecctt OOwwnneerr

For the greatest protection from accidental change, it is
best if the project is owned by a UNIX account which is none
of the staff.  This account is often named the same as the
project, or sometimes there is a single umbrella account for
all projects.

When an aegis project is created, the owner is the user cre-
ating the project, and the group is the user's default
group.  The creating user is installed as the project's
first administrator.

A new project administrator should be created - an actual
user account.  The UNIX password should then be disabled on
the project account - it will never be necessary to use it
again.21

The user nominated as project administrator many then assign
all of the other staff roles.  Aegis takes care of ensuring
-----------
  21 Unless bugs in aegis corrupt the database, in
which case repairs  can  be  accomplished  as  the
project account using a text editor.



Peter Miller     (lib/en/user-guide/c6.0.so)        Page 181





User Guide                                             Aegis


that the baseline is owned by the project account, not any
of the other staff, while development directories always
belong to the developer (but the group will always be the
project group, irrespective of the developer's default
group).

All of the staff working on a project should be members of
the project's group, to be able to browse the baseline, for
reviewers to be able to review changes.  This use of UNIX
groups means that projects may be as secure or open as
desired.

1100..55..  UUSSEENNEETT PPuubblliiccaattiioonn SSttaannddaarrddss

If you are writing software to publish on USENET, a number
of the source newsgroups have publication standards.  This
section describes ways of generating the following files,
required by many of the newsgroups' moderators:

MANIFEST       List of files
               in the distri-
               bution.
Makefile       How to build
               the distribu-
               tion.
CHANGES        What happened
               for this dis-
               tribution.
patchlevel.h   An identifica-
               tion of this
               distribution.


Each of these files may be generated from information known
to aegis, with the aid of some fairly simple shell scripts.

1100..55..11..  CCHHAANNGGEESS

Write this section.

Look in the _a_u_x_/_C_H_A_N_G_E_S_._s_h file included in the aegis dis-
tribution for an example of one way to do this.

1100..55..22..  MMAANNIIFFEESSTT

Write this section.

Look in the _a_u_x_/_M_A_N_I_F_E_S_T_._s_h and _a_u_x_/_M_A_N_I_F_E_S_T_._a_w_k files
included in the aegis distribution for an example of one way
to do this.







Page 182         (lib/en/user-guide/c6.0.so)    Peter Miller





Aegis                                             User Guide


1100..55..33..  MMaakkeeffiillee

Write this section.

Look in the _a_u_x_/_M_a_k_e_f_i_l_e_._s_h and _a_u_x_/_M_a_k_e_f_i_l_e_._a_w_k files
included in the aegis distribution for an example of one way
to do this.

1100..55..44..  ppaattcchhlleevveell..hh

Write this section.

Look in the _a_u_x_/_H_o_w_t_o_._c_o_o_k file included in the aegis dis-
tribution for an example of one way to do this.

1100..55..55..  BBuuiillddiinngg PPaattcchh FFiilleess

The _p_a_t_c_h program by Larry Wall is one of the enduring mar-
vels of USENET.  This section describes how to build input
files for this miracle program.

Write this section.

Look in the _a_u_x_/_p_a_t_c_h_e_s_._s_h file included in the aegis dis-
tribution for an example of one way to do this.
































Peter Miller     (lib/en/user-guide/c6.1.so)        Page 183





User Guide                                             Aegis


1100..66..  HHeetteerrooggeenneeoouuss DDeevveellooppmmeenntt

The aegis program has support for heterogeneous development.
It will enforce that each change be built and tested on each
of a list of architectures.  It determines which architec-
ture it is currently executing on by using the _u_n_a_m_e(2) sys-
tem call.

The _u_n_a_m_e(2) system call can yield uneven results, depending
on the operating systems vendor's interpretation of what it
should return22.  To cope with this, each required architec-
ture for a project is specified as a name and a pattern.

The name is used by aegis internally, and is also available
in the _$_{_A_R_C_H_i_t_e_c_t_u_r_e_} substitution (see _a_e_s_u_b(5) for more
information).

The patterns are simple shell file name patterns (see _s_h(1)
for more information) matched against the output of the
_u_n_a_m_e(2) system call.

The result of _u_n_a_m_e(2) has four fields of interest: _s_y_s_n_a_m_e,
_r_e_l_e_a_s_e, _v_e_r_s_i_o_n and _m_a_c_h_i_n_e.  These are stitched together
with hyphens to form an architecture _v_a_r_i_a_n_t to be matched
by the pattern.

For example, a system the author commonly uses is
"SunOS-4.1.3-8-sun4m" which matches the "SunOS-4.1*-*-sun4*"
pattern.  A solaris system, a very different beast, matches
the "SunOS-5.*-*-sun4*" pattern.  Sun's 386 version of
Solaris matches the "SunOS-5.*-*-i86pc" pattern.  A convex
system matches the "ConvexOS-*-10.*-convex" pattern.

1100..66..11..  PPrroojjeecctt _a_e_g_i_s_._c_o_n_f FFiillee

To require a project to build and test on each of these
architectures, the _a_r_c_h_i_t_e_c_t_u_r_e field of the project
_a_e_g_i_s_._c_o_n_f 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 184         (lib/en/user-guide/c6.1.so)    Peter Miller





Aegis                                             User Guide


     architecture =
     [
       {
         name = "sun4";
         pattern = "SunOS-4.1*-*-sun4*";
       },
       {
         name = "sun5";
         pattern = "SunOS-5.*-*-sun4*";
       },


       {
         name = "sun5pc";
         pattern = "SunOS-5.*-*-i86pc";
       },
       {
         name = "convex";
         pattern = "ConvexOS-*-10.*-*";
       }
     ];

This would require that all changes build and test on each
of the "sun4", "sun5", "sun5pc" and "convex" architectures.

It is also possible to have _o_p_t_i_o_n_a_l architectures.  This
may be used to recognise an environment, but not mandate
that it be built every time.

       {
         name = "solaris-8-sparc";
         pattern = "SunOS-5.8*-*-sun4*";
         mode = optional;
       },

However, once an architecture name appears in a change's
architecture list, it is mandatory for that change.

If the _a_r_c_h_i_t_e_c_t_u_r_e field does not appear in the project
_a_e_g_i_s_._c_o_n_f 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
_a_e_g_i_s_._c_o_n_f file, rather than as a project attribute, because



Peter Miller     (lib/en/user-guide/c6.1.so)        Page 185





User Guide                                             Aegis


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 configuration
file.

1100..66..22..  CChhaannggee AAttttrriibbuuttee

The _a_r_c_h_i_t_e_c_t_u_r_e attribute is inherited by each new change.
A project administrator may subsequently edit the change
attributes to grant exemptions for specific architectures.
See _a_e_c_a(1) for how to do this.

A build must be successfully performed on each of the target
architectures.  Similarly, the tests must be performed suc-
cessfully on each.  These requirements are because there is
often conditional code present to cope with the vagaries of
each architecture, and this needs to be compiled and tested
in each case.

This multiple build and test requirement includes both
development and integration states of each change.

1100..66..33..  NNeettwwoorrkk FFiilleess

This method of heterogeneous development assumes that the
baseline and development directories are available as the
same pathname in all target architectures.  With software
such as NFS, this does not present a great problem, however
NFS locking must also work.

There is also an assumption that all the hosts remotely
mounting NFS file systems will agree on the time, because
aegis uses time stamps to record that various tasks have
been performed.  Software such as _t_i_m_e_d(8) is required23.

1100..66..44..  DDMMTT IImmpplliiccaattiioonnss

This method of heterogeneous development assumes that the
baseline will have a copy of all object files for all target
architectures _s_i_m_u_l_t_a_n_e_o_u_s_l_y.

This means that the configuration file for the DMT will need
to distinguish all the variations of the object files in
some way.  The easiest method is to have a separate object
tree for each architecture24.  To facilitate this, there is
-----------
  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 186         (lib/en/user-guide/c6.1.so)    Peter Miller





Aegis                                             User Guide


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
project _a_e_g_i_s_._c_o_n_f file.

The architecture name used by aegis needs to be used by the
DMT, so that both aegis and the DMT can agree on which
architecture is currently targeted.

1100..66..44..11..  CCooookk EExxaammppllee

As and example of how to do this, the cook recipes from the
DMT chapter are modified as appropriate.  First, the
_b_u_i_l_d___c_o_m_m_a_n_d field of the project _a_e_g_i_s_._c_o_n_f file is
changed to include the _$_{_A_R_C_H_i_t_e_c_t_u_r_e_} substitution:

     build_command =
       "cook -b ${s Howto.cook} \
       project=$p change=$c \
       version=$v arch='$arch' -nl";


Second, the C recipe must be changed to include the archi-
tecture in the path of the result:

     [arch]/%.o: %.c: [collect c_incl
       -eia [prepost "-I" ""
       [search_list]] [resolve %.c]]
     {
       if [not [exists [arch]]] then
         mkdir [arch]
           set clearstat;
       if [exists [target]] then
         rm [target]
           set clearstat;
       [cc] [cc_flags] [prepost "-I"
         "" [search_list]] -c
         [resolve %.c];
       mv %.o [target];
     }


Third, the link recipe must be changed to include the archi-
tecture in the name of the result:














Peter Miller     (lib/en/user-guide/c6.1.so)        Page 187





User Guide                                             Aegis


     [arch]/example: [object_files]
     {
       if [not [exists [arch]]] then
         mkdir [arch]
           set clearstat;
       if [exists [target]] then
         rm [target]
           set clearstat;
       [cc] -o [target] [resolve
         [object_files]] -ly -ll;
     }


The method used to determine the object_files variable is
the same as before, but the object file names now include
the architecture:

     object_files =
       [fromto %.y [arch]/%.o
         [match_mask %.y [source_files]]]
       [fromto %.l [arch]/%.o
         [match_mask %.l [source_files]]]
       [fromto %.c [arch]/%.o
         [match_mask %.c [source_files]]]
       ;


Note that the form of these recipes precludes performing a
build in each target architecture simultaneously, because
intermediate files in the recipes may clash.  However, aegis
prevents simultaneous build, for this and other reasons.

1100..66..55..  TTeesstt IImmpplliiccaattiioonnss

Tests will need to know in which directory the relevant
binary files reside.  The _t_e_s_t___c_o_m_m_a_n_d field of the project
_a_e_g_i_s_._c_o_n_f file may be changed from the default

     test_command =
       "$shell $file_name";

to pass the architecture name to the test

     test_command =
       "$shell $file_name $arch";

This will make the architecture name available as $1 within
the shell script.  Tests should fail elegantly when the
architecture name is not given, or should assume a sensible
default.







Page 188         (lib/en/user-guide/c6.1.so)    Peter Miller





Aegis                                             User Guide


1100..66..66..  CCrroossss CCoommppiilliinngg

If you are cross compiling to a number of different target
architectures, you would not use aegis' heterogeneous devel-
opment support, since it depends on the _u_n_a_m_e(2) system
call, which would tell it nothing useful when cross compil-
ing.  In this case, simply write the DMT configuration file
to cross compile to all architectures in every build.

1100..66..77..  FFiillee VVeerrssiioonn bbyy AArrcchhiitteeccttuurree

There is no intention of ever providing the facility where a
project source file may have different versions depending on
the architecture, but all of these versions overload the
same file name25.

The same effect may be achieved by naming files by architec-
ture, and using the DMT to compile and link those files in
the appropriate architecture.

This has the advantage of making it clear that several vari-
ations of a file exist, one for each architecture, rather
than hiding several related but independent source files
behind the one file name.

1100..77..  RReemmiinnddeerrss

This section documents some scripts available for reminding
users of changes which require their attention.  These
scripts are installed into the _/_u_s_r_/_p_k_g_/_s_h_a_r_e_/_a_e_g_i_s_/_r_e_m_i_n_d
directory, and may be run by _c_r_o_n(8) at appropriate inter-
vals.  You will almost certainly want to customize them for
your site.

1100..77..11..  AAwwaaiittiinngg DDeevveellooppmmeenntt

The _/_u_s_r_/_p_k_g_/_s_h_a_r_e_/_a_e_g_i_s_/_r_e_m_i_n_d_/_a_w_t___d_v_l_p_._s_h script takes a
project name as argument.  It is placed in the project
leader's per-user crontab.  It is suggested that this script
be run weekly, at 8AM on Monday.  This script will send all
developers of the named project email if there are any
changes in the _a_w_a_i_t_i_n_g _d_e_v_e_l_o_p_m_e_n_t state in the named
project.  No mail is sent if there are no changes outstand-
ing.

1100..77..22..  BBeeiinngg DDeevveellooppeedd

The _/_u_s_r_/_p_k_g_/_s_h_a_r_e_/_a_e_g_i_s_/_r_e_m_i_n_d_/_b_n_g___d_v_l_p_d_._s_h script takes no
arguments.  It is placed in each user's per-user crontab.
It is suggested that this script be run weekly, at 8AM on
Monday.  This script takes no arguments, and sends email to
-----------
  25 Some  other  SCM  tools  provide a repository
with this facility.



Peter Miller     (lib/en/user-guide/c6.3.so)        Page 189





User Guide                                             Aegis


the user if they have any changes in the _b_e_i_n_g _d_e_v_e_l_o_p_e_d or
_b_e_i_n_g _i_n_t_e_g_r_a_t_e_d states.  No mail is sent if there are no
changes outstanding.

1100..77..33..  BBeeiinngg RReevviieewweedd

The _/_u_s_r_/_p_k_g_/_s_h_a_r_e_/_a_e_g_i_s_/_r_e_m_i_n_d_/_b_n_g___r_v_w_d_._s_h script takes a
project name as argument.  It is placed in the project
leader's per-user crontab.  It is suggested that this script
be run daily at 8AM.  This script will send all reviewers of
the named project email if there are any changes in the
_b_e_i_n_g _r_e_v_i_e_w_e_d state in the named project.  No mail is sent
if there are no changes outstanding.

1100..77..44..  AAwwaaiittiinngg IInntteeggrraattiioonn

The _/_u_s_r_/_p_k_g_/_s_h_a_r_e_/_a_e_g_i_s_/_r_e_m_i_n_d_/_a_w_t___i_n_t_g_r_t_n_._s_h script takes
a project name as argument.  It is placed in the project
leader's per-user crontab.  It is suggested that this script
be run daily at 8AM.  This script will send all integrators
of the named project email if there are any changes in the
_a_w_a_i_t_i_n_g _i_n_t_e_g_r_a_t_i_o_n state in the named project.  No mail is
sent if there are no changes outstanding.


































Page 190        (lib/en/user-guide/c10.0.so)    Peter Miller





Aegis                                             User Guide


1111..  GGeeooggrraapphhiiccaallllyy DDiissttrriibbuutteedd DDeevveellooppmmeenntt

This chapter describes various methods of collaboratively
developing software using Aegis, where the collaborating
sites are separated by administrative domains or even large
physical distances.

While many Open Source projects on the Internet typify such
development, this chapter will also describe techniques
suitable for commercial enterprises who do not wish to com-
promise their intellectual property.

1111..11..  IInnttrroodduuccttiioonn

The core of the distribution method is the _a_e_d_i_s_t(1) com-
mand.  In its simplest form, the command

     aedist -send | aedist -receive

will clone a change set locally.  This may appear less than
useful (after all, the _a_e_c_l_o_n_e(1) command already exists)
until you consider situations such as

     aedist -send | _e_-_m_a_i_l | aedist -receive

where _e_-_m_a_i_l represents the sending, transport and receiving
of e-mail.  In this example, the change set would be repro-
duced on the e-mail recipient's system, rather than locally.
Similar mechanisms are also possible for web distribution.

1111..11..11..  RRiisskk RReedduuccttiioonn

Receiving change sets in the mail, however, comes with a
number of risks:

+o  You can't just commit it to your repository, because it
   may not even compile.

+o  Even if it does compile, you want to run some tests on it
   first, to make sure it is working and doesn't break any-
   thing.

+o  Finally, you would always check it out, to make sure it
   was appropriate, and didn't do more subtle damage to the
   source.

While these are normal concerns for distributing source over
the Internet, and also internally within companies, they are
the heart of the process employed by Aegis.  All of these
checks and balances are already present.  The receive side
simply creates a normal Aegis change, and applies the normal
Aegis process to it.





Peter Miller    (lib/en/user-guide/c10.0.so)        Page 191





User Guide                                             Aegis


+o  The change set format is unpacked into a private work
   area, not directly into the repository.  This is a normal
   Aegis function.

+o  The change set is then confirmed to build against the
   repository.  All implications flowing from the change are
   exercised.  Build inconsistencies will flag the change
   for attention by a human, and the change set will not be
   committed to the repository.  This is a normal Aegis
   function.

+o  The change set is tested.  If it came accompanied by
   tests, these are run.  Also, relevant tests  from the
   repository are run.  Test inconsistencies will flag the
   change for attention by a human, and the change set will
   not be committed to the repository.  This is a normal
   Aegis function.

+o  Once the change set satisfies these requirements, it must
   still be reviewed by a human before being committed, to
   validate the change set for suitability and completeness.
   This is a normal Aegis function.

1111..11..22..  WWhhaatt ttoo SSeenndd

While there are many risks involved in receiving change
sets, there also problems in figuring out what to send.

At the core of Aegis' design is a transaction.  Think of the
source files as rows in a database table, and each change-
set as a transaction against that table.  The build step
represents maintaining referential integrity of the data-
base, but also represents an input validation step, as does
the review.  And like databases, the transactions are all-
or-nothing affairs, it is not possible to commit "half" a
transaction.

As you can see, Aegis changes are already elegantly vali-
dated, recorded and tracked, and ideally suited to being
packaged and sent to remote repositories.

1111..11..33..  MMeetthhooddss aanndd TTooppoollooggiieess

In distributed systems such as described in this chapter,
there are two clear methods of distribution:

+o The "push" method has the change set producer automati-
  cally send the change-set to a registered list of inter-
  ested consumers.  This is supported by Aegis and _a_e_d_i_s_t.

+o The "pull" method has the change set producer make the
  change sets available for interested consumers to come and
  collect.  This is supported by Aegis and _a_e_d_i_s_t.




Page 192        (lib/en/user-guide/c10.0.so)    Peter Miller





Aegis                                             User Guide


These are two ends of a continuum, and it is possible and
common for a mix-and-match approach to be taken.

There are also many ways of arranging how distribution is
accomplished, and many of the distribution arrangements
(commonly called topologies, when you draw the graphs) are
supported by Aegis and _a_e_d_i_s_t:

+o The star topology has a central master repository, sur-
  rounded by contributing satellite repositories.  The
  satellites are almost always "push" model, however the
  central master could be either "push" or "pull" model.

+o The snowflake topology is like a hierarchical star topol-
  ogy, with contributors feeding staging posts, which even-
  tually feed the master repository.  Common for large Open
  Source Internet projects.  Towards the master repository
  is almost always "push" model, and away from the master is
  almost always "pull" model.

+o The network topology is your basic anarchic autonomous
  collective, with change sets flying about peer-to-peer
  with no particular structure.  Often done as a "push"
  model through an e-mail mailing list.

All of these topologies, and any mixture you can dream up,
are supported by Aegis and _a_e_d_i_s_t.  The choice of the right
topology depends on your project and your team.

1111..11..44..  TThhee RReesstt ooff tthhiiss CChhaapptteerr

Aegis is the ideal medium for hosting distributed projects,
for all the above reasons, and the rest of this chapter
describes a number of different ways of doing this:

[] The second section will describe how to perform these
   actions manually, both send and receive, as this demon-
   strates the method efficiently, and represents a majority
   of the use made of the mechanism.

[] The third section will show how to automate e-mail dis-
   tribution and receipt.  Automated e-mail distribution is
   probably the next most common use.

[] The fourth section will show how to configure distribu-
   tion and receipt using World Wide Web servers and
   browsers.

[] The fifth section deals with security issues, such as
   validating messages and coping with duplicate storms.







Peter Miller    (lib/en/user-guide/c10.1.so)        Page 193





User Guide                                             Aegis


1111..22..  MMaannuuaall OOppeerraattiioonn

This section describes how to use _a_e_d_i_s_t manually, in order
to send and receive change sets.

1111..22..11..  MMaannuuaall SSeenndd

In order to send a change set to another site, it must be
packaged in a form which captures all of the change's
attributes and the contents of the change's files.  This
package must be compressed and encoded in a form which will
survive the various mail transport agents it must pass
through, and then given to the local mail transport agent.
This is done by a single command

     %% aedist -send -c _n_u_m_b_e_r | \
       mail joe.blow@example.com
     %%


All of the usual Aegis command line options are available,
so you could specify the project on the command line if you
needed to.

This command will send the sources from the development
directory, if the change is not yet completed.  This is use-
ful for collaboration between developers, but it isn't
reviewed and integrated, so beware.

It is more usual to send a change which has been completed.
In this case the version of the file which was committed is
sent.  If necessary, the history files will be consulted to
reconstruct this information.  See the "_A_u_t_o_m_a_t_i_c _S_e_n_d" sec-
tion, below, for more discussion of this.

There are many options for customizing the e-mail message
sent to joe.blow@example.com, see _a_e_d_i_s_t(1) for more infor-
mation.

1111..22..22..  SSeennddiinngg BBaasseelliinneess

In order to send the entire contents of the repository to
someone, you use a very similar command:

     %% aedist -send -baseline | \
       mail joe.blow@example.com
     %%


This can be a very large change set, because it is all files
of the project.






Page 194        (lib/en/user-guide/c10.1.so)    Peter Miller





Aegis                                             User Guide


1111..22..33..  SSeennddiinngg BBrraanncchheess

There are times when remote developers are not interested in
a blow-by-blow update of your repository.  Instead they want
to have updates from time to time.  In order to send them
the current state of your active development branch, in this
example "_e_x_a_m_p_l_e_._4_._2", you would use a command of the form

     %% aedist -send -p example.4 -c 2 | \
       mail joe.blow@example.com
     %%

Notice how the correspondence between branches and change
sets is exploited.  The baseline of a branch is the develop-
ment directory of the "super change" is represents.

Branch change sets like this are smaller than whole base-
lines, because they include only the files altered by this
branch, rather then the state of every file in the project.

1111..22..44..  MMaannuuaall RReecceeiivvee

The simplest form of receiving a change set is to save it
from your e-mail program into a file, and then

     %% aedist -receive -file _f_i_l_e_n_a_m_e
     _._._._l_o_t_s _o_f _i_n_f_o_r_m_a_t_i_o_n_._._.
     %%

where _f_i_l_e_n_a_m_e is where you saved the e-mail message.  If
your e-mail program is able to write to a pipe, you can use
a simpler form.  This example uses the Rand Mail Handler's
_s_h_o_w(1) command:

     %% show | aedist -receive
     _._._._l_o_t_s _o_f _i_n_f_o_r_m_a_t_i_o_n_._._.
     %%


Each of these examples assumes that you have used the same
project name locally as that of the sender (it's stored in
the package).  If this isn't the case, you will need to use
the -project option to tell _a_e_d_i_s_t which project to apply
the change to.

The actions performed by _a_e_d_i_s_t on receive are not quite a
mirror of what it does on send.  In particular, send usually
extracts its information from the repository, but receive
ddooeess nnoott put the change set directly into the repository.

On receipt of a change set, _a_e_d_i_s_t creates a new change with
its own development directory, and unpacks the change set
into it, in much the same way as a change would normally be
performed by a developer.  (Indeed, the receiver must be an



Peter Miller    (lib/en/user-guide/c10.1.so)        Page 195





User Guide                                             Aegis


authorized developer.)

Once the change is unpacked, it goes through the usual
development cycle of build, difference and test.  If any
portion of this fails, _a_e_d_i_s_t will stop with a suitable
error message.  If all goes well, development of the change
will end, and it will be left in the _b_e_i_n_g _r_e_v_i_e_w_e_d state.

At this point, a local reviewer must examine the change, and
it proceeds through the change integration process as nor-
mal.

If there is a problem with the change, it can be dealt with
as you would with any other defective change - by developing
it some more.  Or you can email the sender telling them the
problem and use _a_e_d_b_u(1) and _a_e_n_c_u(1) to entirely discard
the change.

1111..22..55..  GGeettttiinngg SSttaarrtteedd

In order to receive a change, you must have a project to
receive it into.  Also, changes tend to be the _d_i_f_f_e_r_e_n_c_e
between an existing repository and what it is to become.
You need some way to get the starting point of the differ-
ences before you can apply any differences.  This section
describes one way of doing this.

You start by creating a normal Aegis project in the usual
way.  That is covered earlier in this User Guide.  It helps
greatly if you give your local project exactly the same name
as the remote project.  It doesn't need the same pathname
for the project directory, just the same project name.

Once you have this project created, request the remote
repository send you a "baseline" change, as described above.
Once you have received this, and it is integrated success-
fully, you are ready to receive and apply change sets.  This
is an inherently "pull" activity, as the source may never
have heard of you before.  The initial baseline may arrive
by e-mail, or floppy disk, or you may retrieve it from the
web, it all depends how the project is being managed.

You will be warned about "potential trojan horse" files in
the baseline change set.  This is normal, because you are
receiving all project configurations file, build files and
test files.  All of these contain executable commands _t_h_a_t
_w_i_l_l _b_e _e_x_e_c_u_t_e_d.  Caveat emptor.  Make sure you trust the
source.

1111..33..  SSnneeaakkeerr NNeett

Another common method of transporting data, sometimes a
quite large amount of it, is to write it onto transportable
media and carry it.



Page 196        (lib/en/user-guide/c10.1.so)    Peter Miller





Aegis                                             User Guide


To write a change set onto a floppy, you would use commands
such as

     %% mount /mnt/floppy
     %% aedist -send -no-base64 \
       -o /mnt/floppy/_c_h_a_n_g_e_._s_e_t
     %% umount /mnt/floppy
     %%

The above command assumes the floppy is pre-formatted, and
that there is a user-permitting line in the _/_e_t_c_/_f_s_t_a_b file,
as is common for many Linux distributions.  The _c_h_a_n_g_e_._s_e_t
can be any filename you like, but is usually project-name
and change-number related.

It takes a very sizable change set to fail to fit on a
1.44MB floppy, because they are compressed (and change sets
exceeding 8MB of source are rare, even for huge projects).
The -no-base64 option is used to avoid the MIME base 64
encoding, which is necessary for e-mail, not not necessary
in this case.  The receive side will automatically figure
out there is no MIME base 64 encoding.

Reading the change set is just as simple, as it closely fol-
lows the other commands for receiving commands sets.

     %% mount /mnt/floppy
     %% aedist -rec -f /mnt/floppy/_c_h_a_n_g_e_._s_e_t
     _._._._l_o_t_s _o_f _o_u_t_p_u_t_._._.
     %% umount /mnt/floppy
     %%

This technique will work for any of the disks available
these days including floppies, Zip, Jaz, _e_t_c.

1111..44..  AAuuttoommaattiicc OOppeerraattiioonn

This section describes how to use _a_e_d_i_s_t to automatically
send change sets via e-mail.

1111..44..11..  SSeennddiinngg

Change sets can be sent automatically when a change passes
integration.  You do this by setting the _i_n_t_e_g_r_a_t_e___p_a_s_s___-
_n_o_t_i_f_y___c_o_m_m_a_n_d field of the project attributes.

In this example, the "example" project sends all integra-
tions to all the addresses on the example-developers mailing
list.  (The mailing list is maintained outside of Aegis,
_e_._g_. by Majordomo.)  The relevant attribute (edited by using
the _a_e_p_a(1) command) looks like this:






Peter Miller    (lib/en/user-guide/c10.2.so)        Page 197





User Guide                                             Aegis


     integrate_pass_notify_command =
       "aedist -p $project -c $change | \
       mail example-users";


Please note that project attributes are inherited by
branches when they are created.  If you don't want all
branches to broadcast all changes, you need to remember to
clear this project attribute _f_r_o_m _t_h_e _b_r_a_n_c_h once the branch
has been created.  Alternatively, use the $version substitu-
tion to decide who to send the change to.

1111..44..22..  RReecceeiivviinngg

_w_r_i_t_e _t_h_i_s _s_e_c_t_i_o_n

You need to set up an e-mail alias, with a wrapper around it
- you probably _d_o_n_'_t want "daemon" as a registered devel-
oper.

While _a_e_d_i_s_t(1) makes every attempt to spot potential trojan
attacks, you really, _r_e_a_l_l_y want PGP validation (or similar
industrial strength digital signatures) before you accept
this kind of input.

1111..55..  WWoorrlldd WWiiddee WWeebb

This section describes how to use _a_e_g_e_t(1) and _a_e_d_i_s_t(1) 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.  You can also automatically
track a remote site, efficiently downloading and applying
new change sets as they appear.

1111..55..11..  SSeerrvveerr

Aegis has a read-only web interface to its database, it is a
web server CGI interface.  If you are running Apache, or
similar, all you have to do is copy (or symlink, if you have
symlinks enabled) the _/_u_s_r_/_p_k_g_/_b_i_n_/_a_e_g_e_t file into the web
server's _c_g_i_-_b_i_n directory.  For example, the default Apache
install would need the following command:

     ln -s /usr/pkg/bin/aeget /var/www/cgi-bin/aeget



1111..55..22..  BBrroowwsseerr

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.





Page 198        (lib/en/user-guide/c10.3.so)    Peter Miller





Aegis                                             User Guide


Edit the _/_e_t_c_/_m_a_i_l_c_a_p file, and add the lines

     # Aegis
     application/aegis-change-set;/usr/pkg/bin/aedist -receive -f %s

You may need to restart your web browser for this to take
effect.

1111..55..33..  HHaannddss--FFrreeee TTrraacckkiinngg

Clients of sites using a web server, such as the various
developers in an open sourec project, it is possible to
automatically "replay" change sets on the server which have
not yet been incorporated at your site.

The command

     aedist --replay -f _n_a_m_e_-_o_f_-_w_e_b_-_s_e_r_v_e_r

will automatically download any remote change sets not
present in the local repository.  It downloads them by using
the _a_e_d_i_s_t(1) command.  It uses commands of the form

     aedist --receive -f _u_r_l_-_o_f_-_c_h_a_n_g_e_-_s_e_t

to download the change sets, which have to go through all of
the usual Aegis process before vecoming part of your local
repository.  This includes code review, unless you have con-
figured the _d_e_v_e_l_o_p___e_n_d___a_c_t_i_o_n field of the project configu-
ration to be _g_o_t_o___a_w_a_i_t_i_n_g___d_e_v_e_l_o_p_m_e_n_t.

If you add this command to a _c_r_o_n_t_a_b_(_1_) _e_n_t_r_y_, _y_o_u _c_a_n _c_h_e_c_k
_t_o _s_e_e _i_f _t_h_e_r_e _a_r_e _c_h_a_n_g_e _s_e_t_s _t_o _s_y_n_c_h_r_o_n_i_z_e _w_i_t_h _o_n_c_e _a
_d_a_y_, _o_r _h_o_w_e_v_e_r _o_f_t_e_n _y_o_u _s_e_t _t_h_e _l_i_n_e _t_o _r_u_n_.

1111..66..  SSeeccuurriittyy

This section deals with security issues.  Security isn't
just "keep the bad guys out", it actually covers _a_v_a_i_l_a_b_i_l_-
_i_t_y, _i_n_t_e_g_r_i_t_y and _c_o_n_f_i_d_e_n_t_i_a_l_i_t_y.

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



Peter Miller    (lib/en/user-guide/c10.4.so)        Page 199





User Guide                                             Aegis


        isn't a large concern, but for corporate users of
        Aegis, non-disclosure of change-sets as they cross
        the Internet is a serious requirement.

As you can see, a strategy of "keep the bad guys out" is
necessary, but not sufficient, to satisfy security.

This section covers the above security issues, as applied to
the use of _a_e_d_i_s_t to move change sets around.

1111..66..11..  TTrroojjaann HHoorrsseess

"A Trojan horse is an apparently useful program containing
hidden functions that can exploit the privileges of the user
[running the program], with a resulting security threat.  A
Trojan horse does things that the program user did not
intend26."

In order to forestall this threat, _a_e_d_i_s_t will cease devel-
opment of the change if it detects the potential for a Tro-
jan horse.  These include...

+o Changing the project _a_e_g_i_s_._c_o_n_f file.  This file contains
  the build command and the difference commands, both of
  which would be run before a reviewer had a chance to con-
  firm 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 _a_e_g_i_s_._c_o_n_f 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.

1111..66..22..  PPGGPP

PGP can be used to validate that the source of a change set
distribution is really someone you trust.

_a_n_y_o_n_e _w_a_n_t _t_o _a_d_v_i_s_e _m_e _w_h_a_t _t_o _p_u_t _h_e_r_e_?

1111..66..33..  SSoorrcceerreerr''ss AApppprreennttiiccee

In a push system, with a central master server and a collec-
tion of contributors, all of which are using automatic send,
as described above, a potential explosion of redundant mes-
sages is possible.  Viz:
-----------
  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.



Page 200        (lib/en/user-guide/c10.4.so)    Peter Miller





Aegis                                             User Guide


+o Contributor integrates a change, which is dispatched to
  the master server.

+o Maintainer integrates the change set into the master
  repository.

+o Master repository automatically dispatches the change set
  to all of the contributors.

+o Each of the contributors receives and integrates the
  change, each of which are dispatched to the master server.

+o The master server is inundated with change sets it already
  has.

+o If these change sets were to be integrated, the storm
  repeats, growing exponentially every time it goes around
  the loop.

To prevent this, _a_e_d_i_s_t does several things...

+o Before the change is built, an _a_e_c_p_u _-_-_u_n_c_h_a_n_g_e_d is run.
  If there is nothing left, the change is abandoned, because
  you already have it.  (This doesn't always work, because
  propagation delays may try to _r_e_v_e_r_s_e a subsequent local
  change.)

+o When a change set is sent, an RFC 822 style header is
  added to the description.  This includes From and Date.
  When a change set is received, a Received line is added.
  Too many Received lines causes the change set to be
  dropped - for a star topology the maximum is 2.  (This
  doesn't always work, because the description could be
  edited to rip it off again.)  (This doesn't always work,
  because the maintainer may edit it in some ways before
  comitting it, and forget to rip off (enough of) the
  header.)  (This doesn't always work, because hierarchical
  topologies will group change sets together.)  (This
  doesn't always work, because a baseline pull will group
  change sets together.)

+o Set the description to indicate it was received by aedist?
  Use this to influence the decision to send it off again at
  integrate pass?  How?

1111..77..  PPaattcchheess

In the open source community, patches are common way of
sharing enhancements to software.  This was particularly
common before the World Wide Web, and usenet was the more
common medium of distribution.  Patches also have the advan-
tage of being fairly small and usually tansportable by email
with few problems.




Peter Miller    (lib/en/user-guide/c10.5.so)        Page 201





User Guide                                             Aegis


1111..77..11..  SSeenndd

If you are participating in an open source project, and
using Aegis to manage your development, the _a_e_p_a_t_c_h _-_s_e_n_d
command may be used to construct a patch to send to the
other developers.

It is very similar in operation to the _a_e_d_i_s_t(1) command,
however it is intended for non-Aegis-using recipients.

To send a change to someone (a completed change, or one in
progress) simply use a command such as

     %% aepatch -send -c _n_u_m_b_e_r | \
       mail joe.blow@example.com
     %%

to send your change as a patch.  Note that it will be com-
pressed (using GNU Zip) and encoded (using MIME base 64),
which produces small files which are going to survive email
transport.

1111..77..22..  RReecceeiivvee

The simplest way of receiving a patch and turn it into a
change set is to save it from your e-mail program into a
file, and then

     %% aepatch -receive -file _f_i_l_e_n_a_m_e
     _._._._l_o_t_s _o_f _i_n_f_o_r_m_a_t_i_o_n_._._.
     %%

where _f_i_l_e_n_a_m_e is where you saved the e-mail message.  If
your e-mail program is able to write to a pipe, you can use
a simpler form.  This example uses the Rand Mail Handler's
_s_h_o_w(1) command:

     %% show | aepatch -receive
     _._._._l_o_t_s _o_f _i_n_f_o_r_m_a_t_i_o_n_._._.
     %%


Each of these examples assumes that you have already set the
project name, either via _a_e_u_c_o_n_f(5) or _a_e___p(1), or you could
use the _-_p_r_o_j_e_c_t option.

The actions performed by _a_e_p_a_t_c_h on receive are not quite a
mirror of what it does on send.  In particular, send usually
extracts its information from the repository, but receive
ddooeess nnoott put the change set directly into the repository.

On receipt of a change set, _a_e_p_a_t_c_h creates a new change
with its own development directory, copies the files into
it, and applies the patch to the files.  The receiver must



Page 202        (lib/en/user-guide/c10.5.so)    Peter Miller





Aegis                                             User Guide


be an authorized developer.

Once the patch is applied, it goes through the usual devel-
opment cycle of build, difference and test.  If any portion
of this fails, _a_e_p_a_t_c_h will stop with a suitable error mes-
sage.  If all goes well, development of the change will end,
and it will be left in the _b_e_i_n_g _r_e_v_i_e_w_e_d state.

At this point, a local reviewer must examine the change, and
it proceeds through the change integration process as nor-
mal.

If there is a problem with the change, it can be dealt with
as you would with any other defective change - by developing
it some more.  Or you can email the sender telling them the
problem and use _a_e_d_b_u(1) and _a_e_n_c_u(1) to entirely discard
the change.

1111..77..33..  LLiimmiittaattiioonnss

Despite a great similarity of command line operations and
operation, the _a_e_p_a_t_c_h command should nnoott be thought of as
an equivalent for the _a_e_d_i_s_t command, or a replacement for
it.

The information provided by _a_e_d_i_s_t _-_s_e_n_d is sufficiently
complete to recreate the change set at the remote end.  No
information is lost.  In contrast, the _a_e_p_a_t_c_h _-_s_e_n_d command
is limited to that information a patch file (see the
_p_a_t_c_h(1) command, from the GNU Diff utils).  There is no
guarantee that the _a_e_p_a_t_c_h _-_s_e_n_d output will be given to
_a_e_p_a_t_c_h _-_r_e_c_e_i_v_e; it must work with _p_a_t_c_h(1), and similar
tools.

Conversely, there is no guarantee that the input to _a_e_p_a_t_c_h
_-_r_e_c_e_i_v_e came from _a_e_p_a_t_c_h _-_s_e_n_d.  It can and must be able
to cope with the outout of a simple _d_i_f_f _-_r _-_N _-_c command,
with no additional information.

All this means, use _a_e_d_i_s_t wherever possible.  The _a_e_p_a_t_c_h
command is to simplify and streamline communication with
non-Aegis developers.















Peter Miller    (lib/en/user-guide/c12.0.so)        Page 203





User Guide                                             Aegis


1122..  FFuurrtthheerr RReeaaddiinngg

This chapter contains information about books, articles or
web sites relevant to some aspect of Aegis or using Aegis.
These references should not be taken as endorements.

If I've missed a good reference, it isn't personal, but I
can't and haven't read everything out there.  Email me the
information and I'll add it to this chapter (no advertising,
please).

1122..11..  SSooffttwwaarree CCoonnffiigguurraattiioonn MMaannaaggeemmeenntt

Eaton, D. (1995), Configuration Management Frequently Asked
Questions, http://www.daveeaton.com/scm/CMFAQ.html
     _T_h_i_s _i_s _a_n _e_s_s_e_n_t_i_a_l _f_i_r_s_t_-_s_t_o_p _f_o_r _i_n_f_o_r_m_a_t_i_o_n _a_b_o_u_t
     _S_o_f_t_w_a_r_e _C_o_n_f_i_g_u_r_a_t_i_o_n _M_a_n_a_g_e_m_e_n_t_.  _I_t _h_a_s _a_n _e_x_c_e_l_l_e_n_t
     _b_o_o_k _l_i_s_t_.

Pool, D., CM Today, http://www.cmtoday.com/
     _T_h_i_s _i_s _a _c_o_n_f_i_g_u_r_a_t_i_o_n _m_a_n_a_g_e_m_e_n_t _p_o_r_t_a_l _s_i_t_e_, _w_i_t_h
     _n_e_w_s _a_n_d _o_t_h_e_r _l_i_n_k_s_.

1122..22..  RReevviieewwiinngg

Baldwin, J. (1992), An Abbreviated C++ Code Inspection
Checklist, http://www2.ics.hawaii.edu/~johnson/FTR/Bib/Bald-
win92.html
     _T_h_i_s _w_e_b _p_a_g_e _t_a_l_k_s _a_b_o_u_t _C_+_+ _c_o_d_e _i_n_s_p_e_c_t_i_o_n_s _w_i_t_h
     _s_o_m_e _u_s_e_f_u_l _s_u_g_g_e_s_t_i_o_n_s _a_b_o_u_t _h_o_w _t_o _c_o_n_d_u_c_t _(_r_a_t_h_e_r
     _f_o_r_m_a_l_) _r_e_v_i_e_w_s _a_n_d _s_o_m_e _f_o_r _C_+_+ _c_o_n_s_t_r_u_c_t_s _t_o _w_a_t_c_h
     _o_u_t _f_o_r_.

























Page 204         (lib/en/user-guide/cA.0.so)    Peter Miller





Aegis                                             User Guide


1133..  AAppppeennddiixx AA:: NNeeww PPrroojjeecctt QQuuiicckk RReeffeerreennccee

For those of you too impatient to read a whole great big
document about how to use the aegis program, this appendix
gives a quick look at how to place a project under aegis.

The style here is an itemized list.  It does not try to be
exhaustive.  For exact details on how to use the various
aegis commands, you should see the manual pages, ditto for
the formats and contents of some files.

Probably the quickest start of all is to copy an already
existing project.  The project used in chapter 2 is com-
plete, assuming you use the author's "cook" dependency main-
tenance tool.  The entirety of this example may be found, if
slightly obfuscated, in the aegis source file
_t_e_s_t_/_0_0_/_t_0_0_1_1_a_._s_h distributed with aegis.

1133..11..  CCrreeaattee tthhee PPrroojjeecctt

The _a_e_n_p_r command is used to create a project.  You must
supply the name on the command line.  The name should be ten
characters or less, six characters or less if you want ver-
sion numbers included.

The user who creates the project is the owner of the
project, and is set as the administrator.  The default group
of the user who created the project is used as the project's
group.

You may want to have a user account which owns the project.
You must create the project as this user, and then use the
_a_e_n_a and _a_e_r_a commands to add an appropriate administrator,
and remove the owning user as an administrator.  After this,
the password for the owning user may be disabled, because
the aegis program will, at appropriate times, set file own-
ership to reflect project ownership or execute commands on
behalf of the project owner _a_s the project owner.

1133..11..11..  AAdddd tthhee SSttaaffff

The _a_e_n_d command is used to add developers.  The _a_e_n_r_v com-
mand is used to add reviewers.  The _a_e_n_i command is used to
add integrators.  These commands may only be performed by a
project administrator.

You will still have to do this, even if the person who cre-
ated the project will be among these people, or even be all
of these people.

1133..11..22..  PPrroojjeecctt AAttttrriibbuutteess

The _a_e_p_a command is used to change project attributes.
These attributes include the description of the project, and



Peter Miller     (lib/en/user-guide/cA.0.so)        Page 205





User Guide                                             Aegis


booleans controlling whether, for example, developers may
review their own work.

The project attributes file is described in the _a_e_p_a_t_t_r(5)
manual entry.

1133..22..  CCrreeaattee CChhaannggee OOnnee

The _a_e_n_c command is used to create a new change.  You will
need to construct a change attributes file with your
favorite text editor before running this command.

The change attributes file is described in the _a_e_c_a_t_t_r(5)
manual entry.

1133..33..  DDeevveelloopp CChhaannggee OOnnee

This is the most grueling step.  Indeed, the integration
step will probably reveal things you missed, and you may
return to the _b_e_i_n_g _d_e_v_e_l_o_p_e_d
 state several times.

One of the people you nominated as a developer will have to
use the _a_e_d_b command to commence development of the first
change.  The _a_e_c_d command can be used to change directory
into the just-created development directory.

Add files to the change.  The _a_e_n_f command is used to create
new files.  If you don't use _a_e_n_f then the aegis program has
no way of knowing whether that file lying there in the
development directory is significant to the project, or just
a shopping list of the groceries you forgot to buy yester-
day.

One particular new file which _m_u_s_t be created by this change
is the project configuration file, usually called _a_e_g_i_s_._c_o_n_f
but can be named something else.  This file tells Aegis what
history mechanism you wish to use, what dependency mainte-
nance 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.




Page 206         (lib/en/user-guide/cA.0.so)    Peter Miller





Aegis                                             User Guide


Use the _a_e_d command to difference the change.  It will need
to difference cleanly before it can advance to the next
step.

Use the _a_e_n_t command to add new tests to the command.  It
will need to have tests before it can advance to the next
step.

Most existing projects don't have formal tests.  These tests
will form a regression test-bed, used to make sure that
future changes never compromise existing functionality.

Use the _a_e_t command to test the change.  It will need to
test cleanly before it can advance to the next step.

Once the change builds, differences and tests cleanly, use
the _a_e_d_e command to end development.

1133..44..  RReevviieeww TThhee CChhaannggee

One of the people nominated as reviewers will have to run
the _a_e_r_p_a_s_s command to say that the change passed review.

The aegis program does not mandate any particular review
mechanism: you could use a single peer to do the review, you
could use a panel, you could set the project so that devel-
opers may review their own work effectively eliminating the
review step.  In projects with as few as two people, it is
always beneficial for someone other than the developer to
review changes.  It is even beneficial for the developer
herself to review the next day.

Should a reviewer actually want to _s_e_e the change, the _a_e_c_d
command may be used to change directory to the development
directory of the change.  The difference files all end with
a "comma D" suffix, so the

     more `find . -name "*,D" -print | sort`

command may be used to search them out and see them.  This
is probably fairly useless for the first change, but is
vital for all subsequent changes.  There is a supplied alias
for this command, it is _a_e_d_m_o_r_e and there is a similar _a_e_d_-
_l_e_s_s alias if you prefer the _l_e_s_s(1) command.

There are some facts that a reviewer _k_n_o_w_s because otherwise
the change would not be in the "being reviewed" state: +o the
change compiles cleanly, +o the change passes all of its
tests.  Other information about the change may be obtained
using the "change_details" variation of the _a_e_l command.

The _a_e_r_f_a_i_l command may also be used by reviewers to fail
reviews and return a change to the developer for further
work; the reviewer must supply a reason for the change



Peter Miller     (lib/en/user-guide/cA.0.so)        Page 207





User Guide                                             Aegis


history to record for all time.  Similarly, the _a_e_d_e_u com-
mand may be used by the developer to resume development of a
change at any time before it is integrated; no stated reason
is required.

1133..55..  IInntteeggrraattee tthhee CChhaannggee

A person nominated as an project integrator then integrates
the change.  This involves making a copy of the integration
directory, applying the modifications described by the
change to this integration directory, then building and
testing all over again.

This re-build and re-test is to ensure that no special
aspect of the developers environment influenced the success
up to this point, such as a unique environment variable set-
ting.  The re-build also ensures that all of the files in
the baseline, remembering that this includes source files
and all other intermediate files required by the build
process, remain consistent with each other, that the base-
line is self-consistent.  The definition of the baseline is
that it passes its own tests, so the tests are run on the
baseline.

Use the _a_e_i_b command to begin integration.

The _a_e_b command is used to build the integration copy of the
change.

The _a_e_t command is used to test the integration copy of the
change.

On later changes, the integration may also require the _a_e_t
_-_b_l command to test the change against the baseline.  This
tests ensures that the test _f_a_i_l_s against the baseline.
This failure is to ensure that bug fixes are accompanied by
tests which reproduce the bug initially, and that the change
has fixed it.  New functionality, naturally, will not be
present in the old baseline, and so tests of new functional-
ity will also fail against the old baseline.

Later changes may also have the regression tests run, using
the _a_e_t _-_r_e_g command.  This can be a very time-consuming
step for projects with a long history, and thus a large col-
lection of tests.  The _a_e_t _-_s_u_g_g_e_s_t command can also be used
to run "representative" sets of existing tests, but a full
regression test run is recommended before a major release,
or, say, weekly if it will complete over the weekend.  This
command is also available to developers, so that they have
fewer surprises from irate integrators.

The integrator may use the _a_e_i_f_a_i_l command to return a
change to its developer for further work; a reason must be
supplied, and should include relevant excerpts from the



Page 208         (lib/en/user-guide/cA.0.so)    Peter Miller





Aegis                                             User Guide


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 project configuration file's history com-
mands 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 subse-
quent changes, except for disk space problems.

Once the history is successfully updated, aegis renames the
integration directory  as the baseline, and throws the old
baseline away.  The development directory is deleted at this
time, too.

1133..66..  WWhhaatt ttoo ddoo NNeexxtt

There, the first change is completed.  The whole cycle may
now be repeated, starting at "Create Change," for all subse-
quent changes, with very few differences.

It is recommended that you read the _C_h_a_n_g_e _D_e_v_e_l_o_p_m_e_n_t _C_y_c_l_e
 chapter for a full worked example of the first four changes
of an example project, including some of the twists which
occur in real-world use of aegis.

Remember, too, the definition:

     aaeeggiiss (ee.j.iz) _n_. a protection, a defence.

It is not always the case that aegis exists to make life
"easier" for the software engineers.  The goal is to have a
baseline which always "works", where "works" is defined as
passing all of its own tests.  Wherever possible, the aegis
program attempts to be as helpful and as unintrusive as pos-
sible, but when the "working" definition is threatened, the
aegis program intrudes as necessary.  (Example: you can't do
an integrate pass without the integration copy building suc-
cessfully.)

All of the "extra work" of writing tests is a long-term win,
where old problems never again reappear.  All of the "extra
work" of reviewing changes means that another pair of eyes
sees the code and finds potential problems before they mani-
fest themselves in shipped product.  All of the "extra work"
of integration ensures that the baseline always works, and
is always self-consistent.  All of the "extra work" of hav-
ing a baseline and separate development directories allows
multiple parallel development, with no inter-developer
interference; and the baseline always works, it is never in
an "in-between" state.  In each case, not doing this "extra



Peter Miller     (lib/en/user-guide/cA.0.so)        Page 209





User Guide                                             Aegis


work" is a false economy.
























































Page 210         (lib/en/user-guide/cB.0.so)    Peter Miller





Aegis                                             User Guide


1144..  AAppppeennddiixx BB:: GGlloossssaarryy

The following is an alphabetical list of terms used in this
document.

administrator
     Person responsible for administering a _p_r_o_j_e_c_t.

awaiting_development
     The state a change is in immediately after creation.

awaiting_integration
     The state a change is in after it has passed review and
     before it is integrated.

awaiting review
     An optional state a change is in after it is developed,
     but before someone has chosen to review it..

baseline
     The repository; where the project master source is
     kept.

being developed
     The state a change is in when it is being worked on.

being integrated
     The state a change is in when it is being integrated
     with the baseline.

being reviewed
     The state a change is in after it is developed.

change
     A collection of files to be applied as a single atomic
     alteration of the baseline.

change number
     Each _c_h_a_n_g_e has a unique number identifying it.

completed
     The state a change is in after it has been integrated
     with the baseline.

delta number
     Each time the _a_e_i_b(1) command is used to start inte-
     grating a _c_h_a_n_g_e into the _b_a_s_e_l_i_n_e a unique number is
     assigned.  This number is the delta number.  This
     allows ascending version numbers to be generated for
     the baseline, independent of change numbers, which are
     inevitably integrated in a different order to their
     creation.





Peter Miller     (lib/en/user-guide/cB.0.so)        Page 211





User Guide                                             Aegis


dependency maintenance tool
     A program or programs external to aegis which may be
     given a set of rules for how to efficiently take a set
     of source files and process them to produce the final
     product.

DMT
     Abbreviation of Dependency Maintenance Tool.

develop_begin
     The command issued to take a change from the _a_w_a_i_t_i_n_g
     _d_e_v_e_l_o_p_m_e_n_t state to the _b_e_i_n_g _d_e_v_e_l_o_p_e_d state.  The
     change will be assigned to the user who executed the
     command.

develop_begin_undo
     The command issued to take a change from the _b_e_i_n_g
     _d_e_v_e_l_o_p_e_d state to the _a_w_a_i_t_i_n_g _d_e_v_e_l_o_p_m_e_n_t state.  Any
     files associated with the change will be removed from
     the development directory and their changes lost.

develop_end
     The command issued to take a change from the _b_e_i_n_g
     _d_e_v_e_l_o_p_e_d state to the _b_e_i_n_g _r_e_v_i_e_w_e_d state, or option-
     ally to the _a_w_a_i_t_i_n_g _r_e_v_i_e_w_e_d state.  The change must
     be known to build and test successfully.

develop_end_undo
     The command issued to take a change from the _b_e_i_n_g
     _r_e_v_i_e_w_e_d state back to the _b_e_i_n_g _d_e_v_e_l_o_p_e_d state.  The
     command must be executed by the original developer.

developer
     A member of staff allowed to develop changes.

development directory
     Each change is given a unique development directory in
     which to edit files and build and test.

history tool
     A program to save and restore previous versions of a
     file, usually by storing edits between the versions for
     efficiency.

integrate_pass
     The command used to take a change from the _b_e_i_n_g _i_n_t_e_-
     _g_r_a_t_e_d state to the _c_o_m_p_l_e_t_e_d state.  The change must
     be known to build and test successfully.

integrate_begin
     The command used to take a change from the _a_w_a_i_t_i_n_g
     _i_n_t_e_g_r_a_t_i_o_n state to the _b_e_i_n_g _i_n_t_e_g_r_a_t_e_d state.





Page 212         (lib/en/user-guide/cB.0.so)    Peter Miller





Aegis                                             User Guide


integrate_begin_undo
     The command used to take a change from the _b_e_i_n_g _i_n_t_e_-
     _g_r_a_t_e_d state to the _a_w_a_i_t_i_n_g _i_n_t_e_g_r_a_t_i_o_n state.

integrate_fail
     The command used to take a change from the _b_e_i_n_g _i_n_t_e_-
     _g_r_a_t_e_d state back to the _b_e_i_n_g _d_e_v_e_l_o_p_e_d state.

integration
     The process of merging the _b_a_s_e_l_i_n_e with the _d_e_v_e_l_o_p_-
     _m_e_n_t _d_i_r_e_c_t_o_r_y to form a new baseline.  This includes
     building and testing the merged directory, before
     replacing the original _b_a_s_e_l_i_n_e with the new merged
     version.

integration directory
     The directory used during _i_n_t_e_g_r_a_t_i_o_n to merge the
     existing _b_a_s_e_l_i_n_e with a change's _d_e_v_e_l_o_p_m_e_n_t _d_i_r_e_c_-
     _t_o_r_y.

integrator
     A staff member who performs _i_n_t_e_g_r_a_t_i_o_n_s_.

new_change
     The command used to create new changes.

new_change_undo
     The command used to destroy changes.

review_begin
     The command used to take a change from the _a_w_a_i_t_i_n_g
     _r_e_v_i_e_w state to the _b_e_i_n_g _r_e_v_i_e_w_e_d state.

review_fail
     The command used to take a change from the _b_e_i_n_g
     _r_e_v_i_e_w_e_d state back to the _b_e_i_n_g _d_e_v_e_l_o_p_e_d state.

review_pass
     The command used to take a change from the _b_e_i_n_g
     _r_e_v_i_e_w_e_d state to the _a_w_a_i_t_i_n_g _i_n_t_e_g_r_a_t_i_o_n state.

reviewer
     A person who may review _c_h_a_n_g_e_s and either pass or fail
     them (_r_e_v_i_e_w___p_a_s_s or _r_e_v_i_e_w___f_a_i_l respectively).

state
     Each _c_h_a_n_g_e is in one of seven states: _a_w_a_i_t_i_n_g _d_e_v_e_l_-
     _o_p_m_e_n_t, _b_e_i_n_g _d_e_v_e_l_o_p_e_d, _a_w_a_i_t_i_n_g _r_e_v_i_e_w, _b_e_i_n_g
     _r_e_v_i_e_w_e_d, _a_w_a_i_t_i_n_g _i_n_t_e_g_r_a_t_i_o_n, _b_e_i_n_g _i_n_t_e_g_r_a_t_e_d or
     _c_o_m_p_l_e_t_e_d.

state transition
     The event resulting in a _c_h_a_n_g_e changing from one state
     to another.



Peter Miller     (lib/en/user-guide/cD.0.so)        Page 213





User Guide                                             Aegis


1155..  AAppppeennddiixx DD:: WWhhyy iiss AAeeggiiss SSeett--UUiidd--RRoooott??

The goal for aegis is to have a project that "works".  There
is a fairly long discussion about this earlier in this User
Guide.  One of the first things that must be done to ensure
that a project is not subject to mystery break downs, is to
make sure that the master source of the project cannot be in
any way altered in an unauthorized fashion.  Note this says
"cannot", a stronger statement than "should not".

Aegis is more complicated than, say, set-group-id RCS,
because of the flaw with set-group-id: the baseline is
writable by the entire development team, so if a developer
says "this development process stinks" he can always bypass
it, and write the baseline directly.  This is a _v_e_r_y common
source of project disasters.  To prevent this, you must have
the baseline read-only, and so the set-group-id trick does
not work.  (The idea here is that there is _n_o way to bypass
the QA portions of the process.  Sure, set-group-id will
prevent accidental edits on the baseline, if the developers
are not members of the group, but it does not prevent _d_e_l_i_b_-
_e_r_a_t_e checkin of unauthorized code.  Again, the emphasis is
on "cannot" rather than "should not".)

Also, using the set-group-id trick, you need multiple copies
of RCS, one for each project.  Aegis can handle many
projects, each with a different owner and group, with a sin-
gle set-uid-root executable.

Aegis has no internal model of security, it uses UNIX secu-
rity, and so becomes each user in turn, so UNIX can deter-
mine the permissions.

1155..11..  EExxaammpplleess

Here are a few examples of the uid changes in common aegis
functions.  Unix "permission denied" errors are not shown,
but it should be clear where they would occur.

new change (aenc):
     become invoking user and read (edit) the change
     attribute file, validate the attribute file, then
     become the project owner to write the change state file
     and the project state file.

develop begin (aedb):
     become the project owner and read the project state
     file and the change state file, to see if the change
     exists and is available for development, and if the
     invoking user is on the developer access control list.
     Become the invoking user, but set the default group to
     the project group, and make a development directory.
     Become the project owner again, and update the change
     state file to say who is developing it and where.



Page 214         (lib/en/user-guide/cD.0.so)    Peter Miller





Aegis                                             User Guide


build (aeb):
     become the project owner to read the project and change
     state files, check that the invoking user is the devel-
     oper of the change, and that the change is in the _b_e_i_n_g
     _d_e_v_e_l_o_p_e_d state.  Become the invoking user, but set the
     default group to the project group, to invoke the build
     command.  Become the project owner to update the change
     state to remember the build result (the exit status).

copy file into change (aecp):
     become the project owner to read the project and change
     state files.  Check that the invoking user is the
     developer and that the change is in the _b_e_i_n_g _d_e_v_e_l_o_p_e_d
     state, and that the file is not already in the change,
     and that the file exists in the baseline.  Become the
     invoking user, but set the default group to the project
     group, and copy the file from the baseline into the
     development directory.  Become the project owner, and
     update the change state file to remember that the file
     is included in the change.

integrate fail (aeifail):
     become the project owner to read the project and change
     state files.  Check that in invoking user is the inte-
     grator of the change, and that the change is in the
     _b_e_i_n_g _i_n_t_e_g_r_a_t_e_d state.  Become the integrator to col-
     lect the integrate fail comments, then become the
     project owner to delete the integration directory, then
     become the developer to make the development directory
     writable again.  Then become the project owner to write
     the change state file, to remember that the change is
     back in the _b_e_i_n_g _d_e_v_e_l_o_p_e_d state.

integrate pass (aeipass):
     become the project owner to read the project and change
     state files.  Check that in invoking user is the inte-
     grator of the change, and that the change is in the
     _b_e_i_n_g _i_n_t_e_g_r_a_t_e_d state.  Make the integration directory
     the new baseline directory and remove the old baseline
     directory.  Write the change and project states to
     reflect the new baseline and the change is in the _c_o_m_-
     _p_l_e_t_e_d state.  Then become the developer to remove the
     development directory.

All the mucking about with default groups is to ensure that
the reviewers, other members of the same group, have access
to the files when it comes time to review the change.  The
umask is also set (not shown) so that the desired level of
"other" access is enforced.

As can be seen, each of the uid change either (a) allows
UNIX to enforce appropriate security, or (b) uses UNIX secu-
rity to ensure that unauthorized tampering of project files
cannot occur.  Each project has an owner and a group:



Peter Miller     (lib/en/user-guide/cD.0.so)        Page 215





User Guide                                             Aegis


members of the development team obtain read-only access to
the project files by membership to the appropriate group, to
actually alter project files requires that the development
procedure embodied by aegis is carried out.  You could have
a single account (not a user's account, usually, for obvious
conflicts of interest) which owns all project sources, or
you could have one account per project.  You can have one
group per project, if you don't want your various projects
to be able to see each other's work, or you could have a
single group for all projects.

1155..22..  SSoouurrccee DDeettaaiillss

For implementation details, see the os_become* functions in
the _a_e_g_i_s_/_o_s_._c file.  The os_become_init function is called
very early in main, in the _a_e_g_i_s_/_m_a_i_n_._c file.  After that,
all accesses are bracketed by os_become and os_become_undo
function calls, sometimes indirectly as project_become* or
user_become*, etc, functions.  You need to actually become
each user, because root is not root over NFS, and thus chown
tricks do not work, and also because duplicating kernel per-
mission checking in aegis is a little non-portable.

Note, also, that most system calls go via the interface
described in the _a_e_g_i_s_/_g_l_u_e_._h file.  This isolates the sys-
tem calls for UNIX variants which do not have the seteuid
function, or do not have a correctly working one.  The code
in the _a_e_g_i_s_/_g_l_u_e_._c file spawns "proxy" process which uses
the setuid function to become the user and stay that way.
If the seteuid function is available, it is used instead,
making aegis more efficient.  This isolation, however, makes
it possible for a system administrator to audit the aegis
code (for trojans) with some degree of confidence.  System
calls should be confined to the _a_e_g_i_s_/_l_o_g_._c, _a_e_g_i_s_/_p_a_g_e_r_._c,
_a_e_g_i_s_/_o_s_._c and _a_e_g_i_s_/_g_l_u_e_._c files.  System calls anywhere
else are probably a Bad Thing.





















Page 216         (lib/en/user-guide/cI.0.so)    Peter Miller





Aegis                                             User Guide


1166..  AAppppeennddiixx II:: IInntteerrnnaattiioonnaalliizzaattiioonn aanndd LLooccaalliizzaattiioonn

The Aegis source code has been internationalized, which is
the process of modifying the original source code to permit
error messages and other text to be presented in a language
other than the author's native English.  This was a large
and often painful task, but it allows a degree of customiza-
tion of error messages and other behaviours which would not
have been otherwise possible.  (It also makes the job of
running a spell-checker over the error messages signifi-
cantly easier.)

Localization is the process of translating the error mes-
sages and other text into various different languages or
nationalities.  This appendix is primarily aimed at localiz-
ers of Aegis.

1166..11..  TThhee ""..ppoo"" FFiilleess

The "lib/en/LC_MESSAGES" directory in the source tree con-
tains the various message files needed to localize Aegis.
You will find a number of ".po" files in this directory,
which translates "programmer cryptic" into English.  You
will see that each message has a comment attached, describ-
ing the message and the context in which it is used.  Many
messages also have "substitutions" described, which are
strings similar to shell variables which may be substituted
into the message - such as the file name for messages which
have something to do with a specific file.

The substitution mechanism is the same one as is used for
the various commands in the project _a_e_g_i_s_._c_o_n_f file, and so
all of the substitutions described in _a_e_s_u_b(5) are available
to the translator.  Note frequent use of the _p_l_u_r_a_l substi-
tution, which allows grammatically correct error messages to
be issued when faced with the singular/plural dichotomy.
Other substitutions include the login name of the executing
user, names of projects, number and state of changes, etc.

Ideally, the task for a translator is to take the _._p_o files
and translate the msgstr lines into the appropriate lan-
guage.  The job will, of course, not be that simple and so
references into the code have been included, so that you can
read the code should context be necessary to correctly
translate the message.

1166..22..  CChheecckkiinngg tthhee CCooddee

There are a number of keywords you need to have for the
_x_g_e_t_t_e_x_t program when extracting message strings.  The get-
text keyword is not used directly, because of the substitu-
tion mechanism wrapped around it.





Peter Miller     (lib/en/user-guide/cI.0.so)        Page 217





User Guide                                             Aegis


              i18n                error_intl
              io_comment_append   fatal_intl
              report_error        verbose_intl
              report_error        gram_error
              rpt_value_error


In general, the _e_t_c_/_H_o_w_t_o_._c_o_o_k file causes the messages to
be extracted into _i_1_8_n_-_t_m_p_/_*_._p_o for checking during the
build.

1166..33..  TTrraannssllaattoorrss WWeellccoommee

If _y_o_u are able to translate the error messages into another
language, please contact Peter Miller
<millerp@canb.auug.org.au> and he will tell you how it is
done.  (Actually, he'll point you to this part of the User
Guide.  :-)

To translate the error messages, look up the two-letter
abbreviation (http://www.w3.org/WAI/ER/IG/ert/iso639.htm) of
the language you are going to translate the error messages
to.  The rest of these instructions will call it _x_x.

In the source tree, you will see a directory called
_l_i_b_/_e_n_/_L_C___M_E_S_S_A_G_E_S which contains some .po files.  These are
the text form of the message catalogues.  You can view them
with a simple text editor.

Create a new directory for your translations, and copy the
English messages into it.

     mkdir lib/_x_x/LC_MESSAGES
     cp lib/en/LC_MESSAGES/*.po \
             lib/_x_x/LC_MESSAGES

Now you need to edit each of the lib/_x_x/LC_MESSAGES/*.po
files, replacing the msgstr strings with suitable transla-
tions.  Leave the msgid strings and the comments untrans-
lated.  These are text files, you can edit them with a sim-
ple text editor.  GNU Emacs has a PO mode to make this eas-
ier.

The GNU Gettext (http://www.gnu.org/directory/gettext.html)
sources have fairly good documentation
(http://www.gnu.org/manual/gettext/index.html) about this
process.

If you want to test your translations, you need to "compile"
the text into the binary form used by the gettext() system
call.  This is done using the _m_s_g_f_m_t(1) program from the GNU
Gettext package.  To see your new translations in action,
you create a /usr/pkg/lib/aegis/_x_x/LC_MESSAGES directory and
arrange for the _m_s_g_f_m_t(1) output to be placed in it.  Some



Page 218         (lib/en/user-guide/cI.0.so)    Peter Miller





Aegis                                             User Guide


of the messages are hard to trigger, don't expect complete
test coverage.

There are almost 600 error messages.  If you average 1 mes-
sage every 2 minutes, this is approximately 20 hours work.
The German translation, for example, required around 12
hours.

When you are done translating, email the results to Peter
Miller <millerp@canb.auug.org.au> and they will be included
in the next release of Aegis.














































Peter Miller    (./lib/en/user-guide/main.ms)       Page 219





User Guide                                             Aegis


.
























































Page ccxx       (./lib/en/user-guide/main.ms)   Peter Miller





Aegis                                             User Guide



                     TTaabbllee ooff CCoonntteennttss


1. Introduction  . . . . . . . . . . . . . . . . . . . .   3
  1.1. Year 2000 Status  . . . . . . . . . . . . . . . .   3
  1.2. What does aegis do?   . . . . . . . . . . . . . .   3
  1.3. Why use aegis?  . . . . . . . . . . . . . . . . .   4
  1.4. How to use this manual  . . . . . . . . . . . . .   5
  1.5. GNU GPL . . . . . . . . . . . . . . . . . . . . .   6
2. How Aegis Works . . . . . . . . . . . . . . . . . . .   7
  2.1. The Model . . . . . . . . . . . . . . . . . . . .   7
     2.1.1. The Baseline . . . . . . . . . . . . . . . .   7
     2.1.2. The Change Mechanism . . . . . . . . . . . .  10
     2.1.3. Change States  . . . . . . . . . . . . . . .  10
     2.1.4. The Software Engineers . . . . . . . . . . .  14
     2.1.5. The Change Process . . . . . . . . . . . . .  17
  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
3. The Change Development Cycle  . . . . . . . . . . . .  29
  3.1. The Developer . . . . . . . . . . . . . . . . . .  30
     3.1.1. Before You Start . . . . . . . . . . . . . .  30
     3.1.2. The First Change . . . . . . . . . . . . . .  30
     3.1.3. The Second Change  . . . . . . . . . . . . .  40
     3.1.4. The Third and Fourth Changes . . . . . . . .  47
     3.1.5. Developer Command Summary  . . . . . . . . .  64
  3.2. The Reviewer  . . . . . . . . . . . . . . . . . .  65
     3.2.1. Before You Start . . . . . . . . . . . . . .  65
     3.2.2. The First Change . . . . . . . . . . . . . .  65
     3.2.3. The Second Change  . . . . . . . . . . . . .  66
     3.2.4. Reviewer Command Summary . . . . . . . . . .  68
  3.3. The Integrator  . . . . . . . . . . . . . . . . .  69
     3.3.1. Before You Start . . . . . . . . . . . . . .  69
     3.3.2. The First Change . . . . . . . . . . . . . .  69
     3.3.3. The Other Changes  . . . . . . . . . . . . .  71
     3.3.4. Integrator Command Summary . . . . . . . . .  72
     3.3.5. Minimum Integrations . . . . . . . . . . . .  72
  3.4. The Administrator . . . . . . . . . . . . . . . .  74
     3.4.1. Before You Start . . . . . . . . . . . . . .  74
     3.4.2. The First Change . . . . . . . . . . . . . .  74
     3.4.3. The Second Change  . . . . . . . . . . . . .  77



Peter Miller    (./lib/en/user-guide/main.ms)        Page mi





User Guide                                             Aegis


     3.4.4. The Third Change . . . . . . . . . . . . . .  77
     3.4.5. The Fourth Change  . . . . . . . . . . . . .  77
     3.4.6. Administrator Command Summary  . . . . . . .  78
  3.5. What to do Next . . . . . . . . . . . . . . . . .  79
  3.6. Common Questions  . . . . . . . . . . . . . . . .  79
     3.6.1. Insulation . . . . . . . . . . . . . . . . .  79
     3.6.2. Partial Check-In . . . . . . . . . . . . . .  81
     3.6.3. Multiple Active Branches . . . . . . . . . .  82
     3.6.4. Collaboration  . . . . . . . . . . . . . . .  82
4. The History Tool  . . . . . . . . . . . . . . . . . .  84
  4.1. History File Names  . . . . . . . . . . . . . . .  84
  4.2. Interfacing . . . . . . . . . . . . . . . . . . .  84
     4.2.1. history_create_command . . . . . . . . . . .  84
     4.2.2. history_get_command  . . . . . . . . . . . .  85
     4.2.3. history_put_command  . . . . . . . . . . . .  85
     4.2.4. history_query_command  . . . . . . . . . . .  85
     4.2.5. history_content_limitation . . . . . . . . .  86
     4.2.6. history_tool_trashes_file  . . . . . . . . .  86
     4.2.7. Quoting Filenames  . . . . . . . . . . . . .  87
     4.2.8. Templates  . . . . . . . . . . . . . . . . .  87
  4.3. Using aesvt . . . . . . . . . . . . . . . . . . .  88
     4.3.1. history_create_command . . . . . . . . . . .  88
     4.3.2. history_put_command  . . . . . . . . . . . .  88
     4.3.3. history_get_command  . . . . . . . . . . . .  88
     4.3.4. history_query_command  . . . . . . . . . . .  89
     4.3.5. Templates  . . . . . . . . . . . . . . . . .  89
     4.3.6. Binary Files . . . . . . . . . . . . . . . .  90
  4.4. Using SCCS  . . . . . . . . . . . . . . . . . . .  91
     4.4.1. history_create_command . . . . . . . . . . .  91
     4.4.2. history_get_command  . . . . . . . . . . . .  91
     4.4.3. history_put_command  . . . . . . . . . . . .  92
     4.4.4. history_query_command  . . . . . . . . . . .  92
     4.4.5. Templates  . . . . . . . . . . . . . . . . .  93
     4.4.6. Binary Files . . . . . . . . . . . . . . . .  93
  4.5. Using RCS . . . . . . . . . . . . . . . . . . . .  94
     4.5.1. history_create_command . . . . . . . . . . .  94
     4.5.2. history_get_command  . . . . . . . . . . . .  95
     4.5.3. history_put_command  . . . . . . . . . . . .  95
     4.5.4. history_query_command  . . . . . . . . . . .  96
     4.5.5. merge_command  . . . . . . . . . . . . . . .  96
     4.5.6. Referential Integrity  . . . . . . . . . . .  97
     4.5.7. Templates  . . . . . . . . . . . . . . . . .  98
     4.5.8. Binary Files . . . . . . . . . . . . . . . .  98
     4.5.9. history_put_trashes_files  . . . . . . . . .  99
  4.6. Using fhist . . . . . . . . . . . . . . . . . . . 100
     4.6.1. history_create_command . . . . . . . . . . . 100
     4.6.2. history_get_command  . . . . . . . . . . . . 100
     4.6.3. history_put_command  . . . . . . . . . . . . 101
     4.6.4. history_query_command  . . . . . . . . . . . 101
     4.6.5. Templates  . . . . . . . . . . . . . . . . . 102
     4.6.6. Capabilities . . . . . . . . . . . . . . . . 102
     4.6.7. Binary Files . . . . . . . . . . . . . . . . 102
  4.7. Detecting History File Corruption . . . . . . . . 104
     4.7.1. General Method . . . . . . . . . . . . . . . 104



Page mii        (./lib/en/user-guide/main.ms)   Peter Miller





Aegis                                             User Guide


     4.7.2. Configuration Commands . . . . . . . . . . . 105
     4.7.3. An Alternative . . . . . . . . . . . . . . . 105
     4.7.4. Aegis' Database  . . . . . . . . . . . . . . 106
5. The Dependency Maintenance Tool . . . . . . . . . . . 107
  5.1. Required Features . . . . . . . . . . . . . . . . 107
     5.1.1. View Paths . . . . . . . . . . . . . . . . . 108
     5.1.2. Dynamic Include File Dependencies  . . . . . 108
  5.2. Development Directory Style . . . . . . . . . . . 110
     5.2.1. View Path  . . . . . . . . . . . . . . . . . 110
     5.2.2. Link the Baseline  . . . . . . . . . . . . . 111
     5.2.3. Copy All Sources . . . . . . . . . . . . . . 112
     5.2.4. Obsolete Features  . . . . . . . . . . . . . 113
  5.3. Using Cook  . . . . . . . . . . . . . . . . . . . 114
     5.3.1. Invoking Cook  . . . . . . . . . . . . . . . 114
     5.3.2. The Recipe File  . . . . . . . . . . . . . . 114
     5.3.3. The Recipe for C . . . . . . . . . . . . . . 116
     5.3.4. The Recipe for Yacc  . . . . . . . . . . . . 118
     5.3.5. The Recipe for Lex . . . . . . . . . . . . . 119
     5.3.6. Recipes for Documents  . . . . . . . . . . . 119
     5.3.7. Templates  . . . . . . . . . . . . . . . . . 120
  5.4. Using Cake  . . . . . . . . . . . . . . . . . . . 121
     5.4.1. Invoking Cake  . . . . . . . . . . . . . . . 121
     5.4.2. The Rules File . . . . . . . . . . . . . . . 122
     5.4.3. The Rule for C . . . . . . . . . . . . . . . 122
     5.4.4. The Rule for Yacc  . . . . . . . . . . . . . 123
     5.4.5. The Rule for Lex . . . . . . . . . . . . . . 124
     5.4.6. Rules for Documents  . . . . . . . . . . . . 124
  5.5. Using Make  . . . . . . . . . . . . . . . . . . . 126
     5.5.1. Invoking Make  . . . . . . . . . . . . . . . 126
     5.5.2. The Rule File  . . . . . . . . . . . . . . . 127
     5.5.3. The Rule for C . . . . . . . . . . . . . . . 128
     5.5.4. The Rule for Yacc  . . . . . . . . . . . . . 129
     5.5.5. The Rule for Lex . . . . . . . . . . . . . . 130
     5.5.6. Rules for Documents  . . . . . . . . . . . . 130
     5.5.7. Other Makes  . . . . . . . . . . . . . . . . 131
     5.5.8. Templates  . . . . . . . . . . . . . . . . . 131
     5.5.9. GNU Make VPATH Patch . . . . . . . . . . . . 131
     5.5.10. GNU Make's VPATH+ . . . . . . . . . . . . . 132
  5.6. Building Executable Scripts . . . . . . . . . . . 133
  5.7. GNU Autoconf  . . . . . . . . . . . . . . . . . . 134
     5.7.1. The Sources  . . . . . . . . . . . . . . . . 134
     5.7.2. Building . . . . . . . . . . . . . . . . . . 134
     5.7.3. Tesing . . . . . . . . . . . . . . . . . . . 136
     5.7.4. An Optimization  . . . . . . . . . . . . . . 136
     5.7.5. Signed-off-by  . . . . . . . . . . . . . . . 137
     5.7.6. Importing the Next Upstream Tarball  . . . . 137
     5.7.7. Importing the Next Upstream Patch  . . . . . 139
  5.8. No Build Required . . . . . . . . . . . . . . . . 139
     5.8.1. Why This May Not Be Such A Good Idea . . . . 139
6. The Difference Tools  . . . . . . . . . . . . . . . . 141
  6.1. Binary Files  . . . . . . . . . . . . . . . . . . 141
  6.2. Interfacing . . . . . . . . . . . . . . . . . . . 141
     6.2.1. diff_command . . . . . . . . . . . . . . . . 141
     6.2.2. merge_command  . . . . . . . . . . . . . . . 142



Peter Miller    (./lib/en/user-guide/main.ms)      Page miii





User Guide                                             Aegis


  6.3. When No Diff is Required  . . . . . . . . . . . . 143
  6.4. Using diff and merge  . . . . . . . . . . . . . . 144
     6.4.1. diff_command . . . . . . . . . . . . . . . . 144
     6.4.2. merge_command  . . . . . . . . . . . . . . . 145
  6.5. Using fhist . . . . . . . . . . . . . . . . . . . 145
     6.5.1. diff_command . . . . . . . . . . . . . . . . 145
     6.5.2. merge_command  . . . . . . . . . . . . . . . 146
7. The Project Attributes  . . . . . . . . . . . . . . . 147
  7.1. Description and Access  . . . . . . . . . . . . . 147
  7.2. Notification Commands . . . . . . . . . . . . . . 147
     7.2.1. Notification by email  . . . . . . . . . . . 148
     7.2.2. Notification by USENET . . . . . . . . . . . 149
  7.3. Exemption Controls  . . . . . . . . . . . . . . . 150
     7.3.1. One Person Projects  . . . . . . . . . . . . 150
     7.3.2. Two Person Projects  . . . . . . . . . . . . 151
     7.3.3. Larger Projects  . . . . . . . . . . . . . . 151
     7.3.4. RSS Feeds  . . . . . . . . . . . . . . . . . 151
8. Testing . . . . . . . . . . . . . . . . . . . . . . . 154
  8.1. Why Bother?   . . . . . . . . . . . . . . . . . . 154
     8.1.1. Projects for which Aegis' Testing is
Most Suitable  . . . . . . . . . . . . . . . . . . . . . 154
     8.1.2. Projects for which Aegis' Testing is
Useful . . . . . . . . . . . . . . . . . . . . . . . . . 155
     8.1.3. Projects for which Aegis' Testing is
Least Useful . . . . . . . . . . . . . . . . . . . . . . 156
  8.2. Writing Tests . . . . . . . . . . . . . . . . . . 158
     8.2.1. Contributors . . . . . . . . . . . . . . . . 158
     8.2.2. General Guidelines . . . . . . . . . . . . . 158
     8.2.3. Bourne Shell . . . . . . . . . . . . . . . . 161
     8.2.4. Perl . . . . . . . . . . . . . . . . . . . . 162
     8.2.5. Batch Testing  . . . . . . . . . . . . . . . 168
9. Branching . . . . . . . . . . . . . . . . . . . . . . 169
  9.1. How To Use Branching  . . . . . . . . . . . . . . 169
  9.2. Transition Using aenrls . . . . . . . . . . . . . 170
  9.3. Cross Branch Merge  . . . . . . . . . . . . . . . 171
  9.4. Multiple Branch Development . . . . . . . . . . . 171
  9.5. Hierarchy of Projects . . . . . . . . . . . . . . 171
     9.5.1. Fundamentals . . . . . . . . . . . . . . . . 172
     9.5.2. Incremental Integration  . . . . . . . . . . 172
     9.5.3. Super-Project Branching  . . . . . . . . . . 173
     9.5.4. Super-Project Testing  . . . . . . . . . . . 173
     9.5.5. The Next Cycle . . . . . . . . . . . . . . . 174
     9.5.6. Bug Fixing . . . . . . . . . . . . . . . . . 174
  9.6. Conflict Resolution . . . . . . . . . . . . . . . 174
     9.6.1. Cross Branch Merge . . . . . . . . . . . . . 175
     9.6.2. Insulation . . . . . . . . . . . . . . . . . 176
  9.7. Ending A Branch . . . . . . . . . . . . . . . . . 176
10. Tips and Traps . . . . . . . . . . . . . . . . . . . 179
  10.1. Renaming Include Files . . . . . . . . . . . . . 179
  10.2. Symbolic Links . . . . . . . . . . . . . . . . . 179
  10.3. User Setup . . . . . . . . . . . . . . . . . . . 180
     10.3.1. The .cshrc or .profile files  . . . . . . . 180
     10.3.2. The AEGIS_PATH environment variable . . . . 180
     10.3.3. The .aegisrc file . . . . . . . . . . . . . 181



Page miv        (./lib/en/user-guide/main.ms)   Peter Miller





Aegis                                             User Guide


     10.3.4. The defaulting mechanism  . . . . . . . . . 181
  10.4. The Project Owner  . . . . . . . . . . . . . . . 181
  10.5. USENET Publication Standards . . . . . . . . . . 182
     10.5.1. CHANGES . . . . . . . . . . . . . . . . . . 182
     10.5.2. MANIFEST  . . . . . . . . . . . . . . . . . 182
     10.5.3. Makefile  . . . . . . . . . . . . . . . . . 183
     10.5.4. patchlevel.h  . . . . . . . . . . . . . . . 183
     10.5.5. Building Patch Files  . . . . . . . . . . . 183
  10.6. Heterogeneous Development  . . . . . . . . . . . 184
     10.6.1. Project _a_e_g_i_s_._c_o_n_f File . . . . . . . . . . 184
     10.6.2. Change Attribute  . . . . . . . . . . . . . 186
     10.6.3. Network Files . . . . . . . . . . . . . . . 186
     10.6.4. DMT Implications  . . . . . . . . . . . . . 186
     10.6.5. Test Implications . . . . . . . . . . . . . 188
     10.6.6. Cross Compiling . . . . . . . . . . . . . . 189
     10.6.7. File Version by Architecture  . . . . . . . 189
  10.7. Reminders  . . . . . . . . . . . . . . . . . . . 189
     10.7.1. Awaiting Development  . . . . . . . . . . . 189
     10.7.2. Being Developed . . . . . . . . . . . . . . 189
     10.7.3. Being Reviewed  . . . . . . . . . . . . . . 190
     10.7.4. Awaiting Integration  . . . . . . . . . . . 190
11. Geographically Distributed Development . . . . . . . 191
  11.1. Introduction . . . . . . . . . . . . . . . . . . 191
     11.1.1. Risk Reduction  . . . . . . . . . . . . . . 191
     11.1.2. What to Send  . . . . . . . . . . . . . . . 192
     11.1.3. Methods and Topologies  . . . . . . . . . . 192
     11.1.4. The Rest of this Chapter  . . . . . . . . . 193
  11.2. Manual Operation . . . . . . . . . . . . . . . . 194
     11.2.1. Manual Send . . . . . . . . . . . . . . . . 194
     11.2.2. Sending Baselines . . . . . . . . . . . . . 194
     11.2.3. Sending Branches  . . . . . . . . . . . . . 195
     11.2.4. Manual Receive  . . . . . . . . . . . . . . 195
     11.2.5. Getting Started . . . . . . . . . . . . . . 196
  11.3. Sneaker Net  . . . . . . . . . . . . . . . . . . 196
  11.4. Automatic Operation  . . . . . . . . . . . . . . 197
     11.4.1. Sending . . . . . . . . . . . . . . . . . . 197
     11.4.2. Receiving . . . . . . . . . . . . . . . . . 198
  11.5. World Wide Web . . . . . . . . . . . . . . . . . 198
     11.5.1. Server  . . . . . . . . . . . . . . . . . . 198
     11.5.2. Browser . . . . . . . . . . . . . . . . . . 198
     11.5.3. Hands-Free Tracking . . . . . . . . . . . . 199
  11.6. Security . . . . . . . . . . . . . . . . . . . . 199
     11.6.1. Trojan Horses . . . . . . . . . . . . . . . 200
     11.6.2. PGP . . . . . . . . . . . . . . . . . . . . 200
     11.6.3. Sorcerer's Apprentice . . . . . . . . . . . 200
  11.7. Patches  . . . . . . . . . . . . . . . . . . . . 201
     11.7.1. Send  . . . . . . . . . . . . . . . . . . . 202
     11.7.2. Receive . . . . . . . . . . . . . . . . . . 202
     11.7.3. Limitations . . . . . . . . . . . . . . . . 203
12. Further Reading  . . . . . . . . . . . . . . . . . . 204
  12.1. Software Configuration Management  . . . . . . . 204
  12.2. Reviewing  . . . . . . . . . . . . . . . . . . . 204
13. Appendix A: New Project Quick Reference  . . . . . . 205
  13.1. Create the Project . . . . . . . . . . . . . . . 205



Peter Miller    (./lib/en/user-guide/main.ms)        Page mv





User Guide                                             Aegis


     13.1.1. Add the Staff . . . . . . . . . . . . . . . 205
     13.1.2. Project Attributes  . . . . . . . . . . . . 205
  13.2. Create Change One  . . . . . . . . . . . . . . . 206
  13.3. Develop Change One . . . . . . . . . . . . . . . 206
  13.4. Review The Change  . . . . . . . . . . . . . . . 207
  13.5. Integrate the Change . . . . . . . . . . . . . . 208
  13.6. What to do Next  . . . . . . . . . . . . . . . . 209
14. Appendix B: Glossary . . . . . . . . . . . . . . . . 211
15. Appendix D: Why is Aegis Set-Uid-Root?   . . . . . . 214
  15.1. Examples . . . . . . . . . . . . . . . . . . . . 214
  15.2. Source Details . . . . . . . . . . . . . . . . . 216
16. Appendix I: Internationalization and Localiza-
tion . . . . . . . . . . . . . . . . . . . . . . . . . . 217
  16.1. The ".po" Files  . . . . . . . . . . . . . . . . 217
  16.2. Checking the Code  . . . . . . . . . . . . . . . 217
  16.3. Translators Welcome  . . . . . . . . . . . . . . 218









































Page mvi                     ()                 Peter Miller


