[Fusionforge-commits] r13725 - in trunk/src/plugins/scmhook: common library/scmsvn library/scmsvn/cronjobs library/scmsvn/hooks library/scmsvn/hooks/checklog library/scmsvn/hooks/checkmimetype library/scmsvn/hooks/commitemail library/scmsvn/skel/post-commit library/scmsvn/skel/pre-commit

Franck VILLAUME nerville at fusionforge.org
Fri Jul 8 15:30:48 CEST 2011


Author: nerville
Date: 2011-07-08 15:30:48 +0200 (Fri, 08 Jul 2011)
New Revision: 13725

Added:
   trunk/src/plugins/scmhook/common/scmhook.class.php
   trunk/src/plugins/scmhook/library/scmsvn/checkLog.class.php
   trunk/src/plugins/scmhook/library/scmsvn/checkMimetype.class.php
   trunk/src/plugins/scmhook/library/scmsvn/commitEmail.class.php
   trunk/src/plugins/scmhook/library/scmsvn/hooks/checklog/
   trunk/src/plugins/scmhook/library/scmsvn/hooks/checklog/check-log.sh
   trunk/src/plugins/scmhook/library/scmsvn/hooks/checkmimetype/
   trunk/src/plugins/scmhook/library/scmsvn/hooks/checkmimetype/check-mime-type.pl
   trunk/src/plugins/scmhook/library/scmsvn/hooks/commitemail/
   trunk/src/plugins/scmhook/library/scmsvn/hooks/commitemail/commit-email.php
   trunk/src/plugins/scmhook/library/scmsvn/hooks/commitemail/commit-email.pl
   trunk/src/plugins/scmhook/library/scmsvn/skel/post-commit/head
   trunk/src/plugins/scmhook/library/scmsvn/skel/pre-commit/head
Removed:
   trunk/src/plugins/scmhook/library/scmsvn/hooks/post-commit/
   trunk/src/plugins/scmhook/library/scmsvn/hooks/pre-commit/
   trunk/src/plugins/scmhook/library/scmsvn/skel/post-commit/post-commit.head
   trunk/src/plugins/scmhook/library/scmsvn/skel/pre-commit/pre-commit.check-log.sh
   trunk/src/plugins/scmhook/library/scmsvn/skel/pre-commit/pre-commit.check-mime-type.pl
   trunk/src/plugins/scmhook/library/scmsvn/skel/pre-commit/pre-commit.head
Modified:
   trunk/src/plugins/scmhook/common/scmhookPlugin.class.php
   trunk/src/plugins/scmhook/library/scmsvn/cronjobs/updateScmRepo.php
Log:
extend scmhook model. better handling for hooks, more OO. Add commitemail post-commit hook

Added: trunk/src/plugins/scmhook/common/scmhook.class.php
===================================================================
--- trunk/src/plugins/scmhook/common/scmhook.class.php	                        (rev 0)
+++ trunk/src/plugins/scmhook/common/scmhook.class.php	2011-07-08 13:30:48 UTC (rev 13725)
@@ -0,0 +1,69 @@
+<?php
+/**
+ * scmhook Class
+ * Copyright 2011, Franck Villaume - Capgemini
+ *
+ * This file is part of FusionForge. FusionForge is free software;
+ * you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the Licence, or (at your option)
+ * any later version.
+ *
+ * FusionForge is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with FusionForge; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+class scmhook {
+	var $name;
+	var $description;
+	var $classname;
+	var $command;
+	var $hooktype;
+	var $label;
+	var $unixname;
+	var $needcopy;
+	var $files = array();
+
+	function getHookCmd() {
+		return $this->command;
+	}
+
+	function getClassname() {
+		return $this->classname;
+	}
+
+	function getName() {
+		return $this->name;
+	}
+
+	function getDescription() {
+		return $this->description;
+	}
+
+	function getHookType() {
+		return $this->hooktype;
+	}
+
+	function getLabel() {
+		return $this->label;
+	}
+
+	function getUnixname() {
+		return $this->unixname;
+	}
+
+	function needCopy() {
+		return $this->needcopy;
+	}
+
+	function getFiles() {
+		return $this->files;
+	}
+}
+?>

Modified: trunk/src/plugins/scmhook/common/scmhookPlugin.class.php
===================================================================
--- trunk/src/plugins/scmhook/common/scmhookPlugin.class.php	2011-07-08 11:14:41 UTC (rev 13724)
+++ trunk/src/plugins/scmhook/common/scmhookPlugin.class.php	2011-07-08 13:30:48 UTC (rev 13725)
@@ -24,14 +24,17 @@
 		$this->Plugin() ;
 		$this->name = "scmhook" ;
 		$this->text = "Scmhook" ; // To show in the tabs, use...
-		$this->hooks[] = "groupmenu" ;	// To put into the project tabs
-		$this->hooks[] = "groupisactivecheckbox" ; // The "use ..." checkbox in editgroupinfo
-		$this->hooks[] = "groupisactivecheckboxpost" ; //
-		$this->hooks[] = "scm_admin_page";
-		$this->hooks[] = "scm_admin_update";
+		$this->_addHook('groupmenu');	// To put into the project tabs
+		$this->_addHook('groupisactivecheckbox'); // The "use ..." checkbox in editgroupinfo
+		$this->_addHook('groupisactivecheckboxpost'); //
+		$this->_addHook('scm_admin_page');
+		$this->_addHook('scm_admin_update');
+		$this->_addHook('artifact_extra_detail');
+		$this->_addHook('task_extra_detail');
 	}
 
 	function CallHook($hookname, &$params) {
+		$returned = true;
 		switch ($hookname) {
 			case "scm_admin_page": {
 				$group_id = $params['group_id'];
@@ -45,7 +48,17 @@
 				$this->update($params);
 				break;
 			}
+			case "artifact_extra_detail": {
+				var_dump($params);
+				$group_id = $params['group_id'];
+				$group = &group_get_object($group_id);
+				if ($group->usesPlugin($this->name)) {
+					$this->displayArtifactExtraDetail();
+				}
+				break;
+			}
 		}
+		return true;
 	}
 
 	function exists($group_id) {
@@ -82,16 +95,10 @@
 	function update($params) {
 		$group_id = $params['group_id'];
 		$hooksString = '';
-		$updatedb = 0;
 		foreach($params as $key => $value) {
 			if ($key == strstr($key, 'scm')) {
 				$hookname = preg_replace('/scm[a-z][a-z][a-z]_/','',$key);
 				if ($key != $hookname) {	//handle the case of scm_enable_anonymous
-					$updatedb = 1;
-					$extensions = $this->getAllowedExtension();
-					foreach($extensions as $extension) {
-						$hookname = preg_replace('/_'.$extension.'$/', '.'.$extension, $hookname);
-					}
 					if (strlen($hooksString)) {
 						$hooksString .= '|'.$hookname;
 					} else {
@@ -100,70 +107,97 @@
 				}
 			}
 		}
-		if ($updatedb) {
-			$res = db_query_params('UPDATE plugin_scmhook set hooks = $1, need_update = 1 where id_group = $2',
-						array($hooksString, $group_id));
+		$res = db_query_params('UPDATE plugin_scmhook set hooks = $1, need_update = 1 where id_group = $2',
+					array($hooksString, $group_id));
 
-			if (!$res)
-				return false;
+		if (!$res)
+			return false;
 
-		}
 		return true;
 	}
 
 	function displayScmHook($group_id) {
+		global $HTML;
+		use_javascript('/js/sortable.js');
 		$hooksAvailable = $this->getAvailableHooks($group_id);
 		$statusDeploy = $this->getStatusDeploy($group_id);
-		if (count($hooksAvailable['pre-commit']) || count($hooksAvailable['post-commit'])) {
-			$hooksEnabled = $this->getEnabledHooks($group_id);
+		$hooksEnabled = $this->getEnabledHooks($group_id);
+		if (count($hooksAvailable)) {
 			echo '<div id="scmhook">';
 			if ($statusDeploy)
 				echo '<p class="warning">'._('Hooks management update process waiting ...').'</p>';
 
 			echo '<h3>'._('Enable Repository Hooks').'</h3>';
-			if (count($hooksAvailable['pre-commit'])) {
-				echo '<table>';
-				echo '<thead><tr><th>'._('pre-commit Hooks').'</th></tr></thead>';
-				echo '<tbody>';
-				for ($i = 0; $i < count($hooksAvailable['pre-commit']); $i++) {
-					$labelHook = preg_replace('/scm[a-z][a-z][a-z]_pre-commit_/','',$hooksAvailable['pre-commit'][$i]);
+			$hooksPreCommit = array();
+			$hooksPostCommit = array();
+			foreach ($hooksAvailable as $hook) {
+				switch ($hook->getHookType()) {
+					case "pre-commit": {
+						$hooksPreCommit[] = $hook;
+						break;
+					}
+					case "post-commit": {
+						$hooksPostCommit[] = $hook;
+						break;
+					}
+					default: {
+						echo 'ici';
+						//byebye hook.... we do not validate you...
+						break;
+					}
+				}
+			}
+			if (count($hooksPreCommit)) {
+				echo '<h4>'._('pre-commit Hooks').'</h4>';
+				$tabletop = array('', _('Hook Name'), _('Description'));
+				$classth = array('unsortable', '', '');
+				echo $HTML->listTableTop($tabletop, false, 'sortable_scmhook_precommit', 'sortable', $classth);
+				foreach ($hooksPreCommit as $hookPreCommit) {
 					echo '<tr><td>';
-					echo '<input name="'.$hooksAvailable['pre-commit'][$i].'" type="checkbox"';
-
-					if (in_array($labelHook, $hooksEnabled))
+					echo '<input type="checkbox" ';
+					echo 'name="'.$hookPreCommit->getLabel().'_'.$hookPreCommit->getClassname().'" ';
+					if (in_array($hookPreCommit->getClassname(), $hooksEnabled))
 						echo ' checked="checked"';
 
 					if ($statusDeploy)
 						echo ' disabled="disabled"';
 
-					echo '/>';
-					echo '<label>'.$labelHook.'</label>';
+					echo ' />';
+					echo '</td><td>';
+					echo $hookPreCommit->getName();
+					echo '</td><td>';
+					echo $hookPreCommit->getDescription();
 					echo '</td></tr>';
 				}
-				echo '</tbody></table>';
+				echo $HTML->listTableBottom();
 			}
-			if (count($hooksAvailable['post-commit'])) {
-				echo '<table>';
-				echo '<thead><tr><th>'._('post-commit Hooks').'</th></tr></thead>';
-				echo '<tbody>';
-				for ($i = 0; $i < count($hooksAvailable['post-commit']); $i++) {
-					$labelHook = preg_replace('/scm[a-z][a-z][a-z]_post-commit_/','',$hooksAvailable['post-commit'][$i]);
+			if (count($hooksPostCommit)) {
+				echo '<h4>'._('post-commit Hooks').'</h4>';
+				$tabletop = array('', _('Hook Name'), _('Description'));
+				$classth = array('unsortable', '', '');
+				echo $HTML->listTableTop($tabletop, false, 'sortable_scmhook_postcommit', 'sortable', $classth);
+				foreach ($hooksPostCommit as $hookPostCommit) {
 					echo '<tr><td>';
-					echo '<input name="'.$hooksAvailable['post-commit'][$i].'" type="checkbox"';
-
-					if (in_array($labelHook, $hooksEnabled))
+					echo '<input type="checkbox" ';
+					echo 'name="'.$hookPostCommit->getLabel().'_'.$hookPostCommit->getClassname().'" ';
+					if (in_array($hookPostCommit->getClassname(), $hooksEnabled))
 						echo ' checked="checked"';
 
 					if ($statusDeploy)
 						echo ' disabled="disabled"';
 
-					echo '/>';
-					echo '<label>'.$labelHook.'</label>';
+					echo ' />';
+					echo '</td><td>';
+					echo $hookPostCommit->getName();
+					echo '</td><td>';
+					echo $hookPostCommit->getDescription();
 					echo '</td></tr>';
 				}
-				echo '</tbody></table>';
+				echo $HTML->listTableBottom();
 			}
 			echo '</div>';
+		} else {
+			echo '<p class="information">'._('No hooks available').'</p>';
 		}
 	}
 
@@ -200,48 +234,26 @@
 		return array();
 	}
 
-	function isHookEnabled($group_id, $hookname) {
-		$res = db_query_params('SELECT hooks FROM plugin_scmhook
-					WHERE id_group = $1
-					AND hooks like $2',
-					array($group_id, '%'.$hookname.'%'));
-
-		if (!$res)
-			return false;
-
-		if (db_numrows($res) != 1)
-			return false;
-
-		return true;
-	}
-
 	function getListLibraryScm() {
 		return array_values(array_diff(scandir(dirname(__FILE__).'/../library/'), Array('.', '..', '.svn')));
 	}
 
 	function getListLibraryHook($scm) {
-		$listHooksPrecommit = array_values(array_diff(scandir(dirname(__FILE__).'/../library/'.$scm.'/hooks/pre-commit'), Array('.', '..', '.svn')));
-		$listHooksPostcommit = array_values(array_diff(scandir(dirname(__FILE__).'/../library/'.$scm.'/hooks/post-commit'), Array('.', '..', '.svn')));
-		$listPrecommit = array_values(array_diff(scandir(dirname(__FILE__).'/../library/'.$scm.'/skel/pre-commit'), Array('.', '..', '.svn', 'pre-commit.head')));
-		$listPostcommit = array_values(array_diff(scandir(dirname(__FILE__).'/../library/'.$scm.'/skel/post-commit'), Array('.', '..', '.svn', 'post-commit.head')));
+		$listHooks = array_values(array_diff(scandir(dirname(__FILE__).'/../library/'.$scm), array('.', '..', '.svn', 'skel', 'hooks', 'depends', 'cronjobs')));
 		$validHooks = array();
-		$validHooks['pre-commit'] = array();
-		foreach($listHooksPrecommit as $hook) {
-			if (in_array('pre-commit.'.$hook, $listPrecommit)) {
-				$validHooks['pre-commit'][] = $scm.'_pre-commit_'.$hook;
+		foreach ($listHooks as $hook) {
+			if (!stristr($hook,'~')) {
+				include dirname(__FILE__).'/../library/'.$scm.'/'.$hook;
+				$hookClassName = preg_replace('/.class.php/','', $hook);
+				$hookObject = new $hookClassName;
+				$validHooks[] = $hookObject;
 			}
 		}
-		$validHooks['post-commit'] = array();
-		foreach($listHooksPostcommit as $hook) {
-			if (in_array('post-commit.'.$hook, $listPostcommit)) {
-				$validHooks['post-commit'][] = $scm.'_post-commit_'.$hook;
-			}
-		}
 		return $validHooks;
 	}
 
-	function getAllowedExtension() {
-		return array("sh", "pl", "php");
+	function displayArtifactExtraDetail() {
+		echo 'TOTO';
 	}
 
 	/**
@@ -251,7 +263,7 @@
 		// this code actually activates/deactivates the plugin after the form was submitted in the project edit public info page
 		$group = group_get_object($params['group']);
 		$flag = strtolower('use_'.$this->name);
-		if ( getIntFromRequest($flag) == 1 ) {
+		if (getIntFromRequest($flag) == 1) {
 			$group->setPluginUse($this->name);
 			$this->add($group->getID());
 		} else {

Added: trunk/src/plugins/scmhook/library/scmsvn/checkLog.class.php
===================================================================
--- trunk/src/plugins/scmhook/library/scmsvn/checkLog.class.php	                        (rev 0)
+++ trunk/src/plugins/scmhook/library/scmsvn/checkLog.class.php	2011-07-08 13:30:48 UTC (rev 13725)
@@ -0,0 +1,38 @@
+<?php
+/**
+ * scmhook checkLog Plugin Class
+ * Copyright 2011, Franck Villaume - Capgemini
+ *
+ * This file is part of FusionForge. FusionForge is free software;
+ * you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the Licence, or (at your option)
+ * any later version.
+ *
+ * FusionForge is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with FusionForge; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+global $gfplugins;
+require_once $gfplugins.'scmhook/common/scmhook.class.php';
+
+class checkLog extends scmhook {
+	function checkLog() {
+		$this->name = "Check log";
+		$this->description = _('Commit message must not be empty.');
+		$this->classname = "checkLog";
+		$this->command = 'sh $SCRIPTPATH/check-log.sh "$1" "$2"';
+		$this->hooktype = "pre-commit";
+		$this->label = "scmsvn";
+		$this->unixname = "checklog";
+		$this->needcopy = 1;
+		$this->files = array(dirname(__FILE__).'/hooks/'.$this->unixname.'/check-log.sh');
+	}
+}
+?>

Added: trunk/src/plugins/scmhook/library/scmsvn/checkMimetype.class.php
===================================================================
--- trunk/src/plugins/scmhook/library/scmsvn/checkMimetype.class.php	                        (rev 0)
+++ trunk/src/plugins/scmhook/library/scmsvn/checkMimetype.class.php	2011-07-08 13:30:48 UTC (rev 13725)
@@ -0,0 +1,38 @@
+<?php
+/**
+ * scmhook checkMimetype Plugin Class
+ * Copyright 2011, Franck Villaume - Capgemini
+ *
+ * This file is part of FusionForge. FusionForge is free software;
+ * you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the Licence, or (at your option)
+ * any later version.
+ *
+ * FusionForge is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with FusionForge; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+global $gfplugins;
+require_once $gfplugins.'scmhook/common/scmhook.class.php';
+
+class checkMimetype extends scmhook {
+	function checkMimetype() {
+		$this->name = "Check Mimetype";
+		$this->description = _('Verify if commited files have svn:mimetype set up correctly.');
+		$this->classname = "checkMimetype";
+		$this->command = 'perl $SCRIPTPATH/check-mime-type.pl "$1" "$2"';
+		$this->hooktype = "pre-commit";
+		$this->label = "scmsvn";
+		$this->unixname = "checkmimetype";
+		$this->needcopy = 1;
+		$this->files = array(dirname(__FILE__).'/hooks/'.$this->unixname.'/check-mime-type.pl');
+	}
+}
+?>

Added: trunk/src/plugins/scmhook/library/scmsvn/commitEmail.class.php
===================================================================
--- trunk/src/plugins/scmhook/library/scmsvn/commitEmail.class.php	                        (rev 0)
+++ trunk/src/plugins/scmhook/library/scmsvn/commitEmail.class.php	2011-07-08 13:30:48 UTC (rev 13725)
@@ -0,0 +1,38 @@
+<?php
+/**
+ * scmhook commitEmail Plugin Class
+ * Copyright 2011, Franck Villaume - Capgemini
+ *
+ * This file is part of FusionForge. FusionForge is free software;
+ * you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the Licence, or (at your option)
+ * any later version.
+ *
+ * FusionForge is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with FusionForge; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+global $gfplugins;
+require_once $gfplugins.'scmhook/common/scmhook.class.php';
+
+class commitEmail extends scmhook {
+	function commitEmail() {
+		$this->name = "Commit Email";
+		$this->description = _('Commit is pushed to commit mailing-list of the project');
+		$this->classname = "commitEmail";
+		$this->hooktype = "post-commit";
+		$this->label = "scmsvn";
+		$this->unixname = "commitemail";
+		$this->needcopy = 0;
+		$this->command = '/usr/bin/php -d include_path='.ini_get('include_path').' '.forge_get_config('plugins_path').'/scmhook/library/'.
+				$this->label.'/hooks/'.$this->unixname.'/commit-email.php "$1" "$2" '.$GLOBALS['group']->getUnixName().'-commits@'.forge_get_config('lists_host');
+	}
+}
+?>

Modified: trunk/src/plugins/scmhook/library/scmsvn/cronjobs/updateScmRepo.php
===================================================================
--- trunk/src/plugins/scmhook/library/scmsvn/cronjobs/updateScmRepo.php	2011-07-08 11:14:41 UTC (rev 13724)
+++ trunk/src/plugins/scmhook/library/scmsvn/cronjobs/updateScmRepo.php	2011-07-08 13:30:48 UTC (rev 13725)
@@ -44,69 +44,121 @@
 	if (is_dir($svndir_root)) {
 		@unlink($svndir_root.'/hooks/pre-commit');
 		@unlink($svndir_root.'/hooks/post-commit');
-		foreach($hooksAvailable['pre-commit'] as $hookAvailable) {
-			@unlink($svndir_root.'/hooks/'.$hookAvailable);
+		$hooksPreCommit = array();
+		$hooksPostCommit = array();
+		foreach ($hooksAvailable as $hook) {
+			switch ($hook->getHookType()) {
+				case "pre-commit": {
+					$hooksPreCommit[] = $hook;
+					break;
+				}
+				case "post-commit": {
+					$hooksPostCommit[] = $hook;
+					break;
+				}
+				default: {
+					//byebye hook.... we do not validate you...
+					break;
+				}
+			}
 		}
-		foreach($hooksAvailable['post-commit'] as $hookAvailable) {
-			@unlink($svndir_root.'/hooks/'.$hookAvailable);
+
+		foreach($hooksPreCommit as $hookPreCommit) {
+			if ($hookPreCommit->needCopy()) {
+				foreach($hookPreCommit->getFiles() as $hookPreCommitFile) {
+					@unlink($svndir_root.'/hooks/'.basename($hookPreCommitFile));
+				}
+			}
 		}
 
+		foreach($hooksPostCommit as $hookPostCommit) {
+			if ($hookPostCommit->needCopy()) {
+				foreach($hookPostCommit->getFiles as $hookPostCommitFile) {
+					@unlink($svndir_root.'/hooks/'.basename($hookPostCommitFile));
+				}
+			}
+		}
+
 		$newHooks = explode('|', $hooksString);
-		foreach($newHooks as $newHook) {
-			if (stristr($newHook, 'pre-commit')) {
-				$filename = preg_replace('/pre-commit_/','',$newHook);
-				copy(dirname(__FILE__).'/../hooks/pre-commit/'.$filename, $svndir_root.'/hooks/'.$filename);
-				chmod($svndir_root.'/hooks/'.$filename, 0755);
+		if (count($newHooks)) {
+			$newHooksPreCommit = array();
+			$newHooksPostCommit = array();
+			foreach($newHooks as $newHook) {
+				foreach($hooksPreCommit as $hookPreCommit) {
+					if ($hookPreCommit->getClassname() == $newHook) {
+						$newHooksPreCommit[] = $hookPreCommit;
+					}
+				}
+				foreach($hooksPostCommit as $hookPostCommit) {
+					if ($hookPostCommit->getClassname() == $newHook) {
+						$newHooksPostCommit[] = $hookPostCommit;
+					}
+				}
 			}
-			if (stristr($newHook, 'post-commit')) {
-				$filename = preg_replace('/post-commit_/','',$newHook);
-				copy(dirname(__FILE__).'/../hooks/post-commit/'.$filename, $svndir_root.'/hooks/'.$filename);
-				chmod($svndir_root.'/hooks/'.$filename, 0755);
+		}
+
+		foreach($newHooksPreCommit as $newHookPreCommit) {
+			if ($newHookPreCommit->needCopy()) {
+				foreach ($newHookPreCommit->getFiles() as $file) {
+					copy($file, $svndir_root.'/hooks/'.basename($file));
+					chmod($svndir_root.'/hooks/'.basename($file), 0755);
+				}
 			}
 		}
-		// prepare the pre-commit
-		$file = fopen("/tmp/pre-commit-$unixname.tmp", "w");
-		fwrite($file, file_get_contents(dirname(__FILE__).'/../skel/pre-commit/pre-commit.head'));
-		$loopid = 0;
-		$string = '';
-		foreach($newHooks as $newHook) {
-			if (stristr($newHook, 'pre-commit.')) {
+
+
+		foreach($newHooksPostCommit as $newHookPostCommit) {
+			if ($newHookPostCommit->needCopy()) {
+				foreach ($newHookPostCommit->getFiles() as $file) {
+					copy($file, $svndir_root.'/hooks/'.basename($file));
+					chmod($svndir_root.'/hooks/'.basename($file), 0755);
+				}
+			}
+		}
+
+		if (count($newHooksPreCommit)) {
+			// prepare the pre-commit
+			$file = fopen("/tmp/pre-commit-$unixname.tmp", "w");
+			fwrite($file, file_get_contents(dirname(__FILE__).'/../skel/pre-commit/head'));
+			$loopid = 0;
+			$string = '';
+			foreach($newHooksPreCommit as $newHookPreCommit) {
 				if ($loopid) {
 					//insert && \ between commands
 					$string .= ' && ';
 				}
-				$string .= rtrim(file_get_contents(dirname(__FILE__).'/../skel/pre-commit/'.$newHook));
+				$string .= $newHookPreCommit->getHookCmd();
 				$loopid = 1;
 			}
+			$string .= "\n";
+			fwrite($file, $string);
+			fclose($file);
+			copy('/tmp/pre-commit-'.$unixname.'.tmp', $svndir_root.'/hooks/pre-commit');
+			chmod($svndir_root.'/hooks/pre-commit', 0755);
+			unlink('/tmp/pre-commit-'.$unixname.'.tmp');
 		}
-		$string .= "\n";
-		fwrite($file, $string);
-		fclose($file);
-		copy('/tmp/pre-commit-'.$unixname.'.tmp', $svndir_root.'/hooks/pre-commit');
-		chmod($svndir_root.'/hooks/pre-commit', 0755);
-		unlink('/tmp/pre-commit-'.$unixname.'.tmp');
 
-		// prepare the post-commit
-		$file = fopen("/tmp/post-commit-$unixname.tmp", "w");
-		fwrite($file, file_get_contents(dirname(__FILE__).'/../skel/post-commit/post-commit.head'));
-		$loopid = 0;
-		$string = '';
-		foreach($newHooks as $newHook) {
-			if (stristr($newHook, 'post-commit.')) {
+		if (count($newHooksPostCommit)) {
+			// prepare the post-commit
+			$file = fopen("/tmp/post-commit-$unixname.tmp", "w");
+			fwrite($file, file_get_contents(dirname(__FILE__).'/../skel/post-commit/head'));
+			$loopid = 0;
+			$string = '';
+			foreach($newHooksPostCommit as $newHookPostCommit) {
 				if ($loopid) {
 					//insert && \ between commands
 					$string .= ' && ';
 				}
-				$string .= rtrim(file_get_contents(dirname(__FILE__).'/../skel/post-commit/'.$newHook));
+				$string .= $newHookPostCommit->getHookCmd();
 				$loopid = 1;
 			}
+			$string .= "\n";
+			fwrite($file, $string);
+			fclose($file);
+			copy('/tmp/post-commit-'.$unixname.'.tmp', $svndir_root.'/hooks/post-commit');
+			chmod($svndir_root.'/hooks/post-commit', 0755);
+			unlink('/tmp/post-commit-'.$unixname.'.tmp');
 		}
-		$string .= "\n";
-		fwrite($file, $string);
-		fclose($file);
-		copy('/tmp/post-commit-'.$unixname.'.tmp', $svndir_root.'/hooks/post-commit');
-		chmod($svndir_root.'/hooks/post-commit', 0755);
-		unlink('/tmp/post-commit-'.$unixname.'.tmp');
 		return true;
 	}
 	return false;

Added: trunk/src/plugins/scmhook/library/scmsvn/hooks/checklog/check-log.sh
===================================================================
--- trunk/src/plugins/scmhook/library/scmsvn/hooks/checklog/check-log.sh	                        (rev 0)
+++ trunk/src/plugins/scmhook/library/scmsvn/hooks/checklog/check-log.sh	2011-07-08 13:30:48 UTC (rev 13725)
@@ -0,0 +1,88 @@
+#!/bin/sh
+
+# PRE-COMMIT HOOK
+#
+# The pre-commit hook is invoked before a Subversion txn is
+# committed.  Subversion runs this hook by invoking a program
+# (script, executable, binary, etc.) named 'pre-commit' (for which
+# this file is a template), with the following ordered arguments:
+#
+#   [1] REPOS-PATH   (the path to this repository)
+#   [2] TXN-NAME     (the name of the txn about to be committed)
+#
+#   [STDIN] LOCK-TOKENS ** the lock tokens are passed via STDIN.
+#
+#   If STDIN contains the line "LOCK-TOKENS:\n" (the "\n" denotes a
+#   single newline), the lines following it are the lock tokens for
+#   this commit.  The end of the list is marked by a line containing
+#   only a newline character.
+#
+#   Each lock token line consists of a URI-escaped path, followed
+#   by the separator character '|', followed by the lock token string,
+#   followed by a newline.
+#
+# The default working directory for the invocation is undefined, so
+# the program should set one explicitly if it cares.
+#
+# If the hook program exits with success, the txn is committed; but
+# if it exits with failure (non-zero), the txn is aborted, no commit
+# takes place, and STDERR is returned to the client.   The hook
+# program can use the 'svnlook' utility to help it examine the txn.
+#
+# On a Unix system, the normal procedure is to have 'pre-commit'
+# invoke other programs to do the real work, though it may do the
+# work itself too.
+#
+#   ***  NOTE: THE HOOK PROGRAM MUST NOT MODIFY THE TXN, EXCEPT  ***
+#   ***  FOR REVISION PROPERTIES (like svn:log or svn:author).   ***
+#
+#   This is why we recommend using the read-only 'svnlook' utility.
+#   In the future, Subversion may enforce the rule that pre-commit
+#   hooks should not modify the versioned data in txns, or else come
+#   up with a mechanism to make it safe to do so (by informing the
+#   committing client of the changes).  However, right now neither
+#   mechanism is implemented, so hook writers just have to be careful.
+#
+# Note that 'pre-commit' must be executable by the user(s) who will
+# invoke it (typically the user httpd runs as), and that user must
+# have filesystem-level permission to access the repository.
+#
+# On a Windows system, you should name the hook program
+# 'pre-commit.bat' or 'pre-commit.exe',
+# but the basic idea is the same.
+#
+# The hook program typically does not inherit the environment of
+# its parent process.  For example, a common problem is for the
+# PATH environment variable to not be set to its usual value, so
+# that subprograms fail to launch unless invoked via absolute path.
+# If you're having unexpected problems with a hook program, the
+# culprisage de log obligatoire !" may be unusual (or missing) environment variables.
+#
+# Here is an example hook script, for a Unix /bin/sh interpreter.
+# For more examples and pre-written hooks, see those in
+# the Subversion repository at
+# http://svn.collab.net/repos/svn/trunk/tools/hook-scripts/ and
+# http://svn.collab.net/repos/svn/trunk/contrib/hook-scripts/
+
+REPOS="$1"
+TXN="$2"
+SVNLOOK=/usr/bin/svnlook
+
+$SVNLOOK log -t "$TXN" "$REPOS" | grep "[a-zA-Z0-9]" > /dev/null
+RESULT=$?
+if [ $RESULT -eq "0" ]; then
+        exit 0
+else
+        echo -e "---------PRE COMMIT HOOK---------" 1>&2
+        echo -e "\nEvery commit must have a log.\n" 1>&2
+        echo -e "---------------------------------" 1>&2
+        exit 1
+fi
+
+
+# Check that the author of this commit has the rights to perform
+# the commit on the files and directories being modified.
+#commit-access-control.pl "$REPOS" "$TXN" commit-access-control.cfg || exit 1
+
+# All checks passed, so allow the commit.
+exit 0


Property changes on: trunk/src/plugins/scmhook/library/scmsvn/hooks/checklog/check-log.sh
___________________________________________________________________
Added: svn:executable
   + *
Added: svn:eol-style
   + native

Added: trunk/src/plugins/scmhook/library/scmsvn/hooks/checkmimetype/check-mime-type.pl
===================================================================
--- trunk/src/plugins/scmhook/library/scmsvn/hooks/checkmimetype/check-mime-type.pl	                        (rev 0)
+++ trunk/src/plugins/scmhook/library/scmsvn/hooks/checkmimetype/check-mime-type.pl	2011-07-08 13:30:48 UTC (rev 13725)
@@ -0,0 +1,241 @@
+#!/usr/bin/env perl
+
+# ====================================================================
+# commit-mime-type-check.pl: check that every added file has the
+# svn:mime-type property set and every added file with a mime-type
+# matching text/* also has svn:eol-style set. If any file fails this
+# test the user is sent a verbose error message suggesting solutions and
+# the commit is aborted.
+#
+# Usage: commit-mime-type-check.pl REPOS TXN-NAME
+# ====================================================================
+# Most of commit-mime-type-check.pl was taken from
+# commit-access-control.pl, Revision 9986, 2004-06-14 16:29:22 -0400.
+# ====================================================================
+# Copyright (c) 2000-2004 CollabNet.  All rights reserved.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution.  The terms
+# are also available at http://subversion.tigris.org/license.html.
+# If newer versions of this license are posted there, you may use a
+# newer version instead, at your option.
+#
+# This software consists of voluntary contributions made by many
+# individuals.  For exact contribution history, see the revision
+# history and logs, available at http://subversion.tigris.org/.
+# ====================================================================
+
+# Turn on warnings the best way depending on the Perl version.
+BEGIN {
+  if ( $] >= 5.006_000)
+    { require warnings; import warnings; }
+  else
+    { $^W = 1; }
+}
+
+use strict;
+use Carp;
+
+
+######################################################################
+# Configuration section.
+
+# Svnlook path.
+my $svnlook = "/usr/bin/svnlook";
+
+# Since the path to svnlook depends upon the local installation
+# preferences, check that the required program exists to insure that
+# the administrator has set up the script properly.
+{
+  my $ok = 1;
+  foreach my $program ($svnlook)
+    {
+      if (-e $program)
+        {
+          unless (-x $program)
+            {
+              warn "$0: required program `$program' is not executable, ",
+                   "edit $0.\n";
+              $ok = 0;
+            }
+        }
+      else
+        {
+          warn "$0: required program `$program' does not exist, edit $0.\n";
+          $ok = 0;
+        }
+    }
+  exit 1 unless $ok;
+}
+
+######################################################################
+# Initial setup/command-line handling.
+
+&usage unless @ARGV == 2;
+
+my $repos        = shift;
+my $txn          = shift;
+
+unless (-e $repos)
+  {
+    &usage("$0: repository directory `$repos' does not exist.");
+  }
+unless (-d $repos)
+  {
+    &usage("$0: repository directory `$repos' is not a directory.");
+  }
+
+# Define two constant subroutines to stand for read-only or read-write
+# access to the repository.
+sub ACCESS_READ_ONLY  () { 'read-only' }
+sub ACCESS_READ_WRITE () { 'read-write' }
+
+
+######################################################################
+# Harvest data using svnlook.
+
+# Change into /tmp so that svnlook diff can create its .svnlook
+# directory.
+my $tmp_dir = '/tmp';
+chdir($tmp_dir)
+  or die "$0: cannot chdir `$tmp_dir': $!\n";
+
+# Figure out what files have added using svnlook.
+my @files_added;
+foreach my $line (&read_from_process($svnlook, 'changed', $repos, '-t', $txn))
+  {
+		# Add only files that were added to @files_added
+    if ($line =~ /^A.  (.*[^\/])$/)
+      {
+        push(@files_added, $1);
+      }
+  }
+
+my @errors;
+foreach my $path ( @files_added )
+	{
+		my $mime_type;
+		my $eol_style;
+
+		# Parse the complete list of property values of the file $path to extract
+		# the mime-type and eol-style
+		foreach my $prop (&read_from_process($svnlook, 'proplist', $repos, '-t',
+		                  $txn, '--verbose', $path))
+			{
+				if ($prop =~ /^\s*svn:mime-type : (\S+)/)
+					{
+						$mime_type = $1;
+					}
+				elsif ($prop =~ /^\s*svn:eol-style : (\S+)/)
+					{
+						$eol_style = $1;
+					}
+			}
+
+		# Detect error conditions and add them to @errors
+		if (not $mime_type)
+			{
+				push @errors, "$path : svn:mime-type undefined";
+			}
+		elsif ($mime_type =~ /^text\// and not $eol_style)
+			{
+				push @errors, "$path : svn:eol-style undefined (svn:mime-type=$mime_type)";
+			}
+	}
+
+# If there are any errors list the problem files and give information
+# on how to avoid the problem. Hopefully people will set up auto-props
+# and will not see this verbose message more than once.
+if (@errors)
+  {
+    #warn "$0:\n\n",
+    warn "-------------------------PRE COMMIT HOOK-------------------------\n\nFiles in error state:\n\t",
+         join("\n\t", @errors), "\n\n",
+				 <<EOS;
+Explication:
+\EEvery file added into SVN must have svn:propriety set on:
+\t\tsvn:mime-type
+\tAll text files must also have svn:eol-style set on:
+\t\tsvn:eol-style
+-------------------------PRE COMMIT HOOK-------------------------
+EOS
+    exit 1;
+  }
+else
+  {
+    exit 0;
+  }
+
+sub usage
+{
+  warn "@_\n" if @_;
+  die "usage: $0 REPOS TXN-NAME\n";
+}
+
+sub safe_read_from_pipe
+{
+  unless (@_)
+    {
+      croak "$0: safe_read_from_pipe passed no arguments.\n";
+    }
+  print "Running @_\n";
+  my $pid = open(SAFE_READ, '-|');
+  unless (defined $pid)
+    {
+      die "$0: cannot fork: $!\n";
+    }
+  unless ($pid)
+    {
+      open(STDERR, ">&STDOUT")
+        or die "$0: cannot dup STDOUT: $!\n";
+      exec(@_)
+        or die "$0: cannot exec `@_': $!\n";
+    }
+  my @output;
+  while (<SAFE_READ>)
+    {
+      chomp;
+      push(@output, $_);
+    }
+  close(SAFE_READ);
+  my $result = $?;
+  my $exit   = $result >> 8;
+  my $signal = $result & 127;
+  my $cd     = $result & 128 ? "with core dump" : "";
+  if ($signal or $cd)
+    {
+      warn "$0: pipe from `@_' failed $cd: exit=$exit signal=$signal\n";
+    }
+  if (wantarray)
+    {
+      return ($result, @output);
+    }
+  else
+    {
+      return $result;
+    }
+}
+
+sub read_from_process
+  {
+  unless (@_)
+    {
+      croak "$0: read_from_process passed no arguments.\n";
+    }
+  my ($status, @output) = &safe_read_from_pipe(@_);
+  if ($status)
+    {
+      if (@output)
+        {
+          die "$0: `@_' failed with this output:\n", join("\n", @output), "\n";
+        }
+      else
+        {
+          die "$0: `@_' failed with no output.\n";
+        }
+    }
+  else
+    {
+      return @output;
+    }
+}

Added: trunk/src/plugins/scmhook/library/scmsvn/hooks/commitemail/commit-email.php
===================================================================
--- trunk/src/plugins/scmhook/library/scmsvn/hooks/commitemail/commit-email.php	                        (rev 0)
+++ trunk/src/plugins/scmhook/library/scmsvn/hooks/commitemail/commit-email.php	2011-07-08 13:30:48 UTC (rev 13725)
@@ -0,0 +1,50 @@
+#! /usr/bin/php
+<?php
+/**
+ * Copyright 2010, Fusionforge Team
+ * Copyright 2011, Franck Villaume - Capgemini
+ *
+ * This file is part of FusionForge. FusionForge is free software;
+ * you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the Licence, or (at your option)
+ * any later version.
+ *
+ * FusionForge is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with FusionForge; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+require_once dirname(__FILE__).'/../../../../../../common/include/env.inc.php';
+require_once $gfcommon.'include/pre.php';
+
+# Begin configuration
+$svnlook = '/usr/bin/svnlook';
+$commit_email_pl = dirname(__FILE__).'/commit-email.pl';
+# End configuration
+
+# Set sendmail path to next script from our configuration.
+putenv("SENDMAIL=".forge_get_config('sendmail_path'));
+
+if(!file_exists($svnlook) || !file_exists($commit_email_pl)) { die("Missing required executables."); }
+
+# Find who made the changes
+if($argc < 4) { die("Invalid arguments."); }
+
+$author = exec("$svnlook author \"$argv[1]\" -r $argv[2]");
+$res_db= db_query_params('SELECT email FROM users where user_name = lower($1) LIMIT 1',
+			array($author));
+if($res_db) {
+	$e = db_fetch_array($res_db);
+	if($e) {
+		passthru("$commit_email_pl --from $e[email] \"$argv[1]\" $argv[2] $argv[3]");
+		exit;
+	}
+}
+passthru("$commit_email_pl \"$argv[1]\" $argv[2] $argv[3]");
+?>

Added: trunk/src/plugins/scmhook/library/scmsvn/hooks/commitemail/commit-email.pl
===================================================================
--- trunk/src/plugins/scmhook/library/scmsvn/hooks/commitemail/commit-email.pl	                        (rev 0)
+++ trunk/src/plugins/scmhook/library/scmsvn/hooks/commitemail/commit-email.pl	2011-07-08 13:30:48 UTC (rev 13725)
@@ -0,0 +1,773 @@
+#!/usr/bin/env perl
+
+# ====================================================================
+# commit-email.pl: send a commit email for commit REVISION in
+# repository REPOS to some email addresses.
+#
+# For usage, see the usage subroutine or run the script with no
+# command line arguments.
+#
+# $HeadURL: http://svn.collab.net/repos/svn/branches/1.1.x/tools/hook-scripts/commit-email.pl.in $
+# $LastChangedDate: 2010-11-02 21:19:18 +0100 (mar. 02 nov. 2010) $
+# $LastChangedBy: vargenau $
+# $LastChangedRevision: 11339 $
+#    
+# ====================================================================
+# Copyright (c) 2000-2004 CollabNet.  All rights reserved.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution.  The terms
+# are also available at http://subversion.tigris.org/license-1.html.
+# If newer versions of this license are posted there, you may use a
+# newer version instead, at your option.
+#
+# This software consists of voluntary contributions made by many
+# individuals.  For exact contribution history, see the revision
+# history and logs, available at http://subversion.tigris.org/.
+# ====================================================================
+
+# Turn on warnings the best way depending on the Perl version.
+BEGIN {
+  if ( $] >= 5.006_000)
+    { require warnings; import warnings; }
+  else
+    { $^W = 1; }
+}
+
+use strict;
+use Carp;
+my ($sendmail, $smtp_server);
+
+######################################################################
+# Configuration section.
+
+# Sendmail path, or SMTP server address.
+# You should define exactly one of these two configuration variables,
+# leaving the other commented out, to select which method of sending
+# email should be used.
+$sendmail = $ENV{SENDMAIL} || "/usr/sbin/sendmail";
+#$smtp_server = "127.0.0.1";
+
+# Svnlook path.
+my $svnlook = "/usr/bin/svnlook";
+
+# By default, when a file is deleted from the repository, svnlook diff
+# prints the entire contents of the file.  If you want to save space
+# in the log and email messages by not printing the file, then set
+# $no_diff_deleted to 1.
+my $no_diff_deleted = 0;
+# By default, when a file is added to the repository, svnlook diff
+# prints the entire contents of the file.  If you want to save space
+# in the log and email messages by not printing the file, then set
+# $no_diff_added to 1.
+my $no_diff_added = 0;
+
+# End of Configuration section.
+######################################################################
+
+# Check that the required programs exist, and the email sending method
+# configuration is sane, to ensure that the administrator has set up
+# the script properly.
+{
+  my $ok = 1;
+  foreach my $program ($sendmail, $svnlook)
+    {
+      next if not defined $program;
+      if (-e $program)
+        {
+          unless (-x $program)
+            {
+              warn "$0: required program `$program' is not executable, ",
+                   "edit $0.\n";
+              $ok = 0;
+            }
+        }
+      else
+        {
+          warn "$0: required program `$program' does not exist, edit $0.\n";
+          $ok = 0;
+        }
+    }
+  if (not (defined $sendmail xor defined $smtp_server))
+    {
+      warn "$0: exactly one of \$sendmail or \$smtp_server must be ",
+           "set, edit $0.\n";
+      $ok = 0;
+    }
+  exit 1 unless $ok;
+}
+
+require Net::SMTP if defined $smtp_server;
+
+######################################################################
+# Initial setup/command-line handling.
+
+# Each value in this array holds a hash reference which contains the
+# associated email information for one project.  Start with an
+# implicit rule that matches all paths.
+my @project_settings_list = (&new_project);
+
+# Process the command line arguments till there are none left.
+# In commit mode: The first two arguments that are not used by a command line
+# option are the repository path and the revision number.
+# In revprop-change mode: The first four arguments that are not used by a
+# command line option are the repository path, the revision number, the
+# author, and the property name. This script has no support for the fifth
+# argument (action) added to the post-revprop-change hook in Subversion
+# 1.2.0 yet - patches welcome!
+my $repos;
+my $rev;
+my $author;
+my $propname;
+
+my $mode = 'commit';
+my $diff_file;
+
+# Use the reference to the first project to populate.
+my $current_project = $project_settings_list[0];
+
+# This hash matches the command line option to the hash key in the
+# project.  If a key exists but has a false value (''), then the
+# command line option is allowed but requires special handling.
+my %opt_to_hash_key = ('--from' => 'from_address',
+                       '--revprop-change' => '',
+                       '-d'     => '',
+                       '-h'     => 'hostname',
+                       '-l'     => 'log_file',
+                       '-m'     => '',
+                       '-r'     => 'reply_to',
+                       '-s'     => 'subject_prefix',
+                       '--diff' => '');
+
+while (@ARGV)
+  {
+    my $arg = shift @ARGV;
+    if ($arg =~ /^-/)
+      {
+        my $hash_key = $opt_to_hash_key{$arg};
+        unless (defined $hash_key)
+          {
+            die "$0: command line option `$arg' is not recognized.\n";
+          }
+
+        my $value;
+        if ($arg ne '--revprop-change')
+          {
+            unless (@ARGV)
+              {
+                die "$0: command line option `$arg' is missing a value.\n";
+              }
+            $value = shift @ARGV;
+          }
+
+        if ($hash_key)
+          {
+            $current_project->{$hash_key} = $value;
+          }
+        else
+          {
+            if ($arg eq '-m')
+              {
+                $current_project                = &new_project;
+                $current_project->{match_regex} = $value;
+                push(@project_settings_list, $current_project);
+              }
+            elsif ($arg eq '-d')
+              {
+                if ($mode ne 'revprop-change')
+                  {
+                    die "$0: `-d' is valid only when used after"
+                      . " `--revprop-change'.\n";
+                  }
+                if ($diff_file)
+                  {
+                    die "$0: command line option `$arg'"
+                      . " can only be used once.\n";
+                  }
+                $diff_file = $value;
+              }
+            elsif ($arg eq '--revprop-change')
+              {
+                if (defined $repos)
+                  {
+                    die "$0: `--revprop-change' must be specified before"
+                      . " the first non-option argument.\n";
+                  }
+                $mode = 'revprop-change';
+              }
+            elsif ($arg eq '--diff')
+              {
+                $current_project->{show_diff} = parse_boolean($value);
+              }
+            else
+              {
+                die "$0: internal error:"
+                  . " should not be handling `$arg' here.\n";
+              }
+          }
+      }
+    else
+      {
+        if (! defined $repos)
+          {
+            $repos = $arg;
+          }
+        elsif (! defined $rev)
+          {
+            $rev = $arg;
+          }
+        elsif (! defined $author && $mode eq 'revprop-change')
+          {
+            $author = $arg;
+          }
+        elsif (! defined $propname && $mode eq 'revprop-change')
+          {
+            $propname = $arg;
+          }
+        else
+          {
+            push(@{$current_project->{email_addresses}}, $arg);
+          }
+      }
+  }
+
+if ($mode eq 'commit')
+  {
+    &usage("$0: too few arguments.") unless defined $rev;
+  }
+elsif ($mode eq 'revprop-change')
+  {
+    &usage("$0: too few arguments.") unless defined $propname;
+  }
+
+# Check the validity of the command line arguments.  Check that the
+# revision is an integer greater than 0 and that the repository
+# directory exists.
+unless ($rev =~ /^\d+/ and $rev > 0)
+  {
+    &usage("$0: revision number `$rev' must be an integer > 0.");
+  }
+unless (-e $repos)
+  {
+    &usage("$0: repos directory `$repos' does not exist.");
+  }
+unless (-d _)
+  {
+    &usage("$0: repos directory `$repos' is not a directory.");
+  }
+
+# Check that all of the regular expressions can be compiled and
+# compile them.
+{
+  my $ok = 1;
+  for (my $i=0; $i<@project_settings_list; ++$i)
+    {
+      my $match_regex = $project_settings_list[$i]->{match_regex};
+
+      # To help users that automatically write regular expressions
+      # that match the root directory using ^/, remove the / character
+      # because subversion paths, while they start at the root level,
+      # do not begin with a /.
+      $match_regex =~ s#^\^/#^#;
+
+      my $match_re;
+      eval { $match_re = qr/$match_regex/ };
+      if ($@)
+        {
+          warn "$0: -m regex #$i `$match_regex' does not compile:\n$@\n";
+          $ok = 0;
+          next;
+        }
+      $project_settings_list[$i]->{match_re} = $match_re;
+    }
+  exit 1 unless $ok;
+}
+
+# Harvest common data needed for both commit or revprop-change.
+
+# Figure out what directories have changed using svnlook.
+my @dirschanged = &read_from_process($svnlook, 'dirs-changed', $repos,
+                                     '-r', $rev);
+
+# Lose the trailing slash in the directory names if one exists, except
+# in the case of '/'.
+my $rootchanged = 0;
+for (my $i=0; $i<@dirschanged; ++$i)
+  {
+    if ($dirschanged[$i] eq '/')
+      {
+        $rootchanged = 1;
+      }
+    else
+      {
+        $dirschanged[$i] =~ s#^(.+)[/\\]$#$1#;
+      }
+  }
+
+# Figure out what files have changed using svnlook.
+my @svnlooklines = &read_from_process($svnlook, 'changed', $repos, '-r', $rev);
+
+# Parse the changed nodes.
+my @adds;
+my @dels;
+my @mods;
+foreach my $line (@svnlooklines)
+  {
+    my $path = '';
+    my $code = '';
+
+    # Split the line up into the modification code and path, ignoring
+    # property modifications.
+    if ($line =~ /^(.).  (.*)$/)
+      {
+        $code = $1;
+        $path = $2;
+      }
+
+    if ($code eq 'A')
+      {
+        push(@adds, $path);
+      }
+    elsif ($code eq 'D')
+      {
+        push(@dels, $path);
+      }
+    else
+      {
+        push(@mods, $path);
+      }
+  }
+
+# Declare variables which carry information out of the inner scope of
+# the conditional blocks below.
+my $subject_base;
+my @body;
+# $author - declared above for use as a command line parameter in
+#   revprop-change mode.  In commit mode, gets filled in below.
+
+if ($mode eq 'commit')
+  {
+    ######################################################################
+    # Harvest data using svnlook.
+
+    # Get the author, date, and log from svnlook.
+    my @infolines = &read_from_process($svnlook, 'info', $repos, '-r', $rev);
+    $author = shift @infolines;
+    my $date = shift @infolines;
+    shift @infolines;
+    my @log = map { "$_\n" } @infolines;
+
+    ######################################################################
+    # Modified directory name collapsing.
+
+    # Collapse the list of changed directories only if the root directory
+    # was not modified, because otherwise everything is under root and
+    # there's no point in collapsing the directories, and only if more
+    # than one directory was modified.
+    my $commondir = '';
+    my @edited_dirschanged = @dirschanged;
+    if (!$rootchanged and @edited_dirschanged > 1)
+      {
+        my $firstline    = shift @edited_dirschanged;
+        my @commonpieces = split('/', $firstline);
+        foreach my $line (@edited_dirschanged)
+          {
+            my @pieces = split('/', $line);
+            my $i = 0;
+            while ($i < @pieces and $i < @commonpieces)
+              {
+                if ($pieces[$i] ne $commonpieces[$i])
+                  {
+                    splice(@commonpieces, $i, @commonpieces - $i);
+                    last;
+                  }
+                $i++;
+              }
+          }
+        unshift(@edited_dirschanged, $firstline);
+
+        if (@commonpieces)
+          {
+            $commondir = join('/', @commonpieces);
+            my @new_dirschanged;
+            foreach my $dir (@edited_dirschanged)
+              {
+                if ($dir eq $commondir)
+                  {
+                    $dir = '.';
+                  }
+                else
+                  {
+                    $dir =~ s#^\Q$commondir/\E##;
+                  }
+                push(@new_dirschanged, $dir);
+              }
+            @edited_dirschanged = @new_dirschanged;
+          }
+      }
+    my $dirlist = join(' ', @edited_dirschanged);
+
+    ######################################################################
+    # Assembly of log message.
+
+    if ($commondir ne '')
+      {
+        $subject_base = "r$rev - in $commondir: $dirlist";
+      }
+    else
+      {
+        $subject_base = "r$rev - $dirlist";
+      }
+
+    # Put together the body of the log message.
+    push(@body, "Author: $author\n");
+    push(@body, "Date: $date\n");
+    push(@body, "New Revision: $rev\n");
+    push(@body, "\n");
+    if (@adds)
+      {
+        @adds = sort @adds;
+        push(@body, "Added:\n");
+        push(@body, map { "   $_\n" } @adds);
+      }
+    if (@dels)
+      {
+        @dels = sort @dels;
+        push(@body, "Removed:\n");
+        push(@body, map { "   $_\n" } @dels);
+      }
+    if (@mods)
+      {
+        @mods = sort @mods;
+        push(@body, "Modified:\n");
+        push(@body, map { "   $_\n" } @mods);
+      }
+    push(@body, "Log:\n");
+    push(@body, @log);
+    push(@body, "\n");
+  }
+elsif ($mode eq 'revprop-change')
+  {
+    ######################################################################
+    # Harvest data.
+
+    my @svnlines;
+    # Get the diff file if it was provided, otherwise the property value.
+    if ($diff_file)
+      {
+        open(DIFF_FILE, $diff_file) or die "$0: cannot read `$diff_file': $!\n";
+        @svnlines = <DIFF_FILE>;
+        close DIFF_FILE;
+      }
+    else
+      {
+        @svnlines = &read_from_process($svnlook, 'propget', '--revprop', '-r',
+                                       $rev, $repos, $propname);
+      }
+
+    ######################################################################
+    # Assembly of log message.
+
+    $subject_base = "propchange - r$rev $propname";
+
+    # Put together the body of the log message.
+    push(@body, "Author: $author\n");
+    push(@body, "Revision: $rev\n");
+    push(@body, "Property Name: $propname\n");
+    push(@body, "\n");
+    unless ($diff_file)
+      {
+        push(@body, "New Property Value:\n");
+      }
+    push(@body, map { /[\r\n]+$/ ? $_ : "$_\n" } @svnlines);
+    push(@body, "\n");
+  }
+
+# Cached information - calculated when first needed.
+my @difflines;
+
+# Go through each project and see if there are any matches for this
+# project.  If so, send the log out.
+foreach my $project (@project_settings_list)
+  {
+    my $match_re = $project->{match_re};
+    my $match    = 0;
+    foreach my $path (@dirschanged, @adds, @dels, @mods)
+      {
+        if ($path =~ $match_re)
+          {
+            $match = 1;
+            last;
+          }
+      }
+
+    next unless $match;
+
+    my @email_addresses = @{$project->{email_addresses}};
+    my $userlist        = join(' ', @email_addresses);
+    my $to              = join(', ', @email_addresses);
+    my $from_address    = $project->{from_address};
+    my $hostname        = $project->{hostname};
+    my $log_file        = $project->{log_file};
+    my $reply_to        = $project->{reply_to};
+    my $subject_prefix  = $project->{subject_prefix};
+    my $subject         = $subject_base;
+    my $diff_wanted     = ($project->{show_diff} and $mode eq 'commit');
+
+    if ($subject_prefix =~ /\w/)
+      {
+        $subject = "$subject_prefix $subject";
+      }
+    my $mail_from = $author;
+
+    if ($from_address =~ /\w/)
+      {
+        $mail_from = $from_address;
+      }
+    elsif ($hostname =~ /\w/)
+      {
+        $mail_from = "$mail_from\@$hostname";
+      }
+    elsif (defined $smtp_server)
+      {
+        die "$0: use of either `-h' or `--from' is mandatory when ",
+            "sending email using direct SMTP.\n";
+      }
+
+    my @head;
+    push(@head, "To: $to\n");
+    push(@head, "From: $mail_from\n");
+    push(@head, "Subject: $subject\n");
+    push(@head, "Reply-to: $reply_to\n") if $reply_to;
+
+    ### Below, we set the content-type etc, but see these comments
+    ### from Greg Stein on why this is not a full solution.
+    #
+    # From: Greg Stein <gstein at lyra.org>
+    # Subject: Re: svn commit: rev 2599 - trunk/tools/cgi
+    # To: dev at subversion.tigris.org
+    # Date: Fri, 19 Jul 2002 23:42:32 -0700
+    #
+    # Well... that isn't strictly true. The contents of the files
+    # might not be UTF-8, so the "diff" portion will be hosed.
+    #
+    # If you want a truly "proper" commit message, then you'd use
+    # multipart MIME messages, with each file going into its own part,
+    # and labeled with an appropriate MIME type and charset. Of
+    # course, we haven't defined a charset property yet, but no biggy.
+    #
+    # Going with multipart will surely throw out the notion of "cut
+    # out the patch from the email and apply." But then again: the
+    # commit emailer could see that all portions are in the same
+    # charset and skip the multipart thang.
+    #
+    # etc etc
+    #
+    # Basically: adding/tweaking the content-type is nice, but don't
+    # think that is the proper solution.
+    push(@head, "Content-Type: text/plain; charset=UTF-8\n");
+    push(@head, "Content-Transfer-Encoding: 8bit\n");
+
+    push(@head, "\n");
+
+    if ($diff_wanted and not @difflines)
+      {
+        # Get the diff from svnlook.
+        my @no_diff_deleted = $no_diff_deleted ? ('--no-diff-deleted') : ();
+        my @no_diff_added = $no_diff_added ? ('--no-diff-added') : ();
+        @difflines = &read_from_process($svnlook, 'diff', $repos,
+                                        '-r', $rev, @no_diff_deleted,
+                                        @no_diff_added);
+        @difflines = map { /[\r\n]+$/ ? $_ : "$_\n" } @difflines;
+      }
+
+    if (defined $sendmail and @email_addresses)
+      {
+        # Open a pipe to sendmail.
+        my $command = "$sendmail -f'$mail_from' $userlist";
+        if (open(SENDMAIL, "| $command"))
+          {
+            print SENDMAIL @head, @body;
+            print SENDMAIL @difflines if $diff_wanted;
+            close SENDMAIL
+              or warn "$0: error in closing `$command' for writing: $!\n";
+          }
+        else
+          {
+            warn "$0: cannot open `| $command' for writing: $!\n";
+          }
+      }
+    elsif (defined $smtp_server and @email_addresses)
+      {
+        my $smtp = Net::SMTP->new($smtp_server);
+        handle_smtp_error($smtp, $smtp->mail($mail_from));
+        handle_smtp_error($smtp, $smtp->recipient(@email_addresses));
+        handle_smtp_error($smtp, $smtp->data());
+        handle_smtp_error($smtp, $smtp->datasend(@head, @body));
+        if ($diff_wanted)
+          {
+            handle_smtp_error($smtp, $smtp->datasend(@difflines));
+          }
+        handle_smtp_error($smtp, $smtp->dataend());
+        handle_smtp_error($smtp, $smtp->quit());
+      }
+
+    # Dump the output to logfile (if its name is not empty).
+    if ($log_file =~ /\w/)
+      {
+        if (open(LOGFILE, ">> $log_file"))
+          {
+            print LOGFILE @head, @body;
+            print LOGFILE @difflines if $diff_wanted;
+            close LOGFILE
+              or warn "$0: error in closing `$log_file' for appending: $!\n";
+          }
+        else
+          {
+            warn "$0: cannot open `$log_file' for appending: $!\n";
+          }
+      }
+  }
+
+exit 0;
+
+sub handle_smtp_error
+{
+  my ($smtp, $retval) = @_;
+  if (not $retval)
+    {
+      die "$0: SMTP Error: " . $smtp->message() . "\n";
+    }
+}
+
+sub usage
+{
+  warn "@_\n" if @_;
+  die "usage (commit mode):\n",
+      "  $0 REPOS REVNUM [[-m regex] [options] [email_addr ...]] ...\n",
+      "usage: (revprop-change mode):\n",
+      "  $0 --revprop-change REPOS REVNUM USER PROPNAME [-d diff_file] \\\n",
+      "    [[-m regex] [options] [email_addr ...]] ...\n",
+      "options are:\n",
+      "  --from email_address  Email address for 'From:' (overrides -h)\n",
+      "  -h hostname           Hostname to append to author for 'From:'\n",
+      "  -l logfile            Append mail contents to this log file\n",
+      "  -m regex              Regular expression to match committed path\n",
+      "  -r email_address      Email address for 'Reply-To:'\n",
+      "  -s subject_prefix     Subject line prefix\n",
+      "  --diff y|n            Include diff in message (default: y)\n",
+      "                        (applies to commit mode only)\n",
+      "\n",
+      "This script supports a single repository with multiple projects,\n",
+      "where each project receives email only for actions that affect that\n",
+      "project.  A project is identified by using the -m command line\n".
+      "option with a regular expression argument.  If the given revision\n",
+      "contains modifications to a path that matches the regular\n",
+      "expression, then the action applies to the project.\n",
+      "\n",
+      "Any of the following -h, -l, -r, -s and --diff command line options\n",
+      "and following email addresses are associated with this project.  The\n",
+      "next -m resets the -h, -l, -r, -s and --diff command line options\n",
+      "and the list of email addresses.\n",
+      "\n",
+      "To support a single project conveniently, the script initializes\n",
+      "itself with an implicit -m . rule that matches any modifications\n",
+      "to the repository.  Therefore, to use the script for a single-\n",
+      "project repository, just use the other command line options and\n",
+      "a list of email addresses on the command line.  If you do not want\n",
+      "a rule that matches the entire repository, then use -m with a\n",
+      "regular expression before any other command line options or email\n",
+      "addresses.\n",
+      "\n",
+      "'revprop-change' mode:\n",
+      "The message will contain a copy of the diff_file if it is provided,\n",
+      "otherwise a copy of the (assumed to be new) property value.\n",
+      "\n";
+}
+
+# Return a new hash data structure for a new empty project that
+# matches any modifications to the repository.
+sub new_project
+{
+  return {email_addresses => [],
+          from_address    => '',
+          hostname        => '',
+          log_file        => '',
+          match_regex     => '.',
+          reply_to        => '',
+          subject_prefix  => '',
+          show_diff       => 1};
+}
+
+sub parse_boolean
+{
+  if ($_[0] eq 'y') { return 1; };
+  if ($_[0] eq 'n') { return 0; };
+
+  die "$0: valid boolean options are 'y' or 'n', not '$_[0]'\n";
+}
+
+# Start a child process safely without using /bin/sh.
+sub safe_read_from_pipe
+{
+  unless (@_)
+    {
+      croak "$0: safe_read_from_pipe passed no arguments.\n";
+    }
+
+  my $pid = open(SAFE_READ, '-|');
+  unless (defined $pid)
+    {
+      die "$0: cannot fork: $!\n";
+    }
+  unless ($pid)
+    {
+      open(STDERR, ">&STDOUT")
+        or die "$0: cannot dup STDOUT: $!\n";
+      exec(@_)
+        or die "$0: cannot exec `@_': $!\n";
+    }
+  my @output;
+  while (<SAFE_READ>)
+    {
+      s/[\r\n]+$//;
+      push(@output, $_);
+    }
+  close(SAFE_READ);
+  my $result = $?;
+  my $exit   = $result >> 8;
+  my $signal = $result & 127;
+  my $cd     = $result & 128 ? "with core dump" : "";
+  if ($signal or $cd)
+    {
+      warn "$0: pipe from `@_' failed $cd: exit=$exit signal=$signal\n";
+    }
+  if (wantarray)
+    {
+      return ($result, @output);
+    }
+  else
+    {
+      return $result;
+    }
+}
+
+# Use safe_read_from_pipe to start a child process safely and return
+# the output if it succeeded or an error message followed by the output
+# if it failed.
+sub read_from_process
+{
+  unless (@_)
+    {
+      croak "$0: read_from_process passed no arguments.\n";
+    }
+  my ($status, @output) = &safe_read_from_pipe(@_);
+  if ($status)
+    {
+      return ("$0: `@_' failed with this output:", @output);
+    }
+  else
+    {
+      return @output;
+    }
+}


Property changes on: trunk/src/plugins/scmhook/library/scmsvn/hooks/commitemail/commit-email.pl
___________________________________________________________________
Added: svn:executable
   + *

Copied: trunk/src/plugins/scmhook/library/scmsvn/skel/post-commit/head (from rev 13718, trunk/src/plugins/scmhook/library/scmsvn/skel/post-commit/post-commit.head)
===================================================================
--- trunk/src/plugins/scmhook/library/scmsvn/skel/post-commit/head	                        (rev 0)
+++ trunk/src/plugins/scmhook/library/scmsvn/skel/post-commit/head	2011-07-08 13:30:48 UTC (rev 13725)
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+SCRIPT=$(readlink -f $0)
+SCRIPTPATH=`dirname $SCRIPT`

Deleted: trunk/src/plugins/scmhook/library/scmsvn/skel/post-commit/post-commit.head
===================================================================
--- trunk/src/plugins/scmhook/library/scmsvn/skel/post-commit/post-commit.head	2011-07-08 11:14:41 UTC (rev 13724)
+++ trunk/src/plugins/scmhook/library/scmsvn/skel/post-commit/post-commit.head	2011-07-08 13:30:48 UTC (rev 13725)
@@ -1,4 +0,0 @@
-#!/bin/sh
-
-SCRIPT=$(readlink -f $0)
-SCRIPTPATH=`dirname $SCRIPT`

Copied: trunk/src/plugins/scmhook/library/scmsvn/skel/pre-commit/head (from rev 13718, trunk/src/plugins/scmhook/library/scmsvn/skel/pre-commit/pre-commit.head)
===================================================================
--- trunk/src/plugins/scmhook/library/scmsvn/skel/pre-commit/head	                        (rev 0)
+++ trunk/src/plugins/scmhook/library/scmsvn/skel/pre-commit/head	2011-07-08 13:30:48 UTC (rev 13725)
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+SCRIPT=$(readlink -f $0)
+SCRIPTPATH=`dirname $SCRIPT`

Deleted: trunk/src/plugins/scmhook/library/scmsvn/skel/pre-commit/pre-commit.check-log.sh
===================================================================
--- trunk/src/plugins/scmhook/library/scmsvn/skel/pre-commit/pre-commit.check-log.sh	2011-07-08 11:14:41 UTC (rev 13724)
+++ trunk/src/plugins/scmhook/library/scmsvn/skel/pre-commit/pre-commit.check-log.sh	2011-07-08 13:30:48 UTC (rev 13725)
@@ -1 +0,0 @@
-sh $SCRIPTPATH/check-log.sh "$1" "$2"

Deleted: trunk/src/plugins/scmhook/library/scmsvn/skel/pre-commit/pre-commit.check-mime-type.pl
===================================================================
--- trunk/src/plugins/scmhook/library/scmsvn/skel/pre-commit/pre-commit.check-mime-type.pl	2011-07-08 11:14:41 UTC (rev 13724)
+++ trunk/src/plugins/scmhook/library/scmsvn/skel/pre-commit/pre-commit.check-mime-type.pl	2011-07-08 13:30:48 UTC (rev 13725)
@@ -1 +0,0 @@
-perl $SCRIPTPATH/check-mime-type.pl "$1" "$2"

Deleted: trunk/src/plugins/scmhook/library/scmsvn/skel/pre-commit/pre-commit.head
===================================================================
--- trunk/src/plugins/scmhook/library/scmsvn/skel/pre-commit/pre-commit.head	2011-07-08 11:14:41 UTC (rev 13724)
+++ trunk/src/plugins/scmhook/library/scmsvn/skel/pre-commit/pre-commit.head	2011-07-08 13:30:48 UTC (rev 13725)
@@ -1,4 +0,0 @@
-#!/bin/sh
-
-SCRIPT=$(readlink -f $0)
-SCRIPTPATH=`dirname $SCRIPT`




More information about the Fusionforge-commits mailing list