From e0c183c1ac0617ad1cce4491bf56ac0a0e1f669c Mon Sep 17 00:00:00 2001 From: midoks Date: Mon, 3 Oct 2022 12:27:44 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8A=A0=E5=85=A5gitea?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- plugins/gitea/hook/commit.tpl | 39 ++ plugins/gitea/hook/commit.tpl.ssh | 36 ++ plugins/gitea/hook/post-receive.tpl | 3 + plugins/gitea/ico.png | Bin 0 -> 26874 bytes plugins/gitea/index.html | 24 ++ .../bak/index_2022_6_19.py => gitea/index.py} | 299 ++++++++------- plugins/gitea/info.json | 16 + plugins/gitea/init.d/gitea.service.tpl | 12 + plugins/gitea/init.d/gitea.tpl | 110 ++++++ plugins/gitea/install.sh | 98 +++++ plugins/gitea/js/gitea.js | 353 ++++++++++++++++++ plugins/gogs/index.py | 5 + plugins/gogs/install.sh | 1 - route/static/app/public.js | 12 + scripts/install/debian.sh | 2 +- 15 files changed, 881 insertions(+), 129 deletions(-) create mode 100755 plugins/gitea/hook/commit.tpl create mode 100755 plugins/gitea/hook/commit.tpl.ssh create mode 100755 plugins/gitea/hook/post-receive.tpl create mode 100644 plugins/gitea/ico.png create mode 100755 plugins/gitea/index.html rename plugins/{gogs/bak/index_2022_6_19.py => gitea/index.py} (74%) create mode 100755 plugins/gitea/info.json create mode 100644 plugins/gitea/init.d/gitea.service.tpl create mode 100644 plugins/gitea/init.d/gitea.tpl create mode 100755 plugins/gitea/install.sh create mode 100755 plugins/gitea/js/gitea.js diff --git a/plugins/gitea/hook/commit.tpl b/plugins/gitea/hook/commit.tpl new file mode 100755 index 000000000..7070accf5 --- /dev/null +++ b/plugins/gitea/hook/commit.tpl @@ -0,0 +1,39 @@ +#!/bin/bash + +echo `date` + +GITADDR="{$GITROOTURL}/{$USERNAME}/{$PROJECT}.git" +GIT_SDIR="{$CODE_DIR}" + +GIT_USER_DIR="${GIT_SDIR}/{$USERNAME}" +GIT_PROJECT_DIR="${GIT_USER_DIR}/{$PROJECT}" + + +git config --global credential.helper store + +# echo $GIT_PROJECT_DIR +if [ ! -d $GIT_PROJECT_DIR ];then + mkdir -p $GIT_USER_DIR && cd $GIT_USER_DIR + git clone $GITADDR +fi + +unset GIT_DIR +cd $GIT_PROJECT_DIR && git pull + +# func 2 +# cd $GIT_PROJECT_DIR && env -i git pull origin master + + +#更新的目的地址 +WEB_PATH={$WEB_ROOT}/{$USERNAME}/{$PROJECT} +mkdir -p $WEB_PATH + +rsync -vauP --delete --exclude=".*" $GIT_PROJECT_DIR/ $WEB_PATH + +sysName=`uname` +if [ $sysName == 'Darwin' ]; then + USER=$(who | sed -n "2,1p" |awk '{print $1}') + chown -R $USER:staff $WEB_PATH +else + chown -R www:www $WEB_PATH +fi \ No newline at end of file diff --git a/plugins/gitea/hook/commit.tpl.ssh b/plugins/gitea/hook/commit.tpl.ssh new file mode 100755 index 000000000..6aac78ca8 --- /dev/null +++ b/plugins/gitea/hook/commit.tpl.ssh @@ -0,0 +1,36 @@ +#!/bin/bash + +echo `date` + +GITADDR="{$GITROOTURL}/{$USERNAME}/{$PROJECT}" +GIT_SDIR="{$CODE_DIR}" + +GIT_USER_DIR="${GIT_SDIR}/{$USERNAME}" +GIT_PROJECT_DIR="${GIT_USER_DIR}/{$PROJECT}" + +# echo $GIT_PROJECT_DIR +if [ ! -d $GIT_PROJECT_DIR ];then + mkdir -p $GIT_USER_DIR && cd $GIT_USER_DIR + git clone $GITADDR +fi + +unset GIT_DIR +cd $GIT_PROJECT_DIR && git pull + +# func 2 +# cd $GIT_PROJECT_DIR && env -i git pull origin master + + + +WEB_PATH={$WEB_ROOT}/{$USERNAME}/{$PROJECT} +mkdir -p $WEB_PATH + +rsync -vauP --delete --exclude=".*" $GIT_PROJECT_DIR/ $WEB_PATH + +sysName=`uname` +if [ $sysName == 'Darwin' ]; then + USER=$(who | sed -n "2,1p" |awk '{print $1}') + chown -R $USER:staff $WEB_PATH +else + chown -R www:www $WEB_PATH +fi \ No newline at end of file diff --git a/plugins/gitea/hook/post-receive.tpl b/plugins/gitea/hook/post-receive.tpl new file mode 100755 index 000000000..0c747ce2f --- /dev/null +++ b/plugins/gitea/hook/post-receive.tpl @@ -0,0 +1,3 @@ +#!/bin/bash + +sh -x {$PATH}/commit 2>{$PATH}/sh.log \ No newline at end of file diff --git a/plugins/gitea/ico.png b/plugins/gitea/ico.png new file mode 100644 index 0000000000000000000000000000000000000000..5dacd7735d38a619e67e849c73d5c50c7f76f60d GIT binary patch literal 26874 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 literal 0 HcmV?d00001 diff --git a/plugins/gitea/index.html b/plugins/gitea/index.html new file mode 100755 index 000000000..8d9fe51d4 --- /dev/null +++ b/plugins/gitea/index.html @@ -0,0 +1,24 @@ +
+
+
+

服务

+

自启动

+ +

手动编辑

+

配置文件

+

配置修改

+

用户列表

+

运行日志

+

提交日志

+

使用说明

+
+
+
+
+
+
+ \ No newline at end of file diff --git a/plugins/gogs/bak/index_2022_6_19.py b/plugins/gitea/index.py similarity index 74% rename from plugins/gogs/bak/index_2022_6_19.py rename to plugins/gitea/index.py index 9bfc0b2a7..c01ca1f94 100755 --- a/plugins/gogs/bak/index_2022_6_19.py +++ b/plugins/gitea/index.py @@ -11,11 +11,10 @@ sys.path.append(os.getcwd() + "/class/core") import mw -cmd = 'ls /usr/local/lib/ | grep python | cut -d \\ -f 1 | awk \'END {print}\'' -info = mw.execShell(cmd) -p = "/usr/local/lib/" + info[0].strip() + "/site-packages" -sys.path.append(p) -import psutil +# cmd = 'ls /usr/local/lib/ | grep python | cut -d \\ -f 1 | awk \'END {print}\'' +# info = mw.execShell(cmd) +# p = "/usr/local/lib/" + info[0].strip() + "/site-packages" +# sys.path.append(p) app_debug = False @@ -24,15 +23,12 @@ if mw.isAppleSystem(): def getPluginName(): - return 'gogs' + return 'gitea' def getPluginDir(): return mw.getPluginDir() + '/' + getPluginName() -sys.path.append(getPluginDir() + "/class") -import mysqlDb - def getServerDir(): return mw.getServerDir() + '/' + getPluginName() @@ -61,18 +57,28 @@ def getArgs(): return tmp +def checkArgs(data, ck=[]): + for i in range(len(ck)): + if not ck[i] in data: + return (False, mw.returnJson(False, '参数:(' + ck[i] + ')没有!')) + return (True, mw.returnJson(True, 'ok')) + + def getInitdConfTpl(): - path = getPluginDir() + "/init.d/gogs.tpl" + path = getPluginDir() + "/init.d/gitea.tpl" return path def getInitdConf(): - path = getServerDir() + "/init.d/gogs" + path = getServerDir() + "/init.d/gitea" return path def getConf(): path = getServerDir() + "/custom/conf/app.ini" + + if not os.path.exists(path): + return mw.returnJson(False, "请先安装初始化!
默认地址:http://" + mw.getLocalIp() + ":3000") return path @@ -140,13 +146,16 @@ def initDreplace(): mw.writeFile(file_bin, content) mw.execShell('chmod +x ' + file_bin) - conf_bin = getConf() - if not os.path.exists(conf_bin): - mw.execShell('mkdir -p ' + getServerDir() + '/custom/conf') - conf_tpl = getConfTpl() - content = mw.readFile(conf_tpl) - content = contentReplace(content) - mw.writeFile(conf_bin, content) + # systemd + systemDir = mw.systemdCfgDir() + systemService = systemDir + '/gitea.service' + systemServiceTpl = getPluginDir() + '/init.d/gitea.service.tpl' + if os.path.exists(systemDir) and not os.path.exists(systemService): + service_path = mw.getServerDir() + se_content = mw.readFile(systemServiceTpl) + se_content = se_content.replace('{$SERVER_PATH}', service_path) + mw.writeFile(systemService, se_content) + mw.execShell('systemctl daemon-reload') log_path = getServerDir() + '/log' if not os.path.exists(log_path): @@ -159,9 +168,14 @@ def getRootUrl(): content = mw.readFile(getConf()) rep = 'ROOT_URL\s*=\s*(.*)' tmp = re.search(rep, content) - if not tmp: - return '' - return tmp.groups()[0] + if tmp: + return tmp.groups()[0] + + rep = 'EXTERNAL_URL\s*=\s*(.*)' + tmp = re.search(rep, content) + if tmp: + return tmp.groups()[0] + return '' def getSshPort(): @@ -192,8 +206,11 @@ def getRootPath(): def getDbConfValue(): - content = mw.readFile(getConf()) + conf = getConf() + if not os.path.exists(conf): + return {} + content = mw.readFile(conf) rep_scope = "\[database\](.*?)\[" tmp = re.findall(rep_scope, content, re.S) @@ -207,18 +224,72 @@ def getDbConfValue(): return r -def pMysqlDb(): - conf = getDbConfValue() - +def pMysqlDb(conf): host = conf['HOST'].split(':') - conn = mysqlDb.mysqlDb() + # pymysql + db = mw.getMyORM() + # MySQLdb | + # db = mw.getMyORMDb() + + db.setPort(int(host[1])) + db.setUser(conf['USER']) + + if 'PASSWD' in conf: + db.setPwd(conf['PASSWD']) + else: + db.setPwd(conf['PASSWORD']) + + db.setDbName(conf['NAME']) + # db.setSocket(getSocketFile()) + db.setCharset("utf8") + return db + + +def pSqliteDb(conf): + # print(conf) + import db + psDb = db.Sql() + + # 默认 + gsdir = getServerDir() + '/data' + dbname = 'gitea' + if conf['PATH'][0] == '/': + # 绝对路径 + pass + else: + path = conf['PATH'].split('/') + gsdir = getServerDir() + '/' + path[0] + dbname = path[1].split('.')[0] - conn.setHost(host[0]) - conn.setUser(conf['USER']) - conn.setPwd(conf['PASSWD']) - conn.setPort(int(host[1])) - conn.setDb(conf['NAME']) - return conn + # print(gsdir, dbname) + psDb.dbPos(gsdir, dbname) + return psDb + + +def getGiteaDbType(conf): + + if 'DB_TYPE' in conf: + return conf['DB_TYPE'] + + if 'TYPE' in conf: + return conf['TYPE'] + + return 'NONE' + + +def pQuery(sql): + conf = getDbConfValue() + gtype = getGiteaDbType(conf) + if gtype == 'sqlite3': + db = pSqliteDb(conf) + data = db.query(sql, []).fetchall() + return data + elif gtype == 'mysql': + db = pMysqlDb(conf) + return db.query(sql) + + print("仅支持mysql|sqlite3配置") + exit(0) def isSqlError(mysqlMsg): @@ -244,93 +315,66 @@ def isSqlError(mysqlMsg): return mw.returnData(True, 'OK') -def start(): - - is_frist = True - conf_bin = getConf() - if os.path.exists(conf_bin): - is_frist = False - +def appOp(method): file = initDreplace() - if is_frist: - return "第一次启动Gogs,默认使用MySQL连接!
可以在配置文件中重新设置,再启动!" - - conn = pMysqlDb() - list_table = conn.query('show tables') - data = isSqlError(list_table) - if not data['status']: - return data['msg'] + if not mw.isAppleSystem(): + data = mw.execShell('systemctl ' + method + ' gogs') + if data[1] == '': + return 'ok' + return 'fail' - data = mw.execShell(__SR + file + ' start') + data = mw.execShell(__SR + file + ' ' + method) if data[1] == '': return 'ok' return data[0] +def start(): + return appOp('start') + + def stop(): - file = initDreplace() - data = mw.execShell(__SR + file + ' stop') - if data[1] == '': - return 'ok' - return data[1] + return appOp('stop') def restart(): - file = initDreplace() - data = mw.execShell(__SR + file + ' restart') - if data[1] == '': - return 'ok' - return data[1] + return appOp('restart') def reload(): - file = initDreplace() - data = mw.execShell(__SR + file + ' reload') - if data[1] == '': - return 'ok' - return data[1] + return appOp('reload') def initdStatus(): - if not app_debug: - os_name = mw.getOs() - if os_name == 'darwin': - return "Apple Computer does not support" - initd_bin = getInitDFile() - if os.path.exists(initd_bin): - return 'ok' - return 'fail' + if mw.isAppleSystem(): + return "Apple Computer does not support" + + shell_cmd = 'systemctl status gitea | grep loaded | grep "enabled;"' + data = mw.execShell(shell_cmd) + if data[0] == '': + return 'fail' + return 'ok' def initdInstall(): - import shutil - if not app_debug: - os_name = mw.getOs() - if os_name == 'darwin': - return "Apple Computer does not support" - - mem_bin = initDreplace() - initd_bin = getInitDFile() - shutil.copyfile(mem_bin, initd_bin) - mw.execShell('chmod +x ' + initd_bin) - mw.execShell('chkconfig --add ' + getPluginName()) + if mw.isAppleSystem(): + return "Apple Computer does not support" + + mw.execShell('systemctl enable gitea') return 'ok' def initdUinstall(): - if not app_debug: - os_name = mw.getOs() - if os_name == 'darwin': - return "Apple Computer does not support" - initd_bin = getInitDFile() - os.remove(initd_bin) - mw.execShell('chkconfig --del ' + getPluginName()) + if mw.isAppleSystem(): + return "Apple Computer does not support" + + mw.execShell('systemctl disable gitea') return 'ok' def runLog(): - log_path = getServerDir() + '/log/gogs.log' + log_path = getServerDir() + '/log/gitea.log' return log_path @@ -340,6 +384,10 @@ def postReceiveLog(): def getGogsConf(): + conf = getConf() + if not os.path.exists(conf): + return mw.returnJson(False, "请先安装初始化!
默认地址:http://" + mw.getLocalIp() + ":3000") + gets = [ {'name': 'DOMAIN', 'type': -1, 'ps': '服务器域名'}, {'name': 'ROOT_URL', 'type': -1, 'ps': '公开的完整URL路径'}, @@ -360,7 +408,7 @@ def getGogsConf(): {'name': 'SHOW_FOOTER_VERSION', 'type': 2, 'ps': 'Gogs版本信息'}, {'name': 'SHOW_FOOTER_TEMPLATE_LOAD_TIME', 'type': 2, 'ps': 'Gogs模板加载时间'}, ] - conf = mw.readFile(getConf()) + conf = mw.readFile(conf) result = [] for g in gets: @@ -370,7 +418,7 @@ def getGogsConf(): continue g['value'] = tmp.groups()[0] result.append(g) - return mw.getJson(result) + return mw.returnJson(True, 'OK', result) def submitGogsConf(): @@ -402,18 +450,27 @@ def submitGogsConf(): def userList(): + + conf = getConf() + if not os.path.exists(conf): + return mw.returnJson(False, "请先安装初始化!
默认地址:http://" + mw.getLocalIp() + ":3000") + + conf = getDbConfValue() + gtype = getGiteaDbType(conf) + if gtype != 'mysql': + return mw.returnJson(False, "仅支持mysql数据操作!") + import math args = getArgs() - page = 1 - page_size = 10 - search = '' - if 'page' in args: - page = int(args['page']) - - if 'page_size' in args: - page_size = int(args['page_size']) + data = checkArgs(args, ['page', 'page_size']) + if not data[0]: + return data[1] + page = int(args['page']) + page_size = int(args['page_size']) + tojs = args['tojs'] + search = '' if 'search' in args: search = args['search'] @@ -421,17 +478,14 @@ def userList(): data['root_url'] = getRootUrl() - pm = pMysqlDb() start = (page - 1) * page_size - list_count = pm.query('select count(id) as num from user') - count = list_count[0][0] + list_count = pQuery('select count(id) as num from user') - list_data = pm.query( + count = list_count[0]["num"] + list_data = pQuery( 'select id,name,email from user order by id desc limit ' + str(start) + ',' + str(page_size)) - - page_info = {'count': count, 'p': page, - 'row': page_size, 'tojs': 'gogsUserList'} - data['list'] = mw.getPage(page_info) + data['list'] = mw.getPage( + {'count': count, 'p': page, 'row': page_size, 'tojs': tojs}) data['page'] = page data['page_size'] = page_size data['page_count'] = int(math.ceil(count / page_size)) @@ -556,8 +610,8 @@ def projectScriptLoad(): cc_content = mw.readFile(commit_tpl) - sshUrl = 'http://127.0.0.1:' + getHttpPort() - cc_content = cc_content.replace('{$GITROOTURL}', sshUrl) + gitPath = getRootPath() + cc_content = cc_content.replace('{$GITROOTURL}', gitPath) cc_content = cc_content.replace('{$CODE_DIR}', codeDir) cc_content = cc_content.replace('{$USERNAME}', user) cc_content = cc_content.replace('{$PROJECT}', args['name']) @@ -570,11 +624,9 @@ def projectScriptLoad(): def projectScriptUnload(): args = getArgs() - if not 'user' in args: - return mw.returnJson(True, 'username missing') - - if not 'name' in args: - return mw.returnJson(True, 'project name missing') + data = checkArgs(args, ['user', 'name']) + if not data[0]: + return data[1] user = args['user'] name = args['name'] + '.git' @@ -591,11 +643,10 @@ def projectScriptUnload(): def projectScriptDebug(): args = getArgs() - if not 'user' in args: - return mw.returnJson(True, 'username missing') + data = checkArgs(args, ['user', 'name']) + if not data[0]: + return data[1] - if not 'name' in args: - return mw.returnJson(True, 'project name missing') user = args['user'] name = args['name'] + '.git' commit_log = getRootPath() + '/' + user + '/' + name + \ @@ -634,14 +685,8 @@ def getTotalStatistics(): st = status() data = {} if st.strip() == 'start': - pm = pMysqlDb() - list_count = pm.query('select count(id) as num from repository') - - if list_count.find("error") > -1: - data['status'] = False - data['count'] = 0 - return mw.returnJson(False, 'fail', data) - + list_count = pQuery('select count(id) as num from repository') + count = list_count[0]["num"] data['status'] = True data['count'] = count data['ver'] = mw.readFile(getServerDir() + '/version.pl').strip() diff --git a/plugins/gitea/info.json b/plugins/gitea/info.json new file mode 100755 index 000000000..2eac70638 --- /dev/null +++ b/plugins/gitea/info.json @@ -0,0 +1,16 @@ +{ + "ps": "Gitea 是一个开源社区驱动的轻量级代码托管解决方案。", + "name": "gitea", + "title": "Gitea", + "versions": ["1.17.2"], + "tip": "soft", + "checks": "server/gitea", + "path":"server/gitea", + "author": "gitea", + "date": "2022-10-03", + "home": "https://dl.gitea.io/", + "type": "Git服务器", + "shell": "install.sh", + "pid": "3", + "sort": 7 +} \ No newline at end of file diff --git a/plugins/gitea/init.d/gitea.service.tpl b/plugins/gitea/init.d/gitea.service.tpl new file mode 100644 index 000000000..62f37d069 --- /dev/null +++ b/plugins/gitea/init.d/gitea.service.tpl @@ -0,0 +1,12 @@ +[Unit] +Description=Gogs +After=network.target + +[Service] +Type=forking +ExecStart={$SERVER_PATH}/gitea/init.d/gitea start +ExecStop={$SERVER_PATH}/gitea/init.d/gitea stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/plugins/gitea/init.d/gitea.tpl b/plugins/gitea/init.d/gitea.tpl new file mode 100644 index 000000000..b00abdf6f --- /dev/null +++ b/plugins/gitea/init.d/gitea.tpl @@ -0,0 +1,110 @@ +#!/bin/sh +# +# /etc/rc.d/init.d/Gitea +# +# Runs the Gogs +# +# +# chkconfig: - 85 15 +# + +### BEGIN INIT INFO +# Provides: Gitea +# Required-Start: $remote_fs $syslog +# Required-Stop: $remote_fs $syslog +# Should-Start: mysql postgresql +# Should-Stop: mysql postgresql +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Start Gitea at boot time. +# Description: Control Gitea. +### END INIT INFO + +# Source function library. +if [ -f /etc/init.d/functions ];then + . /etc/init.d/functions +fi + +if [ -f /etc/rc.d/init.d/functions ];then + . /etc/rc.d/init.d/functions +fi + +# Default values +export HOME={$HOME_DIR} +export USER={$RUN_USER} +NAME=gitea +GOGS_HOME={$SERVER_PATH}/gitea +GOGS_PATH=${GOGS_HOME}/$NAME +GOGS_USER={$RUN_USER} +SERVICENAME="gitea" +LOCKFILE=/tmp/gitea.lock +LOGPATH=${GOGS_HOME}/log +LOGFILE=${LOGPATH}/gitea.log +RETVAL=0 + + +[ -r /etc/sysconfig/$NAME ] && . /etc/sysconfig/$NAME +DAEMON_OPTS="--check $NAME" +[ ! -z "$GOGS_USER" ] && DAEMON_OPTS="$DAEMON_OPTS --user=${GOGS_USER}" + + +status(){ + isStart=`ps -ef|grep 'gitea web' |grep -v grep|awk '{print $2}'` + if [ "$isStart" == '' ];then + echo -e "${SERVICENAME} not running" + else + echo -e "${SERVICENAME}(pid $(echo $isStart)) already running" + fi +} + +start() { + isStart=`ps -ef|grep 'gitea web' |grep -v grep|awk '{print $2}'` + if [ "$isStart" != '' ];then + echo "${SERVICENAME}(pid $(echo $isStart)) already running" + return $RETVAL + fi + + cd ${GOGS_HOME} + echo -e "Starting ${SERVICENAME}: \c" + ${GOGS_PATH} web > ${LOGFILE} 2>&1 & + RETVAL=$? + [ $RETVAL = 0 ] && touch ${LOCKFILE} && echo -e "\033[32mdone\033[0m" + return $RETVAL +} + +stop() { + + pids=`ps -ef|grep 'gitea web' |grep -v grep|awk '{print $2}'` + arr=($pids) + echo -e "Stopping gitea... \c" + for p in ${arr[@]} + do + kill -9 $p + done + echo -e "\033[32mdone\033[0m" +} + +case "$1" in + start) + start + ;; + stop) + stop + ;; + status) + status + ;; + restart) + stop + start + ;; + reload) + stop + start + ;; + *) + echo "Usage: ${NAME} {start|stop|status|restart}" + exit 1 + ;; +esac +exit $RETVAL diff --git a/plugins/gitea/install.sh b/plugins/gitea/install.sh new file mode 100755 index 000000000..eccb221af --- /dev/null +++ b/plugins/gitea/install.sh @@ -0,0 +1,98 @@ +#!/bin/bash +PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin +export PATH + +curPath=`pwd` +rootPath=$(dirname "$curPath") +rootPath=$(dirname "$rootPath") +serverPath=$(dirname "$rootPath") + + +install_tmp=${rootPath}/tmp/mw_install.pl +if [ -f ${rootPath}/bin/activate ];then + source ${rootPath}/bin/activate +fi + + +URL_DOWNLOAD=https://dl.gitea.io/ + +getOs(){ + os=`uname` + if [ "Darwin" == "$os" ];then + echo 'darwin' + else + echo 'linux' + fi + return 0 +} + +getBit(){ + echo `getconf LONG_BIT` +} + + +Install_App() +{ + mkdir -p $serverPath/source/gitea + + echo '正在安装脚本文件...' > $install_tmp + version=$1 + os=`getOs` + + git config --global push.default simple + + if [ "darwin" == "$os" ];then + file=gitea-${version}-darwin-10.12-amd64 + else + file=gitea-${version}-linux-amd64 + fi + + file_xz="${file}.xz" + echo "wget -O $serverPath/source/gitea/$file_xz ${URL_DOWNLOAD}/gitea/${version}/${file_xz}" + if [ ! -f $serverPath/source/gitea/$file_xz ];then + wget -O $serverPath/source/gitea/$file_xz ${URL_DOWNLOAD}/gitea/${version}/${file_xz} + fi + + cd $serverPath/source/gitea && xz -k -d $file_xz + if [ -f $file ];then + mkdir -p $serverPath/gitea + mv $serverPath/source/gitea/$file $serverPath/gitea/gitea + chmod +x $serverPath/gitea/gitea + fi + + if [ -d $serverPath/gitea ];then + echo $version > $serverPath/gitea/version.pl + + cd ${rootPath} && python3 plugins/gitea/index.py start + cd ${rootPath} && python3 plugins/gitea/index.py initd_install + fi + + echo 'install success' > $install_tmp +} + +Uninstall_App() +{ + + if [ -f /usr/lib/systemd/system/gitea.service ];then + systemctl stop gitea + systemctl disable gitea + rm -rf /usr/lib/systemd/system/gitea.service + systemctl daemon-reload + fi + + if [ -f $serverPath/gitea/initd/gitea ];then + $serverPath/gitea/initd/gitea stop + fi + + rm -rf $serverPath/gitea + echo 'uninstall success' > $install_tmp +} + + +action=$1 +version=$2 +if [ "${1}" == 'install' ];then + Install_App $version +else + Uninstall_App $version +fi diff --git a/plugins/gitea/js/gitea.js b/plugins/gitea/js/gitea.js new file mode 100755 index 000000000..8f0a6071a --- /dev/null +++ b/plugins/gitea/js/gitea.js @@ -0,0 +1,353 @@ + +function str2Obj(str){ + var data = {}; + kv = str.split('&'); + for(i in kv){ + v = kv[i].split('='); + data[v[0]] = v[1]; + } + return data; +} + +function gogsPost(method,args,callback, title){ + + var _args = null; + if (typeof(args) == 'string'){ + _args = JSON.stringify(str2Obj(args)); + } else { + _args = JSON.stringify(args); + } + + var _title = '正在获取...'; + if (typeof(title) != 'undefined'){ + _title = title; + } + + var loadT = layer.msg(_title, { icon: 16, time: 0, shade: 0.3 }); + $.post('/plugins/run', {name:'gitea', func:method, args:_args}, function(data) { + layer.close(loadT); + if (!data.status){ + layer.msg(data.msg,{icon:0,time:2000,shade: [0.3, '#000']}); + return; + } + + if(typeof(callback) == 'function'){ + callback(data); + } + },'json'); +} + +function gogsSetConfig(){ + gogsPost('get_gogs_conf', '', function(data){ + var rrdata = $.parseJSON(data.data); + if (!rrdata.status){ + layer.msg(rrdata.msg,{icon:0,time:2000,shade: [0.3, '#000']}); + return; + } + var rdata = rrdata.data; + var mlist = ''; + for (var i = 0; i < rdata.length; i++) { + var w = '140'; + if (rdata[i].name == 'error_reporting') w = '250'; + var ibody = ''; + switch (rdata[i].type) { + case 0: + var selected_1 = (rdata[i].value == 1) ? 'selected' : ''; + var selected_0 = (rdata[i].value == 0) ? 'selected' : ''; + ibody = ''; + break; + case 1: + var selected_1 = (rdata[i].value == 'On') ? 'selected' : ''; + var selected_0 = (rdata[i].value == 'Off') ? 'selected' : ''; + ibody = '' + break; + case 2: + var selected_1 = (rdata[i].value == 'true') ? 'selected' : ''; + var selected_0 = (rdata[i].value == 'false') ? 'selected' : ''; + ibody = '' + break; + } + mlist += '

' + rdata[i].name + '' + ibody + ', ' + rdata[i].ps + '

' + } + var html = '
\ + ' + mlist + '\ +
\ + \ +
\ +
'; + $(".soft-man-con").html(html); + }); +} + + +//提交PHP配置 +function submitGogsConf() { + var data = { + DOMAIN: $("input[name='DOMAIN']").val(), + ROOT_URL: $("input[name='ROOT_URL']").val(), + HTTP_ADDR: $("select[name='HTTP_ADDR']").val(), + HTTP_PORT: $("input[name='HTTP_PORT']").val(), + START_SSH_SERVER: $("select[name='START_SSH_SERVER']").val() || 'false', + SSH_PORT: $("input[name='SSH_PORT']").val(), + REQUIRE_SIGNIN_VIEW: $("select[name='REQUIRE_SIGNIN_VIEW']").val() || 'false', + ENABLE_CAPTCHA: $("select[name='ENABLE_CAPTCHA']").val() || 'true', + DISABLE_REGISTRATION: $("select[name='DISABLE_REGISTRATION']").val() || 'false', + ENABLE_NOTIFY_MAIL: $("select[name='ENABLE_NOTIFY_MAIL']").val() || 'false', + FORCE_PRIVATE: $("select[name='FORCE_PRIVATE']").val() || 'false', + SHOW_FOOTER_BRANDING: $("select[name='SHOW_FOOTER_BRANDING']").val() || 'false', + SHOW_FOOTER_VERSION: $("select[name='SHOW_FOOTER_VERSION']").val() || 'false', + SHOW_FOOTER_TEMPLATE_LOAD_TIME: $("select[name='SHOW_FOOTER_TEMPLATE_LOAD_TIME']").val() || 'false', + }; + + gogsPost('submit_gogs_conf', data, function(ret_data){ + var rdata = $.parseJSON(ret_data.data); + layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 }); + gogsSetConfig(); + }); +} + +function gogsEdit(){ + + gogsPost('gogs_edit',{} , function(data){ + // console.log(data); + var rdata = $.parseJSON(data.data); + var edit = '

通用的手动编辑:

'; + edit +='
\ + \ + \ +
'; + $(".soft-man-con").html(edit); + }); + +} + +function giteaUserList(page, search) { + + var _data = {}; + if (typeof(page) =='undefined'){ + var page = 1; + } + + _data['page'] = page; + _data['page_size'] = 10; + if(typeof(search) != 'undefined'){ + _data['search'] = search; + } + _data['tojs'] = 'giteaUserList'; + + gogsPost('user_list', _data, function(data){ + + var rdata = $.parseJSON(data.data); + if (!rdata.status){ + layer.msg(rdata.msg,{icon:0,time:2000,shade: [0.3, '#000']}); + return; + } + content = '
'; + content += '
'; + + content += '
'; + content += ''; + content += ''; + content += ''; + content += ''; + content += ''; + content += ''; + + content += ''; + + ulist = rdata['data']['data']; + for (i in ulist){ + email = ulist[i]["email"] == '' ? '无' : ulist[i]["email"]; + content += ''+ + ''+ + ''+ + ''+ + ''; + } + + content += ''; + content += '
序号用户或组织邮件地址操作(WEB管理)
'+ulist[i]["id"]+''+ulist[i]["name"]+''+email+'项目管理
'; + + var page = ''; + + content += page; + + $(".soft-man-con").html(content); + }); +} + +function userProjectList(user, search){ + var req = {}; + if (!isNaN(user)){ + req['page'] = user; + req['name'] = user = getCookie('gogsUserSelected'); + } else { + req['page'] = 1; + req['name'] = user; + setCookie('gogsUserSelected', user); + } + + req['page_size'] = 5; + req['search'] = ''; + if(typeof(search) != 'undefined'){ + req['search'] = search; + } + + $('.layui-layer-close1').click(); + gogsPost('user_project_list', req, function(data){ + var rdata = []; + try { + rdata = $.parseJSON(data.data); + } catch(e){} + + if (!rdata['status']){ + layer.msg(rdata['msg'], { icon: 2 }); + return; + } + + var list = ''; + // console.log(rdata); + var project_list = rdata['data']['data']; + for (i in project_list) { + var name = project_list[i]['name']; + list += ''+name+'\ + \ + 源码 | \ + 脚本\ + \ + '; + } + + var page = ''; + + var loadOpen = layer.open({ + type: 1, + title: '用户('+user+')项目列表', + area: '500px', + content:"
\ +
\ +
\ + \ + \ + " + list + "\ +
项目操作
" + + page + + "
" + }); + }); +} + + +function projectScript(user, name,has_hook){ + // console.log(user,name,has_hook); + var html = ''; + if (has_hook){ + html += ''; + html += ''; + html += ''; + html += ''; + } else { + html += ''; + } + + var loadOpen = layer.open({ + type: 1, + title: '['+user+']['+name+']脚本设置', + area: '240px', + content:'
'+html+'
' + }); +} + +function projectScriptEdit(user,name){ + gogsPost('project_script_edit', {'user':user,'name':name}, function(data){ + var rdata = $.parseJSON(data.data); + if (rdata['status']){ + onlineEditFile(0, rdata['data']['path']); + } else { + layer.msg(rdata.msg,{icon:1,time:2000,shade: [0.3, '#000']}); + } + }); +} + +function projectScriptLoad(user,name){ + gogsPost('project_script_load', {'user':user,'name':name}, function(data){ + if (data.data != 'ok'){ + layer.msg(data.data,{icon:0,time:2000,shade: [0.3, '#000']}); + return; + } + + layer.msg('加载成功!',{icon:1,time:2000,shade: [0.3, '#000']}); + setTimeout(function(){ + userProjectList(1); + }, 2000); + }); +} + +function projectScriptUnload(user,name){ + gogsPost('project_script_unload', {'user':user,'name':name}, function(data){ + if (data.data != 'ok'){ + layer.msg(data.data,{icon:0,time:2000,shade: [0.3, '#000']}); + return; + } + + layer.msg('卸载成功!',{icon:1,time:2000,shade: [0.3, '#000']}); + setTimeout(function(){ + userProjectList(1); + }, 2000); + }); +} + +function projectScriptDebug(user,name){ + gogsPost('project_script_debug', {'user':user,'name':name}, function(data){ + var rdata = $.parseJSON(data.data); + if (rdata['status']){ + onlineEditFile(0, rdata['path']); + } else { + layer.msg(rdata.msg,{icon:1,time:2000,shade: [0.3, '#000']}); + } + }); +} + +function getRsaPublic(){ + gogsPost('get_rsa_public', {}, function(data){ + var rdata = $.parseJSON(data.data); + var con = '
\ +
\ + \ +
\ +
    \ +
    ' + layer.open({ + type: 1, + area: "600px", + title: '本机公钥', + closeBtn: 2, + shift: 5, + shadeClose: false, + content:con + }); + }); +} + +function giteaRead(){ + + var readme = ''; + + $('.soft-man-con').html(readme); +} \ No newline at end of file diff --git a/plugins/gogs/index.py b/plugins/gogs/index.py index 4193d04c3..822a48198 100755 --- a/plugins/gogs/index.py +++ b/plugins/gogs/index.py @@ -462,6 +462,11 @@ def userList(): if not os.path.exists(conf): return mw.returnJson(False, "请先安装初始化!
    默认地址:http://" + mw.getLocalIp() + ":3000") + conf = getDbConfValue() + gtype = getGiteaDbType(conf) + if gtype != 'mysql': + return mw.returnJson(False, "仅支持mysql数据操作!") + import math args = getArgs() diff --git a/plugins/gogs/install.sh b/plugins/gogs/install.sh index 73c8eeb8d..47a264866 100755 --- a/plugins/gogs/install.sh +++ b/plugins/gogs/install.sh @@ -29,7 +29,6 @@ getBit(){ Install_gogs() { - pip3 install mysqlclient mkdir -p $serverPath/source/gogs diff --git a/route/static/app/public.js b/route/static/app/public.js index c2a1f072e..3ff15253e 100755 --- a/route/static/app/public.js +++ b/route/static/app/public.js @@ -1598,6 +1598,18 @@ function remove_ssh_menu() { } /*** 其中功能,针对插件通过库使用 start ***/ + +//字符串转数组对象 +function toArrayObject(str){ + var data = {}; + kv = str.split('&'); + for(i in kv){ + v = kv[i].split('='); + data[v[0]] = v[1]; + } + return data; +} + function pluginService(_name, version){ var data = {name:_name, func:'status'} if ( typeof(version) != 'undefined' ){ diff --git a/scripts/install/debian.sh b/scripts/install/debian.sh index 33144e7bd..368e7feee 100644 --- a/scripts/install/debian.sh +++ b/scripts/install/debian.sh @@ -30,7 +30,7 @@ apt install -y expect apt install -y locate locale-gen en_US.UTF-8 localedef -v -c -i en_US -f UTF-8 en_US.UTF-8 -# sudo localedef -i en_US -f UTF-8 en_US.UTF-8 +sudo localedef -i en_US -f UTF-8 en_US.UTF-8 if [ ! -d /root/.acme.sh ];then curl https://get.acme.sh | sh