Explorar el Código

Support updating optional installed apps via git (#6513)

* WIP: Support updating optional installed apps via git

* support app source update via cli

* Update app_languages.php

* Update index.php

* Refactor App Git updating

Refactor Optional App Git updating for more resilience and better handling of ssh remotes and to only update each repository once.

* git app updates fix gui updates for repo based updating
demonspork hace 1 año
padre
commit
38b98fb9d6
Se han modificado 4 ficheros con 280 adiciones y 26 borrados
  1. 42 0
      core/upgrade/app_languages.php
  2. 116 25
      core/upgrade/index.php
  3. 19 1
      core/upgrade/upgrade.php
  4. 103 0
      resources/functions.php

+ 42 - 0
core/upgrade/app_languages.php

@@ -350,6 +350,27 @@ $text['label-upgrade_source']['zh-cn'] = "源代码";
 $text['label-upgrade_source']['ja-jp'] = "ソースコード";
 $text['label-upgrade_source']['ko-kr'] = "소스 코드";
 
+$text['label-update_apps']['en-us'] = "App Source Code";
+$text['label-update_apps']['en-gb'] = "App Source Code";
+$text['label-update_apps']['ar-eg'] = "";
+$text['label-update_apps']['de-at'] = "Quellcode"; //copied from de-de
+$text['label-update_apps']['de-ch'] = "Quellcode"; //copied from de-de
+$text['label-update_apps']['de-de'] = "Quellcode";
+$text['label-update_apps']['es-cl'] = "Código Fuente";
+$text['label-update_apps']['es-mx'] = "Código Fuente"; //copied from es-cl
+$text['label-update_apps']['fr-ca'] = "Code Source"; //copied from fr-fr
+$text['label-update_apps']['fr-fr'] = "Code Source";
+$text['label-update_apps']['he-il'] = "";
+$text['label-update_apps']['it-it'] = "Codice Sorgente";
+$text['label-update_apps']['nl-nl'] = "";
+$text['label-update_apps']['pl-pl'] = "Kod źródłowy";
+$text['label-update_apps']['pt-br'] = "Código Fonte"; //copied from pt-pt
+$text['label-update_apps']['pt-pt'] = "Source Code";
+$text['label-update_apps']['ro-ro'] = "";
+$text['label-update_apps']['ru-ru'] = "Исходный код";
+$text['label-update_apps']['sv-se'] = "Källkod";
+$text['label-update_apps']['uk-ua'] = "Вихідний код";
+
 $text['label-upgrade_schema']['en-us'] = "Schema";
 $text['label-upgrade_schema']['en-gb'] = "Schema";
 $text['label-upgrade_schema']['ar-eg'] = "مخطط";
@@ -850,6 +871,27 @@ $text['description-upgrade_source']['zh-cn'] = "从存储库更新FusionPBX源
 $text['description-upgrade_source']['ja-jp'] = "FusionPBXソースファイルをリポジトリから更新します。";
 $text['description-upgrade_source']['ko-kr'] = "저장소에서 Fusionpbx 소스 파일을 업데이트합니다.";
 
+$text['description-update_apps']['en-us'] = "Updates optional app source files from the respository.";
+$text['description-update_apps']['en-gb'] = "Updates optional app source files from the respository.";
+$text['description-update_apps']['ar-eg'] = "";
+$text['description-update_apps']['de-at'] = "Aktualisiert den Quellcode aus dem Repository"; //copied from de-de
+$text['description-update_apps']['de-ch'] = "Aktualisiert den Quellcode aus dem Repository"; //copied from de-de
+$text['description-update_apps']['de-de'] = "Aktualisiert den Quellcode aus dem Repository";
+$text['description-update_apps']['es-cl'] = "Archivos de origen Actualizaciones del repositorio.";
+$text['description-update_apps']['es-mx'] = "Archivos de origen Actualizaciones del repositorio."; //copied from es-cl
+$text['description-update_apps']['fr-ca'] = "Mise à jour du code source de depuis le dépôt."; //copied from fr-fr
+$text['description-update_apps']['fr-fr'] = "Mise à jour du code source de depuis le dépôt.";
+$text['description-update_apps']['he-il'] = "";
+$text['description-update_apps']['it-it'] = "Aggiorna il files sorgente di dal repository.";
+$text['description-update_apps']['nl-nl'] = "";
+$text['description-update_apps']['pl-pl'] = "Uaktualnia pliki źródłowe z przechowalni.";
+$text['description-update_apps']['pt-br'] = "Atualiza o a partir dos arquivos de código fonte do repositório.";
+$text['description-update_apps']['pt-pt'] = "Arquivos de origem Atualizações do repositório.";
+$text['description-update_apps']['ro-ro'] = "";
+$text['description-update_apps']['ru-ru'] = "Обновляет исходные файлы из репозитория.";
+$text['description-update_apps']['sv-se'] = "Uppdaterar källfiler från respository.";
+$text['description-update_apps']['uk-ua'] = "Оновлення вихідних файлів  з репозиторію Subversion .";
+
 $text['description-upgrade_schema']['en-us'] = "Checks to ensure table and field integrity in the database.";
 $text['description-upgrade_schema']['en-gb'] = "Checks to ensure table and field integrity in the database.";
 $text['description-upgrade_schema']['ar-eg'] = "تحقق من سلامة الطاولة والميدان في قاعدة البيانات";

+ 116 - 25
core/upgrade/index.php

@@ -58,29 +58,45 @@
 
 		//run source update
 		if (!empty($action["upgrade_source"]) && permission_exists("upgrade_source") && !is_dir("/usr/share/examples/fusionpbx")) {
-			$cwd = getcwd();
-			chdir($_SERVER["PROJECT_ROOT"]);
-			exec("git pull 2>&1", $response_source_update);
-			$update_failed = true;
-			if (sizeof($response_source_update) > 0) {
-				$_SESSION["response"]["upgrade_source"] = $response_source_update;
-				foreach ($response_source_update as $response_line) {
-					if (substr_count($response_line, "Updating ") > 0 || substr_count($response_line, "Already up-to-date.") > 0 || substr_count($response_line, "Already up to date.") > 0) {
-						$update_failed = false;
+
+			$project_update_status = git_pull($_SERVER["PROJECT_ROOT"]);
+
+			$_SESSION["response"]["upgrade_source"] = $project_update_status['message'];
+
+			if (!empty($project_update_status['result'])) {
+				message::add($text['message-upgrade_source'], null, $message_timeout);
+			}
+			else {
+				message::add($text['message-upgrade_source_failed'], 'negative', $message_timeout);
+			}
+		}
+
+		//run app source updates
+		if (!empty($action["update_apps"]) && permission_exists("upgrade_source")) {
+			$app_updates = $_POST['app_list'];
+
+			$updateable_repos = git_find_repos($_SERVER["PROJECT_ROOT"]."/app");
+
+			if (is_array($app_updates)) {
+				$apps_updated = true;
+				foreach ($updateable_repos as $repo => $apps) {
+					if (array_search(basename($repo), $app_updates) !== false) {
+						$git_result = git_pull($repo);
+						$_SESSION["response"]["update_apps"][basename($repo)] = $git_result['message'];
 					}
-					
-					if (substr_count($response_line, "error") > 0) {
-						$update_failed = true;
-						break;
+
+					if (!$git_result['result']) {
+						$apps_updated = false;
 					}
+
 				}
 			}
-			chdir($cwd);
-			if ($update_failed) {
-				message::add($text['message-upgrade_source_failed'], 'negative', $message_timeout);
+
+			if ($apps_updated) {
+				message::add($text['message-upgrade_source'], null, $message_timeout);
 			}
 			else {
-				message::add($text['message-upgrade_source'], null, $message_timeout);
+				message::add($text['message-upgrade_source_failed'], 'negative', $message_timeout);
 			}
 		}
 
@@ -155,7 +171,7 @@
 		echo "<table width='100%' border='0' cellpadding='0' cellspacing='0'>\n";
 		echo "<tr onclick=\"document.getElementById('do_source').checked = !document.getElementById('do_source').checked;\">\n";
 		echo "	<td width='30%' class='vncell' style='vertical-align:middle;'>\n";
-		echo "		<div style='".$step_container_style."'><span style='".$step_number_style."'>".$step++."</span></div>";
+		echo "		<div style='".$step_container_style."'><span style='".$step_number_style."'>".$step."</span></div>";
 		echo "		".$text['label-upgrade_source'];
 		echo "	</td>\n";
 		echo "	<td width='70%' class='vtable' style='height: 50px; cursor: pointer;'>\n";
@@ -179,6 +195,68 @@
 		echo "	</td>\n";
 		echo "</tr>\n";
 		echo "</table>\n";
+
+		$step++;
+
+		// find and show apps
+
+		$updateable_repos = git_find_repos($_SERVER["PROJECT_ROOT"]."/app");
+
+		echo "<table width='100%' border='0' cellpadding='0' cellspacing='0'>\n";
+		echo "<tr onclick=\"document.getElementById('do_apps').checked = !document.getElementById('do_apps').checked; $('#tr_app_updates').slideToggle('fast');\">\n";
+		echo "	<td width='30%' class='vncell' style='vertical-align:middle;'>\n";
+		echo "		<div style='".$step_container_style."'><span style='".$step_number_style."'>".$step."</span></div>";
+		echo "		".$text['label-update_apps'];
+		echo "	</td>\n";
+		echo "	<td width='70%' class='vtable' style='height: 50px; cursor: pointer;'>\n";
+		echo "		<input type='checkbox' name='action[update_apps]' id='do_apps' value='1' onclick=\"event.stopPropagation(); $('#tr_app_updates').slideToggle('fast');\"> &nbsp;".$text['description-update_apps']."\n";
+		echo "</a>";
+		echo "	</td>\n";
+		echo "</tr>\n";
+		echo "</table>\n";
+
+
+		echo "<div id='tr_app_updates' style='display: none;'>\n";
+		echo "<table width='100%' border='0' cellpadding='0' cellspacing='0'>\n";
+		echo "<tr>\n";
+		echo "	<td width='30%' class='vncell' style='vertical-align:middle;'>\n";
+		echo "		<div style='".$step_container_style."'><span style='".$step_number_style."'>".$step."B</span></div>";
+		echo "		Apps";
+		echo "	</td>\n";
+		echo "	<td width='70%' class='vtable' style='height: 50px;'>\n";
+
+
+
+		foreach ($updateable_repos as $repo => $apps) {
+			$repo_info = git_repo_info($repo);
+
+			$repo_name = basename($repo);
+
+			if (!$repo_info) {
+				continue;
+			}
+
+			// if (!is_writeable($repo_info['path']."/.git")) {
+			// 	continue;
+			// }
+
+			echo "		<input type='checkbox' name='app_list[]' id='do_apps' value='".$repo_name."'> &nbsp;".$repo_name."<br />\n";
+			echo $text['label-git_branch']." ".$repo_info['branch']."\n";
+			echo "<a href='".$repo_info['url']."/compare/";
+			echo $repo_info['commit'] . "...".$repo_info['branch']." 'target='_blank'> \n";
+			echo $repo_info['commit'] . "</a><br />\n";
+			echo "Apps: ".implode(", ",$apps)."<br />\n";
+			echo "</a>";
+			
+
+		}
+
+		echo "	</td>\n";
+		echo "</tr>\n";
+		echo "</table>\n";
+		echo "</div>\n";
+
+		$step++;
 	}
 
 	if (permission_exists("upgrade_schema")) {
@@ -198,7 +276,7 @@
 		echo "<table width='100%' border='0' cellpadding='0' cellspacing='0'>\n";
 		echo "<tr onclick=\"document.getElementById('do_data_types').checked = !document.getElementById('do_data_types').checked;\">\n";
 		echo "	<td width='30%' class='vncell' style='vertical-align:middle;'>\n";
-		echo "		<div style='".$step_container_style."'><span style='".$step_number_style." letter-spacing: -0.06em;'>".$step++."B</span></div>";
+		echo "		<div style='".$step_container_style."'><span style='".$step_number_style." letter-spacing: -0.06em;'>".$step."B</span></div>";
 		echo "		".$text['label-upgrade_data_types'];
 		echo "	</td>\n";
 		echo "	<td width='70%' class='vtable' style='height: 50px; cursor: pointer;'>\n";
@@ -207,13 +285,14 @@
 		echo "</tr>\n";
 		echo "</table>\n";
 		echo "</div>\n";
+		$step++;
 	}
 
 	if (permission_exists("upgrade_apps")) {
 		echo "<table width='100%' border='0' cellpadding='0' cellspacing='0'>\n";
 		echo "<tr onclick=\"document.getElementById('do_apps').checked = !document.getElementById('do_apps').checked;\">\n";
 		echo "	<td width='30%' class='vncell' style='vertical-align:middle;'>\n";
-		echo "		<div style='".$step_container_style."'><span style='".$step_number_style."'>".$step++."</span></div>";
+		echo "		<div style='".$step_container_style."'><span style='".$step_number_style."'>".$step."</span></div>";
 		echo "		".$text['label-upgrade_apps'];
 		echo "	</td>\n";
 		echo "	<td width='70%' class='vtable' style='height: 50px; cursor: pointer;'>\n";
@@ -221,13 +300,14 @@
 		echo "	</td>\n";
 		echo "</tr>\n";
 		echo "</table>\n";
+		$step++;
 	}
 
 	if (permission_exists("menu_restore")) {
 		echo "<table width='100%' border='0' cellpadding='0' cellspacing='0'>\n";
 		echo "<tr onclick=\"document.getElementById('do_menu').checked = !document.getElementById('do_menu').checked; $('#sel_menu').fadeToggle('fast');\">\n";
 		echo "	<td width='30%' class='vncell' style='vertical-align:middle;'>\n";
-		echo "		<div style='".$step_container_style."'><span style='".$step_number_style."'>".$step++."</span></div>";
+		echo "		<div style='".$step_container_style."'><span style='".$step_number_style."'>".$step."</span></div>";
 		echo "		".$text['label-upgrade_menu'];
 		echo "	</td>\n";
 		echo "	<td width='70%' class='vtable' style='height: 50px; cursor: pointer;'>\n";
@@ -252,13 +332,14 @@
 		echo "	</td>\n";
 		echo "</tr>\n";
 		echo "</table>\n";
+		$step++;
 	}
 
 	if (permission_exists("group_edit")) {
 		echo "<table width='100%' border='0' cellpadding='0' cellspacing='0'>\n";
 		echo "<tr onclick=\"document.getElementById('do_permissions').checked = !document.getElementById('do_permissions').checked;\">\n";
 		echo "	<td width='30%' class='vncell' style='vertical-align:middle;'>\n";
-		echo "		<div style='".$step_container_style."'><span style='".$step_number_style."'>".$step++."</span></div>";
+		echo "		<div style='".$step_container_style."'><span style='".$step_number_style."'>".$step."</span></div>";
 		echo "		".$text['label-upgrade_permissions'];
 		echo "	</td>\n";
 		echo "	<td width='70%' class='vtable' style='height: 50px; cursor: pointer;'>\n";
@@ -266,6 +347,7 @@
 		echo "	</td>\n";
 		echo "</tr>\n";
 		echo "</table>\n";
+		$step++;
 	}
 
 	echo "</form>\n";
@@ -273,9 +355,18 @@
 	echo "<br /><br />";
 	if (!empty($_SESSION["response"]) && is_array($_SESSION["response"])) {
 		foreach($_SESSION["response"] as $part => $response){
-			echo "<b>". $text["label-results"]." - ".$text["label-${part}"]."</b>";
-			echo "<br /><br />";
-			if (is_array($response)) {
+			echo "<b>".$text["label-results"]." - ".$text["label-${part}"];
+			echo "</b><br /><br />";
+			if ($part == "update_apps") {
+				echo "<pre>";
+				foreach ($response as $app_name => $app_response) {
+					foreach ($app_response as $response_line) {
+						echo $app_name.": ".htmlspecialchars($response_line) . "\n";
+					}
+				}
+				echo "</pre>";
+			}
+			elseif (is_array($response)) {
 				echo "<pre>";
 				echo implode("\n", $response);
 				echo "</pre>";

+ 19 - 1
core/upgrade/upgrade.php

@@ -286,4 +286,22 @@
 			}
 	}
 
-?>
+//upgrade optional apps
+	if ($upgrade_type == 'apps') {
+
+		$app_list = git_find_repos($_SERVER["PROJECT_ROOT"]."/app");
+
+		if (!is_array($app_list)) {
+			exit;
+		}
+		print_r($app_list);exit;
+		foreach ($app_list as $repo => $apps) {
+			$path = $repo;
+			$git_result = git_pull($path);
+			foreach ($git_result['message'] as $response_line) {
+				echo $repo . ": " . $response_line . "\n";
+			}
+		}
+	}
+
+?>

+ 103 - 0
resources/functions.php

@@ -2292,4 +2292,107 @@
 		}
 
 	}
+
+//git pull
+if (!function_exists('git_pull')) {
+	function git_pull($path) {
+
+		$cwd = getcwd();
+		chdir($path);
+		exec("GIT_SSH_COMMAND='ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no' git pull 2>&1", $response_source_update);
+
+		$update_status = false;
+
+		if (sizeof($response_source_update) == 0) {
+			return array('result' => false, 'message' => null);
+		}
+
+		foreach ($response_source_update as $response_line) {
+			if (substr_count($response_line, "Updating ") > 0 || substr_count($response_line, "Already up to date.") > 0) {
+				$update_status = true;
+			}
+
+			if (substr_count($response_line, "error") > 0) {
+				$update_status = false;
+				break;
+			}
+		}
+		chdir($cwd);
+
+		return array('result' => $update_status,
+				'message' => $response_source_update);
+
+	}
+}
+
+//git is repository
+if (!function_exists('is_git_repo')) {
+	function is_git_repo($path) {
+		if(!is_dir($path)) {return false;}
+		$cwd = $_SERVER["PROJECT_ROOT"];
+		chdir($path);
+		exec("git rev-parse --show-toplevel", $git_repo, $git_repo_response);
+		chdir($cwd);
+		if (($git_repo[0]) != $cwd && $git_repo_response == 0) {
+			return $git_repo[0];
+		}
+		return false;
+	}
+}
+
+//git repo version information
+if (!function_exists('git_repo_info')) {
+	function git_repo_info($path) {
+
+		if(!is_dir($path)) {
+			return false;
+		}
+
+		$cwd = getcwd();
+		chdir($path);
+
+		//get current branch
+		exec("git rev-parse --abbrev-ref HEAD 2>&1", $git_branch, $git_branch_return);
+		$repo['branch'] = $git_branch[0];
+
+		//get current commit id
+		exec("git log --pretty=format:'%H' -n 1 2>&1", $git_commit, $git_commit_return);
+		$repo['commit'] = $git_commit[0];
+
+		//get remote origin url for updates
+		exec("git config --get remote.origin.url", $git_url);
+		$repo['url'] = preg_replace('/\.git$/', '', $git_url[0] );
+
+		$repo['path'] = $path;
+
+		//to-do detect remote over ssh and reformat to equivalent https url
+
+		chdir($cwd);
+
+		if (!$git_branch_return && !$git_commit_return && $git_url) {
+			return $repo;
+		}
+		else {
+			return false;
+		}
+
+	}
+}
+
+
+//git locate app repositories
+if (!function_exists('git_find_repos')) {
+	function git_find_repos($path) {
+		$apps = scandir($path);
+		$git_repos = array();
+		foreach ($apps as $app) {
+			$git_repo_name = is_git_repo($path."/".$app);
+			if ($git_repo_name != false && !empty($git_repo_name)) {
+				$git_repos[$git_repo_name][] = $app;
+			}
+			unset($git_repo_name);
+		}
+		return $git_repos;
+	}
+}
 ?>