first checkin of files - pages are synced, no media sync support at the moment
authorWolfgang Gassler <wolfgang@gassler.org>
Thu, 1 Nov 2012 22:27:31 +0000 (23:27 +0100)
committerWolfgang Gassler <wolfgang@gassler.org>
Thu, 1 Nov 2012 22:27:31 +0000 (23:27 +0100)
README [new file with mode: 0644]
action/editcommit.php [new file with mode: 0644]
conf/default.php [new file with mode: 0644]
conf/metadata.php [new file with mode: 0644]
lang/en/settings.php [new file with mode: 0644]
lib/Git.php [new file with mode: 0644]
plugin.info.txt [new file with mode: 0644]

diff --git a/README b/README
new file mode 100644 (file)
index 0000000..16e8f89
--- /dev/null
+++ b/README
@@ -0,0 +1,27 @@
+gitbacked Plugin for DokuWiki
+
+Store/Sync pages and media files in a git repository
+
+All documentation for this plugin can be found at
+https://github.com/woolfg/gitbacked
+
+If you install this plugin manually, make sure it is installed in
+lib/plugins/gitbacked/ - if the folder is called different it
+will not work!
+
+Please refer to http://www.dokuwiki.org/plugins for additional info
+on how to install plugins in DokuWiki.
+
+----
+Copyright (C) Wolfgang Gassler <wolfgang@gassler.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; version 2 of the License
+
+This program 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 General Public License for more details.
+
+See the COPYING file in your DokuWiki folder for details
diff --git a/action/editcommit.php b/action/editcommit.php
new file mode 100644 (file)
index 0000000..9cb786f
--- /dev/null
@@ -0,0 +1,70 @@
+<?php
+/**
+ * DokuWiki Plugin gitbacked (Action Component)
+ *
+ * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
+ * @author  Wolfgang Gassler <wolfgang@gassler.org>
+ */
+
+// must be run within Dokuwiki
+if (!defined('DOKU_INC')) die();
+
+if (!defined('DOKU_LF')) define('DOKU_LF', "\n");
+if (!defined('DOKU_TAB')) define('DOKU_TAB', "\t");
+if (!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
+
+require_once DOKU_PLUGIN.'action.php';
+require_once(DOKU_PLUGIN.'gitbacked/lib/Git.php');
+
+class action_plugin_gitbacked_editcommit extends DokuWiki_Action_Plugin {
+
+    public function register(Doku_Event_Handler &$controller) {
+
+       $controller->register_hook('IO_WIKIPAGE_WRITE', 'AFTER', $this, 'handle_io_wikipage_write');
+  
+    }
+
+    public function handle_io_wikipage_write(Doku_Event &$event, $param) {
+
+               $rev = $event->data[3];
+               
+               /* On update to an existing page this event is called twice,
+               * once for the transfer of the old version to the attic (rev will have a value)
+               * and once to write the new version of the page into the wiki (rev is false) 
+               */
+               if (!$rev) {
+
+                       $pagePath = $event->data[0][0];
+                       $pageName = $event->data[2];
+
+                       $authorName = $GLOBALS['USERINFO']['name'];
+                       $editSummary = $GLOBALS['INFO']['meta']['last_change']['sum'];
+
+                       $message = str_replace(
+                               array('%page%','%summary%','%user%'),
+                               array($pageName,$editSummary,$authorName),
+                               $this->getConf('commitMsg')
+                       );
+
+                       //get path to the repo root (by default DokuWiki's savedir)
+                       $repoPath = $this->getConf('repoPath');
+                       
+                       //init the repo and create a new one if it is not present
+                       $repo = new GitRepo($repoPath, true, true);
+                       
+                       //add the changed file and set the commit message
+                       $repo->add($pagePath);
+                       $repo->commit($message);
+
+                       //if the push after Commit option is set we push the active branch to origin
+                       if ($this->getConf('pushAfterCommit')) {
+                               $repo->push('origin',$repo->active_branch());
+                       }
+
+               }
+
+    }
+
+}
+
+// vim:ts=4:sw=4:et:
diff --git a/conf/default.php b/conf/default.php
new file mode 100644 (file)
index 0000000..789b751
--- /dev/null
@@ -0,0 +1,10 @@
+<?php
+/**
+ * Default settings for the gitbacked plugin
+ *
+ * @author Wolfgang Gassler <wolfgang@gassler.org>
+ */
+
+$conf['pushAfterCommit'] = 0;
+$conf['commitMsg']     = '%page% changed with %summary% by %user%';
+$conf['repoPath']      = $GLOBALS['conf']['savedir'];
diff --git a/conf/metadata.php b/conf/metadata.php
new file mode 100644 (file)
index 0000000..56dad30
--- /dev/null
@@ -0,0 +1,11 @@
+<?php
+/**
+ * Options for the gitbacked plugin
+ *
+ * @author Wolfgang Gassler <wolfgang@gassler.org>
+ */
+
+$meta['pushAfterCommit'] = array('onoff');
+$meta['commitMsg'] = array('string');
+$meta['repoPath'] = array('string');
+
diff --git a/lang/en/settings.php b/lang/en/settings.php
new file mode 100644 (file)
index 0000000..58d0468
--- /dev/null
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * English strings for the gitbacked plugin
+ *
+ * @author Wolfgang Gassler <wolfgang@gassler.org>
+ */
+
+$lang['pushAfterCommit'] = 'Push active branch to remote origin after every commit';
+$lang['commitMsg']     = 'Commit Message (%user%,%summary%,%page% are replaced by the corresponding values)';
+$lang['repoPath']      = 'Path of the git repo (e.g. the savedir '.$GLOBALS['conf']['savedir'].')';
\ No newline at end of file
diff --git a/lib/Git.php b/lib/Git.php
new file mode 100644 (file)
index 0000000..36e24ad
--- /dev/null
@@ -0,0 +1,472 @@
+<?php
+
+/*
+ * Git.php
+ *
+ * A PHP git library
+ *
+ * @package    Git.php
+ * @version    0.1.1-a
+ * @author     James Brumond
+ * @copyright  Copyright 2010 James Brumond
+ * @license    http://github.com/kbjr/Git.php
+ * @link       http://code.kbjrweb.com/project/gitphp
+ */
+
+if (__FILE__ == $_SERVER['SCRIPT_FILENAME']) die('Bad load order');
+
+// ------------------------------------------------------------------------
+
+/**
+ * Git Interface Class
+ *
+ * This class enables the creating, reading, and manipulation
+ * of git repositories.
+ *
+ * @class  Git
+ */
+class Git {
+
+       /**
+        * Create a new git repository
+        *
+        * Accepts a creation path, and, optionally, a source path
+        *
+        * @access  public
+        * @param   string  repository path
+        * @param   string  directory to source
+        * @return  GitRepo
+        */
+       public static function &create($repo_path, $source = null) {
+               return GitRepo::create_new($repo_path, $source);
+       }
+
+       /**
+        * Open an existing git repository
+        *
+        * Accepts a repository path
+        *
+        * @access  public
+        * @param   string  repository path
+        * @return  GitRepo
+        */
+       public static function open($repo_path) {
+               return new GitRepo($repo_path);
+       }
+
+       /**
+        * Checks if a variable is an instance of GitRepo
+        *
+        * Accepts a variable
+        *
+        * @access  public
+        * @param   mixed   variable
+        * @return  bool
+        */
+       public static function is_repo($var) {
+               return (get_class($var) == 'GitRepo');
+       }
+
+}
+
+// ------------------------------------------------------------------------
+
+/**
+ * Git Repository Interface Class
+ *
+ * This class enables the creating, reading, and manipulation
+ * of a git repository
+ *
+ * @class  GitRepo
+ */
+class GitRepo {
+
+       protected $repo_path = null;
+
+       public $git_path = '/usr/bin/git';
+
+       /**
+        * Create a new git repository
+        *
+        * Accepts a creation path, and, optionally, a source path
+        *
+        * @access  public
+        * @param   string  repository path
+        * @param   string  directory to source
+        * @return  GitRepo
+        */
+       public static function &create_new($repo_path, $source = null) {
+               if (is_dir($repo_path) && file_exists($repo_path."/.git") && is_dir($repo_path."/.git")) {
+                       throw new Exception('"'.$repo_path.'" is already a git repository');
+               } else {
+                       $repo = new self($repo_path, true, false);
+                       if (is_string($source))
+                               $repo->clone_from($source);
+                       else $repo->run('init');
+                       return $repo;
+               }
+       }
+
+       /**
+        * Constructor
+        *
+        * Accepts a repository path
+        *
+        * @access  public
+        * @param   string  repository path
+        * @param   bool    create if not exists?
+        * @return  void
+        */
+       public function __construct($repo_path = null, $create_new = false, $_init = true) {
+               if (is_string($repo_path))
+                       $this->set_repo_path($repo_path, $create_new, $_init);
+       }
+
+       /**
+        * Set the repository's path
+        *
+        * Accepts the repository path
+        *
+        * @access  public
+        * @param   string  repository path
+        * @param   bool    create if not exists?
+        * @return  void
+        */
+       public function set_repo_path($repo_path, $create_new = false, $_init = true) {
+               if (is_string($repo_path)) {
+                       if ($new_path = realpath($repo_path)) {
+                               $repo_path = $new_path;
+                               if (is_dir($repo_path)) {
+                                       if (file_exists($repo_path."/.git") && is_dir($repo_path."/.git")) {
+                                               $this->repo_path = $repo_path;
+                                       } else {
+                                               if ($create_new) {
+                                                       $this->repo_path = $repo_path;
+                                                       if ($_init) $this->run('init');
+                                               } else {
+                                                       throw new Exception('"'.$repo_path.'" is not a git repository');
+                                               }
+                                       }
+                               } else {
+                                       throw new Exception('"'.$repo_path.'" is not a directory');
+                               }
+                       } else {
+                               if ($create_new) {
+                                       if ($parent = realpath(dirname($repo_path))) {
+                                               mkdir($repo_path);
+                                               $this->repo_path = $repo_path;
+                                               if ($_init) $this->run('init');
+                                       } else {
+                                               throw new Exception('cannot create repository in non-existent directory');
+                                       }
+                               } else {
+                                       throw new Exception('"'.$repo_path.'" does not exist');
+                               }
+                       }
+               }
+       }
+
+       /**
+        * Tests if git is installed
+        *
+        * @access  public
+        * @return  bool
+        */
+       public function test_git() {
+               $descriptorspec = array(
+                       1 => array('pipe', 'w'),
+                       2 => array('pipe', 'w'),
+               );
+               $pipes = array();
+               $resource = proc_open($this->git_path, $descriptorspec, $pipes);
+
+               $stdout = stream_get_contents($pipes[1]);
+               $stderr = stream_get_contents($pipes[2]);
+               foreach ($pipes as $pipe) {
+                       fclose($pipe);
+               }
+
+               $status = trim(proc_close($resource));
+               return ($status != 127);
+       }
+
+       /**
+        * Run a command in the git repository
+        *
+        * Accepts a shell command to run
+        *
+        * @access  protected
+        * @param   string  command to run
+        * @return  string
+        */
+       protected function run_command($command) {
+               $descriptorspec = array(
+                       1 => array('pipe', 'w'),
+                       2 => array('pipe', 'w'),
+               );
+               $pipes = array();
+               $resource = proc_open($command, $descriptorspec, $pipes, $this->repo_path);
+
+               $stdout = stream_get_contents($pipes[1]);
+               $stderr = stream_get_contents($pipes[2]);
+               foreach ($pipes as $pipe) {
+                       fclose($pipe);
+               }
+
+               $status = trim(proc_close($resource));
+               if ($status) throw new Exception($stderr);
+
+               return $stdout;
+       }
+
+       /**
+        * Run a git command in the git repository
+        *
+        * Accepts a git command to run
+        *
+        * @access  public
+        * @param   string  command to run
+        * @return  string
+        */
+       public function run($command) {
+               return $this->run_command($this->git_path." ".$command);
+       }
+
+       /**
+        * Runs a `git add` call
+        *
+        * Accepts a list of files to add
+        *
+        * @access  public
+        * @param   mixed   files to add
+        * @return  string
+        */
+       public function add($files = "*") {
+               if (is_array($files)) $files = '"'.implode('" "', $files).'"';
+               return $this->run("add $files -v");
+       }
+
+       /**
+        * Runs a `git commit` call
+        *
+        * Accepts a commit message string
+        *
+        * @access  public
+        * @param   string  commit message
+        * @return  string
+        */
+       public function commit($message = "") {
+               return $this->run("commit -av -m \"$message\"");
+       }
+
+       /**
+        * Runs a `git clone` call to clone the current repository
+        * into a different directory
+        *
+        * Accepts a target directory
+        *
+        * @access  public
+        * @param   string  target directory
+        * @return  string
+        */
+       public function clone_to($target) {
+               return $this->run("clone --local ".$this->repo_path." $target");
+       }
+
+       /**
+        * Runs a `git clone` call to clone a different repository
+        * into the current repository
+        *
+        * Accepts a source directory
+        *
+        * @access  public
+        * @param   string  source directory
+        * @return  string
+        */
+       public function clone_from($source) {
+               return $this->run("clone --local $source ".$this->repo_path);
+       }
+
+       /**
+        * Runs a `git clone` call to clone a remote repository
+        * into the current repository
+        *
+        * Accepts a source url
+        *
+        * @access  public
+        * @param   string  source url
+        * @return  string
+        */
+       public function clone_remote($source) {
+               return $this->run("clone $source ".$this->repo_path);
+       }
+
+       /**
+        * Runs a `git clean` call
+        *
+        * Accepts a remove directories flag
+        *
+        * @access  public
+        * @param   bool    delete directories?
+        * @return  string
+        */
+       public function clean($dirs = false) {
+               return $this->run("clean".(($dirs) ? " -d" : ""));
+       }
+
+       /**
+        * Runs a `git branch` call
+        *
+        * Accepts a name for the branch
+        *
+        * @access  public
+        * @param   string  branch name
+        * @return  string
+        */
+       public function create_branch($branch) {
+               return $this->run("branch $branch");
+       }
+
+       /**
+        * Runs a `git branch -[d|D]` call
+        *
+        * Accepts a name for the branch
+        *
+        * @access  public
+        * @param   string  branch name
+        * @return  string
+        */
+       public function delete_branch($branch, $force = false) {
+               return $this->run("branch ".(($force) ? '-D' : '-d')." $branch");
+       }
+
+       /**
+        * Runs a `git branch` call
+        *
+        * @access  public
+        * @param   bool    keep asterisk mark on active branch
+        * @return  array
+        */
+       public function list_branches($keep_asterisk = false) {
+               $branchArray = explode("\n", $this->run("branch"));
+               foreach($branchArray as $i => &$branch) {
+                       $branch = trim($branch);
+                       if (! $keep_asterisk)
+                               $branch = str_replace("* ", "", $branch);
+                       if ($branch == "")
+                               unset($branchArray[$i]);
+               }
+               return $branchArray;
+       }
+
+       /**
+        * Returns name of active branch
+        *
+        * @access  public
+        * @param   bool    keep asterisk mark on branch name
+        * @return  string
+        */
+       public function active_branch($keep_asterisk = false) {
+               $branchArray = $this->list_branches(true);
+               $active_branch = preg_grep("/^\*/", $branchArray);
+               reset($active_branch);
+               if ($keep_asterisk)
+                       return current($active_branch);
+               else
+                       return str_replace("* ", "", current($active_branch));
+       }
+
+       /**
+        * Runs a `git checkout` call
+        *
+        * Accepts a name for the branch
+        *
+        * @access  public
+        * @param   string  branch name
+        * @return  string
+        */
+       public function checkout($branch) {
+               return $this->run("checkout $branch");
+       }
+
+
+    /**
+     * Runs a `git merge` call
+     *
+     * Accepts a name for the branch to be merged
+     *
+     * @access  public
+     * @param   string $branch
+     * @return  string
+     */
+    public function merge($branch)
+    {
+        return $this->run("merge $branch --no-ff");
+    }
+
+
+    /**
+     * Runs a git fetch on the current branch
+     *
+     * @access  public
+     * @return  string
+     */
+    public function fetch()
+    {
+        return $this->run("fetch");
+    }
+
+    /**
+     * Add a new tag on the current position
+     *
+     * Accepts the name for the tag and the message
+     *
+     * @param string $tag
+     * @param string $message
+     * @return string
+     */
+    public function add_tag($tag, $message = null)
+    {
+        if ($message === null) {
+            $message = $tag;
+        }
+        return $this->run("tag -a $tag -m $message");
+    }
+
+
+    /**
+     * Push specific branch to a remote
+     *
+     * Accepts the name of the remote and local branch
+     *
+     * @param string $remote
+     * @param string $branch
+     * @return string
+     */
+    public function push($remote, $branch)
+    {
+        return $this->run("push --tags $remote $branch");
+    }
+    
+    /**
+     * Sets the project description.
+     *
+     * @param string $new
+     */
+    public function set_description($new)
+    {
+        file_put_contents($this->repo_path."/.git/description", $new);
+    }
+
+    /**
+     * Gets the project description.
+     *
+     * @return string
+     */
+    public function get_description()
+    {
+        return file_get_contents($this->repo_path."/.git/description");
+    }
+}
+
+/* End Of File */
diff --git a/plugin.info.txt b/plugin.info.txt
new file mode 100644 (file)
index 0000000..15a8089
--- /dev/null
@@ -0,0 +1,7 @@
+base   gitbacked
+author Wolfgang Gassler
+email  wolfgang@gassler.org
+date   2012-10-31
+name   gitbacked plugin
+desc   Pages and Media are stored in Git
+url    https://github.com/woolfg/gitbacked