# -*- Mode: perl; indent-tabs-mode: nil -*-

# generic.sample.buildcf - this is an example buildcf which should be
# useful to most people.  Your needs may be different from this script
# especially if you are running builds on many different OS and platforms
# which require different command sequences.  Each build type
# (construct, test, lint) defines a sequence of commands which is the
# same on all build machines.  They types each have different commands
# to run but the commands are simple because all the difficult work is
# performed inside makefiles and shell scripts.  There is one parser
# on the tinderbox server for each type of build.  This cf file will
# need a copy of the TreeData file on the build machine in order to
# translate the treename into the name of the module and branch and
# correctly set the CVSROOT environment variable.

# Run:

#	./build_shellscript	--buildcf ./generic.sample.buildcf	\
#				--build construct --test 		\
#					-- 				\
#				--tree seamonkey

# to see the completed build script which has all the perl
# variables substituted.


# $Revision: 1.12 $ 
# $Date: 2004/07/18 18:38:36 $ 
# $Author: kestes%walrus.com $ 
# $Source: /cvsroot/mozilla/webtools/tinderbox2/src/clientbin/generic.sample.buildcf,v $ 
# $Name:  $ 


# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is the Tinderbox build tool.
#
# The Initial Developer of the Original Code is Netscape Communications
# Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#

# complete rewrite by Ken Estes, Mail.com (kestes@staff.mail.com).
# Contributor(s): 



package UserDef;


# We use the same tinderbox treedata module which is on the server
# side to translate a treename into a module and branch.

# set the standard tinderbox search path to allow us to compile on the
# machine we run make on.

use lib '/usr/share/tinderbox/lib', '/etc/tinderbox';

use TreeData;


# User configurable variables live in their own namespace so that they
# will not contaminate the build script.  The buildscript will get the
# values it needs via well known functions.  This package may also set
# %ENV to affect the build programs.



# given a time return a human readable string suitable for using as
# part of a CVS checkout.

sub cvs_time_str {
    my ($time) = @_;

    my ($sec,$min,$hour,$mday,$mon,$year,
	$wday,$yday,$isdst) = localtime($time);
    
    $mon++;
    $year += 1900;

    my $str = sprintf "%04d-%02d-%02d %02d:%02d", $year,$mon,$mday,$hour,$min;
    return $str;
}


# given a time return a human readable string suitable for using as
# part of a file name but similar to the CVS checkout string for the
# same time (no space, shell does not likes spaces in filenames; no
# colon tar interprets colons specially).

sub filename_time_str {
    my ($time) = @_;

    my ($sec,$min,$hour,$mday,$mon,$year,
	$wday,$yday,$isdst) = localtime($time);
    
    $mon++;
    $year += 1900;

    my $str = sprintf "%04d-%02d-%02d.%02d%02d", $year,$mon,$mday,$hour,$min;
    return $str;
}



# The environmental variables for building at mozilla/netscape are
# quite complicated, your needs may be much simpler. Putting all
# environmental variable differences into a single function makes it
# clearer exactly how the environment differs on different platforms.

sub build_environment{

    $ENV{PATH} = (
                  '/usr/bin:'.
                  '/bin:'.
                  '/usr/local/bin:'.
		  '/usr/pvcs/oracle/bin:'.
                  '/home/build/bin'.
                  '');

    $ENV{CVS_RSH} = "ssh2";
    
    return 1;
}



sub build_scripts {
    
    my (%args) = @_;
    
    $build_type = $args{'tree_name'};
    $tree_name = $args{'tree_name'};

    my $build_dir = (
                     "/var/cache/tinderbox".
                     "/".
                     $args{'build_type'}.
                     "/".
                     $args{'tree_name'}.
                     "");
    
    # pick a time earlier then the current time. Check out the sources
    # as of that time and use that time as the name of the tar
    # file. Now anyone who wants to recreate the sources of the binary
    # tar can use the tarfile name to checkout the sources as if we had
    # tagged them.  We use a few minutes ago as the checkout time to
    # ensure that the CVS server has time to settle down from any
    # large checkins which may be in progress.

    my $checkout_time = time();
    my $filename_time_str = filename_time_str($checkout_time);
    my $cvs_time_str = cvs_time_str($checkout_time);

    # we give the CVS server time to finish what ever it is doing at
    # this time.

    my $sleep_minutes= 2;
    my $sleep_time = $sleep_minutes*60;

    my $dest_dir="$build_dir/dest";
    chomp $time_stamp;
    my $tar_file = (
                    "/var/spool/builds/".
                    $args{'tree_name'}.
                    "/".
                    $args{'tree_name'}.
                    ".".
                    $filename_time_str.
                    ".tar.gz"
                    );

    my $archive_dir = "/network/archive/$module/$module";
        
  if ($dest_dir) {
      $make_flags .= " PREFIX=$dest_dir ";
   }

  my $branch = $TreeData::VC_TREE{$tree_name}{'branch'};
  my $module = $TreeData::VC_TREE{$tree_name}{'module'};

  if ($branch) {
      $cvs_checkout_flags .= " -r $branch ";
  }

    # pass these variables to the Makefile.orig so that the
    # buildid can contain this information.

    $ENV{'BUILD_CVS_D_TIME'} = $filename_time_str;
    $ENV{'BUILD_BRANCH'} = $branch;
    $ENV{'BUILD_MODULE'} = $module;



# builds describe a sequence of steps needed to perform a "build".
# Each build either succeeds or fails.  Builds can be used for running
# tests and checking source code style in addition to creating binaries.

# Builds may depend on the environment, the OS or special arguments
# passed to the program.  Arguments which are passed after the '--'
# are assumed to be build specific and are ignored by the build
# harness and can be used in defining the build sequence.

# Builds can be architecture dependent (one build name can be used for
# all architectures) or independent (each OS uses a different
# buildname) depending on your application.


# each build can have as many phases as
# are needed (sample: checkout, configure, build, test)


# Each phase must have the following entries:

#	 phase_name: which describes what the phase is.

#	 error_status: the tinderbox status which should be returned
#	 if the phase fails.

#	 script: a list of shell commands to be executed in order
#	 until one fails (each command in a separate shell, similar to make).

#	 dir: the directory which will be local while the script is
#	 executing.




$BUILDS = { 
	   'construct' => [
			   {
			    'phase_name' => "print_environment",
			    'error_status' => "build_failed",
			    'dir' => "/",
			    'script' => [
                                         "sleep $sleep_time",
					 "show_env",
					 "rpm -qa",
                                      	 "rm -rf $build_dir",
                                         "mkdir -p $build_dir",
					],
			   },
			   {
			    'phase_name' => "checkout",
			    'error_status' => "build_failed",
			    'dir' => "$build_dir",
			    'script' => [
					 "cvs checkout $cvs_checkout_flags  -D '$cvs_time_str' $module",
					],
			   },
			    {
			     'phase_name' => "build",
			     'error_status' => "build_failed",
			     'dir' => "$build_dir",
			     'script' => [
                                          ". ./setupenv; ./configure",
                                          ". ./setupenv; make $make_flags all",
                                          ". ./setupenv; make $make_flags install",
                                          "tar zcf $tar_file \./install",
                                          "mv $tar_file $archive_dir",
                                          ". ./setupenv; make $make_flags distclean",
					 ],
                             },
			    {
			     'phase_name' => "doxygen",
			     'error_status' => "test_failed",
			     'dir' => "$build_dir",
			     'script' => [
                                          "doxygen",
					 ],
			    },
			     {
                             'phase_name' => "test",
                             'error_status' => "test_failed",
                             'dir' => "$build_dir/$tree_name",
                             'script' => [
					  "source ./setupenv; make $make_flags test",
					  ],
			     },
			  ],  # end construct
	   
   
	   'smoketest' => [
			   {
			    'phase_name' => "print_environment",
			    'error_status' => "build_failed",
			    'dir' => "/",
			    'script' => [
					 "show_env",
					 "rpm -qa",
					],
			   },
			   {
			    'phase_name' => "checkout",
			    'error_status' => "test_failed",
			    'dir' => "$build_dir",
			    'script' => [
					 "cvs checkout $cvs_checkout_flags $module",
					],
			   },
			    {
			     'phase_name' => "test",
			     'error_status' => "test_failed",
			     'dir' => "$build_dir",
			     'script' => [
					 ". ./setupenv; make $make_flags distclean",
					 ". ./setupenv; make $make_flags test",
					 ],
			    },
			  ],  # end test
	   
   
	   'lint' => [
			   {
			    'phase_name' => "checkout",
			    'error_status' => "build_failed",
			    'dir' => "$build_dir",
			    'script' => [
					 "cvs checkout $cvs_checkout_flags $module",
					],
			   },
			    {
			     'phase_name' => "lint",
			     'error_status' => "lint_failed",
			     'dir' => "$build_dir",
			     'script' => [
					 "make $make_flags lint",
					 ],
			    },
			  ],  # end lint
	   
   
	  }; # end %BUILDS

return $BUILDS;
}


# We have different error parsers defined for each 'type' of build.

sub error_parser_name {
  my (%args) = @_;

  my $parser_name =  $args{'build_type'};
  $parser_name = 'unix';

  return  $parser_name;
}


# Our build names on the tinderbox server (column names) are the
# hostname and OS name (and a few other details). We are running the
# same build instructions on each architecture so it makes sense to
# speak of the 'Solaris Build'.  Other users who do not worry about
# portability may use the buildscript buildname.  These users will have
# tinderbox columns with names like: "seamonkey", "grendel", "aurora"
# (these are the names of the 'type' of build).

sub build_name {
  my (%args) = @_;

    $os = `uname -s`;
    $osver = `uname -r`;
    
    chomp $os;
    chomp $osver;
  

  my ($build_name) = join('-', 
			  $args{'hostname'},
                          $args{'build_type'},
                          $os, $osver, 
			  );
  $build_name =~ s/\.\.+/\./g;

  return $build_name;
}



# person responsible for the build machines.

sub build_administrator {
  my (%args) = @_;

  my $admin = 'your.mailing.address@company.com';

  return $admin;
}

# addressing information for the build messages

sub mail_to {
  my (%args) = @_;

  my $mail_to = 'tinderbox_builds@mail.yourcompany.com';

  return $mail_to;
}


sub mail_from {
  my (%args) = @_;

  my $mail_from = 'tinderbox-build-daemon@'.$args{'hostname'};

  return $mail_from;
}

sub mailer {
  my (%args) = @_;

  my $mailer = 'HTTPPost http://localhost/cgi-bin/cgiwrap/tbox/processmail_builds.cgi';
  # $mailer = 'cat > /tmp/mail.out';
  # $mailer = '/export/home/tinderbox2/bin/processmail_builds';
  # $mailer = '/usr/lib/sendmail -oi -t';

  return $mailer;
}


# Tell the tinderbox webserver what page to display the build
# information.  In our case we use the same build instructions for
# several different products so this information must be passed in on
# the command line.  We must have this information or the build can
# not be displayed on the webserver, so it is a fatal error not to
# provide it.


sub tree_name {
  my (%args) = @_;

  my ($tree) = $args{'tree_name'};

#  my ($argv) = "@ARGV";
#  if ($argv =~ m/--tree\s*=?\s*([a-zA-Z0-9\-\_]+)/) {
#    $tree= $1;
#  } else {
#    die("no tree specified on command line\n");
#  }

  return $tree;
}

1;
