diff options
Diffstat (limited to 'apps/files_versioning/versionstorage.php')
-rw-r--r-- | apps/files_versioning/versionstorage.php | 386 |
1 files changed, 0 insertions, 386 deletions
diff --git a/apps/files_versioning/versionstorage.php b/apps/files_versioning/versionstorage.php deleted file mode 100644 index d083e623df9..00000000000 --- a/apps/files_versioning/versionstorage.php +++ /dev/null @@ -1,386 +0,0 @@ -<?php -/** - * ownCloud file storage implementation for Git repositories - * @author Craig Roberts - * @copyright 2012 Craig Roberts craig0990@googlemail.com - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE - * License as published by the Free Software Foundation; either - * version 3 of the License, or any later version. - * - * This library 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 AFFERO GENERAL PUBLIC LICENSE for more details. - * - * You should have received a copy of the GNU Affero General Public - * License along with this library. If not, see <http://www.gnu.org/licenses/>. - */ - -// Include Granite -require_once('lib_granite.php'); - -// Create a top-level 'Backup' directory if it does not already exist -$user = OC_User::getUser(); -if (OC_Filesystem::$loaded and !OC_Filesystem::is_dir('/Backup')) { - OC_Filesystem::mkdir('/Backup'); - OC_Preferences::setValue(OC_User::getUser(), 'files_versioning', 'head', 'HEAD'); -} - -// Generate the repository path (currently using 'full' repositories, as opposed to bare ones) -$repo_path = DIRECTORY_SEPARATOR - . OC_User::getUser() - . DIRECTORY_SEPARATOR - . 'files' - . DIRECTORY_SEPARATOR - . 'Backup'; - -// Mount the 'Backup' folder using the versioned storage provider below -OC_Filesystem::mount('OC_Filestorage_Versioned', array('repo'=>$repo_path), $repo_path . DIRECTORY_SEPARATOR); - -class OC_Filestorage_Versioned extends OC_Filestorage { - - /** - * Holds an instance of Granite\Git\Repository - */ - protected $repo; - - /** - * Constructs a new OC_Filestorage_Versioned instance, expects an associative - * array with a `repo` key set to the path of the repository's `.git` folder - * - * @param array $parameters An array containing the key `repo` pointing to the - * repository path. - */ - public function __construct($parameters) { - // Get the full path to the repository folder - $path = OC_Config::getValue('datadirectory', OC::$SERVERROOT.'/data') - . $parameters['repo'] - . DIRECTORY_SEPARATOR - . '.git' - . DIRECTORY_SEPARATOR; - - try { - // Attempt to load the repository - $this->repo = new Granite\Git\Repository($path); - } catch (InvalidArgumentException $e) { - // $path is not a valid Git repository, we must create one - Granite\Git\Repository::init($path); - - // Load the newly-initialised repository - $this->repo = new Granite\Git\Repository($path); - - /** - * Create an initial commit with a README file - * FIXME: This functionality should be transferred to the Granite library - */ - $blob = new Granite\Git\Blob($this->repo->path()); - $blob->content('Your Backup directory is now ready for use.'); - - // Create a new tree to hold the README file - $tree = $this->repo->factory('tree'); - // Create a tree node to represent the README blob - $tree_node = new Granite\Git\Tree\Node('README', '100644', $blob->sha()); - $tree->nodes(array($tree_node->name() => $tree_node)); - - // Create an initial commit - $commit = new Granite\Git\Commit($this->repo->path()); - $user_string = OC_User::getUser() . ' ' . time() . ' +0000'; - $commit->author($user_string); - $commit->committer($user_string); - $commit->message('Initial commit'); - $commit->tree($tree); - - // Write it all to disk - $blob->write(); - $tree->write(); - $commit->write(); - - // Update the HEAD for the 'master' branch - $this->repo->head('master', $commit->sha()); - } - - // Update the class pointer to the HEAD - $head = OC_Preferences::getValue(OC_User::getUser(), 'files_versioning', 'head', 'HEAD'); - - // Load the most recent commit if the preference is not set - if ($head == 'HEAD') { - $this->head = $this->repo->head()->sha(); - } else { - $this->head = $head; - } - } - - public function mkdir($path) { - if (mkdir("versioned:/{$this->repo->path()}$path#{$this->head}")) { - $this->head = $this->repo->head()->sha(); - OC_Preferences::setValue(OC_User::getUser(), 'files_versioning', 'head', $head); - return true; - } - - return false; - } - - public function rmdir($path) { - - } - - /** - * Returns a directory handle to the requested path, or FALSE on failure - * - * @param string $path The directory path to open - * - * @return boolean|resource A directory handle, or FALSE on failure - */ - public function opendir($path) { - return opendir("versioned:/{$this->repo->path()}$path#{$this->head}"); - } - - /** - * Returns TRUE if $path is a directory, or FALSE if not - * - * @param string $path The path to check - * - * @return boolean - */ - public function is_dir($path) { - return $this->filetype($path) == 'dir'; - } - - /** - * Returns TRUE if $path is a file, or FALSE if not - * - * @param string $path The path to check - * - * @return boolean - */ - public function is_file($path) { - return $this->filetype($path) == 'file'; - } - - public function stat($path) - { - return stat("versioned:/{$this->repo->path()}$path#{$this->head}"); - } - - /** - * Returns the strings 'dir' or 'file', depending on the type of $path - * - * @param string $path The path to check - * - * @return string Returns 'dir' if a directory, 'file' otherwise - */ - public function filetype($path) { - if ($path == "" || $path == "/") { - return 'dir'; - } else { - if (substr($path, -1) == '/') { - $path = substr($path, 0, -1); - } - - $node = $this->tree_search($this->repo, $this->repo->factory('commit', $this->head)->tree(), $path); - - // Does it exist, or is it new? - if ($node == null) { - // New file - return 'file'; - } else { - // Is it a tree? - try { - $this->repo->factory('tree', $node); - return 'dir'; - } catch (InvalidArgumentException $e) { - // Nope, must be a blob - return 'file'; - } - } - } - } - - public function filesize($path) { - return filesize("versioned:/{$this->repo->path()}$path#{$this->head}"); - } - - /** - * Returns a boolean value representing whether $path is readable - * - * @param string $path The path to check - *( - * @return boolean Whether or not the path is readable - */ - public function is_readable($path) { - return true; - } - - /** - * Returns a boolean value representing whether $path is writable - * - * @param string $path The path to check - *( - * @return boolean Whether or not the path is writable - */ - public function is_writable($path) { - - $head = OC_Preferences::getValue(OC_User::getUser(), 'files_versioning', 'head', 'HEAD'); - if ($head !== 'HEAD' && $head !== $this->repo->head()->sha()) { - // Cannot modify previous commits - return false; - } - return true; - } - - /** - * Returns a boolean value representing whether $path exists - * - * @param string $path The path to check - *( - * @return boolean Whether or not the path exists - */ - public function file_exists($path) { - return file_exists("versioned:/{$this->repo->path()}$path#{$this->head}"); - } - - /** - * Returns an integer value representing the inode change time - * (NOT IMPLEMENTED) - * - * @param string $path The path to check - *( - * @return int Timestamp of the last inode change - */ - public function filectime($path) { - return -1; - } - - /** - * Returns an integer value representing the file modification time - * - * @param string $path The path to check - *( - * @return int Timestamp of the last file modification - */ - public function filemtime($path) { - return filemtime("versioned:/{$this->repo->path()}$path#{$this->head}"); - } - - public function file_get_contents($path) { - return file_get_contents("versioned:/{$this->repo->path()}$path#{$this->head}"); - } - - public function file_put_contents($path, $data) { - $success = file_put_contents("versioned:/{$this->repo->path()}$path#{$this->head}", $data); - if ($success !== false) { - // Update the HEAD in the preferences - OC_Preferences::setValue(OC_User::getUser(), 'files_versioning', 'head', $this->repo->head()->sha()); - return $success; - } - - return false; - } - - public function unlink($path) { - - } - - public function rename($path1, $path2) { - - } - - public function copy($path1, $path2) { - - } - - public function fopen($path, $mode) { - return fopen("versioned:/{$this->repo->path()}$path#{$this->head}", $mode); - } - - public function getMimeType($path) { - if ($this->filetype($path) == 'dir') { - return 'httpd/unix-directory'; - } elseif ($this->filesize($path) == 0) { - // File's empty, returning text/plain allows opening in the web editor - return 'text/plain'; - } else { - $finfo = new finfo(FILEINFO_MIME_TYPE); - /** - * We need to represent the repository path, the file path, and the - * revision, which can be simply achieved with a convention of using - * `.git` in the repository directory (bare or not) and the '#part' - * segment of a URL to specify the revision. For example - * - * versioned://var/www/myrepo.git/docs/README.md#HEAD ('bare' repo) - * versioned://var/www/myrepo/.git/docs/README.md#HEAD ('full' repo) - * versioned://var/www/myrepo/.git/docs/README.md#6a8f...8a54 ('full' repo and SHA-1 commit ID) - */ - $mime = $finfo->buffer(file_get_contents("versioned:/{$this->repo->path()}$path#{$this->head}")); - return $mime; - } - } - - /** - * Generates a hash based on the file contents - * - * @param string $type The hashing algorithm to use (e.g. 'md5', 'sha256', etc.) - * @param string $path The file to be hashed - * @param boolean $raw Outputs binary data if true, lowercase hex digits otherwise - * - * @return string Hashed string representing the file contents - */ - public function hash($type, $path, $raw) { - return hash($type, file_get_contents($path), $raw); - } - - public function free_space($path) { - } - - public function search($query) { - - } - - public function touch($path, $mtime=null) { - - } - - - public function getLocalFile($path) { - } - - /** - * Recursively searches a tree for a path, returning FALSE if is not found - * or an SHA-1 id if it is found. - * - * @param string $repo The repository containing the tree object - * @param string $tree The tree object to search - * @param string $path The path to search for (relative to the tree) - * @param int $depth The depth of the current search (for recursion) - * - * @return string|boolean The SHA-1 id of the sub-tree - */ - private function tree_search($repo, $tree, $path, $depth = 0) - { - $paths = array_values(explode(DIRECTORY_SEPARATOR, $path)); - - $current_path = $paths[$depth]; - - $nodes = $tree->nodes(); - foreach ($nodes as $node) { - if ($node->name() == $current_path) { - - if (count($paths)-1 == $depth) { - // Stop, found it - return $node->sha(); - } - - // Recurse if necessary - if ($node->isDirectory()) { - $tree = $this->repo->factory('tree', $node->sha()); - return $this->tree_search($repo, $tree, $path, $depth + 1); - } - } - } - - return false; - } - -} |