[prev in list] [next in list] [prev in thread] [next in thread]
List: owncloud
Subject: [Owncloud] Files versioning with glip
From: François_K. <daitheflu () free ! fr>
Date: 2011-03-15 14:24:56
Message-ID: 1197182515.7258751300199096330.JavaMail.root () zimbra9-e2 ! priv ! proxad ! net
[Download RAW message or body]
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
["index.php" (text/php)]
<?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);
}
?>
["index2.php" (text/php)]
<?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 = "owncloud@example.org"; // 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
Owncloud@kde.org
https://mail.kde.org/mailman/listinfo/owncloud
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic