| 1 | <?php |
| 2 | /* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
| 3 | /* |
| 4 | # ***** BEGIN LICENSE BLOCK ***** |
| 5 | # This file is part of InDefero, an open source project management application. |
| 6 | # Copyright (C) 2008 Céondo Ltd and contributors. |
| 7 | # |
| 8 | # InDefero is free software; you can redistribute it and/or modify |
| 9 | # it under the terms of the GNU General Public License as published by |
| 10 | # the Free Software Foundation; either version 2 of the License, or |
| 11 | # (at your option) any later version. |
| 12 | # |
| 13 | # InDefero is distributed in the hope that it will be useful, |
| 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 16 | # GNU General Public License for more details. |
| 17 | # |
| 18 | # You should have received a copy of the GNU General Public License |
| 19 | # along with this program; if not, write to the Free Software |
| 20 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
| 21 | # |
| 22 | # ***** END LICENSE BLOCK ***** */ |
| 23 | |
| 24 | /** |
| 25 | * Synchronize the SSH keys with InDefero. |
| 26 | */ |
| 27 | class IDF_Plugin_SyncGit_Cron |
| 28 | { |
| 29 | /** |
| 30 | * Template for the SSH key. |
| 31 | */ |
| 32 | public $template = 'command="python %s %s",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty %s'; |
| 33 | |
| 34 | /** |
| 35 | * Synchronize. |
| 36 | */ |
| 37 | public static function sync() |
| 38 | { |
| 39 | $template = Pluf::factory(__CLASS__)->template; |
| 40 | $cmd = Pluf::f('idf_plugin_syncgit_path_gitserve', '/dev/null'); |
| 41 | $authorized_keys = Pluf::f('idf_plugin_syncgit_path_authorized_keys', false); |
| 42 | if (false == $authorized_keys) { |
| 43 | throw new Pluf_Exception_SettingError('Setting idf_plugin_syncgit_path_authorized_keys not set.'); |
| 44 | } |
| 45 | if (!is_writable($authorized_keys)) { |
| 46 | throw new Exception('Cannot create file: '.$authorized_keys); |
| 47 | } |
| 48 | $out = ''; |
| 49 | $keys = Pluf::factory('IDF_Key')->getList(array('view'=>'join_user')); |
| 50 | foreach ($keys as $key) { |
| 51 | if (strlen($key->content) > 40 // minimal check |
| 52 | and preg_match('/^[a-zA-Z][a-zA-Z0-9_.-]*(@[a-zA-Z][a-zA-Z0-9.-]*)?$/', $key->login)) { |
| 53 | $content = trim(str_replace(array("\n", "\r"), '', $key->content)); |
| 54 | $out .= sprintf($template, $cmd, $key->login, $content)."\n"; |
| 55 | } |
| 56 | } |
| 57 | file_put_contents($authorized_keys, $out, LOCK_EX); |
| 58 | } |
| 59 | |
| 60 | /** |
| 61 | * Mark export of git repositories for the daemon. |
| 62 | */ |
| 63 | public static function markExport() |
| 64 | { |
| 65 | foreach (Pluf::factory('IDF_Project')->getList() as $project) { |
| 66 | $rep = sprintf(Pluf::f('git_repositories'), $project->shortname); |
| 67 | $serve = new IDF_Plugin_SyncGit_Serve(); |
| 68 | $serve->setGitExport($project->shortname, $rep); |
| 69 | } |
| 70 | } |
| 71 | |
| 72 | /** |
| 73 | * Remove orphan repositories. |
| 74 | */ |
| 75 | public static function removeOrphanRepositories() |
| 76 | { |
| 77 | $path = Pluf::f('idf_plugin_syncgit_base_repositories', '/home/git/repositories'); |
| 78 | if (!is_dir($path) || is_link($path)) { |
| 79 | throw new Pluf_Exception_SettingError(sprintf( |
| 80 | 'Directory %s does not exist! Setting "idf_plugin_syncgit_base_repositories not set.', |
| 81 | $path)); |
| 82 | } |
| 83 | if (!is_writable($path)) { |
| 84 | throw new Exception(sprintf('Repository %s is not writable.', $path)); |
| 85 | } |
| 86 | $projects = array(); |
| 87 | foreach (Pluf::factory('IDF_Project')->getList() as $project) { |
| 88 | $projects[] = $project->shortname; |
| 89 | } |
| 90 | unset($project); |
| 91 | $it = new DirectoryIterator($path); |
| 92 | $orphans = array(); |
| 93 | while ($it->valid()) { |
| 94 | if (!$it->isDot() && $it->isDir() && !in_array(basename($it->getFileName(), '.git'), $projects)) { |
| 95 | $orphans[] = $it->getPathName(); |
| 96 | } |
| 97 | $it->next(); |
| 98 | } |
| 99 | if (count($orphans)) { |
| 100 | $cmd = Pluf::f('idf_exec_cmd_prefix', '').'rm -rf '.implode(' ', $orphans); |
| 101 | exec($cmd); |
| 102 | while (list(, $project) = each($orphans)) { |
| 103 | if (is_dir($project)) { |
| 104 | throw new Exception(sprintf('Cannot remove %s directory.', $project)); |
| 105 | } |
| 106 | } |
| 107 | } |
| 108 | } |
| 109 | |
| 110 | /** |
| 111 | * Check if a sync is needed. |
| 112 | * |
| 113 | */ |
| 114 | public static function main() |
| 115 | { |
| 116 | if (file_exists(Pluf::f('idf_plugin_syncgit_sync_file'))) { |
| 117 | @unlink(Pluf::f('idf_plugin_syncgit_sync_file')); |
| 118 | self::sync(); |
| 119 | self::markExport(); |
| 120 | if (Pluf::f('idf_plugin_syncgit_remove_orphans', false)) { |
| 121 | self::removeOrphanRepositories(); |
| 122 | } |
| 123 | } |
| 124 | } |
| 125 | } |
| 126 | |