Skip to content
Snippets Groups Projects
Commit 6953dcf3 authored by Axel Hahn's avatar Axel Hahn
Browse files

- added: skip dereferenced tags in git (tags ending ^{} )

- added: modal infobox in build page if you switch the branch
- added: git uses a cache for taglist and revision infos (ttl is 5 min)
- cut commit message a bit: do not show * [new branch]
parent 0b0dbe0d
No related branches found
No related tags found
No related merge requests found
...@@ -44,7 +44,7 @@ class vcs implements iVcs { ...@@ -44,7 +44,7 @@ class vcs implements iVcs {
private $_aRemoteBranches = array(); private $_aRemoteBranches = array();
/** /**
* name of the remote branch to access * name of the default remote branch to access
* @var type * @var type
*/ */
private $_sCurrentBranch = "origin/master"; private $_sCurrentBranch = "origin/master";
...@@ -55,6 +55,7 @@ class vcs implements iVcs { ...@@ -55,6 +55,7 @@ class vcs implements iVcs {
*/ */
public function __construct($aRepoConfig = array()) { public function __construct($aRepoConfig = array()) {
$this->setConfig($aRepoConfig); $this->setConfig($aRepoConfig);
$this->getRemoteBranches(); // to fill the cache
} }
/** /**
...@@ -82,21 +83,38 @@ class vcs implements iVcs { ...@@ -82,21 +83,38 @@ class vcs implements iVcs {
$this->_aCfg = $aRepoConfig; $this->_aCfg = $aRepoConfig;
// define temp dir // define temp dir
$this->_sTempDir = $this->_aCfg["url"]; $this->_setTempdir();
$this->_sTempDir = preg_replace('/[\@\.\:\/]/', '_', $this->_sTempDir);
$this->_sTempDir = (getenv("temp") ? getenv("temp") : "/tmp") . '/checkout_vcsgit_' . $this->_sTempDir . "/";
$this->_sKeyfile = $this->_aCfg["dataDir"] . "/sshkeys/" . $this->_aCfg["auth"]; $this->_sKeyfile = $this->_aCfg["dataDir"] . "/sshkeys/" . $this->_aCfg["auth"];
$this->_sWrapper = $this->_aCfg["appRootDir"] . "/shellscripts/gitsshwrapper.sh"; $this->_sWrapper = $this->_aCfg["appRootDir"] . "/shellscripts/gitsshwrapper.sh";
return $this->_aCfg = $aRepoConfig; return $this->_aCfg = $aRepoConfig;
} }
private function _setTempdir() {
$this->_sTempDir = $this->_aCfg["url"];
$this->_sTempDir = preg_replace('/[\@\.\:\/]/', '_', $this->_sTempDir);
$this->_sTempDir = (getenv("temp") ? getenv("temp") : "/tmp") . '/checkout_vcsgit_' . $this->_sTempDir . '/';
$this->_sTempDir .= preg_replace('/[\@\.\:\/]/', '_', $this->_sCurrentBranch) . '/';
if (!file_exists($this->_sTempDir . ".git") || true) {
$sGitCmd = 'export GIT_SSH="' . $this->_sWrapper . '" ; export PKEY="' . $this->_sKeyfile . '" ; ';
$sGitCmd.='mkdir -p "' . $this->_sTempDir . '" && cd "' . $this->_sTempDir . '" && ';
$sGitCmd.='git init >/dev/null && ';
$sGitCmd.='git remote add origin "' . $this->getUrl() . '" 2>&1 && ';
// $sGitCmd='time ('.$sGitCmd.')';
exec($sGitCmd, $aOutput, $iRc);
}
return $this->_sTempDir;
}
/** /**
* set the current branch * set the current branch
* @param string $sBranchname name of the branch * @param string $sBranchname name of the branch
*/ */
public function setCurrentBranch($sBranchname) { public function setCurrentBranch($sBranchname) {
return $this->_sCurrentBranch = $sBranchname; $this->_sCurrentBranch = $sBranchname;
$this->_setTempdir();
return $this->_sCurrentBranch;
} }
/** /**
...@@ -140,25 +158,24 @@ class vcs implements iVcs { ...@@ -140,25 +158,24 @@ class vcs implements iVcs {
return $this->_aCfg["type"]; return $this->_aCfg["type"];
} }
/**
* get a nice name for a cache module based on repo url
* @return type
*/
private function _getNameOfCacheModule() { private function _getNameOfCacheModule() {
$sReturn="git".$this->getUrl(); return preg_replace('/([^0-9a-z])/i', "", $this->getUrl());
$sReturn=preg_replace('/([^0-9a-z])/i', "", $sReturn);
// echo "DEBUG: getNameOfCacheModule $sReturn<br>";
return $sReturn;
} }
/** /**
* cleanup cache data for this project (revisions, list of branches+tags) * cleanup cache data for this project (revisions, list of branches+tags)
* @return bool * @return bool
*/ */
private function _cleanupCache(){ private function _cleanupCache($iAge) {
require_once 'cache.class.php'; require_once 'cache.class.php';
$oCache = new AhCache($this->_getNameOfCacheModule()); $oCache = new AhCache($this->_getNameOfCacheModule());
return $oCache->cleanup(); return $oCache->cleanup((int)$iAge);
} }
/** /**
* read remote repository and get an array with names and revisions of * read remote repository and get an array with names and revisions of
* all branches and tags * all branches and tags
...@@ -169,58 +186,65 @@ class vcs implements iVcs { ...@@ -169,58 +186,65 @@ class vcs implements iVcs {
private function _fetchRemoteBranches($bForceNoCache = false) { private function _fetchRemoteBranches($bForceNoCache = false) {
$aReturn = array(); $aReturn = array();
$sGitCmd = 'export GIT_SSH="' . $this->_sWrapper . '" ; export PKEY="' . $this->_sKeyfile . '" ; ';
if (!$this->getUrl()) { if (!$this->getUrl()) {
return false; return false;
} }
$iTtl = 300; // cache for 5 min $iTtl = 300; // cache for 5 min
require_once 'cache.class.php'; require_once 'cache.class.php';
$oCache = new AhCache($this->_getNameOfCacheModule(), "RemoteBranches"); $oCache = new AhCache($this->_getNameOfCacheModule(), "RemoteBranches");
// list of cached branch keys
$aKeysToDelete = array();
if ($oCache->isExpired() || $bForceNoCache) { if ($oCache->isExpired() || $bForceNoCache) {
if (!file_exists($this->_sTempDir . ".git")) { $sWorkdir = dirname($this->_sTempDir) . '/fetchRemoteBranches/';
$sGitCmd.='mkdir "' . $this->_sTempDir . '" && cd "' . $this->_sTempDir . '" && '; $sGitCmd = 'export GIT_SSH="' . $this->_sWrapper . '" ; export PKEY="' . $this->_sKeyfile . '" ; ';
if (!file_exists($sWorkdir . ".git")) {
$sGitCmd.='mkdir -p "' . $sWorkdir . '" && cd "' . $sWorkdir . '" && ';
$sGitCmd.='git init >/dev/null && '; $sGitCmd.='git init >/dev/null && ';
$sGitCmd.='git remote add origin "' . $this->getUrl() . '" 2>&1 && '; $sGitCmd.='git remote add origin "' . $this->getUrl() . '" 2>&1 && ';
} else { } else {
$sGitCmd.='cd "' . $this->_sTempDir . '" 2>&1 && '; $sGitCmd.='cd "' . $sWorkdir . '" 2>&1 && ';
} }
// $sGitCmd.='git branch -r ; '; $sGitCmd.='git ls-remote --heads --tags origin 2>&1 ;';
$sGitCmd.='git ls-remote --heads origin 2>&1 ; git ls-remote --tags origin 2>&1 ';
exec($sGitCmd, $aOutput, $iRc); exec($sGitCmd, $aOutput, $iRc);
if ($iRc == 0) { if ($iRc == 0) {
foreach ($aOutput as $sBranch) {
$aTmp = explode("\t", $sBranch);
$aBranch = explode("/", $aTmp[1]); // use cache that getCommitmessageByBranch can access it
$this->_aRemoteBranches = $oCache->read();
foreach ($aOutput as $sBranchLine) {
$aTmp = explode("\t", $sBranchLine);
$aBranch = explode("/", $aTmp[1]);
$sBranch = array_pop($aBranch); $sBranch = array_pop($aBranch);
$sRevision = $aTmp[0];
// skip dereferences // skip dereferences
// http://stackoverflow.com/questions/15472107/when-listing-git-ls-remote-why-theres-after-the-tag-name // http://stackoverflow.com/questions/15472107/when-listing-git-ls-remote-why-theres-after-the-tag-name
if (!preg_match('/\^\{\}$/', $sBranch)) { if (!preg_match('/\^\{\}$/', $sBranch)) {
$sType = array_pop($aBranch); $sType = array_pop($aBranch);
if ($sType == "heads") { $sName = ($sType == "heads") ? "origin/" . $sBranch : $sBranch;
$sBranch = "origin/" . $sBranch; $sBranchKey = $sName;
}
$aReturn[] = array( $sMessage = $this->getCommitmessageByBranch($sName, $sRevision);
$aReturn[$sBranchKey] = array(
// 'debug'=> $aTmp, // 'debug'=> $aTmp,
'revision' => $aTmp[0], 'revision' => $sRevision,
'name' => $sBranch, 'name' => $sName,
'label' => $sType . ': ' . $sBranch, 'label' => $sType . ': ' . $sBranch,
'type' => $sType 'type' => $sType,
'message' => $sMessage
); );
} }
} }
// echo "DEBUG: refresh cache for branches and tags <br>"; $this->_aRemoteBranches = $aReturn;
$oCache->write($aReturn, $iTtl); $oCache->write($aReturn, $iTtl);
} }
} else { } else {
// echo "DEBUG: using cache for branches and tags <br>"; $this->_aRemoteBranches = $oCache->read();
$aReturn=$oCache->read();
} }
$this->_aRemoteBranches = $aReturn; return $this->_aRemoteBranches;
return $aReturn;
} }
/** /**
...@@ -229,27 +253,70 @@ class vcs implements iVcs { ...@@ -229,27 +253,70 @@ class vcs implements iVcs {
*/ */
public function getRemoteBranches() { public function getRemoteBranches() {
if (!$this->_aRemoteBranches) { if (!$this->_aRemoteBranches) {
$this->_aRemoteBranches = $this->_fetchRemoteBranches(); $this->_fetchRemoteBranches();
} }
return $this->_aRemoteBranches; return $this->_aRemoteBranches;
} }
/** /**
* get current revision and log message from remote repository * get current revision and commit message from remote repository
* @see $this::getRevision * @see $this::getRevision
* @return array * @return array
*/ */
public function getRepoRevision() { public function getRepoRevision() {
return $this->getRevision(false); $sMessage = $this->getCommitmessageByBranch();
if ($sMessage) {
$aReturn = array(
'branch' => $this->_sCurrentBranch,
'revision' => $this->_aRemoteBranches[$this->_sCurrentBranch]['revision'],
'message' => $sMessage,
);
} else {
$aReturn = $this->getRevision(false);
}
return $aReturn;
} }
/** /**
* get current revision and log message from an existing directory or a * get a commit message of a given branch
* @param string $sBranch name of a branch
* @param string $sVerifyRevision optional: verify if this revision is the newsest
* @return string
*/
public function getCommitmessageByBranch($sBranch = false, $sVerifyRevision = false) {
if (!$sBranch) {
$sBranch = $this->_sCurrentBranch;
}
// try to get infos from the cache
if (
(array_key_exists($sBranch, $this->_aRemoteBranches) && $sVerifyRevision && $this->_aRemoteBranches[$sBranch]['revision'] == $sVerifyRevision
) ||
(array_key_exists($sBranch, $this->_aRemoteBranches) && !$sVerifyRevision
)
) {
// it is up to date - doing nothing
return $this->_aRemoteBranches[$sBranch]['message'];
}
// ok, then I need to read it
if ($this->_sCurrentBranch != $sBranch) {
$sSaveBranch = $this->_sCurrentBranch;
$this->setCurrentBranch($sBranch);
$a = $this->getRevision(false);
$this->setCurrentBranch($sSaveBranch);
} else {
$a = $this->getRevision(false);
}
return $a['message'];
}
/**
* get current revision and commit message from an existing directory or a
* remote repository * remote repository
* the return will fill $this->_aData["phases"]["source"] in project class * the return will fill $this->_aData["phases"]["source"] in project class
* (array keys are revision, message or error) * (array keys are revision, message or error)
* if ok: * if ok:
* array( * array(
* "branch" => $sRevision,
* "revision" => $sRevision, * "revision" => $sRevision,
* "message" => $sCommitmessage * "message" => $sCommitmessage
* ); * );
...@@ -258,26 +325,21 @@ class vcs implements iVcs { ...@@ -258,26 +325,21 @@ class vcs implements iVcs {
* array( * array(
* "error" => $sErrormessage, * "error" => $sErrormessage,
* ); * );
* @param string $sWorkDir optional: local directory with initialized git repo
* @return array * @return array
*/ */
public function getRevision($sWorkDir = false) { public function getRevision($sWorkDir = false) {
$aReturn = array(); $aReturn = array();
$sGitCmd = 'export GIT_SSH="' . $this->_sWrapper . '" ; export PKEY="' . $this->_sKeyfile . '" ; ';
if (!$this->getUrl()) { if (!$this->getUrl()) {
return false; return false;
} }
$iTtl=300; // cache for 5 min $sGitCmd = 'export GIT_SSH="' . $this->_sWrapper . '" ; export PKEY="' . $this->_sKeyfile . '" ; ';
require_once 'cache.class.php';
$oCache=new AhCache($this->_getNameOfCacheModule(), "Revision-".$this->_sCurrentBranch ."-". $sWorkDir);
if ($oCache->isExpired()){
if ($sWorkDir) { if ($sWorkDir) {
$sGitCmd.='cd "' . $sWorkDir . '" && '; $sGitCmd.='cd "' . $sWorkDir . '" && ';
} else { } else {
if (!file_exists($this->_sTempDir . ".git")) { if (!file_exists($this->_sTempDir . ".git")) {
$sGitCmd.='mkdir "' . $this->_sTempDir . '" && cd "' . $this->_sTempDir . '" && '; $sGitCmd.='mkdir -p "' . $this->_sTempDir . '" && cd "' . $this->_sTempDir . '" && ';
$sGitCmd.='git init >/dev/null 2>&1 && '; $sGitCmd.='git init >/dev/null 2>&1 && ';
$sGitCmd.='git remote add origin "' . $this->getUrl() . '" 2>&1 && '; $sGitCmd.='git remote add origin "' . $this->getUrl() . '" 2>&1 && ';
} else { } else {
...@@ -286,14 +348,29 @@ class vcs implements iVcs { ...@@ -286,14 +348,29 @@ class vcs implements iVcs {
// TODO: git 1.9 does needs only the line with --tags // TODO: git 1.9 does needs only the line with --tags
$sGitCmd.=' ( ' $sGitCmd.=' ( '
. 'git fetch --update-head-ok --tags --depth 1 2>&1 ; ' . 'git fetch --update-head-ok --tags --depth 1 2>&1 ; ' // 1.5 s
. 'git fetch --update-head-ok --depth 1 2>&1 ' . 'git fetch --update-head-ok --depth 1 2>&1 ' // 1.5 s
. ') && '; . ') && ';
} }
$sGitCmd.='git log -1 "' . $this->_sCurrentBranch . '" 2>&1 ; '; $sGitCmd.='git log -1 "' . $this->_sCurrentBranch . '" 2>&1 ; '; // 0.0 s
$sLoginfo = shell_exec($sGitCmd); $sLoginfo = shell_exec($sGitCmd);
/*
*
* example output:
From gitlab.iml.unibe.ch:admins/imldeployment
* [new branch] master -> origin/master
commit 0b0dbe0dee80ca71ff43a54641d616c131e6fd8a
Author: Axel Hahn
Date: Fri Dec 12 16:35:38 2014 +0100
- added: skip dereferenced tags in git (tags ending ^{} )
- added: modal infobox in build page if you switch the branch
- added: git uses a cache for taglist and revision infos (ttl is 5 min)
*
*/
// parse revision
$sRevision = false; $sRevision = false;
if (preg_match('#commit\ (.*)#', $sLoginfo, $aRev)) { if (preg_match('#commit\ (.*)#', $sLoginfo, $aRev)) {
$sRevision = $aRev[1]; $sRevision = $aRev[1];
...@@ -301,13 +378,19 @@ class vcs implements iVcs { ...@@ -301,13 +378,19 @@ class vcs implements iVcs {
if ($sRevision) { if ($sRevision) {
$sCommitMsg = $sLoginfo;
$sCommitMsg = preg_replace('/From\ .*\n/', '', $sCommitMsg);
$sCommitMsg = preg_replace('/\ \*.*\n/', '', $sCommitMsg);
$sCommitMsg = preg_replace('/commit.*\n/', '', $sCommitMsg);
// keep these to see them in the output:
// $sCommitMsg=preg_replace('/Author:\ .*\n/', '', $sCommitMsg);
// $sCommitMsg=preg_replace('/Date:\ .*\n/', '', $sCommitMsg);
$aReturn = array( $aReturn = array(
"branch" => $this->_sCurrentBranch, "branch" => $this->_sCurrentBranch,
"revision" => $sRevision, "revision" => $sRevision,
"message" => $sLoginfo "message" => $sCommitMsg
); );
// echo "DEBUG: refresh cache for git revision<br>";
$oCache->write($aReturn, $iTtl);
} else { } else {
if (!$sLoginfo) { if (!$sLoginfo) {
$sLoginfo = $sGitCmd; $sLoginfo = $sGitCmd;
...@@ -317,10 +400,6 @@ class vcs implements iVcs { ...@@ -317,10 +400,6 @@ class vcs implements iVcs {
"error" => '<pre>' . $sLoginfo . '<hr>' . $sGitCmd . '</pre>' "error" => '<pre>' . $sLoginfo . '<hr>' . $sGitCmd . '</pre>'
); );
} }
} else {
// echo "DEBUG: use cache for git revision<br>";
$aReturn=$oCache->read();
}
return $aReturn; return $aReturn;
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment