Issue 112: Missing git information for some files (final fix)

This commit is contained in:
Nathan Adams 2016-04-23 12:01:09 -05:00
parent 1fdddf2501
commit 3f699e0afd
3 changed files with 130 additions and 54 deletions

View File

@ -0,0 +1,29 @@
<?php
function IDF_Migrations_32ExternalFile_up()
{
$table = Pluf::factory('IDF_Scm_Cache_Git')->getSqlTable();
$sql = array();
$sql["MySQL"] = "ALTER TABLE " . $table . " CHANGE COLUMN `githash` TEXT NOT NULL DEFAULT '' AFTER `project`;";
$db = Pluf::db();
$engine = Pluf::f('db_engine');
$db->execute($sql[$engine]);
}
function IDF_Migrations_32ExternalFile_down()
{
$table = Pluf::factory('IDF_Scm_Cache_Git')->getSqlTable();
$sql = array();
$sql["MySQL"] = "ALTER TABLE " . $table . " CHANGE COLUMN `githash` VARCHAR(40) NOT NULL AFTER `project`;";
$db = Pluf::db();
$engine = Pluf::f('db_engine');
$db->execute($sql[$engine]);
}

View File

@ -50,10 +50,10 @@ class IDF_Scm_Cache_Git extends Pluf_Model
*/
public function store($infos)
{
foreach ($infos as $blob) {
foreach ($infos as $key => $blob) {
$cache = new IDF_Scm_Cache_Git();
$cache->project = $this->_project;
$cache->githash = $blob->hash;
$cache->githash = $key;
$blob->title = IDF_Commit::toUTF8($blob->title);
$cache->content = IDF_Commit::toUTF8($blob->date) . chr(31)
. IDF_Commit::toUTF8($blob->author) . chr(31)
@ -123,9 +123,8 @@ class IDF_Scm_Cache_Git extends Pluf_Model
),
'githash' =>
array(
'type' => 'Pluf_DB_Field_Varchar',
'type' => 'Pluf_DB_Field_Text',
'blank' => false,
'size' => 40,
'index' => true,
),
'content' =>

View File

@ -343,7 +343,7 @@ class IDF_Scm_Git extends IDF_Scm
$res[] = $file;
}
// Grab the details for each blob and return the list.
return $this->getTreeDetails($res);
return $this->getTreeDetails($res, $commit);
}
/**
@ -718,13 +718,13 @@ class IDF_Scm_Git extends IDF_Scm
* @param array Tree information
* @return array Updated tree information
*/
public function getTreeDetails($tree)
public function getTreeDetails($tree, $commit)
{
$n = count($tree);
$details = array();
for ($i=0;$i<$n;$i++) {
if ($tree[$i]->type == 'blob') {
$details[sha1($tree[$i]->hash . $tree[$i]->fullpath)] = $i;
$details[sha1($tree[$i]->hash . $tree[$i]->fullpath) . ":" . $tree[$i]->hash . ":" . $tree[$i]->fullpath] = $i;
}
}
if (!count($details)) {
@ -742,7 +742,7 @@ class IDF_Scm_Git extends IDF_Scm
}
}
if (count($toapp)) {
$res = $this->appendBlobInfoCache($toapp);
$res = $this->appendBlobInfoCache($toapp, $commit);
foreach ($details as $blob => $idx) {
if (isset($res[$blob])) {
$tree[$idx]->date = $res[$blob]->date;
@ -766,62 +766,110 @@ class IDF_Scm_Git extends IDF_Scm
* @param array The blob for which we need the information
* @return array The information
*/
public function appendBlobInfoCache($blobs)
public function appendBlobInfoCache($blobs, $commit)
{
$rawlog = array();
$cmd = Pluf::f('idf_exec_cmd_prefix', '')
.sprintf('GIT_DIR=%s '.Pluf::f('git_path', 'git').' log --raw --abbrev=40 --pretty=oneline -5000 --skip=%%s',
escapeshellarg($this->repo));
.sprintf('GIT_DIR=%s '.Pluf::f('git_path', 'git').' log --raw --abbrev=40 --pretty=oneline -5000 --skip=%%s %s',
escapeshellarg($this->repo), $commit);
$skip = 0;
$res = array();
self::exec('IDF_Scm_Git::appendBlobInfoCache',
sprintf($cmd, $skip), $rawlog);
while (count($rawlog) and count($blobs)) {
$fileinfoarr = [];
$lookup = [];
$cache = [];
$currentcommit = null;
$rawlog = implode("\n", array_reverse($rawlog));
$tmpRes = [];
foreach(explode("\n", $rawlog) as $line) {
if ($line[0] != ":") { //This is the commit number line
$commit = explode(" ", $line)[0];
$fc = $this->getCommit($commit);
foreach($tmpRes as $r) {
$res[$r["hash"]] = (object) [
"hash" => $r["hash"],
"date" => $fc->date,
"title" => $fc->title,
"author" => $fc->author
if ($line[0] == ":") {
$matches = preg_split('/\s/', $line);
$currentFileHash = $matches[3];
$file = $matches[5];
$fileinfoarr[] = [
"filehash" => $currentFileHash,
"file" => $file
];
}
$tmpRes = [];
} else {
$sides = explode("\t", $line);
$leftSide = trim($sides[0]);
$rightSide = trim($sides[1]);
$leftSideSplit = explode(" ", $leftSide);
$newHash = sha1($leftSideSplit[3] . $rightSide);
$tmpRes[$newHash] = [
"hash" => $newHash
$matches = preg_split('/\s/', $line);
$currentcommit = $matches[0];
if ($fileinfoarr) {
$lookup[$currentcommit] = $fileinfoarr;
$fileinfoarr = [];
}
}
}
$commitData = $this->getCommit($commit);
foreach($blobs as $blobKey => $blobVal) {
list($newhash, $hash, $file) = explode(":", $blobKey);
if (isset($lookup[$commitData->commit])) {
$test = $lookup[$commitData->commit];
} else {
if (isset($lookup[$commitData->parents[0]])) { //tag?
$test = $lookup[$commitData->parents[0]];
} else {
$test = [];
}
}
$found = false;
foreach($test as $fileinfo) {
if ($fileinfo["filehash"] == $hash && $fileinfo["file"] == $file) {
$found = true;
$res[$blobKey] = (object) [
"hash" => $newhash,
"date" => $commitData->date,
"title" => $commitData->title,
"author" => $commitData->author
];
unset($blobs[$newHash]);
$cache[$blobKey] = $res[$blobKey];
}
}
$rawlog = array();
$skip += 5000;
if ($skip > 20000) {
// We are in the case of the import of a big old
// repository, we can store as unknown the commit info
// not to try to retrieve them each time.
foreach ($blobs as $blob => $idx) {
$res[$blob] = (object) array('hash' => $blob,
'date' => '0',
'title' => '----',
'author' => 'Unknown');
}
if (!$found) {
foreach ($lookup as $key=>$val) {
foreach($val as $fileinfo) {
if ($fileinfo["filehash"] == $hash && $fileinfo["file"] == $file) {
$commitTempData = $this->getCommit($key);
$res[$blobKey] = (object) [
"hash" => $newhash,
"date" => $commitTempData->date,
"title" => $commitTempData->title,
"author" => $commitTempData->author
];
$cache[$blobKey] = $res[$blobKey];
$found = true;
break;
}
self::exec('IDF_Scm_Git::appendBlobInfoCache',
sprintf($cmd, $skip), $rawlog);
}
$this->cacheBlobInfo($res);
}
}
// If it's still not found - find the first commit where it's modified and use that
if (!$found) {
foreach ($lookup as $key=>$val) {
foreach($val as $fileinfo) {
if ($fileinfo["file"] == $file) {
$commitTempData = $this->getCommit($key);
$res[$blobKey] = (object) [
"hash" => $newhash,
"date" => $commitTempData->date,
"title" => $commitTempData->title,
"author" => $commitTempData->author
];
$cache[$blobKey] = $res[$blobKey];
break;
}
}
}
}
}
$this->cacheBlobInfo($cache);
return $res;
}