1<?php
2/*=========================================================================
3
4  Program:   CDash - Cross-Platform Dashboard System
5  Module:    $Id$
6  Language:  PHP
7  Date:      $Date$
8  Version:   $Revision$
9
10  Copyright (c) 2002 Kitware, Inc.  All rights reserved.
11  See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
12
13     This software is distributed WITHOUT ANY WARRANTY; without even
14     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15     PURPOSE.  See the above copyright notices for more information.
16
17=========================================================================*/
18// It is assumed that appropriate headers should be included before including this file
19include_once('models/dailyupdatefile.php');
20include_once('models/buildgrouprule.php');
21include_once('models/buildgroupposition.php');
22require_once("cdash/cdashmail.php");
23
24/** Main project class */
25class Project
26{
27  var $Name;
28  var $Id;
29  var $Description;
30  var $HomeUrl;
31  var $CvsUrl;
32  var $DocumentationUrl;
33  var $BugTrackerUrl;
34  var $BugTrackerFileUrl;
35  var $ImageId;
36  var $Public;
37  var $CoverageThreshold;
38  var $TestingDataUrl;
39  var $NightlyTime;
40  var $GoogleTracker;
41  var $EmailLowCoverage;
42  var $EmailTestTimingChanged;
43  var $EmailBrokenSubmission;
44  var $EmailRedundantFailures;
45  var $CvsViewerType;
46  var $TestTimeStd;
47  var $TestTimeStdThreshold;
48  var $ShowTestTime;
49  var $TestTimeMaxStatus;
50  var $EmailMaxItems;
51  var $EmailMaxChars;
52  var $EmailAdministrator;
53  var $ShowIPAddresses;
54  var $DisplayLabels;
55  var $ShowCoverageCode;
56  var $AutoremoveTimeframe;
57  var $AutoremoveMaxBuilds;
58  var $UploadQuota;
59  var $RobotName;
60  var $RobotRegex;
61  var $CTestTemplateScript;
62  var $WebApiKey;
63
64  function __construct()
65    {
66    $this->Initialize();
67    }
68
69  /** Initialize non defined variables */
70  private function Initialize()
71    {
72    if(empty($this->EmailLowCoverage))
73      {
74      $this->EmailLowCoverage=0;
75      }
76    if(empty($this->EmailTestTimingChanged))
77      {
78      $this->EmailTestTimingChanged=0;
79      }
80    if(empty($this->EmailBrokenSubmission))
81      {
82      $this->EmailBrokenSubmission=0;
83      }
84    if(empty($this->EmailRedundantFailures))
85      {
86      $this->EmailRedundantFailures=0;
87      }
88    if(empty($this->EmailAdministrator))
89      {
90      $this->EmailAdministrator=0;
91      }
92    if(empty($this->ShowIPAddresses))
93      {
94      $this->ShowIPAddresses=0;
95      }
96    if(empty($this->ShowTestTime))
97      {
98      $this->ShowTestTime=0;
99      }
100    if(empty($this->DisplayLabels))
101      {
102      $this->DisplayLabels=0;
103      }
104    if(empty($this->ShowCoverageCode))
105      {
106      $this->ShowCoverageCode=0;
107      }
108    if(empty($this->AutoremoveTimeframe))
109      {
110      $this->AutoremoveTimeframe=0;
111      }
112    if(empty($this->AutoremoveMaxBuilds))
113      {
114      $this->AutoremoveMaxBuilds=300;
115      }
116    if(empty($this->UploadQuota))
117      {
118      $this->UploadQuota=0;
119      }
120    if(empty($this->WebApiKey))
121      {
122      $this->WebApiKey='';
123      }
124    }
125
126  /** Add a build group */
127  function AddBuildGroup($buildgroup)
128    {
129    $buildgroup->ProjectId = $this->Id;
130    $buildgroup->Save();
131    }
132
133  /** Delete a project */
134  function Delete()
135    {
136    if(!$this->Id)
137      {
138      return false;
139      }
140    // Remove the project groups and rules
141    $buildgroup = pdo_query("SELECT * FROM buildgroup WHERE projectid=$this->Id");
142    while($buildgroup_array = pdo_fetch_array($buildgroup))
143      {
144      $groupid = $buildgroup_array["id"];
145      pdo_query("DELETE FROM buildgroupposition WHERE buildgroupid=$groupid");
146      pdo_query("DELETE FROM build2grouprule WHERE groupid=$groupid");
147      pdo_query("DELETE FROM build2group WHERE groupid=$groupid");
148      }
149
150    pdo_query("DELETE FROM buildgroup WHERE projectid=$this->Id");
151    pdo_query("DELETE FROM blockbuild WHERE projectid=$this->Id");
152    pdo_query("DELETE FROM user2project WHERE projectid=$this->Id");
153    pdo_query("DELETE FROM labelemail WHERE projectid=$this->Id");
154    pdo_query("DELETE FROM labelemail WHERE projectid=$this->Id");
155    pdo_query("DELETE FROM project2repositories WHERE projectid=$this->Id");
156
157    $dailyupdate = pdo_query("SELECT id FROM dailyupdate WHERE projectid=$this->Id");
158    while($dailyupdate_array = pdo_fetch_array($dailyupdate))
159      {
160      $dailyupdateid = $dailyupdate_array['id'];
161      pdo_query("DELETE FROM dailyupdatefile WHERE dailyupdateid='$dailyupdateid'");
162      }
163
164    pdo_query("DELETE FROM dailyupdate WHERE projectid=$this->Id");
165    pdo_query("DELETE FROM projectrobot WHERE projectid=$this->Id");
166    pdo_query("DELETE FROM projectjobscript WHERE projectid=$this->Id");
167
168    pdo_query("DELETE FROM project WHERE id=$this->Id");
169    }
170
171  /** Return if a project exists */
172  function Exists()
173    {
174    // If no id specify return false
175    if(!$this->Id)
176      {
177      return false;
178      }
179
180    $query = pdo_query("SELECT count(*) FROM project WHERE id='".$this->Id."'");
181    $query_array = pdo_fetch_array($query);
182    if($query_array[0]>0)
183      {
184      return true;
185      }
186    return false;
187    }
188
189  // Save the project in the database
190  function Save()
191    {
192    // Escape the values
193    $Description = pdo_real_escape_string($this->Description);
194    $HomeUrl = pdo_real_escape_string($this->HomeUrl);
195    $CvsUrl = pdo_real_escape_string($this->CvsUrl);
196    $DocumentationUrl = pdo_real_escape_string($this->DocumentationUrl);
197    $BugTrackerUrl = pdo_real_escape_string($this->BugTrackerUrl);
198    $BugTrackerFileUrl = pdo_real_escape_string($this->BugTrackerFileUrl);
199    $TestingDataUrl = pdo_real_escape_string($this->TestingDataUrl);
200    $NightlyTime = pdo_real_escape_string($this->NightlyTime);
201    $GoogleTracker = pdo_real_escape_string($this->GoogleTracker);
202    $RobotName = pdo_real_escape_string($this->RobotName);
203    $RobotRegex = pdo_real_escape_string($this->RobotRegex);
204    $Name = pdo_real_escape_string($this->Name);
205    $CvsViewerType = pdo_real_escape_string($this->CvsViewerType);
206
207    // Check if the project is already
208    if($this->Exists())
209      {
210      // Trim the name
211      $this->Name = trim($this->Name);
212      $this->Initialize();
213      // Update the project
214      $query = "UPDATE project SET ";
215      $query .= "description='".$Description."'";
216      $query .= ",homeurl='".$HomeUrl."'";
217      $query .= ",cvsurl='".$CvsUrl."'";
218      $query .= ",documentationurl='".$DocumentationUrl."'";
219      $query .= ",bugtrackerurl='".$BugTrackerUrl."'";
220      $query .= ",bugtrackerfileurl='".$BugTrackerFileUrl."'";
221      $query .= ",public=".qnum($this->Public);
222      $query .= ",coveragethreshold=".qnum($this->CoverageThreshold);
223      $query .= ",testingdataurl='".$TestingDataUrl."'";
224      $query .= ",nightlytime='".$NightlyTime."'";
225      $query .= ",googletracker='".$GoogleTracker."'";
226      $query .= ",emaillowcoverage=".qnum($this->EmailLowCoverage);
227      $query .= ",emailtesttimingchanged=".qnum($this->EmailTestTimingChanged);
228      $query .= ",emailbrokensubmission=".qnum($this->EmailBrokenSubmission);
229      $query .= ",emailredundantfailures=".qnum($this->EmailRedundantFailures);
230      $query .= ",emailadministrator=".qnum($this->EmailAdministrator);
231      $query .= ",showipaddresses=".qnum($this->ShowIPAddresses);
232      $query .= ",displaylabels=".qnum($this->DisplayLabels);
233      $query .= ",showcoveragecode=".qnum($this->ShowCoverageCode);
234      $query .= ",autoremovetimeframe=".qnum($this->AutoremoveTimeframe);
235      $query .= ",autoremovemaxbuilds=".qnum($this->AutoremoveMaxBuilds);
236      $query .= ",uploadquota=".qnum($this->UploadQuota);
237      $query .= ",cvsviewertype='".$CvsViewerType."'";
238      $query .= ",testtimestd=".qnum($this->TestTimeStd);
239      $query .= ",testtimestdthreshold=".qnum($this->TestTimeStdThreshold);
240      $query .= ",showtesttime=".qnum($this->ShowTestTime);
241      $query .= ",testtimemaxstatus=".qnum($this->TestTimeMaxStatus);
242      $query .= ",emailmaxitems=".qnum($this->EmailMaxItems);
243      $query .= ",emailmaxchars=".qnum($this->EmailMaxChars);
244      $query .= " WHERE id=".qnum($this->Id)."";
245
246      if(!pdo_query($query))
247        {
248        add_last_sql_error("Project Update",$this->Id);
249        return false;
250        }
251
252      if($this->RobotName != '')
253        {
254        // Check if it exists
255        $robot = pdo_query("SELECT projectid FROM projectrobot WHERE projectid=".qnum($this->Id));
256        if(pdo_num_rows($robot)>0)
257          {
258          $query = "UPDATE projectrobot SET robotname='".$RobotName."',authorregex='".$RobotRegex.
259                   "' WHERE projectid=".qnum($this->Id);
260          if(!pdo_query($query))
261            {
262            add_last_sql_error("Project Update",$this->Id);
263            return false;
264            }
265          }
266        else
267          {
268          $query = "INSERT INTO projectrobot(projectid,robotname,authorregex)
269                   VALUES (".qnum($this->Id).",'".$RobotName."','".$RobotRegex."')";
270          if(!pdo_query($query))
271            {
272            add_last_sql_error("Project Update",$this->Id);
273            return false;
274            }
275          }
276        }
277
278      // Insert the ctest template
279      if($this->CTestTemplateScript != '')
280        {
281        $CTestTemplateScript = pdo_real_escape_string($this->CTestTemplateScript);
282
283        // Check if it exists
284        $script = pdo_query("SELECT projectid FROM projectjobscript WHERE projectid=".qnum($this->Id));
285        if(pdo_num_rows($script)>0)
286          {
287          $query = "UPDATE projectjobscript SET script='".$CTestTemplateScript."' WHERE projectid=".qnum($this->Id);
288          if(!pdo_query($query))
289            {
290            return false;
291            }
292          }
293        else
294          {
295          $query = "INSERT INTO projectjobscript(projectid,script)
296                   VALUES (".qnum($this->Id).",'".$CTestTemplateScript."')";
297          if(!pdo_query($query))
298            {
299            return false;
300            }
301          }
302        }
303      else
304        {
305        pdo_query("DELETE FROM projectjobscript WHERE projectid=$this->Id");
306        }
307
308      }
309    else // insert the project
310      {
311      $id = "";
312      $idvalue = "";
313      if($this->Id)
314        {
315        $id = "id,";
316        $idvalue = "'".$this->Id."',";
317        }
318
319      if(strlen($this->ImageId) == 0)
320        {
321        $this->ImageId = 0;
322        }
323
324      // Trim the name
325      $this->Name = trim($this->Name);
326      $this->Initialize();
327      $query = "INSERT INTO project(".$id."name,description,homeurl,cvsurl,bugtrackerurl,bugtrackerfileurl,documentationurl,public,imageid,coveragethreshold,testingdataurl,
328                                    nightlytime,googletracker,emailbrokensubmission,emailredundantfailures,
329                                    emaillowcoverage,emailtesttimingchanged,cvsviewertype,
330                                    testtimestd,testtimestdthreshold,testtimemaxstatus,emailmaxitems,emailmaxchars,showtesttime,emailadministrator,showipaddresses
331                                    ,displaylabels,showcoveragecode,autoremovetimeframe,autoremovemaxbuilds,uploadquota,webapikey)
332                 VALUES (".$idvalue."'$Name','$Description','$HomeUrl','$CvsUrl','$BugTrackerUrl','$BugTrackerFileUrl','$DocumentationUrl',
333                 ".qnum($this->Public).",".qnum($this->ImageId).",".qnum($this->CoverageThreshold).",'$TestingDataUrl','$NightlyTime',
334                 '$GoogleTracker',".qnum($this->EmailBrokenSubmission).",".qnum($this->EmailRedundantFailures).","
335                 .qnum($this->EmailLowCoverage).",".qnum($this->EmailTestTimingChanged).",'$CvsViewerType',".qnum($this->TestTimeStd)
336                 .",".qnum($this->TestTimeStdThreshold).",".qnum($this->TestTimeMaxStatus).",".qnum($this->EmailMaxItems).",".qnum($this->EmailMaxChars).","
337                 .qnum($this->ShowTestTime).",".qnum($this->EmailAdministrator).",".qnum($this->ShowIPAddresses).",".qnum($this->DisplayLabels).",".qnum($this->ShowCoverageCode)
338                 .",".qnum($this->AutoremoveTimeframe).",".qnum($this->AutoremoveMaxBuilds).",".qnum($this->UploadQuota).",'".$this->WebApiKey."')";
339
340      if(!pdo_query($query))
341        {
342        add_last_sql_error("Project Create");
343        return false;
344        }
345
346      if(!$this->Id)
347        {
348        $this->Id = pdo_insert_id("project");
349        }
350
351      if($this->RobotName != '')
352        {
353        $query = "INSERT INTO projectrobot(projectid,robotname,authorregex)
354                 VALUES (".qnum($this->Id).",'".$RobotName."','".$RobotRegex."')";
355        if(!pdo_query($query))
356          {
357          return false;
358          }
359        }
360
361      if($this->CTestTemplateScript != '')
362        {
363        $CTestTemplateScript = pdo_real_escape_string($this->CTestTemplateScript);
364
365        $query = "INSERT INTO projectjobscript(projectid,script)
366                 VALUES (".qnum($this->Id).",'".$$CTestTemplateScript."')";
367        if(!pdo_query($query))
368          {
369          return false;
370          }
371        }
372      }
373
374    return true;
375    }
376
377  /** Get the user's role */
378  function GetUserRole($userid)
379    {
380    if(!$this->Id || !is_numeric($this->Id))
381      {
382      return -1;
383      }
384
385    $role = -1;
386
387    $user2project = pdo_query("SELECT role FROM user2project WHERE userid='$userid' AND projectid='".$this->Id."'");
388    if(pdo_num_rows($user2project)>0)
389      {
390      $user2project_array = pdo_fetch_array($user2project);
391      $role = $user2project_array["role"];
392      }
393
394    return $role;
395    }
396
397  /** Return true if the project exists */
398  function ExistsByName($name)
399    {
400    $project = pdo_query("SELECT id FROM project WHERE name='$name'");
401    if(pdo_num_rows($project)>0)
402      {
403      return true;
404      }
405    return false;
406    }
407
408  /** Get the logo id */
409  function GetLogoId()
410    {
411    $query = pdo_query("SELECT imageid FROM project WHERE id=".$this->Id);
412
413    if(!$query)
414      {
415      add_last_sql_error("Project GetLogoId",$this->Id);
416      return 0;
417      }
418
419    if($query_array = pdo_fetch_array($query))
420      {
421      return $query_array["imageid"];
422      }
423    return 0;
424    }
425
426  /** Fill in all the information from the database */
427  function Fill()
428    {
429    if(!$this->Id)
430      {
431      echo "Project Fill(): Id not set";
432      }
433
434    $project = pdo_query("SELECT * FROM project WHERE id=".$this->Id);
435    if(!$project)
436      {
437      add_last_sql_error("Project Fill",$this->Id);
438      return;
439      }
440
441    if($project_array = pdo_fetch_array($project))
442      {
443      $this->Name = $project_array['name'];
444      $this->Description = $project_array['description'];
445      $this->HomeUrl = $project_array['homeurl'];
446      $this->CvsUrl = $project_array['cvsurl'];
447      $this->DocumentationUrl = $project_array['documentationurl'];
448      $this->BugTrackerUrl = $project_array['bugtrackerurl'];
449      $this->BugTrackerFileUrl = $project_array['bugtrackerfileurl'];
450      $this->ImageId = $project_array['imageid'];
451      $this->Public = $project_array['public'];
452      $this->CoverageThreshold = $project_array['coveragethreshold'];
453      $this->TestingDataUrl = $project_array['testingdataurl'];
454      $this->NightlyTime = $project_array['nightlytime'];
455      $this->GoogleTracker = $project_array['googletracker'];
456      $this->EmailLowCoverage = $project_array['emaillowcoverage'];
457      $this->EmailTestTimingChanged = $project_array['emailtesttimingchanged'];
458      $this->EmailBrokenSubmission = $project_array['emailbrokensubmission'];
459      $this->EmailRedundantFailures = $project_array['emailredundantfailures'];
460      $this->EmailAdministrator = $project_array['emailadministrator'];
461      $this->ShowIPAddresses = $project_array['showipaddresses'];
462      $this->DisplayLabels = $project_array['displaylabels'];
463      $this->ShowCoverageCode = $project_array['showcoveragecode'];
464      $this->AutoremoveTimeframe = $project_array['autoremovetimeframe'];
465      $this->AutoremoveMaxBuilds = $project_array['autoremovemaxbuilds'];
466      $this->UploadQuota = $project_array['uploadquota'];
467      $this->CvsViewerType = $project_array['cvsviewertype'];
468      $this->TestTimeStd = $project_array['testtimestd'];
469      $this->TestTimeStdThreshold = $project_array['testtimestdthreshold'];
470      $this->ShowTestTime = $project_array['showtesttime'];
471      $this->TestTimeMaxStatus = $project_array['testtimemaxstatus'];
472      $this->EmailMaxItems = $project_array['emailmaxitems'];
473      $this->EmailMaxChars = $project_array['emailmaxchars'];
474      $this->WebApiKey = $project_array['webapikey'];
475      if($this->WebApiKey == '')
476        {
477        // If no web API key exists, we add one
478        include_once('cdash/common.php');
479        $newKey = generate_web_api_key();
480        pdo_query("UPDATE project SET webapikey='$newKey' WHERE id=".$this->Id);
481        $this->WebApiKey = $newKey;
482        }
483      }
484
485    // Check if we have a robot
486    $robot = pdo_query("SELECT * FROM projectrobot WHERE projectid=".$this->Id);
487    if(!$robot)
488      {
489      add_last_sql_error("Project Fill",$this->Id);
490      return;
491      }
492
493    if($robot_array = pdo_fetch_array($robot))
494      {
495      $this->RobotName = $robot_array['robotname'];
496      $this->RobotRegex = $robot_array['authorregex'];
497      }
498
499    // Check if we have a ctest script
500    $script = pdo_query("SELECT script FROM projectjobscript WHERE projectid=".$this->Id);
501    if(!$script)
502      {
503      add_last_sql_error("Project Fill",$this->Id);
504      return;
505      }
506    if($script_array = pdo_fetch_array($script))
507      {
508      $this->CTestTemplateScript = $script_array['script'];
509      }
510    }
511
512  /** Add a logo */
513  function AddLogo($contents,$filetype)
514    {
515    if(strlen($contents) == 0)
516      {
517      return;
518      }
519
520    $imgid = $this->GetLogoId();
521    $checksum = crc32($contents);
522
523    //check if we already have a copy of this file in the database
524    $sql = "SELECT id FROM image WHERE checksum = '$checksum'";
525    $result = pdo_query("$sql");
526    if($row = pdo_fetch_array($result))
527      {
528      $imgid = $row["id"];
529      // Insert into the project
530      pdo_query("UPDATE project SET imageid=".qnum($imgid)." WHERE id=".$this->Id);
531      add_last_sql_error("Project AddLogo",$this->Id);
532      }
533    else if($imgid==0)
534      {
535      include("cdash/config.php");
536      if($CDASH_DB_TYPE == "pgsql")
537        {
538        $contents = pg_escape_bytea($contents);
539        }
540      $sql = "INSERT INTO image(img, extension, checksum) VALUES ('$contents', '$filetype', '$checksum')";
541      if(pdo_query("$sql"))
542        {
543        $imgid = pdo_insert_id("image");
544
545        // Insert into the project
546        pdo_query("UPDATE project SET imageid=".qnum($imgid)." WHERE id=".qnum($this->Id));
547        add_last_sql_error("Project AddLogo",$this->Id);
548        }
549      }
550     else // update the current image
551       {
552       include("cdash/config.php");
553       if($CDASH_DB_TYPE == "pgsql")
554         {
555         $contents = pg_escape_bytea($contents);
556         }
557       pdo_query("UPDATE image SET img='$contents',extension='$filetype',checksum='$checksum' WHERE id=".qnum($imgid));
558       add_last_sql_error("Project AddLogo",$this->Id);
559       }
560    return $imgid;
561    }
562
563  /** Add CVS/SVN repositories */
564  function AddRepositories($repositories, $usernames, $passwords,$branches)
565    {
566    // First we update/delete any registered repositories
567    $currentRepository = 0;
568    $repositories_query = pdo_query("SELECT repositoryid FROM project2repositories WHERE projectid=".qnum($this->Id)." ORDER BY repositoryid");
569    add_last_sql_error("Project AddRepositories",$this->Id);
570    while($repository_array = pdo_fetch_array($repositories_query))
571      {
572      $repositoryid = $repository_array["repositoryid"];
573      if(!isset($repositories[$currentRepository]) || strlen($repositories[$currentRepository])==0)
574        {
575        $query = pdo_query("SELECT * FROM project2repositories WHERE repositoryid=".qnum($repositoryid));
576        add_last_sql_error("Project AddRepositories",$this->Id);
577        if(pdo_num_rows($query)==1)
578          {
579          pdo_query("DELETE FROM repositories WHERE id='$repositoryid'");
580          add_last_sql_error("Project AddRepositories",$this->Id);
581          }
582        pdo_query("DELETE FROM project2repositories WHERE projectid=".qnum($this->Id)." AND repositoryid=".qnum($repositoryid));
583        add_last_sql_error("Project AddRepositories",$this->Id);
584        }
585      else
586        {
587        // If the repository is not shared by any other project we update
588        $count_query = pdo_query("SELECT count(*) as c FROM project2repositories WHERE repositoryid=".qnum($repositoryid));
589        $count_array = pdo_fetch_array($count_query);
590        if($count_array['c']==1)
591          {
592          pdo_query("UPDATE repositories SET url='$repositories[$currentRepository]',
593                          username='$usernames[$currentRepository]',
594                          password='$passwords[$currentRepository]',
595                          branch='$branches[$currentRepository]'
596                          WHERE id=".qnum($repositoryid));
597          add_last_sql_error("Project AddRepositories",$this->Id);
598          }
599        else // Otherwise we remove it from the current project and add it to the queue to be created
600          {
601          pdo_query("DELETE FROM project2repositories WHERE projectid=".qnum($this->Id)." AND repositoryid=".qnum($repositoryid));
602          add_last_sql_error("Project AddRepositories",$this->Id);
603          $repositories[] = $repositories[$currentRepository];
604          $usernames[] = $usernames[$currentRepository];
605          $passwords[] = $passwords[$currentRepository];
606          $branches[] = $branches[$currentRepository];
607          }
608        }
609      $currentRepository++;
610      }
611
612    //  Then we add new repositories
613    for($i=$currentRepository;$i<count($repositories);$i++)
614      {
615      $url = $repositories[$i];
616      $username = $usernames[$i];
617      $password = $passwords[$i];
618      $branch = $branches[$i];
619      if(strlen($url) == 0)
620        {
621        continue;
622        }
623
624      // Insert into repositories if not any
625      $repositories_query = pdo_query("SELECT id FROM repositories WHERE url='$url'");
626      if(pdo_num_rows($repositories_query) == 0)
627        {
628        pdo_query("INSERT INTO repositories (url, username, password, branch) VALUES ('$url', '$username', '$password','$branch')");
629        add_last_sql_error("Project AddRepositories",$this->Id);
630        $repositoryid = pdo_insert_id("repositories");
631        }
632      else
633        {
634        $repositories_array = pdo_fetch_array($repositories_query);
635        $repositoryid = $repositories_array["id"];
636        }
637      pdo_query("INSERT INTO project2repositories (projectid,repositoryid) VALUES (".qnum($this->Id).",'$repositoryid')");
638      add_last_sql_error("Project AddRepositories",$this->Id);
639      } // end add repository
640    } // end function   AddRepositories
641
642   /** Get the repositories */
643   function GetRepositories()
644     {
645     $repositories = array();
646     $repository = pdo_query("SELECT url,username,password,branch from repositories,project2repositories
647                               WHERE repositories.id=project2repositories.repositoryid
648                               AND project2repositories.projectid=".qnum($this->Id));
649     add_last_sql_error("Project GetRepositories",$this->Id);
650     while($repository_array = pdo_fetch_array($repository))
651       {
652       $rep['url'] = $repository_array['url'];
653       $rep['username'] = $repository_array['username'];
654       $rep['password'] = $repository_array['password'];
655       $rep['branch'] = $repository_array['branch'];
656       $repositories[] = $rep;
657       }
658     return $repositories;
659     } // end GetRepositories
660
661  /** Get the build groups */
662   function GetBuildGroups()
663     {
664     $buildgroups = array();
665     $query = pdo_query("SELECT id,name,autoremovetimeframe FROM buildgroup
666                         WHERE projectid=".qnum($this->Id));
667
668     add_last_sql_error("Project GetBuildGroups",$this->Id);
669     while($buildgroup = pdo_fetch_array($query))
670       {
671       $group['id'] = $buildgroup['id'];
672       $group['name'] = $buildgroup['name'];
673       $group['autoremovetimeframe'] = $buildgroup['autoremovetimeframe'];
674       $buildgroups[] = $group;
675       }
676     return $buildgroups;
677     } // end GetBuildGroups
678
679  /** Get the list of block builds */
680  function GetBlockedBuilds()
681    {
682    $sites = array();
683    $site = pdo_query("SELECT id,buildname,sitename,ipaddress FROM blockbuild
684                             WHERE projectid=".qnum($this->Id));
685    add_last_sql_error("Project GetBlockedBuilds",$this->Id);
686    while($site_array = pdo_fetch_array($site))
687       {
688       $sites[] = $site_array;
689       }
690    return $sites;
691    }
692
693  /** Get Ids of all the project registered
694   *  Maybe this function should go somewhere else but for now here */
695  function GetIds()
696    {
697    $ids = array();
698    $query = pdo_query("SELECT id FROM project ORDER BY id");
699    add_last_sql_error("Project GetIds",$this->Id);
700    while($query_array = pdo_fetch_array($query))
701      {
702      $ids[] = $query_array["id"];
703      }
704    return $ids;
705    }
706
707  /** Get the Name of the project */
708  function GetName()
709    {
710    if(strlen($this->Name)>0)
711      {
712      return $this->Name;
713      }
714
715    if(!$this->Id)
716      {
717      echo "Project GetName(): Id not set";
718      return false;
719      }
720
721    $project = pdo_query("SELECT name FROM project WHERE id=".qnum($this->Id));
722    if(!$project)
723      {
724      add_last_sql_error("Project GetName",$this->Id);
725      return false;
726      }
727    $project_array = pdo_fetch_array($project);
728    $this->Name = $project_array['name'];
729
730    return $this->Name;
731    }
732
733  /** Get the coveragethreshold */
734  function GetCoverageThreshold()
735    {
736    if(strlen($this->CoverageThreshold)>0)
737      {
738      return $this->CoverageThreshold;
739      }
740
741    if(!$this->Id)
742      {
743      echo "Project GetCoverageThreshold(): Id not set";
744      return false;
745      }
746
747    $project = pdo_query("SELECT coveragethreshold FROM project WHERE id=".qnum($this->Id));
748    if(!$project)
749      {
750      add_last_sql_error("Project GetCoverageThreshold",$this->Id);
751      return false;
752      }
753    $project_array = pdo_fetch_array($project);
754    $this->CoverageThreshold = $project_array['coveragethreshold'];
755
756    return $this->CoverageThreshold;
757    }
758
759  /** Get the number of subproject */
760  function GetNumberOfSubProjects($date=NULL)
761    {
762    if(!$this->Id)
763      {
764      echo "Project GetNumberOfSubprojects(): Id not set";
765      return false;
766      }
767
768     if($date == NULL)
769      {
770      $date = gmdate(FMT_DATETIME);
771      }
772
773    $project = pdo_query("SELECT count(*) AS c FROM subproject WHERE projectid=".qnum($this->Id)." AND (endtime='1980-01-01 00:00:00' OR endtime>'".$date."')");
774    if(!$project)
775      {
776      add_last_sql_error("Project GetNumberOfSubprojects",$this->Id);
777      return false;
778      }
779    $project_array = pdo_fetch_array($project);
780    return $project_array['c'];
781    }
782
783  /** Get the subproject ids*/
784  function GetSubProjects($date=NULL)
785    {
786    if(!$this->Id)
787      {
788      echo "Project GetNumberOfSubprojects(): Id not set";
789      return false;
790      }
791
792    // If not set, the date is now
793    if($date == NULL)
794      {
795      $date = gmdate(FMT_DATETIME);
796      }
797
798    $project = pdo_query("SELECT id FROM subproject WHERE projectid=".qnum($this->Id)." AND
799                          starttime<='".$date."' AND (endtime>'".$date."' OR endtime='1980-01-01 00:00:00')");
800    if(!$project)
801      {
802      add_last_sql_error("Project GetSubProjects",$this->Id);
803      return false;
804      }
805
806    $ids = array();
807    while($project_array = pdo_fetch_array($project))
808      {
809      $ids[] = $project_array['id'];
810      }
811    return $ids;
812    }
813
814  /** Get the last submission of the subproject*/
815  function GetLastSubmission()
816    {
817    if(!$this->Id)
818      {
819      echo "Project GetLastSubmission(): Id not set";
820      return false;
821      }
822
823    $build = pdo_query("SELECT submittime FROM build WHERE projectid=".qnum($this->Id).
824                         " ORDER BY submittime DESC LIMIT 1");
825
826    if(!$build)
827      {
828      add_last_sql_error("Project GetLastSubmission",$this->Id);
829      return false;
830      }
831    $build_array = pdo_fetch_array($build);
832    return date(FMT_DATETIMESTD,strtotime($build_array['submittime']. "UTC"));
833    }
834
835  /** Get the total number of builds for a project*/
836  function GetTotalNumberOfBuilds()
837    {
838    if(!$this->Id)
839      {
840      echo "Project GetTotalNumberOfBuilds(): Id not set";
841      return false;
842      }
843
844    $project = pdo_query("SELECT count(*) FROM build WHERE projectid=".qnum($this->Id));
845
846    if(!$project)
847      {
848      add_last_sql_error("Project GetTotalNumberOfBuilds",$this->Id);
849      return false;
850      }
851    $project_array = pdo_fetch_array($project);
852    return $project_array[0];
853    }
854
855  /** Get the number of builds given a date range */
856  function GetNumberOfBuilds($startUTCdate,$endUTCdate)
857    {
858    if(!$this->Id)
859      {
860      echo "Project GetNumberOfBuilds(): Id not set";
861      return false;
862      }
863
864    $project = pdo_query("SELECT count(build.id) FROM build WHERE projectid=".qnum($this->Id).
865                         " AND build.starttime>'$startUTCdate'
866                           AND build.starttime<='$endUTCdate'");
867
868    if(!$project)
869      {
870      add_last_sql_error("Project GetNumberOfBuilds",$this->Id);
871      return false;
872      }
873    $project_array = pdo_fetch_array($project);
874    return $project_array[0];
875    }
876
877  /** Get the number of builds given per day */
878  function GetBuildsDailyAverage($startUTCdate,$endUTCdate)
879    {
880    if(!$this->Id)
881      {
882      echo "Project GetNumberOfBuilds(): Id not set";
883      return false;
884      }
885    $nbuilds=$this->GetNumberOfBuilds($startUTCdate,$endUTCdate);
886    $project = pdo_query("SELECT starttime FROM build WHERE projectid=".qnum($this->Id).
887                           " AND build.starttime>'$startUTCdate'
888                             AND build.starttime<='$endUTCdate'
889                             ORDER BY starttime ASC
890                             LIMIT 1");
891    $first_build=pdo_fetch_array($project);
892    $first_build=$first_build['starttime'];
893    $nb_days=strtotime($endUTCdate)-strtotime($first_build);
894    $nb_days=intval($nb_days/86400)+1;
895    if(!$project)
896      {
897      return 0;
898      }
899
900    return $nbuilds/$nb_days;
901    }
902
903  /** Get the number of warning builds given a date range */
904  function GetNumberOfWarningBuilds($startUTCdate,$endUTCdate)
905    {
906    if(!$this->Id)
907      {
908      echo "Project GetNumberOfWarningBuilds(): Id not set";
909      return false;
910      }
911
912    $project = pdo_query("SELECT count(*) FROM build,build2group,buildgroup
913                          WHERE build.projectid=".qnum($this->Id).
914                          " AND build.starttime>'$startUTCdate'
915                           AND build.starttime<='$endUTCdate'
916                           AND build2group.buildid=build.id AND build2group.groupid=buildgroup.id
917                           AND buildgroup.includesubprojectotal=1
918                           AND build.buildwarnings>0");
919
920    if(!$project)
921      {
922      add_last_sql_error("Project GetNumberOfWarningBuilds",$this->Id);
923      return false;
924      }
925    $project_array = pdo_fetch_array($project);
926    $count = $project_array[0];
927    return $count;
928    }
929
930  /** Get the number of error builds given a date range */
931  function GetNumberOfErrorBuilds($startUTCdate,$endUTCdate)
932    {
933    if(!$this->Id)
934      {
935      echo "Project GetNumberOfErrorBuilds(): Id not set";
936      return false;
937      }
938
939    // build failures
940    $project = pdo_query("SELECT count(*) FROM build,build2group,buildgroup
941                          WHERE build.projectid=".qnum($this->Id).
942                          " AND build.starttime>'$startUTCdate'
943                           AND build.starttime<='$endUTCdate'
944                           AND build2group.buildid=build.id AND build2group.groupid=buildgroup.id
945                           AND buildgroup.includesubprojectotal=1
946                           AND build.builderrors>0");
947
948    if(!$project)
949      {
950      add_last_sql_error("Project GetNumberOfErrorBuilds",$this->Id);
951      return false;
952      }
953    $project_array = pdo_fetch_array($project);
954    $count = $project_array[0];
955    return $count;
956    }
957
958  /** Get the number of failing builds given a date range */
959  function GetNumberOfPassingBuilds($startUTCdate,$endUTCdate)
960    {
961    if(!$this->Id)
962      {
963      echo "Project GetNumberOfPassingBuilds(): Id not set";
964      return false;
965      }
966
967    $project = pdo_query("SELECT count(*) FROM build,build2group,buildgroup
968                          WHERE build.projectid=".qnum($this->Id).
969                          " AND build.starttime>'$startUTCdate'
970                           AND build.starttime<='$endUTCdate'
971                           AND build2group.buildid=build.id AND build2group.groupid=buildgroup.id
972                           AND buildgroup.includesubprojectotal=1
973                           AND build.builderrors=0
974                           AND build.buildwarnings=0
975                           ");
976
977    if(!$project)
978      {
979      add_last_sql_error("Project GetNumberOfPassingBuilds",$this->Id);
980      return false;
981      }
982    $project_array = pdo_fetch_array($project);
983    return $project_array[0];
984    }
985
986  /** Get the number of failing configure given a date range */
987  function GetNumberOfWarningConfigures($startUTCdate,$endUTCdate)
988    {
989    if(!$this->Id)
990      {
991      echo "Project GetNumberOfWarningConfigures(): Id not set";
992      return false;
993      }
994
995    $project = pdo_query("SELECT count(*) FROM build,configure,build2group,buildgroup
996                          WHERE  configure.buildid=build.id  AND build.projectid=".qnum($this->Id).
997                         " AND build.starttime>'$startUTCdate'
998                           AND build.starttime<='$endUTCdate'
999                           AND build2group.buildid=build.id AND build2group.groupid=buildgroup.id
1000                           AND buildgroup.includesubprojectotal=1
1001                           AND  configure.warnings>0
1002                           ");
1003    if(!$project)
1004      {
1005      add_last_sql_error("Project GetNumberOfWarningConfigures",$this->Id);
1006      return false;
1007      }
1008    $project_array = pdo_fetch_array($project);
1009    return $project_array[0];
1010    }
1011
1012  /** Get the number of failing configure given a date range */
1013  function GetNumberOfErrorConfigures($startUTCdate,$endUTCdate)
1014    {
1015    if(!$this->Id)
1016      {
1017      echo "Project GetNumberOfErrorConfigures(): Id not set";
1018      return false;
1019      }
1020
1021    $project = pdo_query("SELECT count(*) FROM build,configure,buildgroup,build2group
1022                          WHERE  configure.buildid=build.id  AND build.projectid=".qnum($this->Id).
1023                         " AND build.starttime>'$startUTCdate'
1024                           AND build.starttime<='$endUTCdate'
1025                           AND configure.status='1'
1026                          AND build2group.buildid=build.id AND build2group.groupid=buildgroup.id
1027                          AND buildgroup.includesubprojectotal=1");
1028    if(!$project)
1029      {
1030      add_last_sql_error("Project GetNumberOfErrorConfigures",$this->Id);
1031      return false;
1032      }
1033    $project_array = pdo_fetch_array($project);
1034    return $project_array[0];
1035    }
1036
1037  /** Get the number of failing configure given a date range */
1038  function GetNumberOfPassingConfigures($startUTCdate,$endUTCdate)
1039    {
1040    if(!$this->Id)
1041      {
1042      echo "Project GetNumberOfPassingConfigures(): Id not set";
1043      return false;
1044      }
1045
1046    $project = pdo_query("SELECT count(*) FROM configure,build,build2group,buildgroup WHERE build.projectid=".qnum($this->Id).
1047                         " AND build2group.buildid=build.id AND build2group.groupid=buildgroup.id
1048                           AND buildgroup.includesubprojectotal=1
1049                           AND configure.buildid=build.id AND build.starttime>'$startUTCdate'
1050                           AND build.starttime<='$endUTCdate' AND configure.status='0'");
1051    if(!$project)
1052      {
1053      add_last_sql_error("Project GetNumberOfPassingConfigures",$this->Id);
1054      return false;
1055      }
1056    $project_array = pdo_fetch_array($project);
1057    return $project_array[0];
1058    }
1059
1060  /** Get the number of tests given a date range */
1061  function GetNumberOfPassingTests($startUTCdate,$endUTCdate)
1062    {
1063    if(!$this->Id)
1064      {
1065      echo "Project GetNumberOfPassingTests(): Id not set";
1066      return false;
1067      }
1068
1069    $project = pdo_query("SELECT SUM(build.testpassed) FROM build,build2group,buildgroup WHERE build.projectid=".qnum($this->Id).
1070                         " AND build2group.buildid=build.id
1071                           AND build.testpassed>=0
1072                           AND build2group.groupid=buildgroup.id
1073                           AND buildgroup.includesubprojectotal=1
1074                           AND build.starttime>'$startUTCdate'
1075                           AND build.starttime<='$endUTCdate'");
1076    if(!$project)
1077      {
1078      add_last_sql_error("Project GetNumberOfPassingTests",$this->Id);
1079      return false;
1080      }
1081    $project_array = pdo_fetch_array($project);
1082    return $project_array[0];
1083    }
1084
1085  /** Get the number of tests given a date range */
1086  function GetNumberOfFailingTests($startUTCdate,$endUTCdate)
1087    {
1088    if(!$this->Id)
1089      {
1090      echo "Project GetNumberOfFailingTests(): Id not set";
1091      return false;
1092      }
1093
1094    $project = pdo_query("SELECT SUM(build.testfailed) FROM build,build2group,buildgroup WHERE build.projectid=".qnum($this->Id).
1095                         " AND build2group.buildid=build.id
1096                           AND build.testfailed>=0
1097                           AND build2group.groupid=buildgroup.id
1098                           AND buildgroup.includesubprojectotal=1
1099                           AND build.starttime>'$startUTCdate'
1100                           AND build.starttime<='$endUTCdate'");
1101    if(!$project)
1102      {
1103      add_last_sql_error("Project GetNumberOfFailingTests",$this->Id);
1104      return false;
1105      }
1106    $project_array = pdo_fetch_array($project);
1107    return $project_array[0];
1108    }
1109
1110  /** Get the number of tests given a date range */
1111  function GetNumberOfNotRunTests($startUTCdate,$endUTCdate)
1112    {
1113    if(!$this->Id)
1114      {
1115      echo "Project GetNumberOfNotRunTests(): Id not set";
1116      return false;
1117      }
1118
1119    $project = pdo_query("SELECT SUM(build.testnotrun) FROM build,build2group,buildgroup WHERE build.projectid=".qnum($this->Id).
1120                         " AND build2group.buildid=build.id
1121                           AND build.testnotrun>=0
1122                           AND build2group.groupid=buildgroup.id
1123                           AND buildgroup.includesubprojectotal=1
1124                           AND build.starttime>'$startUTCdate'
1125                           AND build.starttime<='$endUTCdate'");
1126    if(!$project)
1127      {
1128      add_last_sql_error("Project GetNumberOfNotRunTests",$this->Id);
1129      return false;
1130      }
1131    $project_array = pdo_fetch_array($project);
1132    return $project_array[0];
1133    }  // end GetNumberOfNotRunTests()
1134
1135  /** Get the labels ids for a given project */
1136  function GetLabels($days)
1137    {
1138    $todaytime = time();
1139    $todaytime -= 3600*24*$days;
1140    $today = date(FMT_DATETIMESTD,$todaytime);
1141
1142    include("cdash/config.php");
1143    $straighthjoin = "";
1144    if($CDASH_DB_TYPE != "pgsql")
1145      {
1146      $straighthjoin = 'STRAIGHT_JOIN';
1147      }
1148
1149    $labelids = array();
1150    $labels = pdo_query("(SELECT labelid AS id FROM label2build,build WHERE label2build.buildid=build.id AND build.projectid=".qnum($this->Id)." AND build.starttime>'$today')
1151                          UNION
1152                          (SELECT labelid AS id FROM label2test,build WHERE label2test.buildid=build.id
1153                                  AND build.projectid=".qnum($this->Id)." AND build.starttime>'$today')
1154                          UNION
1155                          (SELECT ".$straighthjoin." labelid AS id FROM build,label2coveragefile WHERE label2coveragefile.buildid=build.id
1156                                 AND build.projectid=".qnum($this->Id)." AND build.starttime>'$today')
1157                          UNION
1158                          (SELECT ".$straighthjoin." labelid AS id FROM build,buildfailure,label2buildfailure WHERE label2buildfailure.buildfailureid=buildfailure.id
1159                                 AND buildfailure.buildid=build.id AND build.projectid=".qnum($this->Id)." AND build.starttime>'$today')
1160                          UNION
1161                          (SELECT ".$straighthjoin." labelid AS id FROM build,dynamicanalysis,label2dynamicanalysis WHERE label2dynamicanalysis.dynamicanalysisid=dynamicanalysis.id
1162                                 AND dynamicanalysis.buildid=build.id AND build.projectid=".qnum($this->Id)." AND build.starttime>'$today')
1163                          ");
1164
1165    if(!$labels)
1166      {
1167      add_last_sql_error("Project GetLabels",$this->Id);
1168      return false;
1169      }
1170
1171    while($label_array = pdo_fetch_array($labels))
1172      {
1173      $labelids[] = $label_array['labelid'];
1174      }
1175
1176    return array_unique($labelids);
1177    } // end GetLabels()
1178
1179  /** Send an email to the administrator of the project */
1180  function SendEmailToAdmin($subject,$body)
1181    {
1182    if(!$this->Id)
1183      {
1184      echo "Project SendEmailToAdmin(): Id not set";
1185      return false;
1186      }
1187
1188    include('cdash/config.php');
1189
1190    // Check if we should send emails
1191    $project = pdo_query("SELECT emailadministrator,name FROM project WHERE id =".qnum($this->Id));
1192    if(!$project)
1193      {
1194      add_last_sql_error("Project SendEmailToAdmin",$this->Id);
1195      return false;
1196      }
1197    $project_array = pdo_fetch_array($project);
1198
1199    if($project_array['emailadministrator'] == 0)
1200      {
1201      return;
1202      }
1203
1204    // Find the site maintainers
1205    include_once('models/userproject.php');
1206    include_once('models/user.php');
1207    $UserProject = new UserProject();
1208    $UserProject->ProjectId = $this->Id;
1209
1210    $userids = $UserProject->GetUsers(2); // administrators
1211    $email = "";
1212    foreach($userids as $userid)
1213      {
1214      $User = new User;
1215      $User->Id = $userid;
1216      if($email != "")
1217        {
1218        $email .= ", ";
1219        }
1220      $email .= $User->GetEmail();
1221      }
1222
1223    if($email!="")
1224      {
1225      $projectname = $project_array['name'];
1226      $emailtitle = "CDash [".$projectname."] - Administration ";
1227      $emailbody = "Object: ".$subject."\n";
1228      $emailbody .= $body."\n";
1229      $serverName = $CDASH_SERVER_NAME;
1230      if(strlen($serverName) == 0)
1231        {
1232        $serverName = $_SERVER['SERVER_NAME'];
1233        }
1234      $emailbody .= "\n-CDash on ".$serverName."\n";
1235
1236      if(cdashmail("$email", $emailtitle, $emailbody,
1237       "From: CDash <".$CDASH_EMAIL_FROM.">\nReply-To: ".$CDASH_EMAIL_REPLY."\nContent-type: text/plain; charset=utf-8\nX-Mailer: PHP/" . phpversion()."\nMIME-Version: 1.0" ))
1238        {
1239        add_log("email sent to: ".$email,"Project::SendEmailToAdmin");
1240        return;
1241        }
1242      else
1243        {
1244        add_log("cannot send email to: ".$email,"Project::SendEmailToAdmin",LOG_ERR,$this->Id);
1245        }
1246      } // end if email
1247    } // end SendEmailToAdmin
1248
1249
1250  function getDefaultCTestUpdateType()
1251    {
1252    switch ($this->CvsViewerType)
1253      {
1254      case 'cgit':
1255      case 'github':
1256      case 'gitorious':
1257      case 'gitweb':
1258      case 'redmine':
1259        return "git";
1260      break;
1261
1262      case 'websvn':
1263      case 'allura':
1264        return "svn";
1265      break;
1266
1267      case 'hgweb':
1268        return "mercurial";
1269      break;
1270
1271      default:
1272        return "cvs";
1273      break;
1274      }
1275    }
1276
1277
1278  function getDefaultJobTemplateScript()
1279    {
1280    $ctest_script  = '# From this line down, this script may be customized'."\n";
1281    $ctest_script .= '# on the Clients tab of the CDash createProject page.'."\n";
1282    $ctest_script .= '#'."\n";
1283    $ctest_script .= 'if(JOB_MODULE)'."\n";
1284    $ctest_script .= '  set(SOURCE_NAME ${JOB_MODULE})'."\n";
1285    $ctest_script .= '  if(JOB_TAG)'."\n";
1286    $ctest_script .= '    set(SOURCE_NAME ${SOURCE_NAME}-${JOB_TAG})'."\n";
1287    $ctest_script .= '  endif()'."\n";
1288    $ctest_script .= 'else()'."\n";
1289    $ctest_script .= '  set(SOURCE_NAME ${PROJECT_NAME})'."\n";
1290    $ctest_script .= '  if(JOB_BUILDNAME_SUFFIX)'."\n";
1291    $ctest_script .= '    set(SOURCE_NAME ${SOURCE_NAME}-${JOB_BUILDNAME_SUFFIX})'."\n";
1292    $ctest_script .= '  endif()'."\n";
1293    $ctest_script .= 'endif()'."\n";
1294    $ctest_script .= "\n";
1295    $ctest_script .= 'set(CTEST_SOURCE_NAME ${SOURCE_NAME})'."\n";
1296    $ctest_script .= 'set(CTEST_BINARY_NAME ${SOURCE_NAME}-bin)'."\n";
1297    $ctest_script .= 'set(CTEST_DASHBOARD_ROOT "${CLIENT_BASE_DIRECTORY}")'."\n";
1298    $ctest_script .= 'set(CTEST_SOURCE_DIRECTORY "${CTEST_DASHBOARD_ROOT}/${CTEST_SOURCE_NAME}")'."\n";
1299    $ctest_script .= 'set(CTEST_BINARY_DIRECTORY "${CTEST_DASHBOARD_ROOT}/${CTEST_BINARY_NAME}")'."\n";
1300    $ctest_script .= 'set(CTEST_CMAKE_GENERATOR "${JOB_CMAKE_GENERATOR}")'."\n";
1301    $ctest_script .= 'set(CTEST_BUILD_CONFIGURATION "${JOB_BUILD_CONFIGURATION}")'."\n";
1302    $ctest_script .= "\n";
1303
1304    // Construct the buildname
1305    $ctest_script .= 'set(CTEST_SITE "${CLIENT_SITE}")'."\n";
1306    $ctest_script .= 'set(CTEST_BUILD_NAME "${JOB_OS_NAME}-${JOB_OS_VERSION}-${JOB_OS_BITS}-${JOB_COMPILER_NAME}-${JOB_COMPILER_VERSION}")'."\n";
1307    $ctest_script .= 'if(JOB_BUILDNAME_SUFFIX)'."\n";
1308    $ctest_script .= '  set(CTEST_BUILD_NAME ${CTEST_BUILD_NAME}-${JOB_BUILDNAME_SUFFIX})'."\n";
1309    $ctest_script .= 'endif()'."\n";
1310    $ctest_script .= "\n";
1311
1312    // Set the checkout command
1313    $repo_type = $this->getDefaultCTestUpdateType();
1314
1315    if ($repo_type == 'cvs')
1316    {
1317      $ctest_script .= 'if(NOT EXISTS "${CTEST_SOURCE_DIRECTORY}")'."\n";
1318      $ctest_script .= '  set(CTEST_CHECKOUT_COMMAND "cvs -d ${JOB_REPOSITORY} checkout ")'."\n";
1319      $ctest_script .= '  if(JOB_TAG)'."\n";
1320      $ctest_script .= '    set(CTEST_CHECKOUT_COMMAND "${CTEST_CHECKOUT_COMMAND} -r ${JOB_TAG}")'."\n";
1321      $ctest_script .= '  endif()'."\n";
1322      $ctest_script .= '  set(CTEST_CHECKOUT_COMMAND "${CTEST_CHECKOUT_COMMAND} -d ${SOURCE_NAME}")'."\n";
1323      $ctest_script .= '  set(CTEST_CHECKOUT_COMMAND "${CTEST_CHECKOUT_COMMAND} ${JOB_MODULE}")'."\n";
1324      $ctest_script .= 'endif()'."\n";
1325      $ctest_script .= 'set(CTEST_UPDATE_COMMAND "cvs")'."\n";
1326    }
1327
1328    if ($repo_type == 'git')
1329    {
1330      $ctest_script .= 'if(NOT EXISTS "${CTEST_SOURCE_DIRECTORY}")'."\n";
1331      $ctest_script .= '  set(CTEST_CHECKOUT_COMMAND "git clone ${JOB_REPOSITORY} ${SOURCE_NAME}")'."\n";
1332      $ctest_script .= 'endif()'."\n";
1333      $ctest_script .= 'set(CTEST_UPDATE_COMMAND "git")'."\n";
1334    }
1335
1336    if ($repo_type == 'svn')
1337    {
1338      $ctest_script .= 'if(NOT EXISTS "${CTEST_SOURCE_DIRECTORY}")'."\n";
1339      $ctest_script .= '  set(CTEST_CHECKOUT_COMMAND "svn co ${JOB_REPOSITORY} ${SOURCE_NAME}")'."\n";
1340      $ctest_script .= 'endif()'."\n";
1341      $ctest_script .= 'set(CTEST_UPDATE_COMMAND "svn")'."\n";
1342    }
1343
1344    $ctest_script .= "\n";
1345
1346    // Write the initial CMakeCache.txt
1347    //
1348    $ctest_script .= 'file(WRITE "${CTEST_BINARY_DIRECTORY}/CMakeCache.txt" "${JOB_INITIAL_CACHE}")'."\n";
1349    $ctest_script .= "\n";
1350
1351    $ctest_script .= 'ctest_start(${JOB_BUILDTYPE})'."\n";
1352    $ctest_script .= 'ctest_update(SOURCE ${CTEST_SOURCE_DIRECTORY})'."\n";
1353    $ctest_script .= 'ctest_configure(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res)'."\n";
1354    $ctest_script .= 'ctest_build(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res)'."\n";
1355    $ctest_script .= 'ctest_test(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res)'."\n";
1356    $ctest_script .= '# The following lines are used to associate a build id with this job.'."\n";
1357    $ctest_script .= 'set(CTEST_DROP_SITE ${JOB_DROP_SITE})'."\n";
1358    $ctest_script .= 'set(CTEST_DROP_LOCATION ${JOB_DROP_LOCATION})'."\n";
1359    $ctest_script .= 'ctest_submit(RETURN_VALUE res)'."\n";
1360    $ctest_script .= "\n";
1361    $ctest_script .= 'message("DONE")'."\n";
1362
1363    return $ctest_script;
1364    }
1365
1366  /** Returns the total size of all uploaded files for this project */
1367  function GetUploadsTotalSize()
1368    {
1369    if(!$this->Id)
1370      {
1371      add_log('Id not set', 'Project::GetUploadsTotalSize', LOG_ERR);
1372      return false;
1373      }
1374    $totalSizeQuery = pdo_query("SELECT DISTINCT uploadfile.id, uploadfile.filesize AS size
1375                                 FROM build, build2uploadfile, uploadfile
1376                                 WHERE build.projectid=".qnum($this->Id)." AND
1377                                 build.id=build2uploadfile.buildid AND
1378                                 build2uploadfile.fileid=uploadfile.id");
1379    if(!$totalSizeQuery)
1380      {
1381      add_last_sql_error("Project::GetUploadsTotalSize", $this->Id);
1382      return false;
1383      }
1384
1385    $totalSize = 0;
1386    while($result = pdo_fetch_array($totalSizeQuery))
1387      {
1388      $totalSize += $result['size'];
1389      }
1390    return $totalSize;
1391    }
1392
1393  /**
1394   * Return a list of files or urls, each of which has the following key/value pairs:
1395   *  id       - id of the file in the uploadfile table
1396   *  filename - name of the file
1397   *  filesize - size in bytes of the file
1398   *  sha1sum  - sha-1 checksum of the file
1399   *  isurl    - True if filename is a URL
1400   * The files will be returned in order, with the newest first
1401   */
1402  function GetUploadedFilesOrUrls()
1403    {
1404    if(!$this->Id)
1405      {
1406      add_log('Id not set', 'Project::GetUploadedFilesOrUrls', LOG_ERR);
1407      return false;
1408      }
1409    $query = pdo_query("SELECT uploadfile.id, uploadfile.filename, uploadfile.filesize, uploadfile.sha1sum, uploadfile.isurl
1410                        FROM uploadfile, build2uploadfile, build
1411                        WHERE build.projectid=".qnum($this->Id)." AND
1412                        build.id=build2uploadfile.buildid AND
1413                        build2uploadfile.fileid=uploadfile.id ORDER BY build.starttime DESC");
1414    if(!$query)
1415      {
1416      add_last_sql_error("Project::GetUploadedFilesOrUrls", $this->Id);
1417      return false;
1418      }
1419
1420    $files = array();
1421    while($result = pdo_fetch_array($query))
1422      {
1423      $files[] = array('id'=>$result['id'],
1424                       'filename'=>$result['filename'],
1425                       'filesize'=>$result['filesize'],
1426                       'sha1sum'=>$result['sha1sum'],
1427                       'isurl'=>$result['isurl']);
1428      }
1429    return $files;
1430    }
1431
1432  /**
1433   * Checks whether this project has exceeded its upload size quota.  If so,
1434   * Removes the files (starting with the oldest builds) until the total upload size
1435   * is <= the upload quota.
1436   */
1437  function CullUploadedFiles()
1438    {
1439    if(!$this->Id)
1440      {
1441      add_log('Id not set', 'Project::CullUploadedFiles', LOG_ERR);
1442      return false;
1443      }
1444    $totalUploadSize = $this->GetUploadsTotalSize();
1445
1446    if($totalUploadSize > $this->UploadQuota)
1447      {
1448      require_once('cdash/common.php');
1449      add_log('Upload quota exceeded, removing old files', 'Project::CullUploadedFiles',
1450              LOG_INFO, $this->Id);
1451
1452      $query = pdo_query("SELECT DISTINCT build.id AS id
1453                               FROM build, build2uploadfile, uploadfile
1454                               WHERE build.projectid=".qnum($this->Id)." AND
1455                               build.id=build2uploadfile.buildid AND
1456                               build2uploadfile.fileid=uploadfile.id
1457                               ORDER BY build.starttime ASC");
1458
1459      while($builds_array = pdo_fetch_array($query))
1460        {
1461        // Delete the uploaded files
1462        $fileids = '(';
1463        $build2uploadfiles = pdo_query("SELECT fileid FROM build2uploadfile
1464                                 WHERE buildid = ".qnum($builds_array['id']));
1465        while($build2uploadfile_array = pdo_fetch_array($build2uploadfiles))
1466          {
1467          $fileid = $build2uploadfile_array['fileid'];
1468          if($fileids != '(')
1469            {
1470            $fileids .= ',';
1471            }
1472          $fileids .= $fileid;
1473          $totalUploadSize -= unlink_uploaded_file($fileid);
1474          add_log("Removed file $fileid", 'Project::CullUploadedFiles', LOG_INFO, $this->Id);
1475          }
1476
1477        $fileids .= ')';
1478        if(strlen($fileids)>2)
1479          {
1480          pdo_query("DELETE FROM uploadfile WHERE id IN ".$fileids);
1481          pdo_query("DELETE FROM build2uploadfile WHERE fileid IN ".$fileids);
1482          }
1483
1484        // Stop if we get below the quota
1485        if($totalUploadSize <= $this->UploadQuota)
1486          {
1487          break;
1488          }
1489        }
1490      }
1491    }
1492}  // end class Project
1493
1494?>
1495