Merge branch 'zenops_41' into 'master'

Zenops 41

See merge request easycorp/zentaopms!5013
This commit is contained in:
李玉春
2022-08-18 05:21:42 +00:00
113 changed files with 3299 additions and 586 deletions
+2 -1
View File
@@ -379,6 +379,7 @@ $config->objectTables['kanbangroup'] = TABLE_KANBANGROUP;
$config->objectTables['kanbancard'] = TABLE_KANBANCARD;
$config->objectTables['sonarqube'] = TABLE_PIPELINE;
$config->objectTables['gitea'] = TABLE_PIPELINE;
$config->objectTables['gogs'] = TABLE_PIPELINE;
$config->objectTables['gitlab'] = TABLE_PIPELINE;
$config->objectTables['jebkins'] = TABLE_PIPELINE;
$config->objectTables['stage'] = TABLE_STAGE;
@@ -387,7 +388,7 @@ $config->objectTables['repo'] = TABLE_REPO;
$config->newFeatures = array('introduction', 'tutorial', 'youngBlueTheme', 'visions');
$config->pipelineTypeList = array('gitlab', 'sonarqube', 'jenkins', 'gitea');
$config->pipelineTypeList = array('gitlab', 'gogs', 'gitea', 'jenkins', 'sonarqube');
/* Program privs.*/
$config->programPriv = new stdclass();
+2
View File
@@ -0,0 +1,2 @@
ALTER TABLE `zt_job` ADD `lastSyncDate` datetime DEFAULT NULL AFTER `lastTag`;
INSERT INTO `zt_cron` (`m`, `h`, `dom`, `mon`, `dow`, `command`, `remark`, `type`, `buildin`, `status`, `lastTime`) VALUES ('*/5', '*', '*', '*', '*', 'moduleName=compile&methodName=syncCompile', '定时同步构建记录', 'zentao', 1, 'normal', '0000-00-00 00:00:00');
+6 -1
View File
@@ -77,7 +77,12 @@ class baseHelper
/* 处理$viewType和$vars。Set $viewType and $vars. */
if(empty($viewType)) $viewType = $app->getViewType();
if(!is_array($vars)) parse_str($vars, $vars);
if(!is_array($vars))
{
/* Prevent + from converting to spaces. */
$vars = str_replace('+', '%2B', $vars);
parse_str($vars, $vars);
}
/* 生成url链接的开始部分。Set the begin parts of the link. */
if($config->requestType == 'PATH_INFO') $link = $config->webRoot . $appName;
+136 -136
View File
@@ -29,7 +29,7 @@
if (!defined('PCLZIP_READ_BLOCK_SIZE')) {
define( 'PCLZIP_READ_BLOCK_SIZE', 2048 );
}
// ----- File list separator
// In version 1.x of PclZip, the separator for file list is a space
// (which is not a very smart choice, specifically for windows paths !).
@@ -68,7 +68,7 @@
// ----- Optional threshold ratio for use of temporary files
// Pclzip sense the size of the file to add/extract and decide to
// use or not temporary file. The algorythm is looking for
// use or not temporary file. The algorythm is looking for
// memory_limit of PHP and apply a ratio.
// threshold = memory_limit * ratio.
// Recommended values are under 0.5. Default 0.47.
@@ -152,7 +152,7 @@
define( 'PCLZIP_OPT_ADD_TEMP_FILE_ON', 77021 ); // alias
define( 'PCLZIP_OPT_TEMP_FILE_OFF', 77022 );
define( 'PCLZIP_OPT_ADD_TEMP_FILE_OFF', 77022 ); // alias
// ----- File description attributes
define( 'PCLZIP_ATT_FILE_NAME', 79001 );
define( 'PCLZIP_ATT_FILE_NEW_SHORT_NAME', 79002 );
@@ -198,7 +198,7 @@
// ----- Internal error handling
var $error_code = 1;
var $error_string = '';
// ----- Current status of the magic_quotes_runtime
// This value store the php configuration for magic_quotes
// The class can then disable the magic_quotes and reset it after
@@ -332,7 +332,7 @@
}
}
}
// ----- Look for default option values
$this->privOptionDefaultThreshold($v_options);
@@ -341,16 +341,16 @@
$v_att_list = array();
$v_filedescr_list = array();
$p_result_list = array();
// ----- Look if the $p_filelist is really an array
if (is_array($p_filelist)) {
// ----- Look if the first element is also an array
// This will mean that this is a file description entry
if (isset($p_filelist[0]) && is_array($p_filelist[0])) {
$v_att_list = $p_filelist;
}
// ----- The list is a list of string names
else {
$v_string_list = $p_filelist;
@@ -368,7 +368,7 @@
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_filelist");
return 0;
}
// ----- Reformat the string list
if (sizeof($v_string_list) != 0) {
foreach ($v_string_list as $v_string) {
@@ -379,7 +379,7 @@
}
}
}
// ----- For each file in the list check the attributes
$v_supported_attributes
= array ( PCLZIP_ATT_FILE_NAME => 'mandatory'
@@ -528,16 +528,16 @@
$v_att_list = array();
$v_filedescr_list = array();
$p_result_list = array();
// ----- Look if the $p_filelist is really an array
if (is_array($p_filelist)) {
// ----- Look if the first element is also an array
// This will mean that this is a file description entry
if (isset($p_filelist[0]) && is_array($p_filelist[0])) {
$v_att_list = $p_filelist;
}
// ----- The list is a list of string names
else {
$v_string_list = $p_filelist;
@@ -555,14 +555,14 @@
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type '".gettype($p_filelist)."' for p_filelist");
return 0;
}
// ----- Reformat the string list
if (sizeof($v_string_list) != 0) {
foreach ($v_string_list as $v_string) {
$v_att_list[][PCLZIP_ATT_FILE_NAME] = $v_string;
}
}
// ----- For each file in the list check the attributes
$v_supported_attributes
= array ( PCLZIP_ATT_FILE_NAME => 'mandatory'
@@ -996,7 +996,7 @@
// Options :
// PCLZIP_OPT_BY_INDEX :
// PCLZIP_OPT_BY_NAME :
// PCLZIP_OPT_BY_EREG :
// PCLZIP_OPT_BY_EREG :
// PCLZIP_OPT_BY_PREG :
// Return Values :
// 0 on failure,
@@ -1064,7 +1064,7 @@
// --------------------------------------------------------------------------------
function deleteByIndex($p_index)
{
$p_list = $this->delete(PCLZIP_OPT_BY_INDEX, $p_index);
// ----- Return
@@ -1114,7 +1114,7 @@
if (($this->zip_fd = @fopen($this->zipname, 'rb')) == 0)
{
$this->privSwapBackMagicQuotes();
// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in binary read mode');
@@ -1426,7 +1426,7 @@
function privParseOptions(&$p_options_list, $p_size, &$v_result_list, $v_requested_options=false)
{
$v_result=1;
// ----- Read the options
$i=0;
while ($i<$p_size) {
@@ -1466,13 +1466,13 @@
PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
return PclZip::errorCode();
}
// ----- Check for incompatible options
if (isset($v_result_list[PCLZIP_OPT_TEMP_FILE_OFF])) {
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Option '".PclZipUtilOptionText($p_options_list[$i])."' can not be used with option 'PCLZIP_OPT_TEMP_FILE_OFF'");
return PclZip::errorCode();
}
// ----- Check the value
$v_value = $p_options_list[$i+1];
if ((!is_integer($v_value)) || ($v_value<0)) {
@@ -1491,7 +1491,7 @@
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Option '".PclZipUtilOptionText($p_options_list[$i])."' can not be used with option 'PCLZIP_OPT_TEMP_FILE_OFF'");
return PclZip::errorCode();
}
$v_result_list[$p_options_list[$i]] = true;
break;
@@ -1506,7 +1506,7 @@
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Option '".PclZipUtilOptionText($p_options_list[$i])."' can not be used with option 'PCLZIP_OPT_TEMP_FILE_THRESHOLD'");
return PclZip::errorCode();
}
$v_result_list[$p_options_list[$i]] = true;
break;
@@ -1655,7 +1655,7 @@
// ----- Return
return PclZip::errorCode();
}
// ----- Reduce the index list
// each index item in the list must be a couple with a start and
// an end value : [0,3], [5-5], [8-10], ...
@@ -1666,10 +1666,10 @@
// ----- Explode the item
$v_item_list = explode("-", $v_work_list[$j]);
$v_size_item_list = sizeof($v_item_list);
// ----- TBC : Here we might check that each item is a
// real integer ...
// ----- Look for single value
if ($v_size_item_list == 1) {
// ----- Set the option value
@@ -1703,7 +1703,7 @@
}
$v_sort_value = $v_result_list[$p_options_list[$i]][$j]['start'];
}
// ----- Sort the items
if ($v_sort_flag) {
// TBC : To Be Completed
@@ -1806,10 +1806,10 @@
}
}
}
// ----- Look for default values
if (!isset($v_result_list[PCLZIP_OPT_TEMP_FILE_THRESHOLD])) {
}
// ----- Return
@@ -1826,12 +1826,12 @@
function privOptionDefaultThreshold(&$p_options)
{
$v_result=1;
if (isset($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD])
|| isset($p_options[PCLZIP_OPT_TEMP_FILE_OFF])) {
return $v_result;
}
// ----- Get 'memory_limit' configuration value
$v_memory_limit = ini_get('memory_limit');
$v_memory_limit = trim($v_memory_limit);
@@ -1846,15 +1846,15 @@
$v_memory_limit = $v_memory_limit*1048576;
if($last == 'k')
$v_memory_limit = $v_memory_limit*1024;
$p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD] = floor($v_memory_limit*PCLZIP_TEMPORARY_FILE_RATIO);
// ----- Sanity check : No threshold if value lower than 1M
if ($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD] < 1048576) {
unset($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD]);
}
// ----- Return
return $v_result;
}
@@ -1871,10 +1871,10 @@
function privFileDescrParseAtt(&$p_file_list, &$p_filedescr, $v_options, $v_requested_options=false)
{
$v_result=1;
// ----- For each file in the list check the attributes
foreach ($p_file_list as $v_key => $v_value) {
// ----- Check if the option is supported
if (!isset($v_requested_options[$v_key])) {
// ----- Error log
@@ -1893,7 +1893,7 @@
}
$p_filedescr['filename'] = PclZipUtilPathReduction($v_value);
if ($p_filedescr['filename'] == '') {
PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid empty filename for attribute '".PclZipUtilOptionText($v_key)."'");
return PclZip::errorCode();
@@ -1974,10 +1974,10 @@
}
}
}
// end foreach
}
// ----- Return
return $v_result;
}
@@ -1990,7 +1990,7 @@
// or a string to be added as file. For any other type of files (link, other)
// just ignore the item.
// Then prepare the information that will be stored for that file.
// When its a folder, expand the folder with all the files that are in that
// When its a folder, expand the folder with all the files that are in that
// folder (recursively).
// Parameters :
// Return Values :
@@ -2000,20 +2000,20 @@
function privFileDescrExpand(&$p_filedescr_list, &$p_options)
{
$v_result=1;
// ----- Create a result list
$v_result_list = array();
// ----- Look each entry
for ($i=0; $i<sizeof($p_filedescr_list); $i++) {
// ----- Get filedescr
$v_descr = $p_filedescr_list[$i];
// ----- Reduce the filename
$v_descr['filename'] = PclZipUtilTranslateWinPath($v_descr['filename'], false);
$v_descr['filename'] = PclZipUtilPathReduction($v_descr['filename']);
// ----- Look for real file or folder
if (file_exists($v_descr['filename'])) {
if (@is_file($v_descr['filename'])) {
@@ -2031,12 +2031,12 @@
continue;
}
}
// ----- Look for string added as file
else if (isset($v_descr['content'])) {
$v_descr['type'] = 'virtual_file';
}
// ----- Missing file
else {
// ----- Error log
@@ -2045,13 +2045,13 @@
// ----- Return
return PclZip::errorCode();
}
// ----- Calculate the stored filename
$this->privCalculateStoredFilename($v_descr, $p_options);
// ----- Add the descriptor in result list
$v_result_list[sizeof($v_result_list)] = $v_descr;
// ----- Look for folder
if ($v_descr['type'] == 'folder') {
// ----- List of items in folder
@@ -2064,10 +2064,10 @@
if (($v_item_handler == '.') || ($v_item_handler == '..')) {
continue;
}
// ----- Compose the full filename
$v_dirlist_descr[$v_dirlist_nb]['filename'] = $v_descr['filename'].'/'.$v_item_handler;
// ----- Look for different stored filename
// Because the name of the folder was changed, the name of the
// files/sub-folders also change
@@ -2080,34 +2080,34 @@
$v_dirlist_descr[$v_dirlist_nb]['new_full_name'] = $v_item_handler;
}
}
$v_dirlist_nb++;
}
@closedir($v_folder_handler);
}
else {
// TBC : unable to open folder in read mode
}
// ----- Expand each element of the list
if ($v_dirlist_nb != 0) {
// ----- Expand
if (($v_result = $this->privFileDescrExpand($v_dirlist_descr, $p_options)) != 1) {
return $v_result;
}
// ----- Concat the resulting list
$v_result_list = array_merge($v_result_list, $v_dirlist_descr);
}
else {
}
// ----- Free local array
unset($v_dirlist_descr);
}
}
// ----- Get the result list
$p_filedescr_list = $v_result_list;
@@ -2126,7 +2126,7 @@
{
$v_result=1;
$v_list_detail = array();
// ----- Magic quotes trick
$this->privDisableMagicQuotes();
@@ -2456,7 +2456,7 @@
// Function : privAddFileList()
// Description :
// Parameters :
// $p_filedescr_list : An array containing the file description
// $p_filedescr_list : An array containing the file description
// or directory names to add in the zip
// $p_result_list : list of added files with their properties (specially the status field)
// Return Values :
@@ -2474,7 +2474,7 @@
// ----- Format the filename
$p_filedescr_list[$j]['filename']
= PclZipUtilTranslateWinPath($p_filedescr_list[$j]['filename'], false);
// ----- Skip empty file names
// TBC : Can this be possible ? not checked in DescrParseAtt ?
@@ -2526,7 +2526,7 @@
function privAddFile($p_filedescr, &$p_header, &$p_options)
{
$v_result=1;
// ----- Working variable
$p_filename = $p_filedescr['filename'];
@@ -2538,8 +2538,8 @@
// ----- Return
return PclZip::errorCode();
}
// ----- Look for a stored different filename
// ----- Look for a stored different filename
/* TBC : Removed
if (isset($p_filedescr['stored_filename'])) {
$v_stored_filename = $p_filedescr['stored_filename'];
@@ -2564,7 +2564,7 @@
$p_header['offset'] = 0;
$p_header['filename'] = $p_filename;
// TBC : Removed $p_header['stored_filename'] = $v_stored_filename;
$p_header['stored_filename'] = $p_filedescr['stored_filename'];
$p_header['stored_filename'] = strpos(helper::getOS(), 'Windows') !== false ? mb_convert_encoding($p_filedescr['stored_filename'],'GB2312','UTF-8') : $p_filedescr['stored_filename'];
$p_header['extra'] = '';
$p_header['status'] = 'ok';
$p_header['index'] = -1;
@@ -2574,20 +2574,20 @@
$p_header['external'] = 0x00000000;
$p_header['size'] = filesize($p_filename);
}
// ----- Look for regular folder
else if ($p_filedescr['type']=='folder') {
$p_header['external'] = 0x00000010;
$p_header['mtime'] = filemtime($p_filename);
$p_header['size'] = filesize($p_filename);
}
// ----- Look for virtual file
else if ($p_filedescr['type'] == 'virtual_file') {
$p_header['external'] = 0x00000000;
$p_header['size'] = strlen($p_filedescr['content']);
}
// ----- Look for filetime
if (isset($p_filedescr['mtime'])) {
@@ -2639,7 +2639,7 @@
if ($p_header['stored_filename'] == "") {
$p_header['status'] = "filtered";
}
// ----- Check the path length
if (strlen($p_header['stored_filename']) > 0xFF) {
$p_header['status'] = 'filename_too_long';
@@ -2651,7 +2651,7 @@
// ----- Look for a file
if ($p_filedescr['type'] == 'file') {
// ----- Look for using temporary file to zip
if ( (!isset($p_options[PCLZIP_OPT_TEMP_FILE_OFF]))
if ( (!isset($p_options[PCLZIP_OPT_TEMP_FILE_OFF]))
&& (isset($p_options[PCLZIP_OPT_TEMP_FILE_ON])
|| (isset($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD])
&& ($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD] <= $p_header['size'])) ) ) {
@@ -2660,7 +2660,7 @@
return $v_result;
}
}
// ----- Use "in memory" zip algo
else {
@@ -2678,14 +2678,14 @@
// ----- Calculate the CRC
$p_header['crc'] = @crc32($v_content);
// ----- Look for no compression
if ($p_options[PCLZIP_OPT_NO_COMPRESSION]) {
// ----- Set header parameters
$p_header['compressed_size'] = $p_header['size'];
$p_header['compression'] = 0;
}
// ----- Look for normal compression
else {
// ----- Compress the content
@@ -2695,7 +2695,7 @@
$p_header['compressed_size'] = strlen($v_content);
$p_header['compression'] = 8;
}
// ----- Call the header generation
if (($v_result = $this->privWriteFileHeader($p_header)) != 1) {
@fclose($v_file);
@@ -2711,19 +2711,19 @@
// ----- Look for a virtual file (a file from string)
else if ($p_filedescr['type'] == 'virtual_file') {
$v_content = $p_filedescr['content'];
// ----- Calculate the CRC
$p_header['crc'] = @crc32($v_content);
// ----- Look for no compression
if ($p_options[PCLZIP_OPT_NO_COMPRESSION]) {
// ----- Set header parameters
$p_header['compressed_size'] = $p_header['size'];
$p_header['compression'] = 0;
}
// ----- Look for normal compression
else {
// ----- Compress the content
@@ -2733,7 +2733,7 @@
$p_header['compressed_size'] = strlen($v_content);
$p_header['compression'] = 8;
}
// ----- Call the header generation
if (($v_result = $this->privWriteFileHeader($p_header)) != 1) {
@fclose($v_file);
@@ -2799,7 +2799,7 @@
function privAddFileUsingTempFile($p_filedescr, &$p_header, &$p_options)
{
$v_result=PCLZIP_ERR_NO_ERROR;
// ----- Working variable
$p_filename = $p_filedescr['filename'];
@@ -2894,7 +2894,7 @@
// ----- Unlink the temporary file
@unlink($v_gzip_temp_name);
// ----- Return
return $v_result;
}
@@ -2911,7 +2911,7 @@
function privCalculateStoredFilename(&$p_filedescr, &$p_options)
{
$v_result=1;
// ----- Working variables
$p_filename = $p_filedescr['filename'];
if (isset($p_options[PCLZIP_OPT_ADD_PATH])) {
@@ -2939,7 +2939,7 @@
// ----- Remove drive letter if any
$v_stored_filename = PclZipUtilTranslateWinPath($p_filedescr['new_full_name']);
}
// ----- Look for path and/or short name change
else {
@@ -2969,7 +2969,7 @@
if ( (substr($p_filename, 0, 2) == "./")
|| (substr($p_remove_dir, 0, 2) == "./")) {
if ( (substr($p_filename, 0, 2) == "./")
&& (substr($p_remove_dir, 0, 2) != "./")) {
$p_remove_dir = "./".$p_remove_dir;
@@ -2992,10 +2992,10 @@
}
}
}
// ----- Remove drive letter if any
$v_stored_filename = PclZipUtilTranslateWinPath($v_stored_filename);
// ----- Look for path to add
if ($p_add_dir != "") {
if (substr($p_add_dir, -1) == "/")
@@ -3008,7 +3008,7 @@
// ----- Filename (reduce the path of stored name)
$v_stored_filename = PclZipUtilPathReduction($v_stored_filename);
$p_filedescr['stored_filename'] = $v_stored_filename;
// ----- Return
return $v_result;
}
@@ -3159,7 +3159,7 @@
{
// ----- Magic quotes trick
$this->privSwapBackMagicQuotes();
// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in binary read mode');
@@ -3390,7 +3390,7 @@
// ----- Look for extract by ereg rule
// ereg() is deprecated with PHP 5.3
/*
/*
else if ( (isset($p_options[PCLZIP_OPT_BY_EREG]))
&& ($p_options[PCLZIP_OPT_BY_EREG] != "")) {
@@ -3412,7 +3412,7 @@
// ----- Look for extract by index rule
else if ( (isset($p_options[PCLZIP_OPT_BY_INDEX]))
&& ($p_options[PCLZIP_OPT_BY_INDEX] != 0)) {
// ----- Look if the index is in the list
for ($j=$j_start; ($j<sizeof($p_options[PCLZIP_OPT_BY_INDEX])) && (!$v_extract); $j++) {
@@ -3445,7 +3445,7 @@
&& ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) {
$this->privSwapBackMagicQuotes();
PclZip::privErrorLog(PCLZIP_ERR_UNSUPPORTED_COMPRESSION,
"Filename '".$v_header['stored_filename']."' is "
."compressed by an unsupported compression "
@@ -3454,7 +3454,7 @@
return PclZip::errorCode();
}
}
// ----- Check encrypted files
if (($v_extract) && (($v_header['flag'] & 1) == 1)) {
$v_header['status'] = 'unsupported_encryption';
@@ -3486,7 +3486,7 @@
$v_extract = false;
}
// ----- Look for real extraction
if ($v_extract)
{
@@ -3535,7 +3535,7 @@
// ----- Next extracted file
$v_nb_extracted++;
// ----- Look for user callback abort
if ($v_result1 == 2) {
break;
@@ -3671,12 +3671,12 @@
if ($p_path != '') {
$p_entry['filename'] = $p_path."/".$p_entry['filename'];
}
// ----- Check a base_dir_restriction
if (isset($p_options[PCLZIP_OPT_EXTRACT_DIR_RESTRICTION])) {
$v_inclusion
= PclZipUtilPathInclusion($p_options[PCLZIP_OPT_EXTRACT_DIR_RESTRICTION],
$p_entry['filename']);
$p_entry['filename']);
if ($v_inclusion == 0) {
PclZip::privErrorLog(PCLZIP_ERR_DIRECTORY_RESTRICTION,
@@ -3704,7 +3704,7 @@
$p_entry['status'] = "skipped";
$v_result = 1;
}
// ----- Look for abort result
if ($v_result == 2) {
// ----- This status is internal and will be changed in 'skipped'
@@ -3731,7 +3731,7 @@
// ----- Change the file status
$p_entry['status'] = "already_a_directory";
// ----- Look for PCLZIP_OPT_STOP_ON_ERROR
// For historical reason first PclZip implementation does not stop
// when this kind of error occurs.
@@ -3804,10 +3804,10 @@
$v_dir_to_check = dirname($p_entry['filename']);
if (($v_result = $this->privDirCheck($v_dir_to_check, (($p_entry['external']&0x00000010)==0x00000010))) != 1) {
// ----- Change the file status
$p_entry['status'] = "path_creation_fail";
// ----- Return
//return $v_result;
$v_result = 1;
@@ -3846,7 +3846,7 @@
$v_binary_data = pack('a'.$v_read_size, $v_buffer);
@fwrite($v_dest_file, $v_binary_data, $v_read_size);
*/
@fwrite($v_dest_file, $v_buffer, $v_read_size);
@fwrite($v_dest_file, $v_buffer, $v_read_size);
$v_size -= $v_read_size;
}
@@ -3855,7 +3855,7 @@
// ----- Change the file mtime
touch($p_entry['filename'], $p_entry['mtime']);
}
else {
@@ -3868,7 +3868,7 @@
// ----- Look for using temporary file to unzip
if ( (!isset($p_options[PCLZIP_OPT_TEMP_FILE_OFF]))
if ( (!isset($p_options[PCLZIP_OPT_TEMP_FILE_OFF]))
&& (isset($p_options[PCLZIP_OPT_TEMP_FILE_ON])
|| (isset($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD])
&& ($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD] <= $p_entry['size'])) ) ) {
@@ -3877,42 +3877,42 @@
return $v_result;
}
}
// ----- Look for extract in memory
else {
// ----- Read the compressed file in a buffer (one shot)
$v_buffer = @fread($this->zip_fd, $p_entry['compressed_size']);
// ----- Decompress the file
$v_file_content = @gzinflate($v_buffer);
unset($v_buffer);
if ($v_file_content === FALSE) {
// ----- Change the file status
// TBC
$p_entry['status'] = "error";
return $v_result;
}
// ----- Opening destination file
if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0) {
// ----- Change the file status
$p_entry['status'] = "write_error";
return $v_result;
}
// ----- Write the uncompressed data
@fwrite($v_dest_file, $v_file_content, $p_entry['size']);
unset($v_file_content);
// ----- Closing the destination file
@fclose($v_dest_file);
}
// ----- Change the file mtime
@@ -3933,7 +3933,7 @@
if ($p_entry['status'] == "aborted") {
$p_entry['status'] = "skipped";
}
// ----- Look for post-extract callback
elseif (isset($p_options[PCLZIP_CB_POST_EXTRACT])) {
@@ -3967,7 +3967,7 @@
function privExtractFileUsingTempFile(&$p_entry, &$p_options)
{
$v_result=1;
// ----- Creates a temporary file
$v_gzip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.gz';
if (($v_dest_file = @fopen($v_gzip_temp_name, "wb")) == 0) {
@@ -4028,7 +4028,7 @@
// ----- Delete the temporary file
@unlink($v_gzip_temp_name);
// ----- Return
return $v_result;
}
@@ -4106,7 +4106,7 @@
// ----- Read the compressed file in a buffer (one shot)
$v_buffer = @fread($this->zip_fd, $p_entry['compressed_size']);
// ----- Decompress the file
$v_file_content = gzinflate($v_buffer);
unset($v_buffer);
@@ -4187,7 +4187,7 @@
$p_entry['status'] = "skipped";
$v_result = 1;
}
// ----- Look for abort result
if ($v_result == 2) {
// ----- This status is internal and will be changed in 'skipped'
@@ -4209,41 +4209,41 @@
// ----- Look for not compressed file
// if ($p_entry['compressed_size'] == $p_entry['size'])
if ($p_entry['compression'] == 0) {
// ----- Reading the file
$p_string = @fread($this->zip_fd, $p_entry['compressed_size']);
}
else {
// ----- Reading the file
$v_data = @fread($this->zip_fd, $p_entry['compressed_size']);
// ----- Decompress the file
if (($p_string = @gzinflate($v_data)) === FALSE) {
// TBC
}
}
// ----- Trace
}
else {
// TBC : error : can not extract a folder in a string
}
}
// ----- Change abort status
if ($p_entry['status'] == "aborted") {
$p_entry['status'] = "skipped";
}
// ----- Look for post-extract callback
elseif (isset($p_options[PCLZIP_CB_POST_EXTRACT])) {
// ----- Generate a local information
$v_local_header = array();
$this->privConvertHeader2FileInfo($p_entry, $v_local_header);
// ----- Swap the content to header
$v_local_header['content'] = $p_string;
$p_string = '';
@@ -4504,7 +4504,7 @@
}
if ($p_local_header['filename_len'] != $p_central_header['filename_len']) {
}
// ----- Look for flag bit 3
if (($p_local_header['flag'] & 8) == 8) {
$p_local_header['size'] = $p_central_header['size'];
@@ -4590,9 +4590,9 @@
// ----- Add the byte
//$v_bytes = ($v_bytes << 8) | Ord($v_byte);
// Note we mask the old value down such that once shifted we can never end up with more than a 32bit number
// Otherwise on systems where we have 64bit integers the check below for the magic number will fail.
$v_bytes = ( ($v_bytes & 0xFFFFFF) << 8) | Ord($v_byte);
// Note we mask the old value down such that once shifted we can never end up with more than a 32bit number
// Otherwise on systems where we have 64bit integers the check below for the magic number will fail.
$v_bytes = ( ($v_bytes & 0xFFFFFF) << 8) | Ord($v_byte);
// ----- Compare the bytes
if ($v_bytes == 0x504b0506)
@@ -4870,7 +4870,7 @@
// ----- Return
return $v_result;
}
// ----- Check that local file header is same as central file header
if ($this->privCheckFileHeaders($v_local_header,
$v_header_list[$i]) != 1) {
@@ -4954,11 +4954,11 @@
// TBC : I should test the result ...
//@rename($v_zip_temp_name, $this->zipname);
PclZipUtilRename($v_zip_temp_name, $this->zipname);
// ----- Destroy the temporary archive
unset($v_temp_zip);
}
// ----- Remove every files : reset the file
else if ($v_central_dir['entries'] != 0) {
$this->privCloseFd();
@@ -5445,7 +5445,7 @@
}
}
}
// ----- Look for skip
if ($v_skip > 0) {
while ($v_skip > 0) {
@@ -5478,7 +5478,7 @@
function PclZipUtilPathInclusion($p_dir, $p_path)
{
$v_result = 1;
// ----- Look for path beginning by ./
if ( ($p_dir == '.')
|| ((strlen($p_dir) >=2) && (substr($p_dir, 0, 2) == './'))) {
@@ -5646,7 +5646,7 @@
// --------------------------------------------------------------------------------
function PclZipUtilOptionText($p_option)
{
$v_list = get_defined_constants();
for (reset($v_list); $v_key = key($v_list); next($v_list)) {
$v_prefix = substr($v_key, 0, 10);
@@ -5657,7 +5657,7 @@
return $v_key;
}
}
$v_result = 'Unknown';
return $v_result;
+37 -10
View File
@@ -3,6 +3,7 @@ class Gitea
{
public $client;
public $root;
public $repo;
/**
* Construct
@@ -28,8 +29,11 @@ class Gitea
$project = $app->control->loadModel('gitea')->apiGetSingleProject($repo->serviceHost, $repo->serviceProject);
if(isset($project->tokenCloneUrl))
{
$cmd = 'git clone --progress -v "' . $project->tokenCloneUrl . '" "' . $this->root . '"';
$cmd = 'git clone --progress -v "' . $project->tokenCloneUrl . '" "' . $this->root . '" > "' . $app->getTmpRoot() . "log/clone.progress." . strtolower($repo->SCM) . ".{$repo->name}.log\" 2>&1 &";
if(PHP_OS == 'WINNT') $cmd = "start /b $cmd";
exec($cmd);
return $app->control->locate($app->control->createLink('repo', 'showSyncCommit', "repoID={$repo->id}"));
}
}
@@ -40,6 +44,7 @@ class Gitea
if(isset($branches[$branch])) $branch = "origin/$branch";
}
$this->branch = $branch;
$this->repo = $repo;
chdir($this->root);
exec("{$this->client} config core.quotepath false");
@@ -159,7 +164,7 @@ class Gitea
{
$localBranch = trim($localBranch);
if(substr($localBranch, 0, 19) == 'remotes/origin/HEAD') continue;
if(substr($localBranch, 0, 1) == '*') $localBranch = substr($localBranch, 1);
if(substr($localBranch, 0, 1) == '*') continue;
if(substr($localBranch, 0, 15) == 'remotes/origin/') $localBranch = substr($localBranch, 15);
$localBranch = trim($localBranch);
@@ -551,9 +556,15 @@ class Gitea
{
if(!scm::checkRevision($revision)) return array();
if($revision == 'HEAD' and $branch) $revision = $branch;
$revision = is_numeric($revision) ? "--skip=$revision $branch" : $revision;
$count = $count == 0 ? '' : "-n $count";
if($revision == 'HEAD' and $branch)
{
$revision = $branch;
}
elseif(is_numeric($revision))
{
$revision = "--skip=$revision $branch";
}
$count = $count == 0 ? '' : "-n $count";
chdir($this->root);
if($branch)
@@ -598,11 +609,11 @@ class Gitea
list($action, $path) = $file;
$parsedFile = new stdclass();
$parsedFile->revision = $hash;
$parsedFile->path = '/' . trim($path);
$parsedFile->type = 'file';
$parsedFile->action = $action;
$logs['files'][$hash][] = $parsedFile;
$parsedFile->revision = $hash;
$parsedFile->path = '/' . trim($path);
$parsedFile->type = 'file';
$parsedFile->action = $action;
$logs['files'][$hash][] = $parsedFile;
}
}
return $logs;
@@ -690,4 +701,20 @@ class Gitea
return $parsedLogs;
}
/**
* Get download url.
*
* @param string $branch
* @param string $savePath
* @param string $ext
* @access public
* @return string
*/
public function getDownloadUrl($branch = 'master', $savePath = '', $ext = 'zip')
{
global $app;
$api = $app->control->loadModel('gitea')->getApiRoot($this->repo->serviceHost);
return sprintf($api, "/repos/{$this->repo->serviceProject}/archive/{$branch}.zip");
}
}
+2 -1
View File
@@ -840,11 +840,12 @@ class gitlab
* Get download url.
*
* @param string $branch
* @param string $savePath
* @param string $ext
* @access public
* @return string
*/
public function getDownloadUrl($branch = 'master', $ext = 'zip')
public function getDownloadUrl($branch = 'master', $savePath = '', $ext = 'zip')
{
$params = (array) $params;
$params['private_token'] = $this->token;
+41 -4
View File
@@ -3,6 +3,7 @@ class GitRepo
{
public $client;
public $root;
public $repo;
/**
* Construct
@@ -30,6 +31,7 @@ class GitRepo
if(isset($branches[$branch])) $branch = "origin/$branch";
}
$this->branch = $branch;
$this->repo = $repo;
chdir($this->root);
exec("{$this->client} config core.quotepath false");
@@ -540,9 +542,16 @@ class GitRepo
{
if(!scm::checkRevision($revision)) return array();
if($revision == 'HEAD' and $branch) $revision = $branch;
$revision = is_numeric($revision) ? "--skip=$revision $branch" : $revision;
$count = $count == 0 ? '' : "-n $count";
if($revision == 'HEAD' and $branch)
{
$revision = $branch;
}
elseif(is_numeric($revision))
{
$revision = "--skip=$revision $branch";
}
$count = $count == 0 ? '' : "-n $count";
chdir($this->root);
if($branch) execCmd(escapeCmd("$this->client checkout $branch"), 'array');
@@ -603,7 +612,8 @@ class GitRepo
{
$url = new stdclass();
$remote = execCmd(escapeCmd("$this->client remote -v"), 'array');
$pregHttp = '/http(s)?:\/\/(www\.)?[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+(:\d+)*(\/\w+)*\.git/';
if(strpos($remote[0], 'oauth2:')) $remote[0] = preg_replace('/oauth2.*@/', '', $remote[0]);
$pregHttp = '/http(s)?:\/\/(www\.)?[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+(:\d+)*(\/\w+)*(\.git)?/';
$pregSSH = '/ssh:\/\/git@[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+(:\d+)*(\/\w+)*\.git/';
if(preg_match($pregHttp, $remote[0], $matches)) $url->http = $matches[0];
@@ -675,4 +685,31 @@ class GitRepo
return $parsedLogs;
}
/**
* Get download url.
*
* @param string $branch
* @param string $savePath
* @param string $ext
* @access public
* @return string
*/
public function getDownloadUrl($branch = 'master', $savePath = '', $ext = 'zip')
{
global $app, $config;
$gitDir = scandir($this->root);
$files = '';
foreach($gitDir as $path)
{
if(!in_array($path, array('.', '..', '.git'))) $files .= $this->root . DS . "$path,";
}
$app->loadClass('pclzip', true);
$fileName = $savePath . DS . "{$this->repo->name}_$branch.zip";
$zip = new pclzip($fileName);
$zip->create($files, PCLZIP_OPT_REMOVE_PATH, $this->root);
return $config->webRoot . $app->getAppName() . 'data' . DS . 'repo' . DS . "{$this->repo->name}_$branch.zip";
}
}
+755
View File
@@ -0,0 +1,755 @@
<?php
class Gogs
{
public $client;
public $root;
public $repo;
/**
* Construct
*
* @param string $client
* @param string $root
* @param string $username
* @param string $password
* @param string $encoding
* @param object $repo
* @access public
* @return void
*/
public function __construct($client, $root, $username, $password, $encoding = 'UTF-8', $repo = null)
{
putenv('LC_CTYPE=en_US.UTF-8');
$this->client = $client;
$this->root = rtrim($root, DIRECTORY_SEPARATOR);
if(!realpath($this->root) and !empty($repo))
{
global $app;
$project = $app->control->loadModel('gogs')->apiGetSingleProject($repo->serviceHost, $repo->serviceProject);
if(isset($project->tokenCloneUrl))
{
$cmd = 'git clone --progress -v "' . $project->tokenCloneUrl . '" "' . $this->root . '" > "' . $app->getTmpRoot() . "log/clone.progress." . strtolower($repo->SCM) . ".{$repo->name}.log\" 2>&1 &";
if(PHP_OS == 'WINNT') $cmd = "start /b $cmd";
exec($cmd);
return $app->control->locate($app->control->createLink('repo', 'showSyncCommit', "repoID={$repo->id}"));
}
}
$branch = isset($_COOKIE['repoBranch']) ? $_COOKIE['repoBranch'] : '';
if($branch)
{
$branches = $this->branch();
if(isset($branches[$branch])) $branch = "origin/$branch";
}
$this->branch = $branch;
$this->repo = $repo;
chdir($this->root);
exec("{$this->client} config core.quotepath false");
}
/**
* List files.
*
* @param string $path
* @param string $revision
* @access public
* @return array
*/
public function ls($path, $revision = 'HEAD')
{
if(!scm::checkRevision($revision)) return array();
$path = ltrim($path, DIRECTORY_SEPARATOR);
$sub = '';
chdir($this->root);
if(!empty($path)) $sub = ":$path";
if(!empty($this->branch))$revision = $this->branch;
execCmd(escapeCmd("$this->client pull"));
$cmd = escapeCmd("$this->client ls-tree -l $revision$sub");
$list = execCmd($cmd . ' 2>&1', 'array', $result);
if($result) return array();
$infos = array();
foreach($list as $entry)
{
list($mod, $kind, $revision, $size, $name) = preg_split('/[\t ]+/', $entry);
/* Get commit info. */
$pathName = ltrim($path . DIRECTORY_SEPARATOR . $name, DIRECTORY_SEPARATOR);
$cmd = escapeCmd("$this->client log -1 $this->branch -- $pathName");
$commit = execCmd($cmd, 'array');
$logs = $this->parseLog($commit);
if($size > 1024 * 1024)
{
$size = round($size / (1024 * 1024), 2) . 'MB';
}
else if($size > 1024)
{
$size = round($size / 1024, 2) . 'KB';
}
else
{
$size .= 'Bytes';
}
$info = new stdClass();
$info->name = $name;
$info->kind = $kind == 'tree' ? 'dir' : 'file';
$info->revision = $logs ? $logs[0]->revision : $revision;
$info->size = $size;
$info->account = $logs ? $logs[0]->committer : '';
$info->date = $logs ? $logs[0]->time : '';
$info->comment = $logs ? $logs[0]->comment : '';
$infos[] = $info;
unset($info);
}
/* Sort by kind */
foreach($infos as $key => $info) $kinds[$key] = $info->kind;
if($infos) array_multisort($kinds, SORT_ASC, $infos);
return $infos;
}
/**
* Get tags
*
* @param string $path
* @param string $revision
* @access public
* @return array
*/
public function tags($path, $revision = 'HEAD')
{
if(!scm::checkRevision($revision)) return array();
chdir($this->root);
$cmd = escapeCmd("$this->client tag --sort=taggerdate");
$list = execCmd($cmd . ' 2>&1', 'array', $result);
if($result) return array();
foreach($list as $key => $tag)
{
if(!$tag) unset($list[$key]);
}
return $list;
}
/**
* Get branch.
*
* @access public
* @return array
*/
public function branch()
{
chdir($this->root);
/* Get local branch. */
$cmd = escapeCmd("$this->client branch -a");
$list = execCmd($cmd . ' 2>&1', 'array', $result);
if($result) return array();
/* Get default branch. */
$defaultBranch = execCmd("$this->client symbolic-ref refs/remotes/origin/HEAD | sed 's@^refs/remotes/origin/@@'");
$defaultBranch = trim($defaultBranch);
$branches = array();
foreach($list as $localBranch)
{
$localBranch = trim($localBranch);
if(substr($localBranch, 0, 19) == 'remotes/origin/HEAD') continue;
if(substr($localBranch, 0, 1) == '*') continue;
if(substr($localBranch, 0, 15) == 'remotes/origin/') $localBranch = substr($localBranch, 15);
$localBranch = trim($localBranch);
if(empty($localBranch))continue;
if($localBranch != $defaultBranch) $branches[$localBranch] = $localBranch;
}
asort($branches);
if($defaultBranch) $branches = array($defaultBranch => $defaultBranch) + $branches;
return $branches;
}
/**
* Get last log.
*
* @param string $path
* @param int $count
* @access public
* @return array
*/
public function getLastLog($path, $count = 10)
{
$path = ltrim($path, DIRECTORY_SEPARATOR);
$revision = $this->branch ? $this->branch : 'HEAD';
chdir($this->root);
$list = execCmd(escapeCmd("$this->client log -10 $revision -- $path"), 'array');
$logs = $this->parseLog($list);
return $logs;
}
/**
* Get logs
*
* @param string $path
* @param string $fromRevision
* @param string $toRevision
* @param int $count
* @access public
* @return array
*/
public function log($path, $fromRevision = 0, $toRevision = 'HEAD', $count = 0)
{
if(!scm::checkRevision($fromRevision)) return array();
if(!scm::checkRevision($toRevision)) return array();
$path = ltrim($path, DIRECTORY_SEPARATOR);
$count = $count == 0 ? '' : "-n $count";
/* compatible with svn. */
if($fromRevision == 'HEAD' and $this->branch) $fromRevision = $this->branch;
if($toRevision == 'HEAD' and $this->branch) $toRevision = $this->branch;
if($fromRevision === $toRevision)
{
$logs = array();
chdir($this->root);
$list = execCmd(escapeCmd("$this->client log --stat=1024 --name-status --stat-name-width=1000 -1 $fromRevision -- $path"), 'array');
$logs = $this->parseLog($list);
return $logs;
}
if(!$fromRevision)
{
$revisions = " $toRevision";
}
else
{
$revisions = "$fromRevision..$toRevision";
}
chdir($this->root);
$list = execCmd(escapeCmd("$this->client log --stat=1024 --name-status --stat-name-width=1000 $count $revisions -- $path"), 'array');
$logs = $this->parseLog($list);
return $logs;
}
/**
* Blame file
*
* @param string $path
* @param string $revision
* @access public
* @return array
*/
public function blame($path, $revision)
{
if(!scm::checkRevision($revision)) return array();
$path = ltrim($path, DIRECTORY_SEPARATOR);
chdir($this->root);
$list = execCmd(escapeCmd("$this->client blame -l $revision -- $path"), 'array');
$blames = array();
$revLine = 0;
$revision = '';
foreach($list as $line)
{
if(empty($line)) continue;
if($line[0] == '^') $line = substr($line, 1);
preg_match('/^([0-9a-f]{39,40})\s.*\((\S+)\s+([\d-]+)\s(.*)\s(\d+)\)(.*)$/U', $line, $matches);
if(isset($matches[1]) and $matches[1] != $revision)
{
$blame = array();
$blame['revision'] = $matches[1];
$blame['committer'] = $matches[2];
$blame['time'] = $matches[3];
$blame['line'] = $matches[5];
$blame['lines'] = 1;
$blame['content'] = strpos($matches[6], ' ') === false ? $matches[6] : substr($matches[6], 1);
$revision = $matches[1];
$revLine = $matches[5];
$blames[$revLine] = $blame;
}
elseif(isset($matches[5]))
{
$blame = array();
$blame['line'] = $matches[5];
$blame['content'] = strpos($matches[6], ' ') === false ? $matches[6] : substr($matches[6], 1);
$blames[$matches[5]] = $blame;
$blames[$revLine]['lines'] ++;
}
}
return $blames;
}
/**
* Diff file.
*
* @param string $path
* @param string $fromRevision
* @param string $toRevision
* @param string $extra
* @access public
* @return array
*/
public function diff($path, $fromRevision, $toRevision, $extra = '')
{
if(!scm::checkRevision($fromRevision) and $extra != 'isBranchOrTag') return array();
if(!scm::checkRevision($toRevision) and $extra != 'isBranchOrTag') return array();
$path = ltrim($path, DIRECTORY_SEPARATOR);
chdir($this->root);
if($toRevision == 'HEAD' and $this->branch) $toRevision = $this->branch;
if($fromRevision == '^') $fromRevision = $toRevision . '^';
if(strpos($fromRevision, '^') !== false)
{
$list = execCmd(escapeCmd("$this->client log -2 $toRevision --pretty=format:%H -- $path"), 'array');
if(isset($list[1])) $fromRevision = $list[1];
}
$lines = execCmd(escapeCmd("$this->client diff $fromRevision $toRevision -- $path"), 'array');
return $lines;
}
/**
* Cat file.
*
* @param string $entry
* @param string $revision
* @access public
* @return string
*/
public function cat($entry, $revision = 'HEAD')
{
if(!scm::checkRevision($revision)) return false;
chdir($this->root);
if($revision == 'HEAD' and $this->branch) $revision = $this->branch;
$cmd = escapeCmd("$this->client show $revision:$entry");
$content = execCmd($cmd);
if(is_array($content)) $content = implode("\n", $content);
return $content;
}
/**
* Get info.
*
* @param string $entry
* @param string $revision
* @access public
* @return object
*/
public function info($entry, $revision = 'HEAD')
{
if(!scm::checkRevision($revision)) return false;
chdir($this->root);
if($revision == 'HEAD' and $this->branch) $revision = $this->branch;
$path = ltrim($entry, DIRECTORY_SEPARATOR);
$cmd = escapeCmd("$this->client ls-tree $revision -- $path");
$result = execCmd($cmd);
$kind = '';
if($result)
{
$results = explode("\n", trim($result));
if(count($results) >= 2)
{
$kind = 'dir';
}
else
{
list($mode, $type) = explode(' ', $results[0]);
$kind = $type == 'tree' ? 'dir' : 'file';
}
}
$list = execCmd(escapeCmd("$this->client log -1 $revision --pretty=format:%H -- $path"), 'array');
$revision = $list[0];
$info = new stdclass();
$info->kind = $kind;
$info->path = $entry;
$info->revision = $revision;
$info->root = $this->root;
return $info;
}
/**
* Exec git cmd.
*
* @param string $cmd
* @access public
* @return array
*/
public function exec($cmd)
{
chdir($this->root);
return execCmd(escapeCmd("$this->client $cmd"), 'array');
}
/**
* Parse diff.
*
* @param array $lines
* @access public
* @return array
*/
public function parseDiff($lines)
{
if(empty($lines)) return array();
$diffs = array();
$num = count($lines);
$endLine = end($lines);
if(strpos($endLine, '\ No newline at end of file') === 0) $num -= 1;
$newFile = false;
$allFiles = array();
for($i = 0; $i < $num; $i ++)
{
$diffFile = new stdclass();
if(strpos($lines[$i], "diff --git ") === 0)
{
$fileInfo = explode(' ',$lines[$i]);
$fileName = substr($fileInfo[2], strpos($fileInfo[2], '/') + 1);
/* Prevent duplicate display of files. */
if(in_array($fileName, $allFiles)) continue;
$allFiles[] = $fileName;
$diffFile->fileName = $fileName;
for($i++; $i < $num; $i ++)
{
$diff = new stdclass();
/* Fix bug #1757. */
if($lines[$i] == '+++ /dev/null') $newFile = true;
if(strpos($lines[$i], '+++', 0) !== false) continue;
if(strpos($lines[$i], '---', 0) !== false) continue;
if(strpos($lines[$i], '======', 0) !== false) continue;
if(preg_match('/^@@ -(\\d+)(,(\\d+))?\\s+\\+(\\d+)(,(\\d+))?\\s+@@/A', $lines[$i]))
{
$startLines = trim(str_replace(array('@', '+', '-'), '', $lines[$i]));
list($oldStartLine, $newStartLine) = explode(' ', $startLines);
list($diff->oldStartLine) = explode(',', $oldStartLine);
list($diff->newStartLine) = explode(',', $newStartLine);
$oldCurrentLine = $diff->oldStartLine;
$newCurrentLine = $diff->newStartLine;
if($newFile)
{
$oldCurrentLine = $diff->newStartLine;
$newCurrentLine = $diff->oldStartLine;
}
$newLines = array();
for($i++; $i < $num; $i ++)
{
if(preg_match('/^@@ -(\\d+)(,(\\d+))?\\s+\\+(\\d+)(,(\\d+))?\\s+@@/A', $lines[$i]))
{
$i --;
break;
}
if(strpos($lines[$i], "diff --git ") === 0) break;
$line = $lines[$i];
if(strpos($line, '\ No newline at end of file') === 0)continue;
$sign = empty($line) ? '' : $line[0];
if($sign == '-' and $newFile) $sign = '+';
$type = $sign != '-' ? $sign == '+' ? 'new' : 'all' : 'old';
if($sign == '-' || $sign == '+')
{
$line = substr_replace($line, ' ', 1, 0);
if($newFile) $line = preg_replace('/^\-/', '+', $line);
}
$newLine = new stdclass();
$newLine->type = $type;
$newLine->oldlc = $type != 'new' ? $oldCurrentLine : '';
$newLine->newlc = $type != 'old' ? $newCurrentLine : '';
$newLine->line = htmlSpecialString($line);
if($type != 'new') $oldCurrentLine++;
if($type != 'old') $newCurrentLine++;
$newLines[] = $newLine;
}
$diff->lines = $newLines;
$diffFile->contents[] = $diff;
}
if(isset($lines[$i]) and strpos($lines[$i], "diff --git ") === 0)
{
$i --;
$newFile = false;
break;
}
}
$diffs[] = $diffFile;
}
}
return $diffs;
}
/**
* Get commit count.
*
* @param int $commits
* @param string $lastVersion
* @access public
* @return int
*/
public function getCommitCount($commits = 0, $lastVersion = '')
{
if(!scm::checkRevision($lastVersion)) return false;
chdir($this->root);
$revision = $this->branch ? $this->branch : 'HEAD';
return execCmd(escapeCmd("$this->client rev-list --count $revision -- ./"), 'string');
}
/**
* Get first revision.
*
* @access public
* @return string
*/
public function getFirstRevision()
{
chdir($this->root);
$list = execCmd(escapeCmd("$this->client rev-list --reverse HEAD -- ./"), 'array');
return $list[0];
}
/**
* Get latest revision
*
* @access public
* @return string
*/
public function getLatestRevision()
{
chdir($this->root);
$revision = $this->branch ? $this->branch : 'HEAD';
$list = execCmd(escapeCmd("$this->client rev-list -1 $revision -- ./"), 'array');
return $list[0];
}
/**
* Get commits.
*
* @param string $rversion
* @param int $count
* @param string $branch
* @access public
* @return array
*/
public function getCommits($revision = '', $count = 0, $branch = '')
{
if(!scm::checkRevision($revision)) return array();
if($revision == 'HEAD' and $branch)
{
$revision = $branch;
}
elseif(is_numeric($revision))
{
$revision = "--skip=$revision $branch";
}
$count = $count == 0 ? '' : "-n $count";
chdir($this->root);
if($branch)
{
execCmd(escapeCmd("$this->client checkout $branch"));
execCmd(escapeCmd("$this->client pull"));
}
$list = execCmd(escapeCmd("$this->client log $count $revision -- ./"), 'array');
$commits = $this->parseLog($list);
$logs = array();
foreach($commits as $commit)
{
$hash = $commit->revision;
$log = new stdClass();
$log->committer = $commit->committer;
$log->revision = $commit->revision;
$log->comment = $commit->comment;
$log->time = $commit->time;
$logs['commits'][$hash] = $log;
$logs['files'][$hash] = array();
}
if(empty($logs)) return $logs;
$hash = '';
$files = execCmd(escapeCmd("$this->client whatchanged $count $revision --pretty=format:%an@_@%cd@_@%H@_@%s -- ./"), 'array');
foreach($files as $commit)
{
$commit = trim($commit);
if(empty($commit)) continue;
$parsedCommit = explode('@_@', $commit);
if(count($parsedCommit) == 4)
{
list($account, $date, $hash, $comment) = $parsedCommit;
}
else
{
$file = explode(' ', $commit);
$file = explode("\t", end($file));
if(!isset($file[1])) $file[1] = '';
list($action, $path) = $file;
$parsedFile = new stdclass();
$parsedFile->revision = $hash;
$parsedFile->path = '/' . trim($path);
$parsedFile->type = 'file';
$parsedFile->action = $action;
$logs['files'][$hash][] = $parsedFile;
}
}
return $logs;
}
/**
* Get commits by MR branches.
*
* @param string $sourceBranch
* @param string $targetBranch
* @access public
* @return array
*/
public function getMRCommits($sourceBranch, $targetBranch)
{
execCmd(escapeCmd("$this->client checkout $sourceBranch"));
execCmd(escapeCmd("$this->client pull"));
execCmd(escapeCmd("$this->client checkout $targetBranch"));
execCmd(escapeCmd("$this->client pull"));
$commits = execCmd(escapeCmd("$this->client log origin/$sourceBranch ^origin/$targetBranch"), 'array');
$commits = $this->parseLog($commits);
foreach($commits as $commit) $commit->id = $commit->revision;
return $commits;
}
/**
* Get clone url.
*
* @access public
* @return string
*/
public function getCloneUrl()
{
$url = new stdclass();
$remote = execCmd(escapeCmd("$this->client remote -v"), 'array');
$pregHttp = '/http(s)?:\/\/(www\.)?[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+(:\d+)*(\/\w+)*\.git/';
$pregSSH = '/ssh:\/\/git@[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+(:\d+)*(\/\w+)*\.git/';
if(preg_match($pregHttp, $remote[0], $matches)) $url->http = $matches[0];
if(preg_match($pregSSH, $remote[0], $matches)) $url->ssh = $matches[0];
return $url;
}
/**
* Parse log.
*
* @param array $logs
* @access public
* @return array
*/
public function parseLog($logs)
{
$parsedLogs = array();
$i = 0;
foreach($logs as $line)
{
if(strpos($line, 'commit ') === 0)
{
if(isset($log))
{
$log->comment = trim($comment);
$log->change = $changes;
$parsedLogs[$i] = $log;
$i++;
}
$log = new stdclass();
$comment = '';
$changes = array();
$log->revision = trim(preg_replace('/^commit/', '', $line));
}
elseif(strpos($line, 'Author:') === 0)
{
$account = preg_replace('/^Author:/', '', $line);
$log->committer = trim(preg_replace('/<[a-zA-Z0-9_\-\.]+@[a-zA-Z0-9_\-\.]+>/', '', $account));
}
elseif(strpos($line, 'Date:') === 0)
{
$date = trim(preg_replace('/^Date:/', '', $line));
$log->time = date('Y-m-d H:i:s', strtotime($date));
}
elseif(preg_match('/^\s{2,}/', $line))
{
$comment .= $line;
}
elseif(strpos($line, "\t") !== false)
{
list($action, $entry) = explode("\t", $line);
$entry = '/' . trim($entry);
$pathInfo = array();
$pathInfo['action'] = $action;
$pathInfo['kind'] = 'file';
$changes[$entry] = $pathInfo;
}
}
if(isset($log))
{
$log->comment = trim($comment);
$log->change = $changes;
$parsedLogs[$i] = $log;
}
return $parsedLogs;
}
/**
* Get download url.
*
* @param string $branch
* @param string $savePath
* @param string $ext
* @access public
* @return string
*/
public function getDownloadUrl($branch = 'master', $savePath = '', $ext = 'zip')
{
execCmd(escapeCmd("$this->client checkout $branch"));
execCmd(escapeCmd("$this->client pull"));
global $app, $config;
$gitDir = scandir($this->root);
$files = '';
foreach($gitDir as $path)
{
if(!in_array($path, array('.', '..', '.git'))) $files .= $this->root . DS . "$path,";
}
$app->loadClass('pclzip', true);
$fileName = $savePath . DS . "{$this->repo->name}_$branch.zip";
$zip = new pclzip($fileName);
$zip->create($files, PCLZIP_OPT_REMOVE_PATH, $this->root);
return $config->webRoot . $app->getAppName() . 'data' . DS . 'repo' . DS . "{$this->repo->name}_$branch.zip";
}
}
+16 -2
View File
@@ -220,6 +220,19 @@ class scm
return $this->engine->getCommits($version, $count, $branch);
}
/**
* Get commits by MR branches.
*
* @param string $sourceBranch
* @param string $targetBranch
* @access public
* @return array
*/
public function getMRCommits($sourceBranch, $targetBranch)
{
return $this->engine->getMRCommits($sourceBranch, $targetBranch);
}
/**
* Get clone url.
*
@@ -249,13 +262,14 @@ class scm
* Get download url.
*
* @param string $branch
* @param string $savePath
* @param string $ext
* @access public
* @return string
*/
public function getDownloadUrl($branch = '', $ext = 'zip')
public function getDownloadUrl($branch = '', $savePath = '', $ext = 'zip')
{
return $this->engine->getDownloadUrl($branch, $ext);
return $this->engine->getDownloadUrl($branch, $savePath, $ext);
}
}
+30
View File
@@ -9,6 +9,7 @@ class Subversion
public $remote;
public $encoding;
public $svnVersion;
public $repo;
/**
* Construct
@@ -29,6 +30,7 @@ class Subversion
$this->account = $account;
$this->password = $password;
$this->encoding = $encoding;
$this->repo = $repo;
$this->ssh = (stripos($this->root, 'svn') === 0 or stripos($this->root, 'https') === 0) ? true : false;
$this->remote = !(stripos($this->root, 'file') === 0);
$this->client = $this->remote ? $client . " --username @account@ --password @password@" : $client;
@@ -682,4 +684,32 @@ class Subversion
return end($versionOutput);
}
/**
* Get download url.
*
* @param string $branch
* @param string $savePath
* @param string $ext
* @access public
* @return string
*/
public function getDownloadUrl($branch = '', $savePath = '', $ext = 'zip')
{
global $app, $config;
/* Get repo name. */
$pathList = explode('/', trim($this->root, '/'));
$repoDir = $savePath . DS . end($pathList);
execCmd($this->replaceAuth(escapeCmd("$this->client export $this->root $repoDir")));
$fileName = $savePath . DS . "{$this->repo->name}.zip";
$app->loadClass('pclzip', true);
$zip = new pclzip($fileName);
$zip->create($repoDir, PCLZIP_OPT_REMOVE_PATH, $repoDir);
$zfile = $app->loadClass('zfile');
$zfile->removeDir($repoDir);
return $config->webRoot . $app->getAppName() . 'data' . DS . 'repo' . DS . $this->repo->name . '.zip';
}
}
+2 -1
View File
@@ -44,6 +44,7 @@ $config->action->objectNameFields['kanbancard'] = 'name';
$config->action->objectNameFields['sonarqube'] = 'name';
$config->action->objectNameFields['gitlab'] = 'name';
$config->action->objectNameFields['gitea'] = 'name';
$config->action->objectNameFields['gogs'] = 'name';
$config->action->objectNameFields['stage'] = 'name';
$config->action->objectNameFields['apistruct'] = 'name';
$config->action->objectNameFields['repo'] = 'name';
@@ -62,7 +63,7 @@ $config->action->majorList['execution'] = array('opened', 'edited');
$config->action->needGetProjectType = 'build,task,bug,case,testcase,caselib,testtask,testsuite,testreport,doc,issue,release,risk,design,opportunity,trainplan,gapanalysis,researchplan,researchreport,';
$config->action->needGetRelateField = ',story,productplan,release,task,build,bug,testcase,case,testtask,testreport,doc,doclib,issue,risk,opportunity,trainplan,gapanalysis,team,whitelist,researchplan,researchreport,meeting,kanbanlane,kanbancolumn,module,';
$config->action->noLinkModules = ',doclib,module,webhook,gitlab,gitea,sonarqube,pipeline,jenkins,kanban,kanbanspace,kanbancolumn,kanbanlane,kanbanregion,kanbancard,execution,project,traincategory,apistruct,program,product,user,entry,repo,';
$config->action->noLinkModules = ',doclib,module,webhook,gitlab,gitea,gogs,sonarqube,pipeline,jenkins,kanban,kanbanspace,kanbancolumn,kanbanlane,kanbanregion,kanbancard,execution,project,traincategory,apistruct,program,product,user,entry,repo,';
$config->action->preferredTypeNum = 10;
+25 -9
View File
@@ -57,6 +57,7 @@ $lang->action->historyEdit = 'Der Verlauf darf nicht leer sein.';
$lang->action->noDynamic = 'Kein Verlauf. ';
$lang->action->undeletedTips = 'This data did not participate in the merging process during the version upgrade process, so restore is not supported.';
$lang->action->executionNoProject = 'The execution does not belong to a project,please restore the project first';
$lang->action->repoNoServer = 'The repo does not belong to a server,please restore the server first';
$lang->action->repeatChange = '%s with the same name and code already exists in the system, After recovery, the name are \"%s\",the code are \"%s\".';
$lang->action->nameRepeatChange = '%s with the same name already exists in the system, After recovery, the name are \"%s\".';
@@ -128,6 +129,7 @@ $lang->action->objectTypes['whitelist'] = 'Whitelist';
$lang->action->objectTypes['pipeline'] = 'GitLib';
$lang->action->objectTypes['gitlab'] = 'GitLab Server';
$lang->action->objectTypes['gitea'] = 'Gitea Server';
$lang->action->objectTypes['gogs'] = 'Gogs Server';
$lang->action->objectTypes['jenkins'] = 'Jenkins';
$lang->action->objectTypes['mr'] = 'Merge Request';
$lang->action->objectTypes['gitlabproject'] = 'GitLab Project';
@@ -138,6 +140,7 @@ $lang->action->objectTypes['gitlabbranchpriv'] = 'GitLab Protected Branches';
$lang->action->objectTypes['gitlabtag'] = 'GitLab Tag';
$lang->action->objectTypes['gitlabtagpriv'] = 'GitLab Tag Protected';
$lang->action->objectTypes['giteauser'] = 'Gitea User';
$lang->action->objectTypes['gogsuser'] = 'Gogs User';
$lang->action->objectTypes['kanbanspace'] = 'Kanban Space';
$lang->action->objectTypes['kanban'] = 'Kanban';
$lang->action->objectTypes['kanbanregion'] = 'Kanban Region';
@@ -637,19 +640,32 @@ $lang->action->dynamicAction->job['executed'] = 'Execute Job';
$lang->action->dynamicAction->job['deleted'] = 'Delete Job';
$lang->action->dynamicAction->job['undeleted'] = 'Undelete Job';
$lang->action->dynamicAction->sonarqube['created'] = 'Create SonarQube Server';
$lang->action->dynamicAction->sonarqube['edited'] = 'Edit SonarQube Server';
$lang->action->dynamicAction->sonarqube['deleted'] = 'Delete SonarQube Server';
$lang->action->dynamicAction->sonarqube['created'] = 'Create SonarQube Server';
$lang->action->dynamicAction->sonarqube['edited'] = 'Edit SonarQube Server';
$lang->action->dynamicAction->sonarqube['deleted'] = 'Delete SonarQube Server';
$lang->action->dynamicAction->sonarqube['undeleted'] = 'Undelete SonarQube Server';
$lang->action->dynamicAction->sonarqubeproject['deleted'] = 'Delete SonarQube Project';
$lang->action->dynamicAction->gitlab['created'] = 'Create GitLab Server';
$lang->action->dynamicAction->gitlab['edited'] = 'Edit GitLab Server';
$lang->action->dynamicAction->gitlab['deleted'] = 'Delete GitLab Server';
$lang->action->dynamicAction->gitlab['created'] = 'Create GitLab Server';
$lang->action->dynamicAction->gitlab['edited'] = 'Edit GitLab Server';
$lang->action->dynamicAction->gitlab['deleted'] = 'Delete GitLab Server';
$lang->action->dynamicAction->gitlab['undeleted'] = 'Undelete GitLab Server';
$lang->action->dynamicAction->gitea['created'] = 'Create Gitea Server';
$lang->action->dynamicAction->gitea['edited'] = 'Edit Gitea Server';
$lang->action->dynamicAction->gitea['deleted'] = 'Delete Gitea Server';
$lang->action->dynamicAction->gitea['created'] = 'Create Gitea Server';
$lang->action->dynamicAction->gitea['edited'] = 'Edit Gitea Server';
$lang->action->dynamicAction->gitea['deleted'] = 'Delete Gitea Server';
$lang->action->dynamicAction->gitea['undeleted'] = 'Undelete Gitea Server';
$lang->action->dynamicAction->gogs['created'] = 'Create Gogs Server';
$lang->action->dynamicAction->gogs['edited'] = 'Edit Gogs Server';
$lang->action->dynamicAction->gogs['deleted'] = 'Delete Gogs Server';
$lang->action->dynamicAction->gogs['undeleted'] = 'Undelete Gogs Server';
$lang->action->dynamicAction->repo['created'] = 'Create Repo';
$lang->action->dynamicAction->repo['edited'] = 'Edit Repo';
$lang->action->dynamicAction->repo['deleted'] = 'Delete Repo';
$lang->action->dynamicAction->repo['undeleted'] = 'Undelete Repo';
/* Generate the corresponding object link. */
$lang->action->label->product = $lang->productCommon . '|product|view|productID=%s';
+25 -9
View File
@@ -57,6 +57,7 @@ $lang->action->historyEdit = 'The history EditBy cannot be empty.';
$lang->action->noDynamic = 'No dynamics. ';
$lang->action->undeletedTips = 'This data did not participate in the merging process during the version upgrade process, so restore is not supported.';
$lang->action->executionNoProject = 'The execution does not belong to a project,please restore the project first';
$lang->action->repoNoServer = 'The repo does not belong to a server,please restore the server first';
$lang->action->repeatChange = '%s with the same name and code already exists in the system, After recovery, the name are \"%s\",the code are \"%s\".';
$lang->action->nameRepeatChange = '%s with the same name already exists in the system, After recovery, the name are \"%s\".';
@@ -128,6 +129,7 @@ $lang->action->objectTypes['whitelist'] = 'Whitelist';
$lang->action->objectTypes['pipeline'] = 'GitLab Server';
$lang->action->objectTypes['gitlab'] = 'GitLab Server';
$lang->action->objectTypes['gitea'] = 'Gitea Server';
$lang->action->objectTypes['gogs'] = 'Gogs Server';
$lang->action->objectTypes['jenkins'] = 'Jenkins';
$lang->action->objectTypes['mr'] = 'Merge Request';
$lang->action->objectTypes['gitlabproject'] = 'GitLab Project';
@@ -138,6 +140,7 @@ $lang->action->objectTypes['gitlabbranchpriv'] = 'GitLab Protected Branches';
$lang->action->objectTypes['gitlabtag'] = 'GitLab Tag';
$lang->action->objectTypes['gitlabtagpriv'] = 'GitLab Tag Protected';
$lang->action->objectTypes['giteauser'] = 'Gitea User';
$lang->action->objectTypes['gogsuser'] = 'Gogs User';
$lang->action->objectTypes['kanbanspace'] = 'Kanban Space';
$lang->action->objectTypes['kanban'] = 'Kanban';
$lang->action->objectTypes['kanbanregion'] = 'Kanban Region';
@@ -637,19 +640,32 @@ $lang->action->dynamicAction->job['executed'] = 'Execute Job';
$lang->action->dynamicAction->job['deleted'] = 'Delete Job';
$lang->action->dynamicAction->job['undeleted'] = 'Undelete Job';
$lang->action->dynamicAction->sonarqube['created'] = 'Create SonarQube Server';
$lang->action->dynamicAction->sonarqube['edited'] = 'Edit SonarQube Server';
$lang->action->dynamicAction->sonarqube['deleted'] = 'Delete SonarQube Server';
$lang->action->dynamicAction->sonarqube['created'] = 'Create SonarQube Server';
$lang->action->dynamicAction->sonarqube['edited'] = 'Edit SonarQube Server';
$lang->action->dynamicAction->sonarqube['deleted'] = 'Delete SonarQube Server';
$lang->action->dynamicAction->sonarqube['undeleted'] = 'Undelete SonarQube Server';
$lang->action->dynamicAction->sonarqubeproject['deleted'] = 'Delete SonarQube Project';
$lang->action->dynamicAction->gitlab['created'] = 'Create GitLab Server';
$lang->action->dynamicAction->gitlab['edited'] = 'Edit GitLab Server';
$lang->action->dynamicAction->gitlab['deleted'] = 'Delete GitLab Server';
$lang->action->dynamicAction->gitlab['created'] = 'Create GitLab Server';
$lang->action->dynamicAction->gitlab['edited'] = 'Edit GitLab Server';
$lang->action->dynamicAction->gitlab['deleted'] = 'Delete GitLab Server';
$lang->action->dynamicAction->gitlab['undeleted'] = 'Undelete GitLab Server';
$lang->action->dynamicAction->gitea['created'] = 'Create Gitea Server';
$lang->action->dynamicAction->gitea['edited'] = 'Edit Gitea Server';
$lang->action->dynamicAction->gitea['deleted'] = 'Delete Gitea Server';
$lang->action->dynamicAction->gitea['created'] = 'Create Gitea Server';
$lang->action->dynamicAction->gitea['edited'] = 'Edit Gitea Server';
$lang->action->dynamicAction->gitea['deleted'] = 'Delete Gitea Server';
$lang->action->dynamicAction->gitea['undeleted'] = 'Undelete Gitea Server';
$lang->action->dynamicAction->gogs['created'] = 'Create Gogs Server';
$lang->action->dynamicAction->gogs['edited'] = 'Edit Gogs Server';
$lang->action->dynamicAction->gogs['deleted'] = 'Delete Gogs Server';
$lang->action->dynamicAction->gogs['undeleted'] = 'Undelete Gogs Server';
$lang->action->dynamicAction->repo['created'] = 'Create Repo';
$lang->action->dynamicAction->repo['edited'] = 'Edit Repo';
$lang->action->dynamicAction->repo['deleted'] = 'Delete Repo';
$lang->action->dynamicAction->repo['undeleted'] = 'Undelete Repo';
/* Generate the corresponding object link. */
$lang->action->label->product = $lang->productCommon . '|product|view|productID=%s';
+25 -9
View File
@@ -57,6 +57,7 @@ $lang->action->historyEdit = "l'historique Edité Par ne peut pas être v
$lang->action->noDynamic = "Pas d'historique.";
$lang->action->undeletedTips = 'This data did not participate in the merging process during the version upgrade process, so restore is not supported.';
$lang->action->executionNoProject = 'The execution does not belong to a project,please restore the project first';
$lang->action->repoNoServer = 'The repo does not belong to a server,please restore the server first';
$lang->action->repeatChange = '%s with the same name and code already exists in the system, After recovery, the name are \"%s\",the code are \"%s\".';
$lang->action->nameRepeatChange = '%s with the same name already exists in the system, After recovery, the name are \"%s\".';
@@ -128,6 +129,7 @@ $lang->action->objectTypes['whitelist'] = 'Whitelist';
$lang->action->objectTypes['pipeline'] = 'GitLib';
$lang->action->objectTypes['gitlab'] = 'GitLab Server';
$lang->action->objectTypes['gitea'] = 'Gitea Server';
$lang->action->objectTypes['gogs'] = 'Gogs Server';
$lang->action->objectTypes['jenkins'] = 'Jenkins';
$lang->action->objectTypes['mr'] = 'Merge Request';
$lang->action->objectTypes['gitlabproject'] = 'GitLab Project';
@@ -138,6 +140,7 @@ $lang->action->objectTypes['gitlabbranchpriv'] = 'GitLab Protected Branches';
$lang->action->objectTypes['gitlabtag'] = 'GitLab Tag';
$lang->action->objectTypes['gitlabtagpriv'] = 'GitLab Tag Protected';
$lang->action->objectTypes['giteauser'] = 'Gitea User';
$lang->action->objectTypes['gogsuser'] = 'Gogs User';
$lang->action->objectTypes['kanbanspace'] = 'Kanban Space';
$lang->action->objectTypes['kanban'] = 'Kanban';
$lang->action->objectTypes['kanbanregion'] = 'Kanban Region';
@@ -637,19 +640,32 @@ $lang->action->dynamicAction->job['executed'] = 'Execute Job';
$lang->action->dynamicAction->job['deleted'] = 'Delete Job';
$lang->action->dynamicAction->job['undeleted'] = 'Undelete Job';
$lang->action->dynamicAction->sonarqube['created'] = 'Create SonarQube Server';
$lang->action->dynamicAction->sonarqube['edited'] = 'Edit SonarQube Server';
$lang->action->dynamicAction->sonarqube['deleted'] = 'Delete SonarQube Server';
$lang->action->dynamicAction->sonarqube['created'] = 'Create SonarQube Server';
$lang->action->dynamicAction->sonarqube['edited'] = 'Edit SonarQube Server';
$lang->action->dynamicAction->sonarqube['deleted'] = 'Delete SonarQube Server';
$lang->action->dynamicAction->sonarqube['undeleted'] = 'Undelete SonarQube Server';
$lang->action->dynamicAction->sonarqubeproject['deleted'] = 'Delete SonarQube Project';
$lang->action->dynamicAction->gitlab['created'] = 'Create GitLab Server';
$lang->action->dynamicAction->gitlab['edited'] = 'Edit GitLab Server';
$lang->action->dynamicAction->gitlab['deleted'] = 'Delete GitLab Server';
$lang->action->dynamicAction->gitlab['created'] = 'Create GitLab Server';
$lang->action->dynamicAction->gitlab['edited'] = 'Edit GitLab Server';
$lang->action->dynamicAction->gitlab['deleted'] = 'Delete GitLab Server';
$lang->action->dynamicAction->gitlab['undeleted'] = 'Undelete GitLab Server';
$lang->action->dynamicAction->gitea['created'] = 'Create Gitea Server';
$lang->action->dynamicAction->gitea['edited'] = 'Edit Gitea Server';
$lang->action->dynamicAction->gitea['deleted'] = 'Delete Gitea Server';
$lang->action->dynamicAction->gitea['created'] = 'Create Gitea Server';
$lang->action->dynamicAction->gitea['edited'] = 'Edit Gitea Server';
$lang->action->dynamicAction->gitea['deleted'] = 'Delete Gitea Server';
$lang->action->dynamicAction->gitea['undeleted'] = 'Undelete Gitea Server';
$lang->action->dynamicAction->gogs['created'] = 'Create Gogs Server';
$lang->action->dynamicAction->gogs['edited'] = 'Edit Gogs Server';
$lang->action->dynamicAction->gogs['deleted'] = 'Delete Gogs Server';
$lang->action->dynamicAction->gogs['undeleted'] = 'Undelete Gogs Server';
$lang->action->dynamicAction->repo['created'] = 'Create Repo';
$lang->action->dynamicAction->repo['edited'] = 'Edit Repo';
$lang->action->dynamicAction->repo['deleted'] = 'Delete Repo';
$lang->action->dynamicAction->repo['undeleted'] = 'Undelete Repo';
/* Generate the corresponding object link. */
$lang->action->label->product = $lang->productCommon . '|product|view|productID=%s';
+34 -16
View File
@@ -30,13 +30,16 @@ $lang->action->editComment = 'Sửa nhận xét';
$lang->action->create = 'Thêm nhận xét';
$lang->action->comment = 'Nhận xét';
$lang->action->trashTips = 'Ghi chú: Xóa trong ZenTao là hợp lệ.';
$lang->action->textDiff = 'Định dạng văn bản';
$lang->action->original = 'Định dạng gốc';
$lang->action->confirmHideAll = 'Bạn có muốn ẩn tất cả ghi nhận này?';
$lang->action->needEdit = '%s mà bạn muốn khôi phục. Vui lòng edit it.';
$lang->action->historyEdit = 'Lịch sử người cập nhật không thể trống.';
$lang->action->noDynamic = 'Không có lịch sử. ';
$lang->action->trashTips = 'Ghi chú: Xóa trong ZenTao là hợp lệ.';
$lang->action->textDiff = 'Định dạng văn bản';
$lang->action->original = 'Định dạng gốc';
$lang->action->confirmHideAll = 'Bạn có muốn ẩn tất cả ghi nhận này?';
$lang->action->needEdit = '%s mà bạn muốn khôi phục. Vui lòng edit it.';
$lang->action->historyEdit = 'Lịch sử người cập nhật không thể trống.';
$lang->action->noDynamic = 'Không có lịch sử. ';
$lang->action->undeletedTips = 'This data did not participate in the merging process during the version upgrade process, so restore is not supported.';
$lang->action->executionNoProject = 'The execution does not belong to a project,please restore the project first';
$lang->action->repoNoServer = 'The repo does not belong to a server,please restore the server first';
$lang->action->history = new stdclass();
$lang->action->history->action = 'Liên kết';
@@ -102,6 +105,7 @@ $lang->action->objectTypes['whitelist'] = 'Whitelist';
$lang->action->objectTypes['pipeline'] = 'GitLib';
$lang->action->objectTypes['gitlab'] = 'GitLab Server';
$lang->action->objectTypes['gitea'] = 'Gitea Server';
$lang->action->objectTypes['gogs'] = 'Gogs Server';
$lang->action->objectTypes['jenkins'] = 'Jenkins';
$lang->action->objectTypes['mr'] = 'Merge Request';
$lang->action->objectTypes['gitlabproject'] = 'GitLab Project';
@@ -112,6 +116,7 @@ $lang->action->objectTypes['gitlabbranchpriv'] = 'GitLab Protected Branches';
$lang->action->objectTypes['gitlabtag'] = 'GitLab Tag';
$lang->action->objectTypes['gitlabtagpriv'] = 'GitLab Tag Protected';
$lang->action->objectTypes['giteauser'] = 'Gitea User';
$lang->action->objectTypes['gogsuser'] = 'Gogs User';
$lang->action->objectTypes['kanbanspace'] = 'Kanban Space';
$lang->action->objectTypes['kanban'] = 'Kanban';
$lang->action->objectTypes['kanbanregion'] = 'Kanban Region';
@@ -493,19 +498,32 @@ $lang->action->dynamicAction->job['executed'] = 'Execute Job';
$lang->action->dynamicAction->job['deleted'] = 'Delete Job';
$lang->action->dynamicAction->job['undeleted'] = 'Undelete Job';
$lang->action->dynamicAction->sonarqube['created'] = 'Create SonarQube Server';
$lang->action->dynamicAction->sonarqube['edited'] = 'Edit SonarQube Server';
$lang->action->dynamicAction->sonarqube['deleted'] = 'Delete SonarQube Server';
$lang->action->dynamicAction->sonarqube['created'] = 'Create SonarQube Server';
$lang->action->dynamicAction->sonarqube['edited'] = 'Edit SonarQube Server';
$lang->action->dynamicAction->sonarqube['deleted'] = 'Delete SonarQube Server';
$lang->action->dynamicAction->sonarqube['undeleted'] = 'Undelete SonarQube Server';
$lang->action->dynamicAction->sonarqubeproject['deleted'] = 'Delete SonarQube Project';
$lang->action->dynamicAction->gitlab['created'] = 'Create GitLab Server';
$lang->action->dynamicAction->gitlab['edited'] = 'Edit GitLab Server';
$lang->action->dynamicAction->gitlab['deleted'] = 'Delete GitLab Server';
$lang->action->dynamicAction->gitlab['created'] = 'Create GitLab Server';
$lang->action->dynamicAction->gitlab['edited'] = 'Edit GitLab Server';
$lang->action->dynamicAction->gitlab['deleted'] = 'Delete GitLab Server';
$lang->action->dynamicAction->gitlab['undeleted'] = 'Undelete GitLab Server';
$lang->action->dynamicAction->gitea['created'] = 'Create Gitea Server';
$lang->action->dynamicAction->gitea['edited'] = 'Edit Gitea Server';
$lang->action->dynamicAction->gitea['deleted'] = 'Delete Gitea Server';
$lang->action->dynamicAction->gitea['created'] = 'Create Gitea Server';
$lang->action->dynamicAction->gitea['edited'] = 'Edit Gitea Server';
$lang->action->dynamicAction->gitea['deleted'] = 'Delete Gitea Server';
$lang->action->dynamicAction->gitea['undeleted'] = 'Undelete Gitea Server';
$lang->action->dynamicAction->gogs['created'] = 'Create Gogs Server';
$lang->action->dynamicAction->gogs['edited'] = 'Edit Gogs Server';
$lang->action->dynamicAction->gogs['deleted'] = 'Delete Gogs Server';
$lang->action->dynamicAction->gogs['undeleted'] = 'Undelete Gogs Server';
$lang->action->dynamicAction->repo['created'] = 'Create Repo';
$lang->action->dynamicAction->repo['edited'] = 'Edit Repo';
$lang->action->dynamicAction->repo['deleted'] = 'Delete Repo';
$lang->action->dynamicAction->repo['undeleted'] = 'Undelete Repo';
/* Generate the corresponding object link. */
global $config;
+25 -9
View File
@@ -57,6 +57,7 @@ $lang->action->historyEdit = '历史记录编辑不能为空。';
$lang->action->noDynamic = '暂时没有动态。';
$lang->action->undeletedTips = '该数据在版本升级过程中未参与数据归并流程,不支持还原。';
$lang->action->executionNoProject = '该执行没有所属的项目,请先还原项目再还原执行';
$lang->action->repoNoServer = '该代码库没有所属的服务器,请先还原服务器再还原代码库';
$lang->action->repeatChange = '系统内已有同名、同代号的%s,恢复后名称为\"%s\"、代号为\"%s\"。';
$lang->action->nameRepeatChange = '系统内已有同名的%s,恢复后名称为\"%s\"。';
@@ -128,6 +129,7 @@ $lang->action->objectTypes['whitelist'] = '白名单';
$lang->action->objectTypes['pipeline'] = 'GitLab服务器';
$lang->action->objectTypes['gitlab'] = 'GitLab服务器';
$lang->action->objectTypes['gitea'] = 'Gitea服务器';
$lang->action->objectTypes['gogs'] = 'Gogs服务器';
$lang->action->objectTypes['jenkins'] = 'Jenkins';
$lang->action->objectTypes['mr'] = '合并请求';
$lang->action->objectTypes['gitlabproject'] = 'GitLab项目';
@@ -138,6 +140,7 @@ $lang->action->objectTypes['gitlabbranchpriv'] = 'GitLab保护分支';
$lang->action->objectTypes['gitlabtag'] = 'GitLab标签';
$lang->action->objectTypes['gitlabtagpriv'] = 'GitLab标签保护';
$lang->action->objectTypes['giteauser'] = 'Gitea用户';
$lang->action->objectTypes['gogsuser'] = 'Gogs用户';
$lang->action->objectTypes['kanbanspace'] = '看板空间';
$lang->action->objectTypes['kanban'] = '看板';
$lang->action->objectTypes['kanbanregion'] = '看板区域';
@@ -637,19 +640,32 @@ $lang->action->dynamicAction->job['executed'] = '执行构建任务';
$lang->action->dynamicAction->job['deleted'] = '删除构建任务';
$lang->action->dynamicAction->job['undeleted'] = '还原构建任务';
$lang->action->dynamicAction->sonarqube['created'] = '创建SonarQube服务器';
$lang->action->dynamicAction->sonarqube['edited'] = '设置SonarQube服务器';
$lang->action->dynamicAction->sonarqube['deleted'] = '删除SonarQube服务器';
$lang->action->dynamicAction->sonarqube['created'] = '创建SonarQube服务器';
$lang->action->dynamicAction->sonarqube['edited'] = '设置SonarQube服务器';
$lang->action->dynamicAction->sonarqube['deleted'] = '删除SonarQube服务器';
$lang->action->dynamicAction->sonarqube['undeleted'] = '还原SonarQube服务器';
$lang->action->dynamicAction->sonarqubeproject['deleted'] = '删除SonarQube项目';
$lang->action->dynamicAction->gitlab['created'] = '创建GitLab服务器';
$lang->action->dynamicAction->gitlab['edited'] = '编辑GitLab服务器';
$lang->action->dynamicAction->gitlab['deleted'] = '删除GitLab服务器';
$lang->action->dynamicAction->gitlab['created'] = '创建GitLab服务器';
$lang->action->dynamicAction->gitlab['edited'] = '编辑GitLab服务器';
$lang->action->dynamicAction->gitlab['deleted'] = '删除GitLab服务器';
$lang->action->dynamicAction->gitlab['undeleted'] = '还原GitLab服务器';
$lang->action->dynamicAction->gitea['created'] = '创建Gitea服务器';
$lang->action->dynamicAction->gitea['edited'] = '编辑Gitea服务器';
$lang->action->dynamicAction->gitea['deleted'] = '删除Gitea服务器';
$lang->action->dynamicAction->gitea['created'] = '创建Gitea服务器';
$lang->action->dynamicAction->gitea['edited'] = '编辑Gitea服务器';
$lang->action->dynamicAction->gitea['deleted'] = '删除Gitea服务器';
$lang->action->dynamicAction->gitea['undeleted'] = '还原Gitea服务器';
$lang->action->dynamicAction->gogs['created'] = '创建Gogs服务器';
$lang->action->dynamicAction->gogs['edited'] = '编辑Gogs服务器';
$lang->action->dynamicAction->gogs['deleted'] = '删除Gogs服务器';
$lang->action->dynamicAction->gogs['undeleted'] = '还原Gogs服务器';
$lang->action->dynamicAction->repo['created'] = '创建代码库';
$lang->action->dynamicAction->repo['edited'] = '编辑代码库';
$lang->action->dynamicAction->repo['deleted'] = '删除代码库';
$lang->action->dynamicAction->repo['undeleted'] = '还原代码库';
/* 用来生成相应对象的链接。*/
$lang->action->label->product = $lang->productCommon . '|product|view|productID=%s';
+17 -3
View File
@@ -1258,6 +1258,10 @@ class actionModel extends model
$modules = $this->dao->select('id,name')->from(TABLE_MODULE)->where('id')->in(explode(',', $action->extra))->fetchPairs('id');
$action->objectName = implode(',', $modules);
}
elseif($action->objectType == 'mr' and $action->action == 'deleted')
{
$action->objectName = $action->extra;
}
$projectID = isset($relatedProjects[$action->objectType][$action->objectID]) ? $relatedProjects[$action->objectType][$action->objectID] : 0;
@@ -1273,14 +1277,14 @@ class actionModel extends model
/* If action type is login or logout, needn't link. */
if($actionType == 'svncommited' or $actionType == 'gitcommited') $action->actor = zget($commiters, $action->actor);
/* Get gitlab or gitea objectname. */
if(empty($action->objectName) and (substr($objectType, 0, 6) == 'gitlab' or substr($objectType, 0, 5) == 'gitea')) $action->objectName = $action->extra;
/* Get gitlab, gitea or gogs objectname. */
if(empty($action->objectName) and (substr($objectType, 0, 6) == 'gitlab' or substr($objectType, 0, 5) == 'gitea' or substr($objectType, 0, 4) == 'gogs')) $action->objectName = $action->extra;
/* Other actions, create a link. */
$this->setObjectLink($action, $deptUsers);
/* Set merge request link. */
if(empty($action->objectName) and $action->objectType == 'mr') $action->objectLink = '';
if((empty($action->objectName) or $action->action == 'deleted') and $action->objectType == 'mr') $action->objectLink = '';
$action->major = (isset($this->config->action->majorList[$action->objectType]) && in_array($action->action, $this->config->action->majorList[$action->objectType])) ? 1 : 0;
}
@@ -1723,6 +1727,16 @@ class actionModel extends model
if((int)$projectCount == 0) return print(js::error($this->lang->action->executionNoProject));
}
if($action->objectType == 'repo')
{
$repo = $this->dao->select('*')->from(TABLE_REPO)->where('id')->eq($action->objectID)->fetch();
if($repo and in_array($repo->SCM, array('Gitlab', 'Gitea', 'Gogs')))
{
$server = $this->dao->select('*')->from(TABLE_PIPELINE)->where('id')->eq($repo->serviceHost)->andWhere('deleted')->eq('0')->fetch();
if(empty($server)) return print(js::error($this->lang->action->repoNoServer));
}
}
if($action->objectType == 'product')
{
$product = $this->dao->select('id,name,code,acl')->from(TABLE_PRODUCT)->where('id')->eq($action->objectID)->fetch();
+6 -3
View File
@@ -29,9 +29,11 @@ class ciModel extends model
if($this->session->repoID)
{
$repo = $this->loadModel('repo')->getRepoByID($this->session->repoID);
if(!in_array(strtolower($repo->SCM), $this->config->repo->gitServiceList)) unset($this->lang->devops->menu->mr);
if(!empty($repo) and !in_array(strtolower($repo->SCM), $this->config->repo->gitServiceList)) unset($this->lang->devops->menu->mr);
$this->lang->switcherMenu = $this->loadModel('repo')->getSwitcher($this->session->repoID);
$tab = $this->app->tab;
$repos = $this->repo->getRepoPairs($tab);
if(count($repos) > 1) $this->lang->switcherMenu = $this->loadModel('repo')->getSwitcher($this->session->repoID);
}
}
@@ -180,11 +182,12 @@ class ciModel extends model
$data = new stdclass;
$data->status = $pipeline->status;
$data->updateDate = $now;
$data->logs = '';
foreach($jobs as $job)
{
if(empty($job->duration) or $job->duration == '') $job->duration = '-';
$data->logs = "<font style='font-weight:bold'>&gt;&gt;&gt; Job: $job->name, Stage: $job->stage, Status: $job->status, Duration: $job->duration Sec\r\n </font>";
$data->logs .= "<font style='font-weight:bold'>&gt;&gt;&gt; Job: $job->name, Stage: $job->stage, Status: $job->status, Duration: $job->duration Sec\r\n </font>";
$data->logs .= "Job URL: <a href=\"$job->web_url\" target='_blank'>$job->web_url</a> \r\n";
$data->logs .= $this->transformAnsiToHtml($this->gitlab->apiGetJobLog($compile->server, $compile->project, $job->id));
}
+1
View File
@@ -44,6 +44,7 @@ $lang->repo = new stdclass();
$lang->jenkins = new stdclass();
$lang->gitlab = new stdclass();
$lang->gitea = new stdclass();
$lang->gogs = new stdclass();
$lang->mr = new stdclass();
$lang->compile = new stdclass();
$lang->job = new stdclass();
+3 -1
View File
@@ -411,7 +411,7 @@ $lang->devops->menu->code = array('link' => "{$lang->repo->common}|repo|brows
$lang->devops->menu->mr = array('link' => "{$lang->devops->mr}|mr|browse|repoID=%s");
$lang->devops->menu->compile = array('link' => "{$lang->devops->compile}|job|browse|repoID=%s", 'subModule' => 'compile,job');
$lang->devops->menu->app = array('link' => "{$lang->app->common}|app|serverlink|%s");
$lang->devops->menu->set = array('link' => "{$lang->devops->set}|repo|maintain", 'subModule' => 'gitlab,jenkins,sonarqube,gitea', 'alias' => 'setrules,create,edit');
$lang->devops->menu->set = array('link' => "{$lang->devops->set}|repo|maintain", 'subModule' => 'gitlab,jenkins,sonarqube,gitea,gogs', 'alias' => 'setrules,create,edit');
$lang->devops->menuOrder[5] = 'code';
$lang->devops->menuOrder[10] = 'mr';
@@ -424,6 +424,7 @@ $lang->devops->dividerMenu = ',set,';
$lang->devops->menu->set['subMenu'] = new stdclass();
$lang->devops->menu->set['subMenu']->repo = array('link' => "{$lang->devops->repo}|repo|maintain", 'alias' => 'create,edit');
$lang->devops->menu->set['subMenu']->gitlab = array('link' => 'GitLab|gitlab|browse', 'subModule' => 'gitlab');
$lang->devops->menu->set['subMenu']->gogs = array('link' => 'Gogs|gogs|browse', 'subModule' => 'gogs');
$lang->devops->menu->set['subMenu']->gitea = array('link' => 'Gitea|gitea|browse', 'subModule' => 'gitea');
$lang->devops->menu->set['subMenu']->jenkins = array('link' => 'Jenkins|jenkins|browse', 'subModule' => '');
$lang->devops->menu->set['subMenu']->sonarqube = array('link' => 'SonarQube|sonarqube|browse', 'subModule' => 'sonarqube');
@@ -662,6 +663,7 @@ $lang->navGroup->job = 'devops';
$lang->navGroup->jenkins = 'devops';
$lang->navGroup->mr = 'devops';
$lang->navGroup->gitlab = 'devops';
$lang->navGroup->gogs = 'devops';
$lang->navGroup->gitea = 'devops';
$lang->navGroup->sonarqube = 'devops';
$lang->navGroup->sonarqubeproject = 'devops';
+25 -1
View File
@@ -47,6 +47,8 @@ class compile extends control
$this->view->job = $job;
}
$this->compile->syncCompile($repoID, $jobID);
$this->app->loadLang('job');
$this->loadModel('ci')->setMenu($repoID);
@@ -77,7 +79,11 @@ class compile extends control
$build = $this->compile->getByID($buildID);
$job = $this->loadModel('job')->getByID($build->job);
$this->view->logs = str_replace("\r\n","<br />", $build->logs);
if(empty($build->logs) and !in_array($build->status, array('created', 'pending'))) $build->logs = $this->compile->getLogs($job, $build);
$logs = str_replace("\r\n", "<br />", $build->logs);
$logs = str_replace("\n", "<br />", $logs);
$this->view->logs = $logs;
$this->view->build = $build;
$this->view->job = $job;
@@ -87,5 +93,23 @@ class compile extends control
$this->view->position[] = $this->lang->compile->logs;
$this->display();
}
/**
* Sync compiles.
*
* @access public
* @return bool
*/
public function syncCompile()
{
$this->compile->syncCompile();
if(dao::isError())
{
echo json_encode(dao::getError());
return true;
}
echo 'success';
}
}
+4 -3
View File
@@ -1,7 +1,8 @@
<?php
$lang->compile->common = 'Compile';
$lang->compile->browse = 'History';
$lang->compile->logs = 'Logs';
$lang->compile->common = 'Compile';
$lang->compile->browse = 'History';
$lang->compile->logs = 'Logs';
$lang->compile->syncCompile = 'Interface: Sync Compiles.';
$lang->compile->id = 'ID';
$lang->compile->name = 'Name';
+4 -3
View File
@@ -1,7 +1,8 @@
<?php
$lang->compile->common = 'Compile';
$lang->compile->browse = 'History';
$lang->compile->logs = 'Log';
$lang->compile->common = 'Compile';
$lang->compile->browse = 'History';
$lang->compile->logs = 'Log';
$lang->compile->syncCompile = 'Interface: Sync Compiles.';
$lang->compile->id = 'ID';
$lang->compile->name = 'Name';
+4 -3
View File
@@ -1,7 +1,8 @@
<?php
$lang->compile->common = 'Build';
$lang->compile->browse = 'Historique Builds';
$lang->compile->logs = 'Logs des Builds';
$lang->compile->common = 'Build';
$lang->compile->browse = 'Historique Builds';
$lang->compile->logs = 'Logs des Builds';
$lang->compile->syncCompile = 'Interface: Sync Compiles.';
$lang->compile->id = 'ID';
$lang->compile->name = 'Nom';
+4 -3
View File
@@ -1,7 +1,8 @@
<?php
$lang->compile->common = 'Compile';
$lang->compile->browse = 'Lịch sử';
$lang->compile->logs = 'Nhật ký';
$lang->compile->common = 'Compile';
$lang->compile->browse = 'Lịch sử';
$lang->compile->logs = 'Nhật ký';
$lang->compile->syncCompile = 'Interface: Sync Compiles.';
$lang->compile->id = 'ID';
$lang->compile->name = 'Tên';
+4 -3
View File
@@ -1,7 +1,8 @@
<?php
$lang->compile->common = '构建';
$lang->compile->browse = '构建历史';
$lang->compile->logs = '构建日志';
$lang->compile->common = '构建';
$lang->compile->browse = '构建历史';
$lang->compile->logs = '构建日志';
$lang->compile->syncCompile = '接口:同步构建记录';
$lang->compile->id = 'ID';
$lang->compile->name = '构建名称';
+184
View File
@@ -134,6 +134,59 @@ class compileModel extends model
return $url;
}
/**
* Get compile logs.
*
* @param object $job
* @param object $compile
* @access public
* @return string
*/
public function getLogs($job, $compile)
{
$logs = '';
if($job->engine == 'jenkins')
{
$jenkins = $this->loadModel('jenkins')->getByID($job->server);
$jenkinsUser = $jenkins->account;
$jenkinsPassword = $jenkins->token ? $jenkins->token : base64_decode($jenkins->password);
$userPWD = "$jenkinsUser:$jenkinsPassword";
$infoUrl = sprintf('%s/job/%s/api/xml?tree=builds[id,number,queueId]&xpath=//build[queueId=%s]', $jenkins->url, $job->pipeline, $compile->queue);
$response = common::http($infoUrl, '', array(CURLOPT_USERPWD => $userPWD));
if($response)
{
$buildInfo = simplexml_load_string($response);
$buildNumber = $buildInfo->number;
if(empty($buildNumber)) return '';
$logUrl = sprintf('%s/job/%s/%s/consoleText', $jenkins->url, $job->pipeline, $buildNumber);
$logs = common::http($logUrl, '', array(CURLOPT_USERPWD => $userPWD));
$this->dao->update(TABLE_COMPILE)->set('logs')->eq($logs)->where('id')->eq($compile->id)->exec();
}
}
else
{
/* Get jobs by pipeline. */
$pipeline = json_decode($job->pipeline);
$projectID = isset($pipeline->project) ? $pipeline->project : '';
$jobs = $this->loadModel('gitlab')->apiGetJobs($job->server, $projectID, $compile->queue);
$this->loadModel('ci');
foreach($jobs as $gitlabJob)
{
if(empty($gitlabJob->duration) or $gitlabJob->duration == '') $gitlabJob->duration = '-';
$logs .= "<font style='font-weight:bold'>&gt;&gt;&gt; Job: $gitlabJob->name, Stage: $gitlabJob->stage, Status: $gitlabJob->status, Duration: $gitlabJob->duration Sec\r\n </font>";
$logs .= "Job URL: <a href=\"$gitlabJob->web_url\" target='_blank'>$gitlabJob->web_url</a> \r\n";
$logs .= $this->ci->transformAnsiToHtml($this->gitlab->apiGetJobLog($job->server, $projectID, $gitlabJob->id));
}
}
if(!empty($logs)) $this->dao->update(TABLE_COMPILE)->set('logs')->eq($logs)->where('id')->eq($compile->id)->exec();
return $logs;
}
/**
* Save build by job
*
@@ -157,6 +210,137 @@ class compileModel extends model
$this->dao->insert(TABLE_COMPILE)->data($build)->exec();
}
/**
* Sync compiles.
*
* @param int $repoID
* @param int $repoID
* @access public
* @return void
*/
public function syncCompile($repoID = 0, $jobID = 0)
{
if($jobID)
{
$jobList[$jobID] = $this->loadModel('job')->getByID($jobID);
}
else
{
$jobList = $this->loadModel('job')->getList($repoID);
}
$jenkinsPairs = $this->loadModel('pipeline')->getList('jenkins');
$gitlabPairs = $this->loadModel('pipeline')->getList('gitlab');
foreach($jobList as $job)
{
if($job->engine == 'jenkins')
{
$server = zget($jenkinsPairs, $job->server);
$this->syncJenkinsBuildList($server, $job);
}
else
{
$server = zget($gitlabPairs, $job->server);
$this->syncGitLabBuildList($server, $job);
}
}
}
/**
* Sync jenkins build list.
*
* @param object $jenkins
* @param object $job
* @access public
* @return void
*/
public function syncJenkinsBuildList($jenkins, $job)
{
$jenkinsUser = $jenkins->account;
$jenkinsPassword = $jenkins->token ? $jenkins->token : base64_decode($jenkins->password);
/* Get build list by API. */
$url = sprintf('%s/job/%s/api/json?tree=builds[id,number,result,queueId,timestamp]', $jenkins->url, $job->pipeline);
$response = common::http($url, '', array(CURLOPT_USERPWD => "$jenkinsUser:$jenkinsPassword"));
if(!$response) return false;
$compilePairs = $this->dao->select('queue,job')->from(TABLE_COMPILE)->where('job')->eq($job->id)->andWhere('queue')->gt(0)->fetchPairs();
$jobInfo = json_decode($response);
foreach($jobInfo->builds as $build)
{
$lastSyncTime = strtotime($job->lastSyncDate);
if($build->timestamp < $lastSyncTime * 1000) break;
if(isset($compilePairs[$build->queueId])) continue;
$data = new stdclass();
$data->name = $job->name;
$data->job = $job->id;
$data->queue = $build->queueId;
$data->status = $build->result == 'SUCCESS' ? 'success' : 'failure';
$data->createdBy = 'guest';
$data->createdDate = date('Y-m-d H:i:s', $build->timestamp / 1000);
$data->updateDate = $data->createdDate;
$this->dao->insert(TABLE_COMPILE)->data($data)->exec();
}
$now = helper::now();
$this->dao->update(TABLE_JOB)->set('lastSyncDate')->eq($now)->where('id')->eq($job->id)->exec();
}
/**
* Sync gitlab build list.
*
* @param object $gitlab
* @param object $job
* @access public
* @return void
*/
public function syncGitlabBuildList($gitlab, $job)
{
$pipeline = json_decode($job->pipeline);
$projectID = isset($pipeline->project) ? $pipeline->project : '';
$ref = isset($pipeline->reference) ? $pipeline->reference : '';
$url = sprintf($this->loadModel('gitlab')->getApiRoot($gitlab->id, false), "/projects/{$projectID}/pipelines");
/* Get build list by API. */
for($page = 1; true; $page++)
{
$param = $job->lastSyncDate ? '&updated_after=' . date('YYYY-MM-DDThh:mm:ssZ', strtotime($job->lastSyncDate)) : '';
$builds = json_decode(commonModel::http($url . "&ref={$ref}&order_by=id&sort=asc&page={$page}&per_page=100" . $param));
if(!is_array($builds)) break;
if(!empty($builds))
{
$queueIDList = array();
foreach($builds as $build) $queueIDList[] = $build->id;
$compilePairs = $this->dao->select('queue,job')->from(TABLE_COMPILE)->where('job')->eq($job->id)->andWhere('queue')->in($queueIDList)->fetchPairs();
foreach($builds as $build)
{
if(isset($compilePairs[$build->id])) continue;
$data = new stdclass();
$data->name = $job->name;
$data->job = $job->id;
$data->queue = $build->id;
$data->status = $build->status;
$data->createdBy = 'guest';
$data->createdDate = date('Y-m-d H:i:s', strtotime($build->created_at));
$data->updateDate = date('Y-m-d H:i:s', strtotime($build->updated_at));
$this->dao->insert(TABLE_COMPILE)->data($data)->exec();
}
}
if(count($builds) < 100) break;
}
$now = helper::now();
$this->dao->update(TABLE_JOB)->set('lastSyncDate')->eq($now)->where('id')->eq($job->id)->exec();
}
/**
* Execute compile
*
+36 -25
View File
@@ -34,24 +34,30 @@ class git extends control
{
if(isset($_GET['repoUrl'])) $path = $this->get->repoUrl;
$path = helper::safe64Decode($path);
if(common::hasPriv('repo', 'diff'))
$path = helper::safe64Decode($path);
$repos = $this->loadModel('repo')->getListBySCM('Git,Gitlab,Gogs,Gitea', 'haspriv');
$currentRepo = null;
foreach($repos as $repo)
{
$repos = $this->loadModel('repo')->getListBySCM('Git,Gitlab', 'haspriv');
foreach($repos as $repo)
{
if(strpos($path, $repo->path) === 0)
{
$entry = $this->repo->encodePath(str_replace($repo->path, '', $path));
$oldRevision = "$revision^";
$this->locate($this->repo->createLink('diff', "repoID=$repo->id&objectID=0&entry=$entry&oldRevision=$oldRevision&revision=$revision", 'html', 'true'));
}
}
if(!empty($repo->path) and strpos($path, $repo->path) === 0) $currentRepo = $repo;
}
if($currentRepo and common::hasPriv('repo', 'diff'))
{
$entry = $this->repo->encodePath(str_replace($currentRepo->path, '', $path));
$oldRevision = "$revision^";
return $this->locate($this->repo->createLink('diff', "repoID=$currentRepo->id&objectID=0&entry=$entry&oldRevision=$oldRevision&revision=$revision", 'html', 'true'));
}
if($currentRepo)
{
$scm = $this->app->loadClass('scm');
$scm->setEngine($currentRepo);
}
$this->view->path = $path;
$this->view->revision = $revision;
$this->view->diff = $this->git->diff($path, $revision);
$this->view->diff = $currentRepo ? $scm->diff($path, $revision) : '';
$this->display();
}
@@ -68,23 +74,28 @@ class git extends control
{
if(isset($_GET['repoUrl'])) $path = $this->get->repoUrl;
$path = helper::safe64Decode($path);
if(common::hasPriv('repo', 'view'))
$path = helper::safe64Decode($path);
$repos = $this->loadModel('repo')->getListBySCM('Git,Gitlab,Gogs,Gitea', 'haspriv');
$currentRepo = null;
foreach($repos as $repo)
{
$repos = $this->loadModel('repo')->getListBySCM('Git,Gitlab', 'haspriv');
foreach($repos as $repo)
{
if(strpos($path, $repo->path) === 0)
{
$entry = $this->repo->encodePath(str_replace($repo->path, '', $path));
$this->locate($this->repo->createLink('view', "repoID=$repo->id&objectID=0&entry=$entry&revision=$revision", 'html', true));
}
}
if(!empty($repo->path) and strpos($path, $repo->path) === 0) $currentRepo = $repo;
}
if($currentRepo and common::hasPriv('repo', 'view'))
{
$entry = $this->repo->encodePath(str_replace($currentRepo->path, '', $path));
return $this->locate($this->repo->createLink('view', "repoID=$currentRepo->id&objectID=0&entry=$entry&revision=$revision", 'html', true));
}
if($currentRepo)
{
$scm = $this->app->loadClass('scm');
$scm->setEngine($currentRepo);
}
$this->view->path = $path;
$this->view->revision = $revision;
$this->view->code = $this->git->cat($path, $revision);
$this->view->code = $currentRepo ? $scm->cat($path, $revision) : '';
$this->display();
}
+14 -8
View File
@@ -128,18 +128,24 @@ class gitModel extends model
$branches = $this->repo->getBranches($repo);
$commits = $repo->commits;
$gitlabAccountPairs = array();
$accountPairs = array();
if($repo->SCM == 'Gitlab')
{
$gitlabUserList = $this->loadModel('gitlab')->apiGetUsers($repo->gitService);
$acountIDPairs = $this->gitlab->getUserIdAccountPairs($repo->gitService);
foreach($gitlabUserList as $gitlabUser) $gitlabAccountPairs[$gitlabUser->realname] = zget($acountIDPairs, $gitlabUser->id, '');
$userList = $this->loadModel('gitlab')->apiGetUsers($repo->gitService);
$acountIDPairs = $this->gitlab->getUserIdAccountPairs($repo->gitService);
foreach($userList as $gitlabUser) $accountPairs[$gitlabUser->realname] = zget($acountIDPairs, $gitlabUser->id, '');
}
elseif($repo->SCM == 'Gitea')
{
$gitlabUserList = $this->loadModel('gitea')->apiGetUsers($repo->gitService);
$acountIDPairs = $this->gitea->getUserAccountIdPairs($repo->gitService, 'openID,account');
foreach($gitlabUserList as $gitlabUser) $gitlabAccountPairs[$gitlabUser->realname] = zget($acountIDPairs, $gitlabUser->id, '');
$userList = $this->loadModel('gitea')->apiGetUsers($repo->gitService);
$acountIDPairs = $this->gitea->getUserAccountIdPairs($repo->gitService, 'openID,account');
foreach($userList as $gitlabUser) $accountPairs[$gitlabUser->realname] = zget($acountIDPairs, $gitlabUser->id, '');
}
elseif($repo->SCM == 'Gogs')
{
$userList = $this->loadModel('gogs')->apiGetUsers($repo->gitService);
$acountIDPairs = $this->gogs->getUserAccountIdPairs($repo->gitService, 'openID,account');
foreach($userList as $gitlabUser) $accountPairs[$gitlabUser->realname] = zget($acountIDPairs, $gitlabUser->id, '');
}
/* Update code commit history. */
@@ -183,7 +189,7 @@ class gitModel extends model
' task:' . join(' ', $objects['tasks']) .
' bug:' . join(',', $objects['bugs']));
if($lastVersion != $version) $this->repo->saveAction2PMS($objects, $log, $this->repoRoot, $repo->encoding, 'git', $gitlabAccountPairs);
if($lastVersion != $version) $this->repo->saveAction2PMS($objects, $log, $this->repoRoot, $repo->encoding, 'git', $accountPairs);
}
else
{
+1 -1
View File
@@ -141,9 +141,9 @@ class gitea extends control
{
if($confirm != 'yes') return print(js::confirm($this->lang->gitea->confirmDelete, inlink('delete', "id=$giteaID&confirm=yes")));
$oldGitea = $this->loadModel('pipeline')->getByID($giteaID);
$actionID = $this->pipeline->delete($giteaID, 'gitea');
if(!$actionID) return print(js::error($this->lang->pipeline->delError));
$gitea = $this->pipeline->getByID($giteaID);
$changes = common::createChanges($oldGitea, $gitea);
-1
View File
@@ -1,5 +1,4 @@
<?php
$lang->gitea = new stdclass;
$lang->gitea->common = 'Gitea';
$lang->gitea->browse = 'Gitea Browse';
$lang->gitea->search = 'Search';
-1
View File
@@ -1,5 +1,4 @@
<?php
$lang->gitea = new stdclass;
$lang->gitea->common = 'Gitea';
$lang->gitea->browse = 'Gitea Browse';
$lang->gitea->search = 'Search';
-1
View File
@@ -1,5 +1,4 @@
<?php
$lang->gitea = new stdclass;
$lang->gitea->common = 'Gitea';
$lang->gitea->browse = 'Gitea Browse';
$lang->gitea->search = 'Search';
-1
View File
@@ -1,5 +1,4 @@
<?php
$lang->gitea = new stdclass;
$lang->gitea->common = 'Gitea';
$lang->gitea->browse = 'Gitea Browse';
$lang->gitea->search = 'Search';
-1
View File
@@ -1,5 +1,4 @@
<?php
$lang->gitea = new stdclass;
$lang->gitea->common = 'Gitea';
$lang->gitea->browse = '浏览Gitea';
$lang->gitea->search = '搜索';
-1
View File
@@ -1,5 +1,4 @@
<?php
$lang->gitea = new stdclass;
$lang->gitea->common = 'Gitea';
$lang->gitea->browse = '浏览Gitea';
$lang->gitea->search = '搜索';
+9 -16
View File
@@ -228,11 +228,10 @@ class gitlab extends control
{
if($confirm != 'yes') return print(js::confirm($this->lang->gitlab->confirmDelete, inlink('delete', "id=$id&confirm=yes")));
$oldGitLab = $this->gitlab->getByID($id);
$this->loadModel('action');
$this->gitlab->delete(TABLE_PIPELINE, $id);
$oldGitLab = $this->loadModel('pipeline')->getByID($id);
$actionID = $this->pipeline->delete($id, 'gitlab');
if(!$actionID) return print(js::error($this->lang->pipeline->delError));
$actionID = $this->dao->lastInsertID();
$gitLab = $this->gitlab->getByID($id);
$changes = common::createChanges($oldGitLab, $gitLab);
$this->action->logHistory($actionID, $changes);
@@ -722,7 +721,7 @@ class gitlab extends control
$gitlab = $this->gitlab->getByID($gitlabID);
$repos = $this->loadModel('repo')->getRepoListByClient($gitlabID);
$repoPairs = array();
foreach($repos as $repo) $repoPairs[$repo->path] = $repo->id;
foreach($repos as $repo) $repoPairs[$repo->serviceProject] = $repo->id;
$this->view->gitlab = $gitlab;
$this->view->keyword = urldecode(urldecode($keyword));
@@ -966,17 +965,13 @@ class gitlab extends control
/**
* Import gitlab issue to zentaopms.
*
* @param int $repoID
* @param int $gitlabID
* @param int $projectID
* @access public
* @return void
*/
public function importIssue($repoID)
public function importIssue($gitlabID, $projectID)
{
$repo = $this->loadModel('repo')->getRepoByID($repoID);
$productIDList = explode(',', $repo->product);
$gitlabID = $repo->gitService;
$projectID = $repo->project;
$gitlab = $this->gitlab->getByID($gitlabID);
if($gitlab) $user = $this->gitlab->apiGetCurrentUser($gitlab->url, $gitlab->token);
if(empty($user->is_admin)) return print(js::alert($this->lang->gitlab->tokenLimit) . js::locate($this->createLink('gitlab', 'edit', array('gitlabID' => $gitlabID))));
@@ -1053,13 +1048,11 @@ class gitlab extends control
}
}
$products = array('' => '');
$this->loadModel("product");
foreach($productIDList as $productID) $products[$productID] = $this->product->getByID($productID)->name;
$products = $this->loadModel("product")->getPairs();
$this->view->title = $this->lang->gitlab->common . $this->lang->colon . $this->lang->gitlab->importIssue;
$this->view->importable = empty($gitlabIssues) ? false : true;
$this->view->products = $products;
$this->view->products = array('' => '') + $products;
$this->view->gitlabID = $gitlabID;
$this->view->gitlabProjectID = $projectID;
$this->view->objectTypes = $this->config->gitlab->objectTypes;
-1
View File
@@ -1,5 +1,4 @@
<?php
$lang->gitlab = new stdclass;
$lang->gitlab->common = 'GitLab';
$lang->gitlab->browse = 'GitLab Browse';
$lang->gitlab->search = 'Search';
-1
View File
@@ -1,5 +1,4 @@
<?php
$lang->gitlab = new stdclass;
$lang->gitlab->common = 'GitLab';
$lang->gitlab->browse = 'GitLab Browse';
$lang->gitlab->search = 'Search';
-1
View File
@@ -1,5 +1,4 @@
<?php
$lang->gitlab = new stdclass;
$lang->gitlab->common = 'GitLab';
$lang->gitlab->browse = 'GitLab Browse';
$lang->gitlab->search = 'Search';
-1
View File
@@ -1,5 +1,4 @@
<?php
$lang->gitlab = new stdclass;
$lang->gitlab->common = 'GitLab';
$lang->gitlab->browse = 'GitLab Browse';
$lang->gitlab->search = 'Search';
-1
View File
@@ -1,5 +1,4 @@
<?php
$lang->gitlab = new stdclass;
$lang->gitlab->common = 'GitLab';
$lang->gitlab->browse = '浏览GitLab';
$lang->gitlab->search = '搜索';
-1
View File
@@ -1,5 +1,4 @@
<?php
$lang->gitlab = new stdclass;
$lang->gitlab->common = 'GitLab';
$lang->gitlab->browse = '瀏覽GitLab';
$lang->gitlab->search = '搜索';
+17 -1
View File
@@ -986,7 +986,7 @@ class gitlabModel extends model
*/
public function apiGetSingleProject($gitlabID, $projectID)
{
$url = sprintf($this->getApiRoot($gitlabID), "/projects/$projectID");
$url = sprintf($this->getApiRoot($gitlabID, false), "/projects/$projectID");
return json_decode(commonModel::http($url));
}
@@ -2879,4 +2879,20 @@ class gitlabModel extends model
$html .= '</div>';
return $html;
}
/**
* Get pipeline with api.
*
* @param int $gitlabID
* @param int $projectID
* @param string $branch
* @access public
* @return object|array
*/
public function apiGetPipeline($gitlabID, $projectID, $branch)
{
$apiRoot = $this->getApiRoot($gitlabID);
$url = sprintf($apiRoot, "/projects/$projectID/pipelines") . "&ref=$branch";
return json_decode(commonModel::http($url));
}
}
+1 -1
View File
@@ -56,7 +56,7 @@
<td><?php echo $gitlabUser->email;?></td>
<td><?php echo html::select("zentaoUsers[$gitlabUser->id]", $userPairs, $gitlabUser->zentaoAccount, "class='form-control select chosen'" );?></td>
<td>
<?php if(isset($bindedUsers[$gitlabUser->zentaoAccount])):?>
<?php if(in_array($gitlabUser->id, $bindedUsers)):?>
<?php $zentaoAccount = zget($userPairs, $gitlabUser->zentaoAccount, '');?>
<?php if(!empty($zentaoAccount)):?>
<?php echo $lang->gitlab->binded;?>
+13 -9
View File
@@ -60,15 +60,19 @@
<td class='text' title='<?php echo substr($gitlabProject->last_activity_at, 0, 10);?>'><?php echo substr($gitlabProject->last_activity_at, 0, 10);?></td>
<td class='c-actions'>
<?php
echo common::buildIconButton('gitlab', 'browseBranch', "gitlabID=$gitlabID&projectID=$gitlabProject->id", '', 'list', 'treemap', '', '', false, '', $this->lang->gitlab->browseBranch, 0, $gitlabProject->default_branch);
echo common::buildIconButton('gitlab', 'browseTag', "gitlabID=$gitlabID&projectID=$gitlabProject->id", '', 'list', 'tag', '', '', false, '', $this->lang->gitlab->browseTag, 0, $gitlabProject->default_branch);
echo common::buildIconButton('gitlab', 'manageBranchPriv', "gitlabID=$gitlabID&projectID=$gitlabProject->id", '', 'list', 'branch-lock', '', '', false, '', $this->lang->gitlab->browseBranchPriv, 0, ($gitlabProject->isMaintainer and $gitlabProject->default_branch));
echo common::buildIconButton('gitlab', 'manageTagPriv', "gitlabID=$gitlabID&projectID=$gitlabProject->id", '', 'list', 'tag-lock', '', '', false, '', $this->lang->gitlab->browseTagPriv, 0, ($gitlabProject->isMaintainer and $gitlabProject->default_branch));
echo common::buildIconButton('gitlab', 'manageProjectMembers', 'repoID=' . zget($repoPairs, $gitlabProject->id), '', 'list', 'team', '', '', false, '', '', 0, isset($repoPairs[$gitlabProject->id]));
echo common::buildIconButton('gitlab', 'createWebhook', 'repoID=' . zget($repoPairs, $gitlabProject->id), '', 'list', 'change', 'hiddenwin', '', false, '', '', 0, isset($repoPairs[$gitlabProject->id]));
echo common::buildIconButton('gitlab', 'importIssue', 'repoID=' . zget($repoPairs, $gitlabProject->id), '', 'list', 'link', '', '', false, '', '', 0, isset($repoPairs[$gitlabProject->id]));
echo common::buildIconButton('gitlab', 'editProject', "gitlabID=$gitlabID&projectID=$gitlabProject->id", '', 'list', 'edit', '', '', false, '', '', 0, $gitlabProject->adminer);
echo common::buildIconButton('gitlab', 'deleteProject', "gitlabID=$gitlabID&projectID=$gitlabProject->id", '', 'list', 'trash', 'hiddenwin', '', false, '', '', 0, $gitlabProject->adminer);
$hasRepoClass = isset($repoPairs[$gitlabProject->id]) ? '' : 'disabled';
$adminerClass = $gitlabProject->adminer ? '' : 'disabled';
$maintainerClass = $gitlabProject->isMaintainer ? '' : 'disabled';
$defaultBranchClass = $gitlabProject->adminer ? '' : 'disabled';
echo common::printIcon('gitlab', 'browseBranch', "gitlabID=$gitlabID&projectID=$gitlabProject->id", '', 'list', 'treemap', '', $defaultBranchClass, false, '', $this->lang->gitlab->browseBranch);
echo common::printIcon('gitlab', 'browseTag', "gitlabID=$gitlabID&projectID=$gitlabProject->id", '', 'list', 'tag', '', $defaultBranchClass, false, '', $this->lang->gitlab->browseTag);
echo common::printIcon('gitlab', 'manageBranchPriv', "gitlabID=$gitlabID&projectID=$gitlabProject->id", '', 'list', 'branch-lock', '', $defaultBranchClass . ' ' . $maintainerClass, false, '', $this->lang->gitlab->browseBranchPriv);
echo common::printIcon('gitlab', 'manageTagPriv', "gitlabID=$gitlabID&projectID=$gitlabProject->id", '', 'list', 'tag-lock', '', $defaultBranchClass . ' ' . $maintainerClass, false, '', $this->lang->gitlab->browseTagPriv);
echo common::printIcon('gitlab', 'manageProjectMembers', 'repoID=' . zget($repoPairs, $gitlabProject->id), '', 'list', 'team', '', $hasRepoClass);
echo common::printIcon('gitlab', 'createWebhook', 'repoID=' . zget($repoPairs, $gitlabProject->id), '', 'list', 'change', 'hiddenwin', $hasRepoClass);
echo common::printIcon('gitlab', 'importIssue', "gitlabID=$gitlabID&projectID=$gitlabProject->id", '', 'list', 'link');
echo common::printIcon('gitlab', 'editProject', "gitlabID=$gitlabID&projectID=$gitlabProject->id", '', 'list', 'edit', '', $adminerClass);
echo common::printIcon('gitlab', 'deleteProject', "gitlabID=$gitlabID&projectID=$gitlabProject->id", '', 'list', 'trash', 'hiddenwin', $adminerClass);
?>
</td>
</tr>
+6
View File
@@ -0,0 +1,6 @@
<?php
$config->gogs->create = new stdclass;
$config->gogs->create->requiredFields = 'name,url,token';
$config->gogs->edit = new stdclass;
$config->gogs->edit->requiredFields = 'name,url,token';
+222
View File
@@ -0,0 +1,222 @@
<?php
/**
* The control file of gogs module of ZenTaoPMS.
*
* @copyright Copyright 2009-2022 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL(http://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
* @author Liyuchun <liyuchun@easycorp.ltd>
* @package product
* @version $Id: ${FILE_NAME} 5144 2022-08-01 liyuchun@easycorp.ltd $
* @link http://www.zentao.net
*/
class gogs extends control
{
/**
* The gogs constructor.
* @param string $moduleName
* @param string $methodName
*/
public function __construct($moduleName = '', $methodName = '')
{
parent::__construct($moduleName, $methodName);
/* This is essential when changing tab(menu) from gogs to repo. */
/* Optional: common::setMenuVars('devops', $this->session->repoID); */
$this->loadModel('ci')->setMenu();
}
/**
* Browse gogs.
*
* @param string $orderBy
* @param int $recTotal
* @param int $recPerPage
* @param int $pageID
* @access public
* @return void
*/
public function browse($orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1)
{
$this->app->loadClass('pager', $static = true);
$pager = new pager($recTotal, $recPerPage, $pageID);
/* Admin user don't need bind. */
$gogsList = $this->gogs->getList($orderBy, $pager);
$myGogses = $this->gogs->getGogsListByAccount();
foreach($gogsList as $gogs)
{
$gogs->isBindUser = true;
if(!$this->app->user->admin and !isset($myGogses[$gogs->id])) $gogs->isBindUser = false;
}
$this->view->title = $this->lang->gogs->common . $this->lang->colon . $this->lang->gogs->browse;
$this->view->gogsList = $gogsList;
$this->view->orderBy = $orderBy;
$this->view->pager = $pager;
$this->display();
}
/**
* Create a gogs.
*
* @access public
* @return void
*/
public function create()
{
if($_POST)
{
$this->checkToken();
$gogsID = $this->gogs->create();
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
$actionID = $this->loadModel('action')->create('gogs', $gogsID, 'created');
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('browse')));
}
$this->view->title = $this->lang->gogs->common . $this->lang->colon . $this->lang->gogs->lblCreate;
$this->display();
}
/**
* View a gogs.
* @param int $gogsID
* @access public
* @return void
*/
public function view($gogsID)
{
$gogs = $this->gogs->getByID($gogsID);
$this->view->title = $this->lang->gogs->common . $this->lang->colon . $this->lang->gogs->view;
$this->view->gogs = $gogs;
$this->view->users = $this->loadModel('user')->getPairs('noclosed');
$this->view->actions = $this->loadModel('action')->getList('gogs', $gogsID);
$this->view->preAndNext = $this->loadModel('common')->getPreAndNextObject('pipeline', $gogsID);
$this->display();
}
/**
* Edit a gogs.
*
* @param int $gogsID
* @access public
* @return void
*/
public function edit($gogsID)
{
$oldGogs = $this->gogs->getByID($gogsID);
if($_POST)
{
$this->checkToken();
$this->gogs->update($gogsID);
$gogs = $this->gogs->getByID($gogsID);
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
$this->loadModel('action');
$actionID = $this->action->create('gogs', $gogsID, 'edited');
$changes = common::createChanges($oldGogs, $gogs);
$this->action->logHistory($actionID, $changes);
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('browse')));
}
$this->view->title = $this->lang->gogs->common . $this->lang->colon . $this->lang->gogs->edit;
$this->view->gogs = $oldGogs;
$this->display();
}
/**
* Delete a gogs.
*
* @param int $gogsID
* @access public
* @return void
*/
public function delete($gogsID, $confirm = 'no')
{
if($confirm != 'yes') return print(js::confirm($this->lang->gogs->confirmDelete, inlink('delete', "id=$gogsID&confirm=yes")));
$oldGogs = $this->loadModel('pipeline')->getByID($gogsID);
$actionID = $this->pipeline->delete($gogsID, 'gogs');
if(!$actionID) return print(js::error($this->lang->pipeline->delError));
$gogs = $this->pipeline->getByID($gogsID);
$changes = common::createChanges($oldGogs, $gogs);
$this->loadModel('action')->logHistory($actionID, $changes);
return print(js::reload('parent'));
}
/**
* Check post token has admin permissions.
*
* @access protected
* @return void
*/
protected function checkToken()
{
$gogs = fixer::input('post')->trim('url,token')->get();
$this->dao->update('gogs')->data($gogs)->batchCheck($this->config->gogs->create->requiredFields, 'notempty');
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
$result = $this->gogs->checkTokenAccess($gogs->url, $gogs->token);
if($result === false) return $this->send(array('result' => 'fail', 'message' => array('url' => array($this->lang->gogs->hostError))));
if(!$result) return $this->send(array('result' => 'fail', 'message' => array('token' => array($this->lang->gogs->tokenLimit))));
return true;
}
/**
* Bind gogs user to zentao users.
*
* @param int $gogsID
* @access public
* @return void
*/
public function bindUser($gogsID)
{
$zentaoUsers = $this->dao->select('account,email,realname')->from(TABLE_USER)->fetchAll('account');
$userPairs = $this->loadModel('user')->getPairs('noclosed|noletter');
if($_POST)
{
$this->gogs->bindUser($gogsID);
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $this->server->http_referer));
}
$this->view->title = $this->lang->gogs->bindUser;
$this->view->userPairs = $userPairs;
$this->view->gogsUsers = $this->gogs->apiGetUsers($gogsID);
$this->view->bindedUsers = $this->gogs->getUserAccountIdPairs($gogsID);
$this->view->matchedResult = $this->gogs->getMatchedUsers($gogsID, $this->view->gogsUsers, $zentaoUsers);
$this->display();
}
/**
* Ajax getProjectBranches
*
* @param int $gogsID
* @param string $project
* @access public
* @return void
*/
public function ajaxGetProjectBranches($gogsID, $project)
{
if(!$gogsID or !$project) return $this->send(array('message' => array()));
$project = urldecode(base64_decode($project));
$branches = $this->gogs->apiGetBranches($gogsID, $project);
$options = "<option value=''></option>";
foreach($branches as $branch)
{
$options .= "<option value='{$branch->name}'>{$branch->name}</option>";
}
$this->send($options);
}
}
+2
View File
@@ -0,0 +1,2 @@
.c-id {width: 60px;}
.c-name {width: 200px;}
+2
View File
@@ -0,0 +1,2 @@
#publicTip {padding-left: 10px;}
.table-form>tbody>tr>th {width: 110px;}
+35
View File
@@ -0,0 +1,35 @@
<?php
$lang->gogs->common = 'Gogs';
$lang->gogs->browse = 'Gogs Browse';
$lang->gogs->search = 'Search';
$lang->gogs->create = 'Create Gogs';
$lang->gogs->edit = 'Edit Gogs';
$lang->gogs->view = 'View Gogs';
$lang->gogs->delete = 'Delete Gogs';
$lang->gogs->confirmDelete = 'Do you want to delete this Gogs server?';
$lang->gogs->bindUser = 'Bind User';
$lang->gogs->gogsAvatar = 'Avatar';
$lang->gogs->gogsAccount = 'Gogs Account';
$lang->gogs->gogsEmail = 'Email';
$lang->gogs->zentaoAccount = 'Zentao Account';
$lang->gogs->bindingStatus = 'Binding Status';
$lang->gogs->notBind = 'Not bind';
$lang->gogs->binded = 'Binded';
$lang->gogs->bindDynamic = '%s and Zentao user %s';
$lang->gogs->browseAction = 'Gogs List';
$lang->gogs->deleteAction = 'Delete Gogs';
$lang->gogs->id = 'ID';
$lang->gogs->name = "Server Name";
$lang->gogs->url = 'Server URL';
$lang->gogs->token = 'Token';
$lang->gogs->tokenLimit = "The current token has no admin privilege. Please regenerate one with root user in Gogs.";
$lang->gogs->hostError = "So the current Gogs server address is invalid, please confirm that the current server can be accessed and try again.";
$lang->gogs->bindUserError = "Can not bind users repeatedly %s";
$lang->gogs->server = "Server List";
$lang->gogs->lblCreate = 'Create Gogs Server';
$lang->gogs->emptyError = " cannot be empty";
$lang->gogs->createSuccess = "Create success";
+35
View File
@@ -0,0 +1,35 @@
<?php
$lang->gogs->common = 'Gogs';
$lang->gogs->browse = 'Gogs Browse';
$lang->gogs->search = 'Search';
$lang->gogs->create = 'Create Gogs';
$lang->gogs->edit = 'Edit Gogs';
$lang->gogs->view = 'View Gogs';
$lang->gogs->delete = 'Delete Gogs';
$lang->gogs->confirmDelete = 'Do you want to delete this Gogs server?';
$lang->gogs->bindUser = 'Bind User';
$lang->gogs->gogsAvatar = 'Avatar';
$lang->gogs->gogsAccount = 'Gogs Account';
$lang->gogs->gogsEmail = 'Email';
$lang->gogs->zentaoAccount = 'Zentao Account';
$lang->gogs->bindingStatus = 'Binding Status';
$lang->gogs->notBind = 'Not bind';
$lang->gogs->binded = 'Binded';
$lang->gogs->bindDynamic = '%s and Zentao user %s';
$lang->gogs->browseAction = 'Gogs List';
$lang->gogs->deleteAction = 'Delete Gogs';
$lang->gogs->id = 'ID';
$lang->gogs->name = "Server Name";
$lang->gogs->url = 'Server URL';
$lang->gogs->token = 'Token';
$lang->gogs->tokenLimit = "The current token has no admin privilege. Please regenerate one with root user in Gogs.";
$lang->gogs->hostError = "So the current Gogs server address is invalid, please confirm that the current server can be accessed and try again.";
$lang->gogs->bindUserError = "Can not bind users repeatedly %s";
$lang->gogs->server = "Server List";
$lang->gogs->lblCreate = 'Create Gogs Server';
$lang->gogs->emptyError = " cannot be empty";
$lang->gogs->createSuccess = "Create success";
+35
View File
@@ -0,0 +1,35 @@
<?php
$lang->gogs->common = 'Gogs';
$lang->gogs->browse = 'Gogs Browse';
$lang->gogs->search = 'Search';
$lang->gogs->create = 'Create Gogs';
$lang->gogs->edit = 'Edit Gogs';
$lang->gogs->view = 'View Gogs';
$lang->gogs->delete = 'Delete Gogs';
$lang->gogs->confirmDelete = 'Do you want to delete this Gogs server?';
$lang->gogs->bindUser = 'Bind User';
$lang->gogs->gogsAvatar = 'Avatar';
$lang->gogs->gogsAccount = 'Gogs Account';
$lang->gogs->gogsEmail = 'Email';
$lang->gogs->zentaoAccount = 'Zentao Account';
$lang->gogs->bindingStatus = 'Binding Status';
$lang->gogs->notBind = 'Not bind';
$lang->gogs->binded = 'Binded';
$lang->gogs->bindDynamic = '%s and Zentao user %s';
$lang->gogs->browseAction = 'Gogs List';
$lang->gogs->deleteAction = 'Delete Gogs';
$lang->gogs->id = 'ID';
$lang->gogs->name = "Server Name";
$lang->gogs->url = 'Server URL';
$lang->gogs->token = 'Token';
$lang->gogs->tokenLimit = "The current token has no admin privilege. Please regenerate one with root user in Gogs.";
$lang->gogs->hostError = "So the current Gogs server address is invalid, please confirm that the current server can be accessed and try again.";
$lang->gogs->bindUserError = "Can not bind users repeatedly %s";
$lang->gogs->server = "Server List";
$lang->gogs->lblCreate = 'Create Gogs Server';
$lang->gogs->emptyError = " cannot be empty";
$lang->gogs->createSuccess = "Create success";
+35
View File
@@ -0,0 +1,35 @@
<?php
$lang->gogs->common = 'Gogs';
$lang->gogs->browse = 'Gogs Browse';
$lang->gogs->search = 'Search';
$lang->gogs->create = 'Create Gogs';
$lang->gogs->edit = 'Edit Gogs';
$lang->gogs->view = 'View Gogs';
$lang->gogs->delete = 'Delete Gogs';
$lang->gogs->confirmDelete = 'Do you want to delete this Gogs server?';
$lang->gogs->gogsAvatar = 'Avatar';
$lang->gogs->bindUser = 'Bind User';
$lang->gogs->gogsEmail = 'Email';
$lang->gogs->gogsAccount = 'Gogs Account';
$lang->gogs->zentaoAccount = 'Zentao Account';
$lang->gogs->bindingStatus = 'Binding Status';
$lang->gogs->notBind = 'Not bind';
$lang->gogs->binded = 'Binded';
$lang->gogs->bindDynamic = '%s and Zentao user %s';
$lang->gogs->browseAction = 'Gogs List';
$lang->gogs->deleteAction = 'Delete Gogs';
$lang->gogs->id = 'ID';
$lang->gogs->name = "Server Name";
$lang->gogs->url = 'Server URL';
$lang->gogs->token = 'Token';
$lang->gogs->tokenLimit = "The current token has no admin privilege. Please regenerate one with root user in Gogs.";
$lang->gogs->hostError = "So the current Gogs server address is invalid, please confirm that the current server can be accessed and try again.";
$lang->gogs->bindUserError = "Can not bind users repeatedly %s";
$lang->gogs->server = "Server List";
$lang->gogs->lblCreate = 'Create Gogs Server';
$lang->gogs->emptyError = " cannot be empty";
$lang->gogs->createSuccess = "Create success";
+35
View File
@@ -0,0 +1,35 @@
<?php
$lang->gogs->common = 'Gogs';
$lang->gogs->browse = '浏览Gogs';
$lang->gogs->search = '搜索';
$lang->gogs->create = '添加Gogs';
$lang->gogs->edit = '编辑Gogs';
$lang->gogs->view = '查看Gogs';
$lang->gogs->delete = '删除Gogs';
$lang->gogs->confirmDelete = '确认删除该Gogs吗?';
$lang->gogs->bindUser = '绑定用户';
$lang->gogs->gogsAvatar = '头像';
$lang->gogs->gogsAccount = 'Gogs用户';
$lang->gogs->gogsEmail = '邮箱';
$lang->gogs->zentaoAccount = '禅道用户';
$lang->gogs->bindingStatus = '绑定状态';
$lang->gogs->notBind = '未绑定';
$lang->gogs->binded = '已绑定';
$lang->gogs->bindDynamic = '%s与禅道用户%s';
$lang->gogs->browseAction = 'Gogs列表';
$lang->gogs->deleteAction = '删除Gogs';
$lang->gogs->id = 'ID';
$lang->gogs->name = "服务器名称";
$lang->gogs->url = '服务器地址';
$lang->gogs->token = 'Token';
$lang->gogs->tokenLimit = "Gogs Token权限不足。";
$lang->gogs->hostError = "当前Gogs服务器地址无效,请确认当前服务器可被访问";
$lang->gogs->bindUserError = "不能重复绑定用户 %s";
$lang->gogs->server = "服务器列表";
$lang->gogs->lblCreate = '添加Gogs服务器';
$lang->gogs->emptyError = "不能为空";
$lang->gogs->createSuccess = "创建成功";
+32
View File
@@ -0,0 +1,32 @@
<?php
$lang->gogs->common = 'Gogs';
$lang->gogs->browse = '浏览Gogs';
$lang->gogs->search = '搜索';
$lang->gogs->create = '添加Gogs';
$lang->gogs->edit = '编辑Gogs';
$lang->gogs->view = '查看Gogs';
$lang->gogs->delete = '删除Gogs';
$lang->gogs->confirmDelete = '确认删除该Gogs吗?';
$lang->gogs->bindUser = '绑定用户';
$lang->gogs->gogsAccount = 'Gogs用户';
$lang->gogs->zentaoAccount = '禅道用户';
$lang->gogs->bindingStatus = '绑定状态';
$lang->gogs->notBind = '未绑定';
$lang->gogs->binded = '已绑定';
$lang->gogs->bindDynamic = '%s与禅道用户%s';
$lang->gogs->browseAction = 'Gogs列表';
$lang->gogs->deleteAction = '删除Gogs';
$lang->gogs->id = 'ID';
$lang->gogs->name = "服务器名称";
$lang->gogs->url = '服务器地址';
$lang->gogs->token = 'Token';
$lang->gogs->tokenLimit = "Gogs Token权限不足。";
$lang->gogs->hostError = "当前Gogs服务器地址无效,请确认当前服务器可被访问";
$lang->gogs->server = "服务器列表";
$lang->gogs->lblCreate = '添加Gogs服务器';
$lang->gogs->emptyError = "不能为空";
$lang->gogs->createSuccess = "创建成功";
+583
View File
@@ -0,0 +1,583 @@
<?php
/**
* The model file of gogs module of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL(http://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
* @author Chenqi <chenqi@cnezsoft.com>
* @package product
* @version $Id: $
* @link http://www.zentao.net
*/
class gogsModel extends model
{
/**
* Get a gogs by id.
*
* @param int $id
* @access public
* @return object
*/
public function getByID($id)
{
return $this->loadModel('pipeline')->getByID($id);
}
/**
* Get gogs list.
*
* @param string $orderBy
* @param object $pager
* @access public
* @return array
*/
public function getList($orderBy = 'id_desc', $pager = null)
{
$gogsList = $this->loadModel('pipeline')->getList('gogs', $orderBy, $pager);
return $gogsList;
}
/**
* Get gogs pairs.
*
* @access public
* @return array
*/
public function getPairs()
{
return $this->loadModel('pipeline')->getPairs('gogs');
}
/**
* Get gogs api base url by gogs id.
*
* @param int $gogsID
* @access public
* @return string
*/
public function getApiRoot($gogsID)
{
$gogs = $this->getByID($gogsID);
if(!$gogs) return '';
return rtrim($gogs->url, '/') . '/api/v1%s' . "?token={$gogs->token}";
}
/**
* Create a gogs.
*
* @access public
* @return bool
*/
public function create()
{
return $this->loadModel('pipeline')->create('gogs');
}
/**
* Update a gogs.
*
* @param int $id
* @access public
* @return bool
*/
public function update($id)
{
return $this->loadModel('pipeline')->update($id);
}
/**
* Bind users.
*
* @param int $gogsID
* @access public
* @return array
*/
public function bindUser($gogsID)
{
$userPairs = $this->loadModel('user')->getPairs('noclosed|noletter');
$users = $this->post->zentaoUsers;
$gogsNames = $this->post->gogsUserNames;
$accountList = array();
$repeatUsers = array();
foreach($users as $openID => $user)
{
if(empty($user)) continue;
if(isset($accountList[$user])) $repeatUsers[] = zget($userPairs, $user);
$accountList[$user] = $openID;
}
if(count($repeatUsers))
{
dao::$errors[] = sprintf($this->lang->gogs->bindUserError, join(',', $repeatUsers));
return false;
}
$user = new stdclass;
$user->providerID = $gogsID;
$user->providerType = 'gogs';
$oldUsers = $this->dao->select('*')->from(TABLE_OAUTH)->where('providerType')->eq($user->providerType)->andWhere('providerID')->eq($user->providerID)->fetchAll('openID');
foreach($users as $openID => $account)
{
$existAccount = isset($oldUsers[$openID]) ? $oldUsers[$openID] : '';
if($existAccount and $existAccount->account != $account)
{
$this->dao->delete()
->from(TABLE_OAUTH)
->where('openID')->eq($openID)
->andWhere('providerType')->eq($user->providerType)
->andWhere('providerID')->eq($user->providerID)
->exec();
$this->loadModel('action')->create('gogsuser', $gogsID, 'unbind', '', sprintf($this->lang->gogs->bindDynamic, $gogsNames[$openID], $zentaoUsers[$existAccount->account]->realname));
}
if(!$existAccount or $existAccount->account != $account)
{
if(!$account) continue;
$user->account = $account;
$user->openID = $openID;
$this->dao->insert(TABLE_OAUTH)->data($user)->exec();
$this->loadModel('action')->create('gogsuser', $gogsID, 'bind', '', sprintf($this->lang->gogs->bindDynamic, $gogsNames[$openID], $zentaoUsers[$account]->realname));
}
}
}
/**
* Api error handling.
*
* @param object $response
* @access public
* @return bool
*/
public function apiErrorHandling($response)
{
if(!empty($response->error))
{
dao::$errors[] = $response->error;
return false;
}
if(!empty($response->message))
{
if(is_string($response->message))
{
$errorKey = array_search($response->message, $this->lang->gogs->apiError);
dao::$errors[] = $errorKey === false ? $response->message : zget($this->lang->gogs->errorLang, $errorKey);
}
else
{
foreach($response->message as $field => $fieldErrors)
{
if(is_string($fieldErrors))
{
$errorKey = array_search($fieldErrors, $this->lang->gogs->apiError);
if($fieldErrors) dao::$errors[$field][] = $errorKey === false ? $fieldErrors : zget($this->lang->gogs->errorLang, $errorKey);
}
else
{
foreach($fieldErrors as $error)
{
$errorKey = array_search($error, $this->lang->gogs->apiError);
if($error) dao::$errors[$field][] = $errorKey === false ? $error : zget($this->lang->gogs->errorLang, $errorKey);
}
}
}
}
}
if(!$response) dao::$errors[] = false;
return false;
}
/**
* Check token access.
*
* @param string $url
* @param string $token
* @access public
* @return void
*/
public function checkTokenAccess($url = '', $token = '')
{
$apiRoot = rtrim($url, '/') . '/api/v1%s' . "?token={$token}";
$url = sprintf($apiRoot, "/user");
$httpData = commonModel::httpWithHeader($url);
$user = json_decode($httpData['body']);
if(empty($httpData['header'])) return false;
if(empty($user)) return null;
/* Check whether the token belongs to the administrator by edit user. */
$editUserUrl = sprintf($apiRoot, "/admin/users/" . $user->username);
$data = new stdclass();
$data->login_name = $user->login;
$data->email = $user->email;
$result = commonModel::http($editUserUrl, $data, array(), array(), 'data', 'PATCH');
$user = json_decode($result);
if(empty($user)) return null;
return true;
}
/**
* Get Gogs id list by user account.
*
* @param string $account
* @access public
* @return array
*/
public function getGogsListByAccount($account = '')
{
if(!$account) $account = $this->app->user->account;
return $this->dao->select('providerID,openID')->from(TABLE_OAUTH)
->where('providerType')->eq('gogs')
->andWhere('account')->eq($account)
->fetchPairs('providerID');
}
/**
* Get zentao account gogs user id pairs of one gogs.
*
* @param int $gogsID
* @access public
* @return array
*/
public function getUserAccountIdPairs($gogsID, $fields = 'account,openID')
{
return $this->dao->select($fields)->from(TABLE_OAUTH)
->where('providerType')->eq('gogs')
->andWhere('providerID')->eq($gogsID)
->fetchPairs();
}
/**
* Get gogs user id by zentao account.
*
* @param int $gogsID
* @param string $zentaoAccount
* @access public
* @return array
*/
public function getUserIDByZentaoAccount($gogsID, $zentaoAccount)
{
return $this->dao->select('openID')->from(TABLE_OAUTH)
->where('providerType')->eq('gogs')
->andWhere('providerID')->eq($gogsID)
->andWhere('account')->eq($zentaoAccount)
->fetch('openID');
}
/**
* Get matched gogs users.
*
* @param int $gogsID
* @param array $gogsUsers
* @param array $zentaoUsers
* @access public
* @return array
*/
public function getMatchedUsers($gogsID, $gogsUsers, $zentaoUsers)
{
$matches = new stdclass;
foreach($gogsUsers as $gogsUser)
{
foreach($zentaoUsers as $zentaoUser)
{
if($gogsUser->account == $zentaoUser->account) $matches->accounts[$gogsUser->account][] = $zentaoUser->account;
if($gogsUser->realname == $zentaoUser->realname) $matches->names[$gogsUser->realname][] = $zentaoUser->account;
if($gogsUser->email == $zentaoUser->email) $matches->emails[$gogsUser->email][] = $zentaoUser->account;
}
}
$bindedUsers = $this->getUserAccountIdPairs($gogsID, 'openID,account');
$matchedUsers = array();
foreach($gogsUsers as $gogsUser)
{
if(isset($bindedUsers[$gogsUser->account]))
{
$gogsUser->zentaoAccount = $bindedUsers[$gogsUser->account];
$matchedUsers[] = $gogsUser;
continue;
}
$matchedZentaoUsers = array();
if(isset($matches->accounts[$gogsUser->account])) $matchedZentaoUsers = array_merge($matchedZentaoUsers, $matches->accounts[$gogsUser->account]);
if(isset($matches->emails[$gogsUser->email])) $matchedZentaoUsers = array_merge($matchedZentaoUsers, $matches->emails[$gogsUser->email]);
if(isset($matches->names[$gogsUser->realname])) $matchedZentaoUsers = array_merge($matchedZentaoUsers, $matches->names[$gogsUser->realname]);
$matchedZentaoUsers = array_unique($matchedZentaoUsers);
if(count($matchedZentaoUsers) == 1)
{
$gogsUser->zentaoAccount = current($matchedZentaoUsers);
$matchedUsers[] = $gogsUser;
}
}
return $matchedUsers;
}
/**
* Get project by api.
*
* @param int $gogsID
* @param int $projectID
* @access public
* @return void
*/
public function apiGetSingleProject($gogsID, $projectID)
{
$apiRoot = $this->getApiRoot($gogsID);
if(!$apiRoot) return array();
$url = sprintf($apiRoot, "/repos/$projectID");
$project = json_decode(commonModel::http($url));
if(isset($project->name))
{
$project->name_with_namespace = $project->full_name;
$project->path_with_namespace = $project->full_name;
$project->http_url_to_repo = $project->html_url;
$project->name_with_namespace = $project->full_name;
$gogs = $this->getByID($gogsID);
$oauth = "oauth2:{$gogs->token}@";
$project->tokenCloneUrl = preg_replace('/(http(s)?:\/\/)/', "\$1$oauth", $project->html_url);
}
return $project;
}
/**
* Get projects by api.
*
* @param int $gogsID
* @access public
* @return array
*/
public function apiGetProjects($gogsID)
{
$apiRoot = $this->getApiRoot($gogsID);
if(!$apiRoot) return array();
$user = $this->apiGetAdminer($gogsID);
if(!$user) return array();
$url = sprintf($apiRoot, "/users/{$user->username}/repos");
$allResults = array();
for($page = 1; true; $page++)
{
$results = json_decode(commonModel::http($url . "&page={$page}&limit=50"));
if(!is_array($results)) break;
if(!empty($results)) $allResults = array_merge($allResults, $results);
if(count($results) < 50) break;
}
return $allResults;
}
/**
* Api get adminer.
*
* @param int $gogsID
* @access public
* @return void
*/
public function apiGetAdminer($gogsID)
{
$apiRoot = $this->getApiRoot($gogsID);
if(!$apiRoot) return array();
$url = sprintf($apiRoot, "/user");
$user = json_decode(commonModel::http($url));
return isset($user->username) ? $user : null;
}
/**
* Get gogs user list.
*
* @param int $gogsID
* @param bool $onlyLinked
* @access public
* @return array
*/
public function apiGetUsers($gogsID, $onlyLinked = false)
{
$response = array();
$apiRoot = $this->getApiRoot($gogsID);
for($page = 1; true; $page++)
{
$url = sprintf($apiRoot, "/admin/users") . "&page={$page}&limit=20";
$result = json_decode(commonModel::http($url));
if(empty($result->data)) break;
$response = array_merge($response, $result->data);
$page += 1;
}
if(empty($response)) return array();
/* Get linked users. */
$linkedUsers = array();
if($onlyLinked) $linkedUsers = $this->getUserAccountIdPairs($gogsID, 'openID,account');
$users = array();
foreach($response as $gogsUser)
{
if($onlyLinked and !isset($linkedUsers[$gogsUser->id])) continue;
$user = new stdclass;
$user->id = $gogsUser->id;
$user->realname = $gogsUser->full_name ? $gogsUser->full_name : $gogsUser->username;
$user->account = $gogsUser->username;
$user->email = zget($gogsUser, 'email', '');
$user->avatar = $gogsUser->avatar_url;
$user->createdAt = zget($gogsUser, 'created', '');
$user->lastActivityOn = zget($gogsUser, 'login', '');
$users[] = $user;
}
return $users;
}
/**
* Get project repository branches by api.
*
* @param int $gogsID
* @param string $project
* @access public
* @return object
*/
public function apiGetBranches($gogsID, $project, $pager = null)
{
$url = sprintf($this->getApiRoot($gogsID), "/repos/{$project}/branches");
$allResults = array();
for($page = 1; true; $page++)
{
$results = json_decode(commonModel::http($url . "&page={$page}&limit=50"));
if(!is_array($results)) break;
if(!empty($results)) $allResults = array_merge($allResults, $results);
if(count($results) < 100) break;
}
return $allResults;
}
/**
* Get upstream project by API.
*
* @param int $gogsID
* @param string $project
* @access public
* @return void
*/
public function apiGetUpstream($gogsID, $project)
{
$currentProject = $this->apiGetSingleProject($gogsID, $project);
if(isset($currentProject->parent->full_name)) return $currentProject->parent->full_name;
return array();
}
/**
* Get branches.
*
* @param int $gogsID
* @param string $project
* @access public
* @return array
*/
public function getBranches($gogsID, $project)
{
$rawBranches = $this->apiGetBranches($gogsID, $project);
$branches = array();
foreach($rawBranches as $branch) $branches[] = $branch->name;
return $branches;
}
/**
* Get gogs user id and realname pairs of one gogs.
*
* @param int $gogsID
* @access public
* @return array
*/
public function getUserIdRealnamePairs($gogsID)
{
return $this->dao->select('oauth.openID as openID,user.realname as realname')
->from(TABLE_OAUTH)->alias('oauth')
->leftJoin(TABLE_USER)->alias('user')
->on("oauth.account = user.account")
->where('providerType')->eq('gogs')
->andWhere('providerID')->eq($gogsID)
->fetchPairs();
}
/**
* Get single branch by API.
*
* @param int $gogsID
* @param string $project
* @param string $branchName
* @access public
* @return object
*/
public function apiGetSingleBranch($gogsID, $project, $branchName)
{
$url = sprintf($this->getApiRoot($gogsID), "/repos/$project/branches/$branchName");
$branch = json_decode(commonModel::http($url));
if($branch)
{
$gogs = $this->getByID($gogsID);
$branch->web_url = "{$gogs->url}/$project/src/$branchName";
}
return $branch;
}
/**
* Get protect branches of one project.
*
* @param int $gogsID
* @param string $project
* @param string $keyword
* @access public
* @return array
*/
public function apiGetBranchPrivs($gogsID, $project, $keyword = '')
{
$keyword = urlencode($keyword);
$url = sprintf($this->getApiRoot($gogsID), "/repos/$project/branch_protections");
$branches = json_decode(commonModel::http($url));
if(!is_array($branches)) return array();
$newBranches = array();
foreach($branches as $branch)
{
$branch->name = $branch->Name;
if(empty($keyword) || stristr($branch->name, $keyword)) $newBranches[] = $branch;
}
return $newBranches;
}
/**
* Api delete branch.
*
* @param int $gogsID
* @param string $project
* @param string $branch
* @access public
* @return void
*/
public function apiDeleteBranch($gogsID, $project, $branch)
{
$url = sprintf($this->getApiRoot($gogsID), "/repos/$project/branches/$branch");
return json_decode(commonModel::http($url, null, array(CURLOPT_CUSTOMREQUEST => 'DELETE')));
}
}
+85
View File
@@ -0,0 +1,85 @@
<?php
/**
* The bind user view of gogs module of ZenTaoPMS.
*
* @copyright Copyright 2009-2022 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL(http://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
* @author Yuchun Li <liyuchun@easycorp.ltd>
* @package gogs
* @version $Id$
* @link http://www.zentao.net
*/
?>
<?php include '../../common/view/header.html.php';?>
<div id="mainContent" class="main-content">
<div class="main-header">
<h2><?php echo $lang->gogs->bindUser;?></h2>
</div>
<form method='post' class='load-indicator main-form form-ajax' enctype='multipart/form-data'>
<div class="table-responsive">
<table class="table table-borderless w-800px">
<thead>
<tr>
<th class='w-60px'><?php echo $lang->gogs->gogsAvatar;?></th>
<th><?php echo $lang->gogs->gogsAccount;?></th>
<th><?php echo $lang->gogs->gogsEmail;?></th>
<th class='w-150px'><?php echo $lang->gogs->zentaoAccount;?></th>
<th><?php echo $lang->gogs->bindingStatus;?></th>
</tr>
</thead>
<tbody>
<?php foreach($gogsUsers as $gogsUser):?>
<?php if(isset($gogsUser->zentaoAccount)) continue;?>
<?php echo html::hidden("gogsUserNames[$gogsUser->account]", $gogsUser->realname);?>
<tr>
<td><?php echo html::image($gogsUser->avatar, "height=40");?></td>
<td class='text-left'>
<strong><?php echo $gogsUser->realname;?></strong>
<br>
<?php echo $gogsUser->account;?>
</td>
<td><?php echo $gogsUser->email;?></td>
<td><?php echo html::select("zentaoUsers[$gogsUser->account]", $userPairs, '', "class='form-control select chosen'" );?></td>
<td><?php echo $lang->gogs->notBind;?></td>
</tr>
<?php endforeach;?>
<?php foreach($gogsUsers as $gogsUser):?>
<?php if(!isset($gogsUser->zentaoAccount)) continue;?>
<?php echo html::hidden("gogsUserNames[$gogsUser->account]", $gogsUser->realname);?>
<tr>
<td><?php echo html::image($gogsUser->avatar, "height=40");?></td>
<td>
<strong><?php echo $gogsUser->realname;?></strong>
<br>
<?php echo $gogsUser->account;?>
</td>
<td><?php echo $gogsUser->email;?></td>
<td><?php echo html::select("zentaoUsers[$gogsUser->account]", $userPairs, $gogsUser->zentaoAccount, "class='form-control select chosen'" );?></td>
<td>
<?php if(isset($bindedUsers[$gogsUser->zentaoAccount])):?>
<?php $zentaoAccount = zget($userPairs, $gogsUser->zentaoAccount, '');?>
<?php if(!empty($zentaoAccount)):?>
<?php echo $lang->gogs->binded;?>
<?php else:?>
<?php echo '<span class="text-red">' . $lang->gogs->bindedError . '</span>';?>
<?php endif;?>
<?php else:?>
<?php echo $lang->gogs->notBind;?>
<?php endif;?>
</td>
</tr>
<?php endforeach;?>
</tbody>
<tfoot>
<tr>
<td colspan="5" class="text-center form-actions">
<?php echo html::submitButton();?>
<?php if(!isonlybody()) echo html::a(inlink('browse', ""), $lang->goback, '', 'class="btn btn-wide"');?>
</td>
</tr>
</tfoot>
</table>
</div>
</form>
</div>
<?php include '../../common/view/footer.html.php';?>
+73
View File
@@ -0,0 +1,73 @@
<?php
/**
* The browse view file of gogs module of ZenTaoPMS.
*
* @copyright Copyright 2009-2017 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL(http://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
* @author Gang Liu <liugang@cnezsoft.com>
* @package gogs
* @version $Id$
* @link http://www.zentao.net
*/
?>
<?php include '../../common/view/header.html.php';?>
<div id="mainMenu" class="clearfix">
<div class="btn-toolbar pull-left">
<?php echo html::a($this->createLink('gogs', 'browse'), "<span class='text'>{$lang->gogs->server}</span>", '', "class='btn btn-link btn-active-text'");?>
</div>
<div class="btn-toolbar pull-right">
<?php if(common::hasPriv('gogs', 'create')) common::printLink('gogs', 'create', "", "<i class='icon icon-plus'></i> " . $lang->gogs->create, '', "class='btn btn-primary'");?>
</div>
</div>
<?php if(empty($gogsList)):?>
<div class="table-empty-tip">
<p>
<span class="text-muted"><?php echo $lang->noData;?></span>
<?php if(common::hasPriv('gogs', 'create')):?>
<?php echo html::a($this->createLink('gogs', 'create'), "<i class='icon icon-plus'></i> " . $lang->gogs->create, '', "class='btn btn-info'");?>
<?php endif;?>
</p>
</div>
<?php else:?>
<div id='mainContent' class='main-row'>
<form class='main-table' id='ajaxForm' method='post'>
<table id='gogsList' class='table has-sort-head table-fixed'>
<thead>
<tr>
<?php $vars = "orderBy=%s&recTotal={$pager->recTotal}&recPerPage={$pager->recPerPage}&pageID={$pager->pageID}";?>
<th class='c-id'><?php common::printOrderLink('id', $orderBy, $vars, $lang->gogs->id);?></th>
<th class='c-name w-300px'><?php common::printOrderLink('name', $orderBy, $vars, $lang->gogs->name);?></th>
<th class='text'><?php common::printOrderLink('url', $orderBy, $vars, $lang->gogs->url);?></th>
<th class='c-actions-3 text-center'><?php echo $lang->actions;?></th>
</tr>
</thead>
<tbody>
<?php foreach ($gogsList as $id => $gogs): ?>
<tr class='text'>
<td class='text'><?php echo $id;?></td>
<td class='text-c-name' title='<?php echo $gogs->name;?>'>
<?php if(common::hasPriv('gogs', 'view')):?>
<a class="iframe" href="<?php echo $this->createLink('gogs', 'view', "gogsID=$id", '', true); ?>"><?php echo $gogs->name;?></a>
<?php else:?>
<?php echo $gogs->name;?>
<?php endif;?>
</td>
<td class='text' title='<?php echo $gogs->url;?>'><?php echo html::a($gogs->url, $gogs->url, '_target');?></td>
<td class='c-actions'>
<?php
common::printIcon('gogs', 'edit', "gogsID=$id", '', 'list', 'edit');
echo common::buildIconButton('gogs', 'bindUser', "gogsID=$id", '', 'list', 'link', '', '', false, '', '', 0, $gogs->isBindUser);
common::printIcon('gogs', 'delete', "gogsID=$id", '', 'list', 'trash', 'hiddenwin');
?>
</td>
</tr>
<?php endforeach;?>
</tbody>
</table>
<?php if($gogsList):?>
<div class='table-footer'><?php $pager->show('right', 'pagerjs');?></div>
<?php endif;?>
</form>
</div>
<?php endif;?>
<?php include '../../common/view/footer.html.php';?>
+45
View File
@@ -0,0 +1,45 @@
<?php
/**
* The create view file of gogs module of ZenTaoPMS.
*
* @copyright Copyright 2009-2017 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL(http://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
* @author Gang Liu <liugang@cnezsoft.com>
* @package gogs
* @version $Id$
* @link http://www.zentao.net
*/
?>
<?php include '../../common/view/header.html.php';?>
<div id='mainContent' class='main-row'>
<div class='main-col main-content'>
<div class='center-block'>
<div class='main-header'>
<h2><?php echo $lang->gogs->lblCreate;?></h2>
</div>
<form id='gogsForm' method='post' class='form-ajax'>
<table class='table table-form'>
<tr>
<th><?php echo $lang->gogs->name;?></th>
<td class='required'><?php echo html::input('name', '', "class='form-control'");?></td>
<td class="tips-git"></td>
</tr>
<tr>
<th><?php echo $lang->gogs->url;?></th>
<td class='required'><?php echo html::input('url', '', "class='form-control'");?></td>
</tr>
<tr>
<th><?php echo $lang->gogs->token;?></th>
<td><?php echo html::input('token', '', "class='form-control'");?></td>
</tr>
<tr>
<td colspan='2' class='text-center form-actions'>
<?php echo html::submitButton();?>
</td>
</tr>
</table>
</form>
</div>
</div>
</div>
<?php include '../../common/view/footer.html.php';?>
+45
View File
@@ -0,0 +1,45 @@
<?php
/**
* The edit view file of gogs module of ZenTaoPMS.
*
* @copyright Copyright 2009-2017 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL(http://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
* @author Gang Liu <liugang@cnezsoft.com>
* @package gogs
* @version $Id$
* @link http://www.zentao.net
*/
?>
<?php include '../../common/view/header.html.php';?>
<div id='mainContent' class='main-row'>
<div class='main-col main-content'>
<div class='center-block'>
<div class='main-header'>
<h2><?php echo $lang->gogs->edit;?></h2>
</div>
<form id='gogsForm' method='post' class='form-ajax'>
<table class='table table-form'>
<tr>
<th><?php echo $lang->gogs->name;?></th>
<td class='required'><?php echo html::input('name', isset($gogs->name) ? $gogs->name : '', "class='form-control'");?></td>
<td class="tips-git"></td>
</tr>
<tr>
<th><?php echo $lang->gogs->url;?></th>
<td class='required'><?php echo html::input('url', isset($gogs->url) ? $gogs->url : '', "class='form-control'");?></td>
</tr>
<tr>
<th><?php echo $lang->gogs->token;?></th>
<td><?php echo html::input('token', isset($gogs->token) ? $gogs->token : '', "class='form-control'");?></td>
</tr>
<tr>
<td colspan='2' class='text-center form-actions'>
<?php echo html::submitButton();?>
</td>
</tr>
</table>
</form>
</div>
</div>
</div>
<?php include '../../common/view/footer.html.php';?>
+37
View File
@@ -0,0 +1,37 @@
<?php
/**
* The view file of GitLab module of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL(http://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
* @author dave.li <lichengjun@cnezsoft.com>
* @package GitLab
* @version $Id: view.html.php 4728 2013-05-03 06:14:34Z david18810279601@gmail.com $
* @link http://www.zentao.net
* */
?>
<?php include '../../common/view/header.html.php';?>
<style>.action-cell {margin-bottom: 10px;}</style>
<div id="mainMenu" class="clearfix">
<div class="btn-toolbar pull-left">
<div class="page-title">
<span class="label label-id"><?php echo $gogs->id?></span>
<span class="text" title="<?php echo $gogs->name;?>" style='color: #3c4354'><?php echo $gogs->name;?></span>
<?php if($gogs->deleted):?>
<span class='label label-danger'><?php echo $lang->gogs->deleted;?></span>
<?php endif; ?>
</div>
</div>
</div>
<div id="mainContent" class="main-row">
<div class="main-col col-8">
<div class="cell">
<div class="detail">
<div class="detail-title"><?php echo $lang->gogs->url;?></div>
<div class="detail-content article-content"><?php echo html::a($gogs->url, $gogs->url, '_target');?></div>
</div>
</div>
<div class='cell action-cell'><?php include '../../common/view/action.html.php';?></div>
</div>
</div>
<?php include '../../common/view/footer.html.php';?>
+22 -3
View File
@@ -69,7 +69,8 @@ $lang->moduleOrder[215] = 'message';
$lang->moduleOrder[220] = 'gitlab';
$lang->moduleOrder[225] = 'mr';
$lang->moduleOrder[230] = 'app';
$lang->moduleOrder[235] = 'gitea';
$lang->moduleOrder[235] = 'gogs';
$lang->moduleOrder[240] = 'gitea';
$lang->resource = new stdclass();
@@ -1180,11 +1181,13 @@ $lang->ci->methodOrder[5] = 'commitResult';
$lang->ci->methodOrder[10] = 'checkCompileStatus';
$lang->resource->compile = new stdclass();
$lang->resource->compile->browse = 'browse';
$lang->resource->compile->logs = 'logs';
$lang->resource->compile->browse = 'browse';
$lang->resource->compile->logs = 'logs';
$lang->resource->compile->syncCompile = 'syncCompile';
$lang->compile->methodOrder[5] = 'browse';
$lang->compile->methodOrder[10] = 'logs';
$lang->compile->methodOrder[15] = 'syncCompile';
$lang->resource->jenkins = new stdclass();
$lang->resource->jenkins->browse = 'browseAction';
@@ -1391,6 +1394,22 @@ $lang->gitlab->methodOrder[145] = 'browseTag';
$lang->gitlab->methodOrder[150] = 'createTag';
$lang->gitlab->methodOrder[155] = 'deleteTag';
/* Gogs. */
$lang->resource->gogs = new stdclass();
$lang->resource->gogs->browse = 'browse';
$lang->resource->gogs->create = 'create';
$lang->resource->gogs->edit = 'edit';
$lang->resource->gogs->view = 'view';
$lang->resource->gogs->delete = 'delete';
$lang->resource->gogs->bindUser = 'bindUser';
$lang->gogs->methodOrder[5] = 'browse';
$lang->gogs->methodOrder[10] = 'create';
$lang->gogs->methodOrder[15] = 'edit';
$lang->gogs->methodOrder[20] = 'view';
$lang->gogs->methodOrder[25] = 'delete';
$lang->gogs->methodOrder[30] = 'bindUser';
/* Gitea. */
$lang->resource->gitea = new stdclass();
$lang->resource->gitea->browse = 'browse';
+2 -2
View File
@@ -1,5 +1,5 @@
<?php
$config->jenkins->create = new stdclass();
$config->jenkins->edit = new stdclass();
$config->jenkins->create->requiredFields = 'name,url';
$config->jenkins->edit->requiredFields = 'name,url';
$config->jenkins->create->requiredFields = 'name,url,account';
$config->jenkins->edit->requiredFields = 'name,url,account';
+13 -1
View File
@@ -49,12 +49,24 @@ class job extends control
$pager = new pager($recTotal, $recPerPage, $pageID);
$this->app->loadLang('compile');
$this->view->jobList = $this->job->getList($repoID, $orderBy, $pager);
$jobList = $this->job->getList($repoID, $orderBy, $pager);
$this->loadModel('gitlab');
foreach($jobList as $job)
{
$job->canExec = true;
if($job->engine == 'gitlab')
{
$pipeline = json_decode($job->pipeline);
$branch = $this->gitlab->apiGetSingleBranch($job->server, $pipeline->project, $pipeline->reference);
if($branch and isset($branch->can_push) and !$branch->can_push) $job->canExec = false;
}
}
$this->view->title = $this->lang->ci->job . $this->lang->colon . $this->lang->job->browse;
$this->view->position[] = $this->lang->ci->job;
$this->view->position[] = $this->lang->job->browse;
$this->view->repoID = $repoID;
$this->view->jobList = $jobList;
$this->view->orderBy = $orderBy;
$this->view->pager = $pager;
+1 -1
View File
@@ -5,6 +5,6 @@
#server_chosen .chosen-single {border-right: 0px;}
#pipelineBox {width: 385px;}
#svnDirBox .input-group {width: unset !important;}
#paramDiv .input-group {padding: 3px;}
#jenkinsServerTR .input-group-addon {border-left-width: 0 !important;}
.chosen-container .chosen-drop{z-index: 1100;} /* from c20b7e7a5 */
+1 -1
View File
@@ -5,4 +5,4 @@
#server_chosen .chosen-single {border-right: 0px;}
#pipelineBox {width: 385px;}
#svnDirBox .input-group {width: unset !important;}
#paramDiv .input-group {padding: 3px;}
#jenkinsServerTR .input-group-addon {border-left-width: 0 !important;}
+18
View File
@@ -181,6 +181,15 @@ class jobModel extends model
{
$repo = $this->loadModel('repo')->getRepoByID($job->repo);
$project = zget($repo, 'project');
if(!empty($repo))
{
$pipeline = $this->loadModel('gitlab')->apiGetPipeline($repo->serviceHost, $repo->serviceProject, $this->post->reference);
if(!is_array($pipeline) or empty($pipeline))
{
dao::$errors['repo'] = $this->lang->job->engineTips->error;
return false;
}
}
$job->server = (int)zget($repo, 'serviceHost', 0);
$job->pipeline = json_encode(array('project' => $project, 'reference' => $this->post->reference));
@@ -298,6 +307,15 @@ class jobModel extends model
{
$repo = $this->loadModel('repo')->getRepoByID($job->gitlabRepo);
$project = zget($repo, 'project');
if(!empty($repo))
{
$pipeline = $this->loadModel('gitlab')->apiGetPipeline($repo->serviceHost, $repo->serviceProject, $this->post->reference);
if(!is_array($pipeline) or empty($pipeline))
{
dao::$errors['repo'] = $this->lang->job->engineTips->error;
return false;
}
}
$job->repo = $job->gitlabRepo;
$job->server = (int)zget($repo, 'serviceHost', 0);
+1 -1
View File
@@ -74,7 +74,7 @@
<?php
common::printIcon('compile', 'browse', "repoID={$job->repo}&jobID=$id", '', 'list', 'history');
common::printIcon('job', 'edit', "jobID=$id", '', 'list', 'edit');
common::printIcon('job', 'exec', "jobID=$id", '', 'list', 'play');
common::printIcon('job', 'exec', "jobID=$id", '', 'list', 'play', '', $job->canExec ? '' : 'disabled');
if(common::hasPriv('job', 'delete')) echo html::a($this->createLink('job', 'delete', "jobID=$id"), '<i class="icon-trash"></i>', 'hiddenwin', "title='{$lang->job->delete}' class='btn'");
?>
</td>
+3 -3
View File
@@ -62,7 +62,7 @@
</tr>
<tr>
<th><?php echo $lang->job->triggerType; ?></th>
<td><?php echo html::select('triggerType', $lang->job->triggerTypeList, '', "class='form-control'");?></td>
<td><?php echo html::select('triggerType', $lang->job->triggerTypeList, '', "class='form-control chosen'");?></td>
<td colspan="2"></td>
</tr>
<tr id='svnDirBox' class='svn-fields'>
@@ -122,9 +122,9 @@
<th><?php echo $lang->job->customParam;?></th>
<td colspan='2' id='paramDiv'>
<div class='table-row input-group'>
<span class='input-group-addon w-50px'><?php echo $lang->job->paramName; ?></span>
<span class='input-group-addon <?php echo common::checkNotCN() ? 'w-60px' : 'w-50px'?>'><?php echo $lang->job->paramName; ?></span>
<?php echo html::input('paramName[]', '', "class='form-control'"); ?>
<span class='input-group-addon w-40px'><?php echo $lang->job->paramValue; ?></span>
<span class='input-group-addon <?php echo common::checkNotCN() ? 'w-60px' : 'w-40px'?>'><?php echo $lang->job->paramValue; ?></span>
<?php echo html::select('paramValue[]', $lang->job->paramValueList, '', "class='form-control' onchange='setParamName(this)'"); ?>
<?php echo html::input('paramValue[]', '', "class='form-control hidden' id='paramValue' disabled"); ?>
<span class='input-group-addon w-90px'>
+3 -3
View File
@@ -63,7 +63,7 @@
<tr>
<th><?php echo $lang->job->triggerType;?></th>
<?php if($repoType == 'Subversion') $lang->job->triggerTypeList['tag'] = $lang->job->dirChange;?>
<td><?php echo html::select('triggerType', $lang->job->triggerTypeList, $job->triggerType, "class='form-control'");?></td>
<td><?php echo html::select('triggerType', $lang->job->triggerTypeList, $job->triggerType, "class='form-control chosen'");?></td>
<td colspan="2"></td>
</tr>
<tr id='svnDirBox' class='svn-fields'>
@@ -170,9 +170,9 @@
<?php endforeach;?>
<?php endif;?>
<div class='table-row input-group'>
<span class='input-group-addon w-50px'><?php echo $lang->job->paramName;?></span>
<span class='input-group-addon <?php echo common::checkNotCN() ? 'w-60px' : 'w-50px'?>'><?php echo $lang->job->paramName; ?></span>
<?php echo html::input('paramName[]', '', "class='form-control' id='paramName'");?>
<span class='input-group-addon w-40px'><?php echo $lang->job->paramValue;?></span>
<span class='input-group-addon <?php echo common::checkNotCN() ? 'w-60px' : 'w-40px'?>'><?php echo $lang->job->paramValue; ?></span>
<?php echo html::select('paramValue[]', $lang->job->paramValueList, '', "class='form-control' onchange='setParamName(this)'");?>
<?php echo html::input('paramValue[]', '', "class='form-control hidden' id='paramValue' disabled");?>
<span class='input-group-addon w-90px'>
+1 -1
View File
@@ -33,4 +33,4 @@ $config->mrapproval->create = new stdclass();
$config->mrapproval->create->skippedFields = '';
$config->mrapproval->create->requiredFields = 'mrID,account,date,action';
$config->mr->gitServiceList = array('gitlab', 'gitea');
$config->mr->gitServiceList = array('gitlab', 'gitea', 'gogs');
+22 -13
View File
@@ -34,7 +34,7 @@ class mr extends control
$this->app->loadClass('pager', $static = true);
$pager = new pager($recTotal, $recPerPage, $pageID);
$repos = $this->loadModel('repo')->getListBySCM(array('Gitlab', 'Gitea'));
$repos = $this->loadModel('repo')->getListBySCM(array('Gitlab', 'Gitea', 'Gogs'));
if(empty($repos)) $this->locate($this->repo->createLink('create'));
$repoID = $this->repo->saveState($repoID, $objectID);
@@ -69,10 +69,14 @@ class mr extends control
{
$openIDList = $this->loadModel('gitlab')->getGitLabListByAccount($this->app->user->account);
}
else
elseif($repo->SCM == 'Gitea')
{
$openIDList = $this->loadModel('gitea')->getGiteaListByAccount($this->app->user->account);
}
elseif($repo->SCM == 'Gogs')
{
$openIDList = $this->loadModel('gogs')->getGogsListByAccount($this->app->user->account);
}
}
$this->view->title = $this->lang->mr->common . $this->lang->colon . $this->lang->mr->browse;
@@ -108,22 +112,26 @@ class mr extends control
$repoID = $this->loadModel('repo')->saveState(0);
$repo = $this->repo->getRepoByID($repoID);
$this->loadModel('gitlab');
$this->loadModel('gitea');
$this->loadModel('gogs');
if($repo->SCM == 'Gitea')
{
$project = $this->gitea->apiGetSingleProject($repo->gitService, $repo->project);
if(empty($project) or !$project->allow_merge_commits) $repo = array();
}
$hosts = $this->loadModel('pipeline')->getList(array('gitea', 'gitlab'));
$hosts = $this->loadModel('pipeline')->getList(array('gitea', 'gitlab', 'gogs'));
if(!$this->app->user->admin)
{
$gitlabUsers = $this->loadModel('gitlab')->getGitLabListByAccount();
$gitlabUsers = $this->gitlab->getGitLabListByAccount();
$giteaUsers = $this->gitea->getGiteaListByAccount();
$gogsUsers = $this->gogs->getGogsListByAccount();
foreach($hosts as $hostID => $host)
{
if($host->type == 'gitlab' and isset($gitlabUsers[$hostID])) continue;
if($host->type == 'gitea' and isset($giteaUsers[$hostID])) continue;
if($host->type == 'gitea' and isset($giteaUsers[$hostID])) continue;
if($host->type == 'gogs' and isset($gogsUsers[$hostID])) continue;
unset($hosts[$hostID]);
}
@@ -243,6 +251,7 @@ class mr extends control
if(isset($res->message)) return print(js::alert($this->mr->convertApiError($res->message)));
}
$this->dao->delete()->from(TABLE_MR)->where('id')->eq($MRID)->exec();
$this->loadModel('action')->create('mr', $MRID, 'deleted', '', $MR->title);
echo js::locate(inlink('browse'), 'parent');
}
@@ -359,7 +368,7 @@ class mr extends control
}
}
if(isset($MR->hostID)) $rawMR = $this->mr->apiAcceptMR($MR->hostID, $MR->targetProject, $MR->mriid, $MR);
if(isset($MR->hostID)) $rawMR = $this->mr->apiAcceptMR($MR);
if(isset($rawMR->state) and $rawMR->state == 'merged')
{
$this->mr->logMergedAction($MR);
@@ -621,7 +630,7 @@ class mr extends control
$this->loadModel('search')->setSearchParams($this->config->product->search);
$MR = $this->mr->getByID($MRID);
$relatedStories = $this->mr->getCommitedLink($MR->hostID, $MR->targetProject, $MR->mriid, 'story');
$relatedStories = $this->mr->getCommitedLink($MR, 'story');
$linkedStories = $this->mr->getLinkList($MRID, $product->id, 'story');
if($browseType == 'bySearch')
@@ -706,7 +715,7 @@ class mr extends control
$this->loadModel('search')->setSearchParams($this->config->bug->search);
$MR = $this->mr->getByID($MRID);
$relatedBugs = $this->mr->getCommitedLink($MR->hostID, $MR->targetProject, $MR->mriid, 'bug');
$relatedBugs = $this->mr->getCommitedLink($MR, 'bug');
$linkedBugs = $this->mr->getLinkList($MRID, $product->id, 'bug');
if($browseType == 'bySearch')
@@ -778,7 +787,7 @@ class mr extends control
$this->loadModel('search')->setSearchParams($this->config->execution->search);
$MR = $this->mr->getByID($MRID);
$relatedTasks = $this->mr->getCommitedLink($MR->hostID, $MR->targetProject, $MR->mriid, 'task');
$relatedTasks = $this->mr->getCommitedLink($MR, 'task');
$linkedTasks = $this->mr->getLinkList($MRID, $product->id, 'task');
/* Get executions by product. */
@@ -1036,7 +1045,7 @@ class mr extends control
$targetBranch = $this->post->targetBranch;
$result = $this->mr->checkSameOpened($hostID, $sourceProject, $sourceBranch, $targetProject, $targetBranch);
echo json_encode($result);
return print(json_encode($result));
}
/**
@@ -1051,11 +1060,11 @@ class mr extends control
{
$host = $this->loadModel('pipeline')->getByID($hostID);
$scm = $host->type;
if($scm == 'gitea') $project = urldecode(base64_decode($project));
if(in_array($scm, array('gitea', 'gogs'))) $project = urldecode(base64_decode($project));
$branches = $this->loadModel($scm)->apiGetBranchPrivs($hostID, $project);
$branchPrivs = array();
$branches = $this->loadModel($scm)->apiGetBranchPrivs($hostID, $project);
foreach($branches as $branch) $branchPrivs[$branch->name] = $branch->name;
echo json_encode($branchPrivs);
return print(json_encode($branchPrivs));
}
}
+5 -1
View File
@@ -156,10 +156,14 @@ $(function()
{
var url = createLink('repo', 'ajaxGetGitlabProjects', "gitlabID=" + hostID + "&projectIdList=&filter=IS_DEVELOPER");
}
else
else if(hosts[hostID].type == 'gitea')
{
var url = createLink('repo', 'ajaxGetGiteaProjects', "giteaID=" + hostID);
}
else if(hosts[hostID].type == 'gogs')
{
var url = createLink('repo', 'ajaxGetGogsProjects', "gogsID=" + hostID);
}
$.get(url, function(response)
{
if(response == "<option value=''></option>" && confirm(mrLang.addForApp) == true) window.open(hosts[hostID].url);
+132 -59
View File
@@ -126,6 +126,19 @@ class mrModel extends model
return array($hostID => array_column($projects, null, 'full_name'));
}
/**
* Get gogs projects.
*
* @param int $hostID
* @access public
* @return array
*/
public function getGogsProjects($hostID = 0)
{
$projects = $this->loadModel('gogs')->apiGetProjects($hostID);
return array($hostID => array_column($projects, null, 'full_name'));
}
/**
* Get gitlab projects.
*
@@ -424,9 +437,9 @@ class mrModel extends model
{
$gitUsers = $this->loadModel('gitlab')->getUserIdAccountPairs($MR->hostID);
}
elseif($rawMR->gitService == 'gitea')
else
{
$gitUsers = $this->loadModel('gitea')->getUserAccountIdPairs($MR->hostID, 'openID,account');
$gitUsers = $this->loadModel($rawMR->gitService)->getUserAccountIdPairs($MR->hostID, 'openID,account');
}
$newMR = new stdclass;
@@ -472,6 +485,7 @@ class mrModel extends model
$this->loadModel('gitlab');
$this->loadModel('gitea');
$this->loadModel('gogs');
foreach($MRList as $key => $MR)
{
if($MR->status != 'opened') continue;
@@ -499,7 +513,8 @@ class mrModel extends model
}
else
{
$users = $this->gitea->getUserAccountIdPairs($MR->hostID, 'openID,account');
$scm = strtolower($scm);
$users = $this->$scm->getUserAccountIdPairs($MR->hostID, 'openID,account');
}
$newMR = new stdclass;
@@ -657,21 +672,21 @@ class mrModel extends model
}
return json_decode(commonModel::http($url, $MRObject));
}
else
elseif(in_array($host->type, array('gitea', 'gogs')))
{
$url = sprintf($this->loadModel('gitea')->getApiRoot($hostID), "/repos/$projectID/pulls");
$url = sprintf($this->loadModel($host->type)->getApiRoot($hostID), "/repos/$projectID/pulls");
$MRObject->head = $MR->sourceBranch;
$MRObject->base = $MR->targetBranch;
$MRObject->body = $MR->description;
if($MR->assignee)
{
$assignee = $this->gitea->getUserIDByZentaoAccount($this->post->hostID, $MR->assignee);
$assignee = $this->{$host->type}->getUserIDByZentaoAccount($this->post->hostID, $MR->assignee);
if($assignee) $MRObject->assignee = $assignee;
}
$mergeResult = json_decode(commonModel::http($url, $MRObject));
if(isset($mergeResult->number)) $mergeResult->iid = $mergeResult->number;
if(isset($mergeResult->number)) $mergeResult->iid = $host->type == 'gitea' ? $mergeResult->number : $mergeResult->id;
if(isset($mergeResult->mergeable))
{
if($mergeResult->mergeable) $mergeResult->merge_status = 'can_be_merged';
@@ -722,6 +737,22 @@ class mrModel extends model
$MR->target_project_id = $projectID;
}
}
elseif($scm == 'Gogs')
{
foreach($response as $MR)
{
$MR->iid = $MR->id;
$MR->state = $MR->state == 'open' ? 'opened' : $MR->state;
if($MR->merged) $MR->state = 'merged';
$MR->merge_status = $MR->mergeable ? 'can_be_merged' : 'cannot_be_merged';
$MR->description = $MR->body;
$MR->target_branch = $MR->base_branch;
$MR->source_branch = $MR->head_branch;
$MR->source_project_id = $projectID;
$MR->target_project_id = $projectID;
}
}
return $response;
}
@@ -773,7 +804,7 @@ class mrModel extends model
$url = sprintf($this->gitlab->getApiRoot($hostID), "/projects/$projectID/merge_requests/$MRID");
$MR = json_decode(commonModel::http($url));
}
else
else if($host->type == 'gitea')
{
$url = sprintf($this->loadModel('gitea')->getApiRoot($hostID), "/repos/$projectID/pulls/$MRID");
$MR = json_decode(commonModel::http($url));
@@ -796,6 +827,29 @@ class mrModel extends model
$MR->has_conflicts = empty($diff) ? true : false;
}
}
else if($host->type == 'gogs')
{
$url = sprintf($this->loadModel('gogs')->getApiRoot($hostID), "/repos/$projectID/pulls/$MRID");
$MR = json_decode(commonModel::http($url));
if(isset($MR->html_url))
{
$diff = $this->apiGetDiffs($hostID, $projectID, $MRID);
$MR->web_url = $MR->html_url;
$MR->iid = $MR->id;
$MR->state = $MR->state == 'open' ? 'opened' : $MR->state;
if($MR->merged) $MR->state = 'merged';
$MR->merge_status = $MR->mergeable ? 'can_be_merged' : 'cannot_be_merged';
$MR->changes_count = empty($diff) ? 0 : 1;
$MR->description = $MR->body;
$MR->target_branch = $MR->base_branch;
$MR->source_branch = $MR->head_branch;
$MR->source_project_id = $projectID;
$MR->target_project_id = $projectID;
$MR->has_conflicts = empty($diff) ? true : false;
}
}
$MR->gitService = $host->type;
return $MR;
@@ -849,18 +903,18 @@ class mrModel extends model
}
else
{
$url = sprintf($this->loadModel('gitea')->getApiRoot($hostID), "/repos/$projectID/pulls/$MRID");
$url = sprintf($this->loadModel($host->type)->getApiRoot($hostID), "/repos/$projectID/pulls/$MRID");
$newMR->base = $MR->targetBranch;
$newMR->body = $MR->description;
if($MR->assignee)
{
$assignee = $this->gitea->getUserIDByZentaoAccount($this->post->hostID, $MR->assignee);
$assignee = $this->{$host->type}->getUserIDByZentaoAccount($this->post->hostID, $MR->assignee);
if($assignee) $newMR->assignee = $assignee;
}
$mergeResult = json_decode(commonModel::http($url, $newMR, array(), array(), 'json', 'PATCH'));
if(isset($mergeResult->number)) $mergeResult->iid = $mergeResult->number;
if(isset($mergeResult->number)) $mergeResult->iid = $host->type == 'gitea' ? $mergeResult->number : $mergeResult->id;
if(isset($mergeResult->mergeable))
{
if($mergeResult->mergeable) $mergeResult->merge_status = 'can_be_merged';
@@ -923,7 +977,7 @@ class mrModel extends model
}
else
{
$url = sprintf($this->loadModel('gitea')->getApiRoot($hostID), "/repos/$projectID/pulls/$MRID");
$url = sprintf($this->loadModel($host->type)->getApiRoot($hostID), "/repos/$projectID/pulls/$MRID");
return json_decode(commonModel::http($url, array('state' => 'closed'), array(), array(), 'json', 'PATCH'));
}
}
@@ -946,7 +1000,7 @@ class mrModel extends model
$url = sprintf($this->gitlab->getApiRoot($hostID), "/projects/$projectID/merge_requests/$MRID") . '&state_event=reopen';
return json_decode(commonModel::http($url, null, array(CURLOPT_CUSTOMREQUEST => 'PUT')));
}
else
elseif($host->type == 'gitea')
{
$url = sprintf($this->loadModel('gitea')->getApiRoot($hostID), "/repos/$projectID/pulls/$MRID");
$MR = json_decode(commonModel::http($url, array('state' => 'open'), array(), array(), 'json', 'PATCH'));
@@ -961,6 +1015,23 @@ class mrModel extends model
$MR->source_project_id = $projectID;
$MR->target_project_id = $projectID;
return $MR;
}
elseif($host->type == 'gogs')
{
$url = sprintf($this->loadModel('gitea')->getApiRoot($hostID), "/repos/$projectID/pulls/$MRID");
$MR = json_decode(commonModel::http($url, array('state' => 'open'), array(), array(), 'json', 'PATCH'));
$MR->iid = $MR->id;
$MR->state = $MR->state == 'open' ? 'opened' : $MR->state;
if($MR->merged) $MR->state = 'merged';
$MR->merge_status = $MR->mergeable ? 'can_be_merged' : 'cannot_be_merged';
$MR->description = $MR->body;
$MR->target_branch = $MR->base_branch;
$MR->source_branch = $MR->head_branch;
$MR->source_project_id = $projectID;
$MR->target_project_id = $projectID;
return $MR;
}
}
@@ -968,37 +1039,37 @@ class mrModel extends model
/**
* Accept MR by API.
*
* @link https://docs.gitlab.com/ee/api/merge_requests.html#accept-mr
* @param int $hostID
* @param int $projectID
* @param int $MRID
* @param object $MR
* @access public
* @return object
*/
public function apiAcceptMR($hostID, $projectID, $MRID, $MR = null)
public function apiAcceptMR($MR)
{
$host = $this->loadModel('pipeline')->getByID($hostID);
$host = $this->loadModel('pipeline')->getByID($MR->hostID);
if($host->type == 'gitlab')
{
$apiRoot = $this->gitlab->getApiRoot($hostID);
$approveUrl = sprintf($apiRoot, "/projects/$projectID/merge_requests/$MRID/approved");
$apiRoot = $this->gitlab->getApiRoot($MR->hostID);
$approveUrl = sprintf($apiRoot, "/projects/$MR->targetProject/merge_requests/$MR->mriid/approved");
commonModel::http($approveUrl, null, array(CURLOPT_CUSTOMREQUEST => 'POST'));
$url = sprintf($apiRoot, "/projects/$projectID/merge_requests/$MRID/merge");
$url = sprintf($apiRoot, "/projects/$MR->targetProject/merge_requests/$MR->mriid/merge");
return json_decode(commonModel::http($url, null, array(CURLOPT_CUSTOMREQUEST => 'PUT')));
}
elseif($host->type == 'gitea')
else
{
$apiRoot = $this->loadModel('gitea')->getApiRoot($hostID);
$url = sprintf($apiRoot, "/repos/$projectID/pulls/$MRID/merge");
$apiRoot = $this->loadModel($host->type)->getApiRoot($MR->hostID);
$url = sprintf($apiRoot, "/repos/$MR->targetProject/pulls/$MR->mriid/merge");
$merge = ($MR and $MR->squash == '1') ? 'squash' : 'merge';
$data = array('Do' => $merge);
if($MR and $MR->removeSourceBranch == '1') $data['delete_branch_after_merge'] = true;
if($MR->removeSourceBranch == '1') $data['delete_branch_after_merge'] = true;
$rowMR = json_decode(commonModel::http($url, $data, array(), array(), 'json', 'POST'));
if(!isset($rowMR->massage)) $rowMR = $this->apiGetSingleMR($hostID, $projectID, $MRID);
if(!isset($rowMR->massage))
{
$rowMR = $this->apiGetSingleMR($MR->hostID, $MR->targetProject, $MR->mriid);
if($data['delete_branch_after_merge'] == true) $this->loadModel('gogs')->apiDeleteBranch($MR->hostID, $MR->targetProject, $MR->sourceBranch);
}
return $rowMR;
}
@@ -1155,29 +1226,6 @@ class mrModel extends model
return json_decode(commonModel::http($url));
}
/**
* Get diff commits of MR from GitLab API.
*
* @param int $hostID
* @param int $projectID
* @param int $MRID
* @access public
* @return object
*/
public function apiGetDiffCommits($hostID, $projectID, $MRID)
{
$host = $this->loadModel('pipeline')->getByID($hostID);
if($host->type == 'gitlab')
{
$url = sprintf($this->gitlab->getApiRoot($hostID), "/projects/$projectID/merge_requests/$MRID/commits");
}
else
{
$url = sprintf($this->loadModel('gitea')->getApiRoot($hostID), "/repos/$projectID/pulls/$MRID/commits");
}
return json_decode(commonModel::http($url));
}
/**
* Get diff of MR from Gitea API.
*
@@ -1666,6 +1714,33 @@ class mrModel extends model
->fetchPairs();
}
/**
* Get diff commits of MR.
*
* @param object $MR
* @access public
* @return array
*/
public function getDiffCommits($MR)
{
$host = $this->loadModel('pipeline')->getByID($MR->hostID);
if($host->type == 'gogs')
{
$repo = $this->loadModel('repo')->getRepoByID($MR->repoID);
$scm = $this->app->loadClass('scm');
$scm->setEngine($repo);
return $scm->getMRCommits($MR->sourceBranch, $MR->targetBranch);
}
else
{
$projectID = $MR->targetProject;
$MRID = $MR->mriid;
if($host->type == 'gitlab') $url = sprintf($this->loadModel('gitlab')->getApiRoot($MR->hostID), "/projects/$projectID/merge_requests/$MRID/commits");
if($host->type == 'gitea') $url = sprintf($this->loadModel('gitea')->getApiRoot($MR->hostID), "/repos/$projectID/pulls/$MRID/commits");
return json_decode(commonModel::http($url));
}
}
/**
* Create an mr link.
*
@@ -1797,21 +1872,19 @@ class mrModel extends model
/**
* Get links by mr commites.
*
* @param int $hostID
* @param int $projectID
* @param int $MRID
* @param string $type
* @param object $MR
* @param string $type
* @access public
* @return array
*/
public function getCommitedLink($hostID, $projectID, $MRID, $type)
public function getCommitedLink($MR, $type)
{
$DiffCommits = $this->apiGetDiffCommits($hostID, $projectID, $MRID);
$diffCommits = $this->getDiffCommits($MR);
$commits = array();
foreach($DiffCommits as $DiffCommit)
foreach($diffCommits as $diffCommit)
{
if(isset($DiffCommit->id)) $commits[] = substr($DiffCommit->id, 0, 10);
if(isset($diffCommit->id)) $commits[] = substr($diffCommit->id, 0, 10);
}
return $this->dao->select('objectID')->from(TABLE_ACTION)->where('objectType')->eq($type)->andWhere('extra')->in($commits)->fetchPairs('objectID');
@@ -1863,7 +1936,7 @@ class mrModel extends model
*/
public function logMergedAction($MR)
{
$this->loadModel('action')->create('mr', $MR->id, 'merged');
$this->loadModel('action')->create('mr', $MR->id, 'mergedmr');
$product = $this->getMRProduct($MR);
$stories = $this->getLinkList($MR->id, $product->id, 'story');
+7 -3
View File
@@ -91,17 +91,21 @@
<td class='text' title='<?php echo $MR->createdDate;?>'><?php echo $MR->createdDate;?></td>
<td class='c-actions'>
<?php
$canDelete = ($app->user->admin or (isset($projects[$MR->hostID][$MR->sourceProject]->owner->id) and $projects[$MR->hostID][$MR->sourceProject]->owner->id == $openIDList[$MR->hostID])) ? '' : 'disabled';
$canDelete = ($app->user->admin or (isset($openIDList[$MR->hostID]) and isset($projects[$MR->hostID][$MR->sourceProject]->owner->id) and $projects[$MR->hostID][$MR->sourceProject]->owner->id == $openIDList[$MR->hostID])) ? '' : 'disabled';
if($repo->SCM == 'Gitlab')
{
$canEdit = (isset($projects[$MR->hostID][$MR->sourceProject]->isDeveloper) and $projects[$MR->hostID][$MR->sourceProject]->isDeveloper == true) ? '' : 'disabled';
}
else
elseif($repo->SCM == 'Gitea')
{
$canEdit = (isset($projects[$MR->hostID][$MR->sourceProject]->allow_merge_commits) and $projects[$MR->hostID][$MR->sourceProject]->allow_merge_commits == true) ? '' : 'disabled';
}
elseif($repo->SCM == 'Gogs')
{
$canEdit = (isset($projects[$MR->hostID][$MR->sourceProject]->permissions->push) and $projects[$MR->hostID][$MR->sourceProject]->permissions->push) ? '' : 'disabled';
}
common::printLink('mr', 'view', "MRID={$MR->id}", '<i class="icon icon-eye"></i>', '', "title='{$lang->mr->view}' class='btn btn-info'");
common::printIcon('mr', 'edit', "MRID={$MR->id}", $MR, 'list', '', '', '', false, "{$canEdit}");
common::printIcon('mr', 'edit', "MRID={$MR->id}", $MR, 'list', '', '', $canEdit);
common::printLink('mr', 'diff', "MRID={$MR->id}", '<i class="icon icon-diff"></i>', '', "title='{$lang->mr->viewDiff}' class='btn btn-info'");
common::printLink('mr', 'link', "MRID={$MR->id}", '<i class="icon icon-link"></i>', '', "title='{$lang->mr->link}' class='btn btn-info'" . ($MR->linkButton == false ? 'disabled' : ''));
common::printLink('mr', 'delete', "MRID={$MR->id}", '<i class="icon icon-trash"></i>', 'hiddenwin', "title='{$lang->mr->delete}' class='btn btn-info {$canDelete}'");
+7 -3
View File
@@ -50,7 +50,7 @@
<th style="white-space: nowrap;"><?php echo $lang->mr->targetProject;?></th>
<td>
<div class='input-group'>
<?php if($MR->status == 'merged' or $MR->status == 'closed'):?>
<?php if($MR->status == 'merged' or $MR->status == 'closed' or $host->type == 'gogs'):?>
<span class='fix-border text-left'>
<?php echo $host->type == 'gitlab' ? $this->loadModel('gitlab')->apiGetSingleProject($MR->hostID, $MR->targetProject)->name_with_namespace : $MR->targetProject;?>:
<?php echo $MR->targetBranch;?>
@@ -79,9 +79,13 @@
<tr>
<th><?php echo $lang->mr->removeSourceBranch;?></th>
<td colspan='1'>
<?php
$attr = '';
if($MR->canDeleteBranch and $MR->removeSourceBranch == '1') $attr .= 'checked ';
if(!$MR->canDeleteBranch) $attr .= 'disabled';
?>
<div class="checkbox-primary" title="<?php echo $lang->mr->notDelbranch;?>">
<?php $checked = $MR->canDeleteBranch and $MR->removeSourceBranch== '1' ? 'checked' : '' ?>
<input type="checkbox" <?php echo $checked;?> <?php if(!$MR->canDeleteBranch) echo 'disabled';?> name="removeSourceBranch" value="1" id="removeSourceBranch">
<input type="checkbox" <?php echo $attr;?> name="removeSourceBranch" value="1" id="removeSourceBranch">
<label for="removeSourceBranch"></label>
</div>
</td>
+4 -4
View File
@@ -89,7 +89,7 @@
?>
<?php foreach($stories as $story):?>
<?php
$viewLink = $this->createLink('story', 'view', "storyID=$story->id");
$viewLink = $this->createLink('story', 'view', "storyID=$story->id", '', true);
$totalEstimate += $story->estimate;
?>
<tr data-id='<?php echo $story->id;?>'>
@@ -102,7 +102,7 @@
<td class='text-left nobr' title='<?php echo $story->title?>'>
<?php
if($story->parent > 0) echo "<span class='label label-badge label-light' title={$lang->story->children}>{$lang->story->childrenAB}</span>";
echo html::a($viewLink , $story->title);
echo html::a($viewLink , $story->title, '', 'class="iframe"');
?>
</td>
<td><?php echo zget($users, $story->openedBy);?></td>
@@ -168,7 +168,7 @@
<?php printf('%03d', $bug->id);?>
</td>
<td><span class='label-pri label-pri-<?php echo $bug->pri;?>' title='<?php echo zget($lang->bug->priList, $bug->pri, $bug->pri);?>'><?php echo zget($lang->bug->priList, $bug->pri, $bug->pri);?></span></td>
<td class='text-left nobr' title='<?php echo $bug->title?>'><?php echo html::a($this->createLink('bug', 'view', "bugID=$bug->id"), $bug->title);?></td>
<td class='text-left nobr' title='<?php echo $bug->title?>'><?php echo html::a($this->createLink('bug', 'view', "bugID=$bug->id", '', true), $bug->title, '', 'class="iframe"');?></td>
<td><?php echo zget($users, $bug->openedBy);?></td>
<td><?php echo zget($users, $bug->assignedTo);?></td>
<td>
@@ -230,7 +230,7 @@
<?php printf('%03d', $task->id);?>
</td>
<td><span class='label-pri label-pri-<?php echo $task->pri;?>' title='<?php echo zget($lang->task->priList, $task->pri, $task->pri);?>'><?php echo zget($lang->task->priList, $task->pri, $task->pri);?></span></td>
<td class='text-left nobr' title='<?php echo $task->name?>'><?php echo html::a($this->createLink('task', 'view', "taskID=$task->id"), $task->name);?></td>
<td class='text-left nobr' title='<?php echo $task->name?>'><?php echo html::a($this->createLink('task', 'view', "taskID=$task->id", '', true), $task->name, '', 'class="iframe"');?></td>
<td><?php echo zget($users, $task->finishedBy);?></td>
<td><?php echo zget($users, $task->assignedTo);?></td>
<td>
+1
View File
@@ -5,3 +5,4 @@ $lang->pipeline->url = 'Server URL';
$lang->pipeline->token = 'Token';
$lang->pipeline->account = 'Username';
$lang->pipeline->password = 'Password';
$lang->pipeline->delError = 'The server has some repos, please delete them and operate';
+1
View File
@@ -5,3 +5,4 @@ $lang->pipeline->url = 'Server URL';
$lang->pipeline->token = 'Token';
$lang->pipeline->account = 'Username';
$lang->pipeline->password = 'Password';
$lang->pipeline->delError = 'The server has some repos, please delete them and operate';
+1
View File
@@ -5,3 +5,4 @@ $lang->pipeline->url = 'Server URL';
$lang->pipeline->token = 'Token';
$lang->pipeline->account = 'Username';
$lang->pipeline->password = 'Password';
$lang->pipeline->delError = 'The server has some repos, please delete them and operate';
+1
View File
@@ -5,3 +5,4 @@ $lang->pipeline->url = 'Server URL';
$lang->pipeline->token = 'Token';
$lang->pipeline->account = 'Username';
$lang->pipeline->password = 'Password';
$lang->pipeline->delError = 'The server has some repos, please delete them and operate';
+1
View File
@@ -5,3 +5,4 @@ $lang->pipeline->url = '服务器地址';
$lang->pipeline->token = 'Token';
$lang->pipeline->account = '用户名';
$lang->pipeline->password = '密码';
$lang->pipeline->delError = '当前服务器下有代码库,请删除代码库后操作';
+25 -1
View File
@@ -87,6 +87,9 @@ class pipelineModel extends model
->batchCheck($this->config->pipeline->create->requiredFields, 'notempty')
->batchCheck("url", 'URL')
->check('name', 'unique', "`type` = '$type'")
->checkIF($type == 'jenkins', 'account', 'notempty')
->checkIF($type == 'jenkins' and !$pipeline->token, 'password', 'notempty')
->checkIF($type == 'jenkins' and !$pipeline->password, 'token', 'notempty')
->autoCheck()
->exec();
if(dao::isError()) return false;
@@ -118,6 +121,9 @@ class pipelineModel extends model
->batchCheck($this->config->pipeline->edit->requiredFields, 'notempty')
->batchCheck("url", 'URL')
->check('name', 'unique', "`type` = '$type' and id <> $id")
->checkIF($type == 'jenkins', 'account', 'notempty')
->checkIF($type == 'jenkins' and !$pipeline->token, 'password', 'notempty')
->checkIF($type == 'jenkins' and !$pipeline->password, 'token', 'notempty')
->autoCheck()
->where('id')->eq($id)
->exec();
@@ -131,10 +137,28 @@ class pipelineModel extends model
* @param string $id the id to be deleted
* @param string $object the action object
* @access public
* @return int
* @return int|bool
*/
public function delete($id, $object = 'gitlab')
{
if(in_array($object, array('gitlab', 'gitea', 'gogs')))
{
$repo = $this->dao->select('*')->from(TABLE_REPO)
->where('deleted')->eq('0')
->andWhere('SCM')->eq(ucfirst($object))
->andWhere('serviceHost')->eq($id)
->fetch();
if($repo) return false;
}
elseif($object == 'sonarqube')
{
$job = $this->dao->select('id,name,repo,deleted')->from(TABLE_JOB)
->where('frame')->eq('sonarqube')
->andWhere('server')->eq($id)
->andWhere('deleted')->eq('0')
->fetch();
if($job) return false;
}
$this->dao->update(TABLE_PIPELINE)->set('deleted')->eq(1)->where('id')->eq($id)->exec();
$this->loadModel('action')->create($object, $id, 'deleted', '', ACTIONMODEL::CAN_UNDELETED);
+2 -1
View File
@@ -52,7 +52,8 @@ $config->repo->gitlab->apiPath = "%s/api/v4/projects/%s/repository/";
$config->repo->gitea = new stdclass;
$config->repo->gitea->apiPath = "%s/api/v1/repos/%s/";
$config->repo->gitServiceList = array('gitlab', 'gitea');
$config->repo->gitServiceList = array('gitlab', 'gitea', 'gogs');
$config->repo->gitTypeList = array('Gitlab', 'Gitea', 'Gogs', 'Git');
$config->repo->rules['module']['task'] = 'Task';
$config->repo->rules['module']['bug'] = 'Bug';
+87 -75
View File
@@ -46,8 +46,7 @@ class repo extends control
public function commonAction($repoID = 0, $objectID = 0)
{
$tab = $this->app->tab;
$this->repos = $this->repo->getRepoPairs($tab, $objectID);
$this->repoGroup = $this->repo->getRepoGroup($tab, $objectID);
$this->repos = $this->repo->getRepoPairs($tab, $objectID);
if($tab == 'project')
{
@@ -129,6 +128,7 @@ class repo extends control
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
$actionID = $this->loadModel('action')->create('repo', $repoID, 'created');
if($this->viewType == 'json') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'id' => $repoID));
$link = $this->repo->createLink('showSyncCommit', "repoID=$repoID&objectID=$objectID", '', false) . '#app=' . $this->app->tab;
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $link));
@@ -172,6 +172,10 @@ class repo extends control
$noNeedSync = $this->repo->update($repoID);
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
$newRepo = $this->repo->getRepoByID($repoID);
$actionID = $this->loadModel('action')->create('repo', $repoID, 'edited');
$changes = common::createChanges($repo, $newRepo);
$this->action->logHistory($actionID, $changes);
if(!$noNeedSync)
{
$link = $this->repo->createLink('showSyncCommit', "repoID=$repoID");
@@ -192,6 +196,7 @@ class repo extends control
{
if($scm == 'gitlab') $options[$project->id] = $project->name_with_namespace;
if($scm == 'gitea') $options[$project->full_name] = $project->full_name;
if($scm == 'gogs') $options[$project->full_name] = $project->full_name;
}
$this->view->projects = $options;
@@ -239,7 +244,7 @@ class repo extends control
$this->repo->delete(TABLE_REPO, $repoID);
if(dao::isError()) return print(js::error(dao::getError()));
echo js::reload('parent');
return print(js::reload('parent'));
}
/**
@@ -299,7 +304,7 @@ class repo extends control
}
$this->app->loadClass('pager', $static = true);
$pager = new pager(0, 8, 1);
$pager = new pager(0, 10, 1);
$logType = 'file';
$revisions = $this->repo->getCommits($repo, '/' . $entry, 'HEAD', $logType, $pager);
@@ -308,13 +313,13 @@ class repo extends control
foreach($revisions as $log)
{
if($revision == 'HEAD' and $i == 0) $revision = $log->revision;
if($revision == $log->revision) $revisionName = strpos($repo->SCM, 'Git') !== false ? $this->repo->getGitRevisionName($log->revision, $log->commit) : $log->revision;
if($revision == $log->revision) $revisionName = in_array($repo->SCM, $this->config->repo->gitTypeList) ? $this->repo->getGitRevisionName($log->revision, $log->commit) : $log->revision;
$i++;
}
if(!isset($revisionName))
{
if(strpos($repo->SCM, 'Git') !== false) $gitCommit = $this->dao->select('*')->from(TABLE_REPOHISTORY)->where('revision')->eq($revision)->andWhere('repo')->eq($repo->id)->fetch('commit');
$revisionName = (strpos($repo->SCM, 'Git') !== false and isset($gitCommit)) ? $this->repo->getGitRevisionName($revision, $gitCommit) : $revision;
if(in_array($repo->SCM, $this->config->repo->gitTypeList)) $gitCommit = $this->dao->select('*')->from(TABLE_REPOHISTORY)->where('revision')->eq($revision)->andWhere('repo')->eq($repo->id)->fetch('commit');
$revisionName = (in_array($repo->SCM, $this->config->repo->gitTypeList) and isset($gitCommit)) ? $this->repo->getGitRevisionName($revision, $gitCommit) : $revision;
}
$this->view->revisions = $revisions;
@@ -337,6 +342,7 @@ class repo extends control
$this->view->pager = $pager;
$this->view->logType = $logType;
$this->view->info = $info;
$this->view->pathInfo = $pathInfo;
$this->view->title = $this->lang->repo->common . $this->lang->colon . $this->lang->repo->view;
$this->view->position[] = $this->lang->repo->common;
@@ -386,7 +392,7 @@ class repo extends control
/* Set branch or tag for git. */
$branches = $tags = $branchesAndTags = array();
if(strpos($repo->SCM, 'Git') !== false)
if(in_array($repo->SCM, $this->config->repo->gitTypeList))
{
$scm = $this->app->loadClass('scm');
$scm->setEngine($repo);
@@ -415,7 +421,7 @@ class repo extends control
/* Load pager. */
$this->app->loadClass('pager', $static = true);
$pager = new pager(0, 8, 1);
$pager = new pager(0, 10, 1);
if($_POST)
{
@@ -436,7 +442,7 @@ class repo extends control
/* Update code commit history. */
$commentGroup = $this->loadModel('job')->getTriggerGroup('commit', array($repo->id));
if($refresh and strpos($repo->SCM, 'Git') !== false)
if($refresh and in_array($repo->SCM, $this->config->repo->gitTypeList))
{
$branch = $this->cookie->repoBranch;
$this->loadModel('git')->updateCommit($repo, $commentGroup, false);
@@ -479,13 +485,13 @@ class repo extends control
$revisions = $this->repo->getCommits($repo, $path, $revision, $logType, $pager);
/* Synchronous commit only in root path. */
if(strpos($repo->SCM, 'Git') !== false and empty($path) and $infos and empty($revisions)) $this->locate($this->repo->createLink('showSyncCommit', "repoID=$repoID&objectID=$objectID&branch=" . base64_encode($this->cookie->repoBranch)));
if(in_array($repo->SCM, $this->config->repo->gitTypeList) and empty($path) and $infos and empty($revisions)) $this->locate($this->repo->createLink('showSyncCommit', "repoID=$repoID&objectID=$objectID&branch=" . helper::safe64Encode(base64_encode($this->cookie->repoBranch))));
$this->view->title = $this->lang->repo->common;
$this->view->repo = $repo;
$this->view->repos = $this->repos;
$this->view->revisions = $revisions;
$this->view->repoGroup = $this->repoGroup;
$this->view->repoGroup = $this->repo->getRepoGroup($this->app->tab, $objectID);
$this->view->revision = $revision;
$this->view->infos = $infos;
$this->view->repoID = $repoID;
@@ -590,7 +596,7 @@ class repo extends control
$history = $this->dao->select('*')->from(TABLE_REPOHISTORY)->where('revision')->eq($log[0]->revision)->andWhere('repo')->eq($repoID)->fetch();
if($history)
{
if(strpos($repo->SCM, 'Git') !== false)
if(in_array($repo->SCM, $this->config->repo->gitTypeList))
{
$thisAndPrevRevisions = $this->scm->exec("rev-list -n 2 {$history->revision} --");
@@ -608,7 +614,7 @@ class repo extends control
if(empty($oldRevision))
{
$oldRevision = '^';
if($history and strpos($repo->SCM, 'Git') !== false) $oldRevision = "{$history->revision}^";
if($history and in_array($repo->SCM, $this->config->repo->gitTypeList)) $oldRevision = "{$history->revision}^";
}
$changes = array();
@@ -694,7 +700,7 @@ class repo extends control
if($encoding != 'utf-8') $blames[$i]['content'] = helper::convertEncoding($blame['content'], $encoding);
}
$log = strpos($repo->SCM, 'Git') !== false ? $this->dao->select('revision,commit')->from(TABLE_REPOHISTORY)->where('revision')->eq($revision)->andWhere('repo')->eq($repo->id)->fetch() : '';
$log = in_array($repo->SCM, $this->config->repo->gitTypeList) ? $this->dao->select('revision,commit')->from(TABLE_REPOHISTORY)->where('revision')->eq($revision)->andWhere('repo')->eq($repo->id)->fetch() : '';
$this->view->title = $this->lang->repo->common;
$this->view->repoID = $repoID;
@@ -705,8 +711,8 @@ class repo extends control
$this->view->entry = $entry;
$this->view->file = $file;
$this->view->encoding = str_replace('-', '_', $encoding);
$this->view->historys = strpos($repo->SCM, 'Git') !== false ? $this->dao->select('revision,commit')->from(TABLE_REPOHISTORY)->where('revision')->in($revisions)->andWhere('repo')->eq($repo->id)->fetchPairs() : '';
$this->view->revisionName = ($log and strpos($repo->SCM, 'Git') !== false) ? $this->repo->getGitRevisionName($log->revision, $log->commit) : $revision;
$this->view->historys = in_array($repo->SCM, $this->config->repo->gitTypeList) ? $this->dao->select('revision,commit')->from(TABLE_REPOHISTORY)->where('revision')->in($revisions)->andWhere('repo')->eq($repo->id)->fetchPairs() : '';
$this->view->revisionName = ($log and in_array($repo->SCM, $this->config->repo->gitTypeList)) ? $this->repo->getGitRevisionName($log->revision, $log->commit) : $revision;
$this->view->blames = $blames;
$this->display();
}
@@ -736,6 +742,12 @@ class repo extends control
$repo = $this->repo->getRepoByID($repoID);
$entry = $this->repo->decodePath($entry);
if($repo->SCM == 'Git' and !is_dir($repo->path))
{
$error = sprintf($this->lang->repo->error->notFound, $repo->name, $repo->path);
return print(js::error($error) . js::locate($this->repo->createLink('maintain')));
}
$pathInfo = pathinfo($entry);
$suffix = '';
if(isset($pathInfo["extension"])) $suffix = strtolower($pathInfo["extension"]);
@@ -822,7 +834,7 @@ class repo extends control
$this->view->newRevision = $newRevision;
$this->view->oldRevision = $oldRevision;
$this->view->revision = $newRevision;
$this->view->historys = strpos($repo->SCM, 'Git') !== false ? $this->dao->select('revision,commit')->from(TABLE_REPOHISTORY)->where('revision')->in("$oldRevision,$newRevision")->andWhere('repo')->eq($repo->id)->fetchPairs() : '';
$this->view->historys = in_array($repo->SCM, $this->config->repo->gitTypeList) ? $this->dao->select('revision,commit')->from(TABLE_REPOHISTORY)->where('revision')->in("$oldRevision,$newRevision")->andWhere('repo')->eq($repo->id)->fetchPairs() : '';
$this->view->info = $info;
$this->view->title = $this->lang->repo->common . $this->lang->colon . $this->lang->repo->diff;
@@ -909,7 +921,7 @@ class repo extends control
$this->commonAction($repoID, $objectID);
if($repoID == 0) $repoID = $this->session->repoID;
if($branch) $branch = base64_decode($branch);
if($branch) $branch = base64_decode(helper::safe64Decode($branch));
$this->view->title = $this->lang->repo->common . $this->lang->colon . $this->lang->repo->showSyncCommit;
$this->view->position[] = $this->lang->repo->showSyncCommit;
@@ -938,11 +950,33 @@ class repo extends control
if(empty($repo)) return;
if($repo->synced) return print('finish');
if(in_array($repo->SCM, array('Gitea', 'Gogs')))
{
$logFile = realPath($this->app->getTmpRoot() . "/log/clone.progress." . strtolower($repo->SCM) . ".{$repo->name}.log");
if($logFile)
{
$content = file($logFile);
$lastLine = $content[count($content) - 1];
if(!strpos($lastLine, 'done'))
{
return print(1);
}
elseif(strpos($lastLine, 'fatal') !== false)
{
return print('finish');
}
else
{
@unlink($logFile);
}
}
}
$this->commonAction($repoID);
$this->scm->setEngine($repo);
$branchID = '';
if(strpos($repo->SCM, 'Git') !== false and empty($branchID))
if(in_array($repo->SCM, $this->config->repo->gitTypeList) and empty($branchID))
{
$branches = $this->scm->branch();
if($branches)
@@ -979,7 +1013,7 @@ class repo extends control
$version = empty($latestInDB) ? 1 : $latestInDB->commit + 1;
$logs = array();
$revision = $version == 1 ? 'HEAD' : ($repo->SCM == 'Git' ? $latestInDB->commit : $latestInDB->revision);
$revision = $version == 1 ? 'HEAD' : (in_array($repo->SCM, array('Git', 'Gitea', 'Gogs')) ? $latestInDB->commit : $latestInDB->revision);
if($type == 'batch')
{
$logs = $this->scm->getCommits($revision, $this->config->repo->batchNum, $branchID);
@@ -994,7 +1028,7 @@ class repo extends control
{
if(!$repo->synced)
{
if(strpos($repo->SCM, 'Git') !== false)
if(in_array($repo->SCM, $this->config->repo->gitTypeList))
{
if($branchID) $this->repo->saveExistCommits4Branch($repo->id, $branchID);
@@ -1029,8 +1063,8 @@ class repo extends control
set_time_limit(0);
$repo = $this->repo->getRepoByID($repoID);
if(empty($repo)) return;
if(strpos($repo->SCM, 'Git') === false) return print('finish');
if($branch) $branch = base64_decode($branch);
if(!in_array($repo->SCM, $this->config->repo->gitTypeList)) return print('finish');
if($branch) $branch = base64_decode(helper::safe64Decode($branch));
$this->scm->setEngine($repo);
@@ -1040,7 +1074,7 @@ class repo extends control
$latestInDB = $this->dao->select('DISTINCT t1.*')->from(TABLE_REPOHISTORY)->alias('t1')
->leftJoin(TABLE_REPOBRANCH)->alias('t2')->on('t1.id=t2.revision')
->where('t1.repo')->eq($repoID)
->beginIF(strpos($repo->SCM, 'Git') !== false and $this->cookie->repoBranch)->andWhere('t2.branch')->eq($this->cookie->repoBranch)->fi()
->beginIF(in_array($repo->SCM, $this->config->repo->gitTypeList) and $this->cookie->repoBranch)->andWhere('t2.branch')->eq($this->cookie->repoBranch)->fi()
->orderBy('t1.time')
->limit(1)
->fetch();
@@ -1078,7 +1112,7 @@ class repo extends control
* @access public
* @return void
*/
public function ajaxSideCommits($repoID, $path, $objectID = 0, $type = 'dir', $recTotal = 0, $recPerPage = 8, $pageID = 1)
public function ajaxSideCommits($repoID, $path, $objectID = 0, $type = 'dir', $recTotal = 0, $recPerPage = 10, $pageID = 1)
{
if($this->get->repoPath) $path = $this->get->repoPath;
$this->app->loadClass('pager', $static = true);
@@ -1198,8 +1232,8 @@ class repo extends control
/**
* Ajax get gitea projects.
*
* @param string $gitlabID
* @param string $projectIdList
* @param string $gitlabID
* @param string $projectIdList
* @access public
* @return void
*/
@@ -1214,11 +1248,31 @@ class repo extends control
return print($options);
}
/**
* Ajax get gogs projects.
*
* @param string $gitlabID
* @param string $projectIdList
* @access public
* @return void
*/
public function ajaxGetGogsProjects($gogsID)
{
$projects = $this->loadModel('gogs')->apiGetProjects($gogsID);
$options = "<option value=''></option>";
if(!empty($projects))
{
foreach($projects as $project) $options .= "<option value='{$project->full_name}' data-name='{$project->name}'>{$project->full_name}</option>";
}
return print($options);
}
/**
* Ajax get gitlab projects.
*
* @param string $gitlabID
* @param string $token
* @param string $gitlabID
* @param string $token
* @access public
* @return void
*/
@@ -1356,7 +1410,6 @@ class repo extends control
{
$repo = $this->repo->getRepoByID($repoID);
$savePath = $this->app->getDataRoot() . 'repo';
$fileName = $savePath . DS . $repo->name . '.zip';
if(!is_dir($savePath))
{
if(!is_writable($this->app->getDataRoot())) return print(js::alert(sprintf($this->lang->repo->error->noWritable, dirname($savePath))) . js::close());
@@ -1364,50 +1417,9 @@ class repo extends control
}
$repo = $this->repo->getRepoByID($repoID);
if($repo->SCM == 'Gitlab')
{
$this->scm = $this->app->loadClass('scm');
$this->scm->setEngine($repo);
$url = $this->scm->getDownloadUrl($branch);
}
elseif($repo->SCM == 'Gitea')
{
$api = $this->loadModel('gitea')->getApiRoot($repo->serviceHost);
$url = sprintf($api, "/repos/{$repo->serviceProject}/archive/{$branch}.zip");
}
elseif($repo->SCM == 'Git')
{
$gitDir = scandir($repo->path);
$files = '';
foreach($gitDir as $path)
{
if(!in_array($path, array('.', '..', '.git'))) $files .= $repo->path . DS . "$path,";
}
$this->app->loadClass('pclzip', true);
$zip = new pclzip($fileName);
if($zip->create($files, PCLZIP_OPT_REMOVE_PATH, $repo->path) === 0) return print(js::alert($zip->errorInfo()) . js::close());
$url = $this->config->webRoot . $this->app->getAppName() . 'data' . DS . 'repo' . DS . $repo->name . '.zip';
}
else
{
/* Checkout repo. */
chdir($savePath);
$this->scm = $this->app->loadClass('scm');
$this->scm->setEngine($repo);
$this->scm->exec('export ' . $repo->path);
/* Get repo name. */
$pathList = explode('/', trim($repo->path, '/'));
$repoDir = end($pathList);
$this->app->loadClass('pclzip', true);
$zip = new pclzip($fileName);
if($zip->create($repoDir, PCLZIP_OPT_REMOVE_PATH, $repoDir) === 0) return print(js::alert($zip->errorInfo()) . js::close());
$url = $this->config->webRoot . $this->app->getAppName() . 'data' . DS . 'repo' . DS . $repo->name . '.zip';
}
$this->scm = $this->app->loadClass('scm');
$this->scm->setEngine($repo);
$url = $this->scm->getDownloadUrl($branch, $savePath);
$this->locate($url);
}
+1
View File
@@ -9,3 +9,4 @@
pre {margin-bottom: 0px; display: block; white-space: pre-wrap; padding: 0px 3px; border: 0px; background: none;}
.line {font-weight: bold; border: 1px solid #E4E4E4; background-color: #fafafa; color: #999; text-align: center;}
.panel-actions.pull-right {margin-top: -5px;}
.action-onlybody {right: 30px;}
+16 -10
View File
@@ -64,12 +64,12 @@ h3 {font-size: 16px;}
/* Pre row */
.repoCode table > tbody > tr.over > td {background: #f8eec7;}
.repoCode table > tbody > tr.over > th {background: #cdcdcd; color: #333;}
.repoCode table > tbody > tr.over > th {background: #cdcdcd !important; color: #333 !important;}
/* Comment-btn */
.comment-btn {position: relative; margin: 0; padding: 0; display: none;}
.repoCode tr.over .comment-btn {display: block;}
.comment-btn .icon-wrapper {display: block; position: absolute; background: #4183C4; border-radius: 2px; width: 24px; height: 20px; left: -6px; top: -2; line-height: 20px; text-align: center; color: #fff; cursor: pointer; transition: transform 0.2s;}
.comment-btn .icon-wrapper {display: block; position: absolute; background: #4183C4; border-radius: 2px; width: 24px; height: 20px; left: -6px; top: -2; line-height: 20px; text-align: center; color: #fff; cursor: pointer;}
.comment-btn .icon-wrapper:before {display: block; content: ' '; right: -4px; top: 6px; position: absolute; border-left: 4px solid #4183C4; border-right: 0 solid transparent; border-bottom: 4px solid transparent; border-top: 4px solid transparent; width: 0; height: 0;}
.comment-btn .icon-wrapper:hover {background: #169; transform: scale(1.1);}
.comment-btn .icon-wrapper:hover:before {border-left-color: #169;}
@@ -79,7 +79,7 @@ h3 {font-size: 16px;}
.repoCode tr.commented .comment-btn {display: block; float:left;}
.repoCode tr.commented .comment-btn .icon-wrapper {background: none; border: none; width: 24px; line-height: 18px; height: 18px; left: -6px; color: #4183c4;}
.repoCode tr.commented .comment-btn .icon-wrapper:hover {border-color: #169; color: #169;}
.repoCode tr.commented .comment-btn .icon-wrapper > i:before {font-size: 18px; transform: scale(-1, 1); display: inline-block;}
.repoCode tr.commented .comment-btn .icon-wrapper > i:before {font-size: 18px; display: inline-block;}
.repoCode tr.commented .comment-btn .icon-wrapper:before {display: none;}
.repoCode tr.over.commented .comment-btn {margin-left: -20px; width: 25px; height:18px;}
@@ -89,7 +89,9 @@ h3 {font-size: 16px;}
.repoCode tr.over.commented .comment-btn .icon-wrapper:before, .repoCode tr.selected.commented .comment-btn .icon-wrapper:before {display: block;}
/* repo action form */
.repoCode .comment-list, .repoCode .comment-actions {max-width: 900px;}
.repoCode .comment-actions {max-width: 900px;}
.repoCode table {table-layout: fixed;}
.repoCode table td {white-space: pre-line;}
.repoCode .bugFormContainer {border: 1px solid #bbb; margin: 0 0 0 15px; padding: 10px 20px 10px 10px; max-width: 880px; background: #fff;}
.repoCode .bugFormContainer th {width: 70px;}
@@ -106,17 +108,17 @@ h3 {font-size: 16px;}
.repoCode .comment-cell {background: #eee; white-space: normal;}
.repoCode .comment-cell .panel {margin: 10px; border-color: #bbb;}
.repoCode .comment-cell .panel-body {padding: 6px 10px;}
.repoCode .comment-cell .panel-actions.pull-right {margin-right: 0; margin-top: 0;}
.repoCode .comment-cell .panel-actions.pull-right {margin-right: 0; margin-top: -25px; position: unset;}
.repoCode .comment-cell .editing .panel-body, .repoCode .comment-cell .commentContainer.show-form .panel-body {display: none;}
.repoCode .comment-cell .bug-edit-form, {padding: 10px; display: none;}
.repoCode .comment-cell .editing .bug-edit-form, .repoCode .comment-cell .commentContainer.show-form .comment-edit-form {display: block;}
.repoCode .comment {border: 1px solid #e5e5e5; background: #fafafa; padding: 5px 10px; margin-bottom: 10px;}
.repoCode .comment {border: 1px solid #e5e5e5; background: #fafafa; padding: 5px 10px 1px; margin-bottom: 10px;}
.repoCode .comment .comment-edit-form {margin-top: 10px;}
.repoCode .panel-bug .steps {background: #f1f1f1; padding: 5px 10px;}
.repoCode .panel-bug .bug-edit-form {margin-bottom: 10px;}
.repoCode .panel-bug .panel-body {display: none;}
.repoCode .panel-bug .panel-heading {cursor: pointer;}
.repoCode .panel-bug .panel-heading {cursor: pointer; border-bottom: 1px solid #edf3ff;}
.repoCode .panel-bug.show .panel-body {display: block;}
.repoCode .panel-bug.show .icon-chevron-sign-down:before {content: '\e711';}
.repoCode .panel-bug.show-edit-form .bug-edit-form,
@@ -128,7 +130,7 @@ h3 {font-size: 16px;}
.repoCode .comment .comment-edit-form,
.repoCode .panel-bug.show-edit-form .panel-body .title,
.repoCode .panel-bug.show-edit-form .bug-date,
.repoCode .comment.show-form .comment-content, .repoCode .comment.show-form .comment-date {display: none;}
.repoCode .comment.show-form .comment-content {display: none;}
.repoCode .text-content {white-space: normal; white-space: pre-line;}
.repoCode .text-muted {color: #aaa;}
@@ -175,8 +177,8 @@ h3 {font-size: 16px;}
.transparent {border-color:transparent; background: none repeat scroll 0 0 transparent;}
.transparent:hover {border-color:transparent; background: none repeat scroll 0 0 transparent;}
.side-col {width: 600px;}
#sidebar > .side-body {width: 580px;}
.side-col {width: 550px;}
#sidebar > .side-body {width: 530px;}
.hide-sidebar #sidebar > .side-body {display: none;}
#sidebar>.sidebar-toggle {left: 5px; right: auto;}
@@ -192,3 +194,7 @@ h3 {font-size: 16px;}
.dropdown-menu li > a.selected {color: #3123ae !important; background: #f2eafc !important; line-height: 20px; border-radius: 5px;}
.tips-git a {padding-bottom: 1px;}
.bug-lines {font-size: revert;}
.comment.show-form .comment-form-div {margin-top: 20px; padding-bottom: 10px;}
.comment .avatar {margin-right: 10px;}
+5 -6
View File
@@ -54,17 +54,15 @@ $(function()
*/
function scmChanged(scm)
{
if(scm == 'Git' || scm == 'Gitea')
if(scm == 'Git' || scm == 'Gitea' || scm == 'Gogs')
{
$('.account-fields').addClass('hidden');
$('.tips-git').removeClass('hidden');
$('.tips-svn').addClass('hidden');
}
else
{
$('.account-fields').removeClass('hidden');
$('.tips-git').addClass('hidden');
$('.tips-svn').removeClass('hidden');
}
@@ -76,11 +74,12 @@ function scmChanged(scm)
}
else
{
$('.tips').addClass('hidden');
$('tr.service').toggle(true);
if(scm == 'Gitea')
if(scm == 'Gitea' || scm == 'Gogs')
{
$('tr.hide-service:not(".hide-gitea")').toggle(true);
$('tr.hide-gitea').toggle(false);
$('tr.hide-service:not(".hide-git")').toggle(true);
$('tr.hide-git').toggle(false);
}
else
{
+5 -4
View File
@@ -38,7 +38,7 @@ $(function()
*/
function scmChanged(scm, isFirstRequest = false)
{
if(scm == 'Git' || scm == 'Gitea')
if(scm == 'Git' || scm == 'Gitea' || scm == 'Gogs')
{
$('.account-fields').addClass('hidden');
@@ -60,11 +60,12 @@ function scmChanged(scm, isFirstRequest = false)
}
else
{
$('.tips').addClass('hidden');
$('tr.service').toggle(true);
if(scm == 'Gitea')
if(scm == 'Gitea' || scm == 'Gogs')
{
$('tr.hide-service:not(".hide-gitea")').toggle(true);
$('tr.hide-gitea').toggle(false);
$('tr.hide-service:not(".hide-git")').toggle(true);
$('tr.hide-git').toggle(false);
}
else
{
+1 -1
View File
@@ -13,7 +13,7 @@ $(document).ready(function()
for(var i = 0 ; i < arr.length ; i++)
{
line = i + 1;
code += "<tr data-line='" + line +"'><th id='L" + line + "'><div class='comment-btn view'><span class='icon-wrapper'><i class='icon-plus'></i></span></div>" + line + "</th><td>" + (arr[i] || '&nbsp;') + rowTip + "</td></tr>";
code += "<tr data-line='" + line +"'><th id='L" + line + "'><span class='comment-btn view'><span class='icon-wrapper'><i class='icon-bug'></i><span class='label label-light label-badge bug-num'>0</span></span></span><span>" + line + "</span></th><td>" + (arr[i] || '&nbsp;') + rowTip + "</td></tr>";
}
$pre.html("<table><tbody>" + code + "</tbody></table>");
}
+1
View File
@@ -142,6 +142,7 @@ $lang->repo->encodingList['utf_8'] = 'UTF-8';
$lang->repo->encodingList['gbk'] = 'GBK';
$lang->repo->scmList['Gitlab'] = 'GitLab';
$lang->repo->scmList['Gogs'] = 'Gogs';
$lang->repo->scmList['Gitea'] = 'Gitea';
$lang->repo->scmList['Git'] = 'Git';
$lang->repo->scmList['Subversion'] = 'SVN';
+1
View File
@@ -142,6 +142,7 @@ $lang->repo->encodingList['utf_8'] = 'UTF-8';
$lang->repo->encodingList['gbk'] = 'GBK';
$lang->repo->scmList['Gitlab'] = 'GitLab';
$lang->repo->scmList['Gogs'] = 'Gogs';
$lang->repo->scmList['Gitea'] = 'Gitea';
$lang->repo->scmList['Git'] = 'Git';
$lang->repo->scmList['Subversion'] = 'SVN';
+1
View File
@@ -142,6 +142,7 @@ $lang->repo->encodingList['utf_8'] = 'UTF-8';
$lang->repo->encodingList['gbk'] = 'GBK';
$lang->repo->scmList['Gitlab'] = 'GitLab';
$lang->repo->scmList['Gogs'] = 'Gogs';
$lang->repo->scmList['Gitea'] = 'Gitea';
$lang->repo->scmList['Git'] = 'Git';
$lang->repo->scmList['Subversion'] = 'Subversion';
+1
View File
@@ -142,6 +142,7 @@ $lang->repo->encodingList['utf_8'] = 'UTF-8';
$lang->repo->encodingList['gbk'] = 'GBK';
$lang->repo->scmList['Gitlab'] = 'GitLab';
$lang->repo->scmList['Gogs'] = 'Gogs';
$lang->repo->scmList['Gitea'] = 'Gitea';
$lang->repo->scmList['Git'] = 'Git';
$lang->repo->scmList['Subversion'] = 'SVN';
+1
View File
@@ -142,6 +142,7 @@ $lang->repo->encodingList['utf_8'] = 'UTF-8';
$lang->repo->encodingList['gbk'] = 'GBK';
$lang->repo->scmList['Gitlab'] = 'GitLab';
$lang->repo->scmList['Gogs'] = 'Gogs';
$lang->repo->scmList['Gitea'] = 'Gitea';
$lang->repo->scmList['Git'] = '本地 Git';
$lang->repo->scmList['Subversion'] = 'Subversion';
+1
View File
@@ -135,6 +135,7 @@ $lang->repo->encodingList['utf_8'] = 'UTF-8';
$lang->repo->encodingList['gbk'] = 'GBK';
$lang->repo->scmList['Gitlab'] = 'GitLab';
$lang->repo->scmList['Gogs'] = 'Gogs';
$lang->repo->scmList['Gitea'] = 'Gitea';
$lang->repo->scmList['Git'] = '本地 Git';
$lang->repo->scmList['Subversion'] = 'Subversion';
+45 -61
View File
@@ -58,7 +58,7 @@ class repoModel extends model
}
if(!in_array(strtolower($repo->SCM), $this->config->repo->gitServiceList)) unset($this->lang->devops->menu->mr);
$this->lang->switcherMenu = $this->getSwitcher($repoID);
if(count($repos) > 1) $this->lang->switcherMenu = $this->getSwitcher($repoID);
}
common::setMenuVars('devops', $repoID);
@@ -188,18 +188,12 @@ class repoModel extends model
if(!$this->checkConnection()) return false;
$isPipelineServer = in_array(strtolower($this->post->SCM), $this->config->repo->gitServiceList) ? true : false;
if($isPipelineServer)
{
if($this->post->serviceHost == '') dao::$errors['serviceHost'] = sprintf($this->lang->error->notempty, $this->lang->repo->serviceHost);
if($this->post->serviceProject == '') dao::$errors['serviceProject'] = sprintf($this->lang->error->notempty, $this->lang->repo->serviceProject);
if(dao::isError()) return false;
}
$data = fixer::input('post')
->setIf($isPipelineServer, 'password', $this->post->serviceToken)
->setIf($isPipelineServer and $this->post->SCM == 'Gitlab', 'path', '')
->setIf($isPipelineServer and $this->post->SCM == 'Gitlab', 'client', '')
->setIf($isPipelineServer, 'extra', $this->post->serviceProject)
->setIf($this->post->SCM == 'Gitlab', 'path', '')
->setIf($this->post->SCM == 'Gitlab', 'client', '')
->setIf($this->post->SCM == 'Gitlab', 'extra', $this->post->serviceProject)
->setIf($isPipelineServer, 'prefix', '')
->setIf($this->post->SCM == 'Git', 'account', '')
->setIf($this->post->SCM == 'Git', 'password', '')
@@ -208,19 +202,7 @@ class repoModel extends model
->join('product', ',')
->get();
if($isPipelineServer)
{
$repo = $this->dao->select('id')->from(TABLE_REPO)
->where('SCM')->eq($this->post->SCM)
->andWhere('serviceHost')->eq($data->client)
->andWhere('serviceProject')->eq($data->path)
->fetch();
if(!empty($repo)) dao::$errors['serviceProject'] = sprintf($this->lang->error->unique, $this->lang->repo->serviceProject, $repo->name);
if(dao::isError()) return false;
}
$data->acl = empty($data->acl) ? '' : json_encode($data->acl);
if($data->SCM == 'Subversion')
{
$scm = $this->app->loadClass('scm');
@@ -234,12 +216,12 @@ class repoModel extends model
if($data->encrypt == 'base64') $data->password = base64_encode($data->password);
$this->dao->insert(TABLE_REPO)->data($data, $skip = 'serviceToken')
->batchCheck($this->config->repo->create->requiredFields, 'notempty')
->checkIF($data->SCM != 'Gitlab', 'path,client', 'notempty')
->checkIF($isPipelineServer, 'serviceHost,serviceProject', 'notempty')
->checkIF($data->SCM == 'Subversion', $this->config->repo->svn->requiredFields, 'notempty')
->checkIF($data->SCM == 'Gitea', $this->config->repo->gitea->requiredFields, 'notempty')
->checkIF($data->SCM == 'Git', 'path', 'unique', "`SCM` = 'Git'")
->checkIF($data->SCM == 'Subversion', 'path', 'unique', "`SCM` = 'Subversion'")
->batchCheckIF($data->SCM != 'Gitlab', 'path,client', 'notempty')
->batchCheckIF($isPipelineServer, 'serviceHost,serviceProject', 'notempty')
->batchCheckIF($data->SCM == 'Subversion', $this->config->repo->svn->requiredFields, 'notempty')
->check('name', 'unique', "`SCM` = '{$data->SCM}'")
->checkIF($isPipelineServer, 'serviceProject', 'unique', "`SCM` = '{$data->SCM}' and `serviceHost` = '{$data->serviceHost}'")
->checkIF(!$isPipelineServer, 'path', 'unique', "`SCM` = '{$data->SCM}' and `serviceHost` = '{$data->serviceHost}'")
->autoCheck()
->exec();
@@ -271,17 +253,12 @@ class repoModel extends model
$repo = $this->getRepoByID($id);
$isPipelineServer = in_array(strtolower($this->post->SCM), $this->config->repo->gitServiceList) ? true : false;
if($isPipelineServer)
{
if($this->post->serviceHost == '') dao::$errors['serviceHost'] = sprintf($this->lang->error->notempty, $this->lang->repo->serviceHost);
if($this->post->serviceProject == '') dao::$errors['serviceProject'] = sprintf($this->lang->error->notempty, $this->lang->repo->serviceProject);
}
$data = fixer::input('post')
->setIf($isPipelineServer, 'password', $this->post->serviceToken)
->setIf($isPipelineServer and $this->post->SCM == 'Gitlab', 'path', '')
->setIf($isPipelineServer and $this->post->SCM == 'Gitlab', 'client', '')
->setIf($isPipelineServer, 'extra', $this->post->serviceProject)
->setIf($this->post->SCM == 'Gitlab', 'path', '')
->setIf($this->post->SCM == 'Gitlab', 'client', '')
->setIf($this->post->SCM == 'Gitlab', 'extra', $this->post->serviceProject)
->setDefault('prefix', $repo->prefix)
->setIf($this->post->SCM == 'Gitlab', 'prefix', '')
->setDefault('client', 'svn')
@@ -308,29 +285,18 @@ class repoModel extends model
$data->prefix = '';
}
if($isPipelineServer)
{
$repo = $this->dao->select('id')->from(TABLE_REPO)
->where('SCM')->eq($this->post->SCM)
->andWhere('serviceHost')->eq($data->client)
->andWhere('serviceProject')->eq($data->path)
->andWhere('id')->ne($id)
->fetch();
if(!empty($repo)) dao::$errors['serviceProject'] = sprintf($this->lang->error->unique, $this->lang->repo->serviceProject, $repo->name);
if(dao::isError()) return false;
}
if($data->client != $repo->client and !$this->checkClient()) return false;
if(!$this->checkConnection()) return false;
if($data->encrypt == 'base64') $data->password = base64_encode($data->password);
$this->dao->update(TABLE_REPO)->data($data, $skip = 'serviceToken')
->batchCheck($this->config->repo->edit->requiredFields, 'notempty')
->checkIF($data->SCM != 'Gitlab', 'path,client', 'notempty')
->checkIF($data->SCM == 'Subversion', $this->config->repo->svn->requiredFields, 'notempty')
->checkIF($data->SCM == 'Gitlab', 'extra', 'notempty')
->checkIF($data->SCM == 'Git', 'path', 'unique', "`SCM` = 'Git' and `id` <> $id")
->checkIF($data->SCM == 'Subversion', 'path', 'unique', "`SCM` = 'Subversion' and `id` <> $id")
->batchCheckIF($data->SCM != 'Gitlab', 'path,client', 'notempty')
->batchCheckIF($isPipelineServer, 'serviceHost,serviceProject', 'notempty')
->batchCheckIF($data->SCM == 'Subversion', $this->config->repo->svn->requiredFields, 'notempty')
->check('name', 'unique', "`SCM` = '{$data->SCM}' and `id` <> $id")
->checkIF($isPipelineServer, 'serviceProject', 'unique', "`SCM` = '{$data->SCM}' and `serviceHost` = '{$data->serviceHost}' and `id` <> $id")
->checkIF(!$isPipelineServer, 'path', 'unique', "`SCM` = '{$data->SCM}' and `serviceHost` = '{$data->serviceHost}' and `id` <> $id")
->autoCheck()
->where('id')->eq($id)->exec();
@@ -436,17 +402,22 @@ class repoModel extends model
$repo = str_replace('[gitlab]', '', $repo);
$repos['Gitlab'][$id] = $repo;
}
if(strpos($repo, '[gitea]') !== false)
elseif(strpos($repo, '[gogs]') !== false)
{
$repo = str_replace('[gogs]', '', $repo);
$repos['Gogs'][$id] = $repo;
}
elseif(strpos($repo, '[gitea]') !== false)
{
$repo = str_replace('[gitea]', '', $repo);
$repos['Gitea'][$id] = $repo;
}
if(strpos($repo, '[svn]') !== false)
elseif(strpos($repo, '[svn]') !== false)
{
$repo = str_replace('[svn]', '', $repo);
$repos['SVN'][$id] = $repo;
}
if(strpos($repo, '[git]') !== false)
elseif(strpos($repo, '[git]') !== false)
{
$repo = str_replace('[git]', '', $repo);
$repos['Git'][$id] = $repo;
@@ -1415,17 +1386,19 @@ class repoModel extends model
return false;
}
}
elseif($scm == 'Gitea')
elseif(in_array($scm, array('Gitea', 'Gogs')))
{
if($this->post->name != '' and $this->post->serviceProject != '')
{
$project = $this->loadModel('gitea')->apiGetSingleProject($this->post->serviceHost, $this->post->serviceProject);
$module = strtolower($scm);
$project = $this->loadModel($module)->apiGetSingleProject($this->post->serviceHost, $this->post->serviceProject);
if(isset($project->tokenCloneUrl))
{
$path = dirname(dirname(dirname(__FILE__))) . '/tmp/repo/' . $this->post->name . '_gitea';
$path = $this->app->getAppRoot() . 'www/data/repo/' . $this->post->name . '_' . $module;
if(!realpath($path))
{
$cmd = 'git clone --progress -v "' . $project->tokenCloneUrl . '" "' . $path . '"';
$cmd = 'git clone --progress -v "' . $project->tokenCloneUrl . '" "' . $path . '" > "' . $this->app->getTmpRoot() . "log/clone.progress.$module.{$this->post->name}.log\" 2>&1 &";
if(PHP_OS == 'WINNT') $cmd = "start /b $cmd";
exec($cmd);
}
$_POST['path'] = $path;
@@ -2073,7 +2046,7 @@ class repoModel extends model
$repo->password = $service ? $service->token : '';
$repo->codePath = $project ? $project->web_url : $repo->path;
}
elseif($repo->SCM == 'Gitea')
elseif(in_array($repo->SCM, array('Gitea', 'Gogs')))
{
$repo->codePath = $service ? "{$service->url}/{$repo->serviceProject}" : $repo->path;
}
@@ -2091,8 +2064,10 @@ class repoModel extends model
*/
public function getRepoListByClient($gitlabID, $projectID = 0)
{
$server = $this->loadModel('pipeline')->getByID($gitlabID);
return $this->dao->select('*')->from(TABLE_REPO)->where('deleted')->eq('0')
->andWhere('synced')->eq(1)
->beginIF($server)->andWhere('SCM')->eq(ucfirst($server->type))->fi()
->andWhere('serviceHost')->eq($gitlabID)
->beginIF($projectID)->andWhere('serviceProject')->eq($projectID)->fi()
->fetchAll();
@@ -2214,6 +2189,15 @@ class repoModel extends model
$url->ssh = $project->ssh_url;
}
}
elseif($repo->SCM == 'Gogs')
{
$project = $this->loadModel('gogs')->apiGetSingleProject($repo->gitService, $repo->project);
if(isset($project->id))
{
$url->http = $project->clone_url;
$url->ssh = $project->ssh_url;
}
}
else
{
$this->scm = $this->app->loadClass('scm');
+1 -1
View File
@@ -53,7 +53,7 @@ if(isset($entry)) $pathInfo .= '&type=file';
<?php if(common::hasPriv('repo', 'diff')) echo html::submitButton($lang->repo->diff, '', count($revisions) < 2 ? 'disabled btn btn-primary' : 'btn btn-primary')?>
<?php echo html::a($this->repo->createLink('log', "repoID=$repoID&objectID=$objectID&entry=" . $this->repo->encodePath($path) . "&revision=HEAD&type=$logType"), $lang->repo->allLog, '', "class='allLogs' data-app='{$this->app->tab}'");?>
<div class='pull-right'>
<ul id="repoPageSize" class="pager" data-ride="pager" data-elements="size_menu" data-rec-total="<?php echo $pager->recTotal;?>" data-rec-per-page="<?php echo $pager->recPerPage;?>" data-page="<?php echo $pager->pageID;?>"></ul>
<ul id="repoPageSize" class="pager" data-ride="pager" data-elements="size_menu" data-rec-total="<?php echo $pager->recTotal;?>" data-rec-per-page="<?php echo $pager->recPerPage;?>" data-page="<?php echo $pager->pageID;?>"></ul>
<div class='btn-group'>
<?php
$prePage = $pager->pageID == 1 ? 1 : $pager->pageID - 1;
+1 -1
View File
@@ -54,7 +54,7 @@ css::import($jsRoot . 'misc/highlight/styles/github.css');
<div class='panel-heading'>
<div class='panel-title'><?php echo $entry;?></div>
<?php $encodePath = $this->repo->encodePath($entry);?>
<div class='panel-actions'>
<div class='panel-actions <?php echo isonlybody() ? "action-onlybody" : ""?>'>
<div class='btn-group'>
<?php echo html::commonButton(zget($lang->repo->encodingList, $encoding, $lang->repo->encoding) . "<span class='caret'></span>", "id='encoding' data-toggle='dropdown'", 'btn dropdown-toggle')?>
<ul class='dropdown-menu' role='menu' aria-labelledby='encoding'>

Some files were not shown because too many files have changed in this diff Show More