New plugin repo cloned using new GitRepo class. Readme and info displayed in wide modal dialog.

This commit is contained in:
Andrew Manning 2016-05-07 18:39:19 -04:00
parent 284d86ad76
commit 0746794e81
5 changed files with 170 additions and 160 deletions

View File

@ -1,7 +1,7 @@
<?php <?php
namespace Zotlabs\Module; namespace Zotlabs\Module;
use PHPGit\Git as Git; use \Zotlabs\Storage\GitRepo as GitRepo;
/** /**
* @file mod/admin.php * @file mod/admin.php
@ -1359,6 +1359,15 @@ class Admin extends \Zotlabs\Web\Controller {
'$submit' => t('Download Plugin Repo') '$submit' => t('Download Plugin Repo')
) )
); );
$newRepoModalID = random_string(3);
$newRepoModal = replace_macros(
get_markup_template('generic_modal.tpl'), array(
'$id' => $newRepoModalID,
'$title' => t('Install new repo'),
'$ok' => t('OK'),
'$cancel' => t('Cancel')
)
);
$t = get_markup_template('admin_plugins.tpl'); $t = get_markup_template('admin_plugins.tpl');
return replace_macros($t, array( return replace_macros($t, array(
@ -1372,7 +1381,9 @@ class Admin extends \Zotlabs\Web\Controller {
'$form_security_token' => get_form_security_token('admin_plugins'), '$form_security_token' => get_form_security_token('admin_plugins'),
'$addrepo' => t('Add Plugin Repo'), '$addrepo' => t('Add Plugin Repo'),
'$expandform' => false, '$expandform' => false,
'$form' => $admin_plugins_add_repo_form '$form' => $admin_plugins_add_repo_form,
'$newRepoModal' => $newRepoModal,
'$newRepoModalID' => $newRepoModalID
)); ));
} }
@ -1669,57 +1680,23 @@ class Admin extends \Zotlabs\Web\Controller {
function admin_page_plugins_post($action) { function admin_page_plugins_post($action) {
switch($action) { switch($action) {
case 'addrepo': case 'addrepo':
require_once('library/markdown.php'); require_once('library/markdown.php');
if(array_key_exists('repoURL',$_REQUEST)) { if(array_key_exists('repoURL',$_REQUEST)) {
require __DIR__ . '/../../library/PHPGit.autoload.php'; // Load PHPGit dependencies require __DIR__ . '/../../library/PHPGit.autoload.php'; // Load PHPGit dependencies
logger('Repo URL submitted: ' . $_REQUEST['repoURL']); logger('Repo URL submitted: ' . $_REQUEST['repoURL']);
$repoURL = $_REQUEST['repoURL']; $repoURL = $_REQUEST['repoURL'];
$urlpath = parse_url($repoURL, PHP_URL_PATH); $git = new GitRepo('sys', $repoURL, true);
$lastslash = strrpos($urlpath, '/') + 1;
$gitext = strrpos($urlpath, '.'); $repo = $git->probeRepo($git->path);
if ($gitext) {
$reponame = substr($urlpath, $lastslash, $gitext - $lastslash);
} else {
logger('invalid git repo URL');
notice('Invalid git repo URL');
break;
}
$storepath = realpath(__DIR__ . '/../../store/');
//logger('storepath: ' . $storepath);
$repopath = $storepath . '/pluginrepos/' . $reponame;
$git = new Git();
if (!file_exists($repopath)) {
//logger('repopath does not exist');
if (mkdir($repopath, 0770, true)) {
$cloned = $git->clone($repoURL, $repopath);
if (!$cloned) {
logger('git clone failed');
notice('Repo coule not be cloned. Filesystem path error.');
json_return_and_die(array('message' => 'Repo could not be cloned. Filesystem path error.', 'success' => false));
}
//json_return_and_die(array('repo'=> $repo, 'message' => 'Successfully cloned to: ' . $repopath , 'success' => true));
} else {
logger('repopath could not be created');
notice('Repo coule not be cloned. Filesystem path error.');
json_return_and_die(array('message' => 'Repo could not be cloned. Filesystem path error', 'success' => false));
}
}
$git->setRepository($repopath);
$repo = array();
$repo['url'] = $repoURL;
$repo['branches'] = $git->branch(['all' => true]);
$repo['objects'] = array();
$repo['readme'] = $repo['manifest'] = null; $repo['readme'] = $repo['manifest'] = null;
foreach ($git->tree('master') as $object) { foreach ($git->git->tree('master') as $object) {
if ($object['type'] == 'blob' && (strtolower($object['file']) === 'readme.md' || strtolower($object['file']) === 'readme')) { if ($object['type'] == 'blob' && (strtolower($object['file']) === 'readme.md' || strtolower($object['file']) === 'readme')) {
$repo['readme'] = Markdown($git->cat->blob($object['hash'])); $repo['readme'] = Markdown($git->git->cat->blob($object['hash']));
} else if ($object['type'] == 'blob' && strtolower($object['file']) === 'manifest.json') { } else if ($object['type'] == 'blob' && strtolower($object['file']) === 'manifest.json') {
$repo['manifest'] = $git->cat->blob($object['hash']); $repo['manifest'] = $git->git->cat->blob($object['hash']);
} }
} }
//logger('repo: ' . json_encode($repo));
json_return_and_die(array('repo'=> $repo, 'message' => '', 'success' => true)); json_return_and_die(array('repo'=> $repo, 'message' => '', 'success' => true));
} else { } else {

View File

@ -1,106 +0,0 @@
<?php
namespace Zotlabs\Storage;
use PHPGit\Git as PHPGit;
require __DIR__ . '/../../library/PHPGit.autoload.php'; // Load PHPGit dependencies
/**
* Description of Git
*
* @author Andrew Manning <andrewmanning@grid.reticu.li>
*/
class GitRepo {
public $url = null;
public $name = null;
public $path = null;
private $repoID = null;
private $channel = null;
private $git = null;
private $repoBasePath = __DIR__ . '/../../store/git';
function __construct($channel = 'sys', $name = null, $url = null, $clone = false) {
$this->channel = $channel;
$this->git = new PHPGit();
if ($name) {
$this->name = $name;
$this->path = $this->repoBasePath . "/" . $this->channel . "/" . $this->name;
if (file_exists($this->path)) {
// ignore the $url input if it exists
$this->git->setRepository($this->path);
// TODO: get repo metadata
} else if ($url && validate_url($url)) {
$this->url = $url;
$this->repoID = random_string();
// create the folder and clone the repo at url to that folder if $clone is true
if ($clone) {
if (mkdir($this->path, 0770, true)) {
$this->git->setRepository($this->path);
if (!$this->cloneRepo()) {
// TODO: throw error
logger('git clone failed: ' . json_encode($this->git));
}
} else {
logger('git repo path could not be created: ' . json_encode($this->git));
}
}
}
} else {
// Construct an empty GitRepo object
//$this->name = random_string(32);
//$this->repoID = random_string();
}
}
/**
* delete repository from disk
*/
public function delete() {
return $this->delTree($this->getRepoPath());
}
public function getRepoPath() {
return $this->path;
}
public function setRepoPath($directory) {
if (file_exists($directory)) {
$this->path->$directory;
$this->git->setRepository($directory);
return true;
}
return false;
}
public function getRepoID() {
return $this->repoID;
}
public function setIdentity($user_name, $user_email) {
// setup user for commit messages
$this->git->config->set("user.name", $user_name, ['global' => false, 'system' => false]);
$this->git->config->set("user.email", $user_email, ['global' => false, 'system' => false]);
}
public function cloneRepo() {
if (validate_url($this->url) && file_exists($this->path)) {
return $this->git->clone($this->url, $this->path);
}
}
public static function probeRepo($dir) {
if (!file_exists($dir)) {
return null;
}
$git = new PHPGit();
$git->setRepository($dir);
$repo = array();
$repo['remote'] = $git->remote();
$repo['branches'] = $git->branch(['all' => true]);
$repo['logs'] = $git->log(array('limit' => 50));
return $repo;
}
}

127
Zotlabs/Storage/GitRepo.php Normal file
View File

@ -0,0 +1,127 @@
<?php
namespace Zotlabs\Storage;
use PHPGit\Git as PHPGit;
require __DIR__ . '/../../library/PHPGit.autoload.php'; // Load PHPGit dependencies
/**
* Description of Git
*
* @author Andrew Manning <andrewmanning@grid.reticu.li>
*/
class GitRepo {
public $url = null;
public $name = null;
public $path = null;
private $repoID = null;
private $channel = null;
public $git = null;
private $repoBasePath = null;
function __construct($channel = 'sys', $url = null, $clone = false, $name = null) {
$this->repoBasePath = __DIR__ . '/../../store/git';
$this->channel = $channel;
$this->git = new PHPGit();
if ($name) {
$this->name = $name;
} else {
$this->name = $this->getRepoNameFromURL($url);
}
if (!$this->name) {
logger('Error creating GitRepo. No repo name found.');
return null;
}
$this->path = $this->repoBasePath . "/" . $this->channel . "/" . $this->name;
if (file_exists($this->path)) {
// ignore the $url input if it exists
$this->git->setRepository($this->path);
// TODO: get repo metadata
} else if ($url && validate_url($url) && $this->isValidGitRepoURL($url)) {
$this->url = $url;
$this->repoID = random_string();
// create the folder and clone the repo at url to that folder if $clone is true
if ($clone) {
if (mkdir($this->path, 0770, true)) {
$this->git->setRepository($this->path);
if (!$this->cloneRepo()) {
// TODO: throw error
logger('git clone failed: ' . json_encode($this->git));
}
} else {
logger('git repo path could not be created: ' . json_encode($this->git));
}
}
}
}
/**
* delete repository from disk
*/
public function delete() {
return $this->delTree($this->getRepoPath());
}
public function getRepoPath() {
return $this->path;
}
public function setRepoPath($directory) {
if (file_exists($directory)) {
$this->path->$directory;
$this->git->setRepository($directory);
return true;
}
return false;
}
public function getRepoID() {
return $this->repoID;
}
public function setIdentity($user_name, $user_email) {
// setup user for commit messages
$this->git->config->set("user.name", $user_name, ['global' => false, 'system' => false]);
$this->git->config->set("user.email", $user_email, ['global' => false, 'system' => false]);
}
public function cloneRepo() {
if (validate_url($this->url) && $this->isValidGitRepoURL($this->url) && file_exists($this->path)) {
return $this->git->clone($this->url, $this->path);
}
}
public static function probeRepo($dir) {
if (!file_exists($dir)) {
return null;
}
$git = new PHPGit();
$git->setRepository($dir);
$repo = array();
$repo['remote'] = $git->remote();
$repo['branches'] = $git->branch(['all' => true]);
$repo['logs'] = $git->log(array('limit' => 50));
return $repo;
}
public static function isValidGitRepoURL($url) {
if (strrpos(parse_url($url, PHP_URL_PATH), '.')) {
return true;
} else {
return false;
}
}
public static function getRepoNameFromURL($url) {
$urlpath = parse_url($url, PHP_URL_PATH);
$lastslash = strrpos($urlpath, '/') + 1;
$gitext = strrpos($urlpath, '.');
if ($gitext) {
return substr($urlpath, $lastslash, $gitext - $lastslash);
} else {
return null;
}
}
}

View File

@ -34,7 +34,7 @@
</div> </div>
</div> </div>
{{$newRepoModal}}
<script> <script>
function adminPluginsAddRepo() { function adminPluginsAddRepo() {
var repoURL = $('#id_repoURL').val(); var repoURL = $('#id_repoURL').val();
@ -44,16 +44,13 @@
function(response) { function(response) {
$('#chat-rotator').spin(false); $('#chat-rotator').spin(false);
if (response.success) { if (response.success) {
$('#new-repo-info').html('<h3>Repo Info</h3><p>' + response.message + '</p>'); var modalBody = $('#generic-modal-body-{{$newRepoModalID}}');
modalBody.html('<div>'+response.repo.readme+'</div>');
$('#new-repo-info').append('<h4>Branches</h4><p>'+JSON.stringify(response.repo.branches)+'</p>'); modalBody.append('<h2>Repo Info</h2><p>Message: ' + response.message + '</p>');
$('#new-repo-info').append('<h4>URL</h4><p>'+response.repo.url+'</p>'); modalBody.append('<h4>Branches</h4><p>'+JSON.stringify(response.repo.branches)+'</p>');
$('#new-repo-info').append('<h4>Objects</h4><ul>'); modalBody.append('<h4>Remotes</h4><p>'+JSON.stringify(response.repo.remote)+'</p>');
for(var i = 0; i<response.repo.objects.length; i++) { $('.modal-dialog').width('80%');
$('#new-repo-info').append('<li>'+response.repo.objects[i]+'</li>'); $('#generic-modal-{{$newRepoModalID}}').modal();
}
$('#new-repo-info').append('</ul>');
$('#new-repo-info').append('<h4>Readme</h4><p>'+response.repo.readme+'</p>');
} else { } else {
window.console.log('Error adding repo :' + response['message']); window.console.log('Error adding repo :' + response['message']);
} }

View File

@ -0,0 +1,15 @@
<div class="modal" id="generic-modal-{{$id}}" tabindex="-1" role="dialog" aria-labelledby="generic-modal-{{$id}}" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title" id="generic-modal-title-{{$id}}">{{$title}}</h4>
</div>
<div class="modal-body" id="generic-modal-body-{{$id}}"></div>
<div class="modal-footer">
<button id="generic-modal-cancel-{{$id}}" type="button" class="btn btn-default" data-dismiss="modal">{{$cancel}}</button>
<button id="generic-modal-ok-{{$id}}" type="button" class="btn btn-primary">{{$ok}}</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->