Hi !
As some might know, I played a bit with Glip (http://fimml.at/#glip), mostly
because I was curious to see what could be achieved with it.
Hopefully, the guy that wrote Glip also wrote a Wiki engine -called eWiki- that
uses Glip, so, I had a great example :)
*Please keep in mind that this was just testing.*
I still hope it will be useful.
1/ My first goal was to get one file history. There is no 'git log' thing, so I
had to reproduce its behaviour.
The result is pretty good, but not the same as the one 'git log -- file' would
produce. There are two main reasons for this :
- My small function only returns commits where the content of the considered
file has changed,
- It ignores merge commits (normally, we will have one and only one branch, so
merge commits shouldn't exist).
The major drawback is that I had to loop through every commit and compare each
of them with its parent to see if the file has changed or not. This can be time
and resource consuming with big repo. I sadly haven't found another solution.
2/ The second goal was to write "objects" to the repository. This is where
things begin to be fun ^^
The first drawback is that the repo has to exist, and a first commit must have
been done so that the 'master' branch actually exists. I didn't find a solution
to create the branch via PHP, so I did it by hand, for testing purpose. We will
have to find a solution for this. Maybe some git expert could help us.
The example given by the eWiki source code shows that the dev has chosen to
build a new branch for each commit, and to merge it with the 'master' one. I
don't really know why... I decided to keep a single branch. So I update the
current tree, build commit details and write everything to the repository. It
seems to work quite well. I clearly lack some knowledge in git, and I'd like
someone that knows it very well to check if it works well or not. I ran 'git
fsck' and it seemd to be OK, yet not sure.
I joined my source code for those who are interested in it. Please excuse me,
it's really poor and would need some huge refactor.
This was done on the fly for testing purpose. You'll need Glip to run it.
- index.php is only about reading data from a repo.
- index2.php will try to build a commit for a single file and then show this
file history.
In both cases, you will need a repo with a least one commit (so that the master
branch exists).
I *strongly* recommend you not to use a working repo if you want to test it.
'git clone' one or build a new one quickly.
For index2.php to work, you will need to 'chmod' the git repo so that your
webserver has read/write access to it.
You can edit everything at your own convenience.
And, as always, ideas and comments are welcome.
Cheers,
--
François
<?php
// This is for testing purpose only !
// Path to the repository :
$repository = dirname(__FILE__).'/owncloud/.git';
// File that's going to be examined :
$f = "index.php";
// Sets timezone to GMT :
date_default_timezone_set("GMT");
// Glip is required, of course :
require_once(dirname(__FILE__).'/3rdparty/glip/lib/glip.php');
// Let's go :
$repo = new Git($repository);
// -------------------------------------------------------------------------
function getVersions($file)
{
global $repo;
$r = array();
$branch = $repo->getObject($repo->getTip('master'));
$commits = $branch->getHistory();
foreach($commits as $commit)
{
$p = FALSE;
$parent = $commit->parents[0];
if(!empty($parent))
{
$parent = $commit->repo->getObject($parent);
$p = $parent->find($file);
if($p===FALSE)
$p = NULL;
// Get our blob in the currently examined commit :
$blob = $commit->find($file);
// Check if it is the same as the 1st parent's one :
if($blob!==$p)
{
$r[] = $commit;
}
}
}
$r = array_reverse($r);
return $r;
}
// -------------------------------------------------------------------------
// Checkout the 'master' branch :
$master_name = $repo->getTip('master');
$commit = $repo->getObject($master_name); //returns GitCommit object that refers to the last commit of the 'master' branch.
// Print information about the last revision :
print "Last revision on branch master (".sha1_hex($commit->getName())."):<br />";
print $commit->author->name." (".$commit->author->email.")<br />";
print date("r", $commit->committer->time)."<br />";
print $commit->summary."<br /><br />";
// -------------------------------------------------------------------------
$versions = getVersions($f);
print "History of file <em>".$f."</em> (".sizeof($versions)." revisions) :<br /><br />";
foreach($versions as $v)
{
print "Commit ID : ".sha1_hex($v->getName())."<br />";
print "date : ".date("r", $v->committer->time)."<br /><br />";
//$entry = new stdClass;
//$entry->summary = $v->summary;
//$entry->author = $v->author->name;
//$entry->time = $v->author->time;
//$entry->commit = sha1_hex($v->getName());
//array_unshift($history, $entry);
}
?>
<?php
// Path to the repository :
$repository = dirname(__FILE__).'/.git';
// File that's going to be examined :
$file = "index.php";
// Sets timezone to GMT :
date_default_timezone_set("GMT");
// Glip is required, of course :
require_once(dirname(__FILE__).'/3rdparty/glip/lib/glip.php');
// Let's go :
$repo = new Git($repository);
$branch = $repo->getObject($repo->getTip('master'));
$content = file_get_contents($file);
// -------------------------------------------------------------------------
// Function definition :
function getVersions($file)
{
global $repo;
$r = array();
$branch = $repo->getObject($repo->getTip('master'));
$commits = $branch->getHistory();
foreach($commits as $commit)
{
$p = FALSE;
$parent = $commit->parents[0];
if(!empty($parent))
{
$parent = $commit->repo->getObject($parent);
$p = $parent->find($file);
if($p===FALSE)
$p = NULL;
// Get our blob in the currently examined commit :
$blob = $commit->find($file);
// Check if it is the same as the 1st parent's one :
if($blob!==$p)
{
$r[] = $commit;
}
}
}
$r = array_reverse($r);
return $r;
}
// -------------------------------------------------------------------------
// Commits a new version of the $file file :
// FIXME:
// BEFORE COMMITTING :
// * Check if $f file exists.
// * Check if $f file content has changed.
// *
$pending = array(); // Contains all objects that need to be written.
$blob = new GitBlob($repo);
$blob->data = $content;
$blob->rehash();
$pending[] = $blob;
$f = fopen(sprintf('%s/refs/heads/%s', $repo->dir, 'master'), 'a+b');
flock($f, LOCK_EX);
$ref = stream_get_contents($f);
$tree = $repo->getObject($branch->tree);
$pending = array_merge($pending, $tree->updateNode($file, 0100640, $blob->getName()));
$tree->rehash();
$pending[] = $tree;
$stamp = new GitCommitStamp();
$stamp->name = "ownCloud_versionner"; // Needed.
$stamp->email = "[email protected]"; // Needed.
$stamp->time = time();
$stamp->offset = idate('Z', $stamp->time);
$newcommit = new GitCommit($repo);
$newcommit->tree = $tree->getName();
$newcommit->parents = array($branch->getName());
$newcommit->author = $stamp;
$newcommit->committer = $stamp;
$newcommit->summary = sprintf('%s: %s', $file, "Automatically saved new version.");
$newcommit->detail = '';
$newcommit->rehash();
$pending[] = $newcommit;
foreach($pending as $obj)
$obj->write();
ftruncate($f, 0);
fwrite($f, sha1_hex($newcommit->getName()));
fclose($f);
// -------------------------------------------------------------------------
// Display $file history :
$versions = getVersions($file);
print "History of file <em>".$file."</em> (".sizeof($versions)." revisions) :<br /><br />";
foreach($versions as $v)
{
print "Commit ID : ".sha1_hex($v->getName())."<br />";
var_dump($v->committer);
print "date : ".date("r", $v->committer->time)."<br /><br />";
//$entry = new stdClass;
//$entry->summary = $v->summary;
//$entry->author = $v->author->name;
//$entry->time = $v->author->time;
//$entry->commit = sha1_hex($v->getName());
//array_unshift($history, $entry);
}
?>_______________________________________________
Owncloud mailing list
[email protected]
https://mail.kde.org/mailman/listinfo/owncloud