mirror of
https://github.com/minetest/contentdb.git
synced 2025-01-10 15:07:35 +01:00
Add VCS import from Github
This commit is contained in:
parent
5424f0aa34
commit
92717f31dd
@ -322,6 +322,7 @@ class PackageRelease(db.Model):
|
|||||||
releaseDate = db.Column(db.DateTime, nullable=False)
|
releaseDate = db.Column(db.DateTime, nullable=False)
|
||||||
url = db.Column(db.String(100), nullable=False)
|
url = db.Column(db.String(100), nullable=False)
|
||||||
approved = db.Column(db.Boolean, nullable=False, default=False)
|
approved = db.Column(db.Boolean, nullable=False, default=False)
|
||||||
|
task_id = db.Column(db.String(32), nullable=True)
|
||||||
|
|
||||||
|
|
||||||
def getEditURL(self):
|
def getEditURL(self):
|
||||||
|
@ -1,12 +1,18 @@
|
|||||||
import flask
|
import flask, json
|
||||||
from flask.ext.sqlalchemy import SQLAlchemy
|
from flask.ext.sqlalchemy import SQLAlchemy
|
||||||
import urllib.request
|
import urllib.request
|
||||||
from urllib.parse import urlparse
|
from urllib.parse import urlparse, quote_plus
|
||||||
|
|
||||||
from app import app
|
from app import app
|
||||||
from app.models import *
|
from app.models import *
|
||||||
from app.tasks import celery
|
from app.tasks import celery
|
||||||
|
|
||||||
|
class TaskError(Exception):
|
||||||
|
def __init__(self, value):
|
||||||
|
self.value = value
|
||||||
|
def __str__(self):
|
||||||
|
return repr(self.value)
|
||||||
|
|
||||||
|
|
||||||
class GithubURLMaker:
|
class GithubURLMaker:
|
||||||
def __init__(self, url):
|
def __init__(self, url):
|
||||||
# Rewrite path
|
# Rewrite path
|
||||||
@ -18,6 +24,8 @@ class GithubURLMaker:
|
|||||||
user = m.group(1)
|
user = m.group(1)
|
||||||
repo = m.group(2)
|
repo = m.group(2)
|
||||||
self.baseUrl = "https://raw.githubusercontent.com/" + user + "/" + repo.replace(".git", "") + "/master"
|
self.baseUrl = "https://raw.githubusercontent.com/" + user + "/" + repo.replace(".git", "") + "/master"
|
||||||
|
self.user = user
|
||||||
|
self.repo = repo
|
||||||
|
|
||||||
def isValid(self):
|
def isValid(self):
|
||||||
return self.baseUrl is not None
|
return self.baseUrl is not None
|
||||||
@ -31,6 +39,13 @@ class GithubURLMaker:
|
|||||||
def getScreenshotURL(self):
|
def getScreenshotURL(self):
|
||||||
return self.baseUrl + "/screenshot.png"
|
return self.baseUrl + "/screenshot.png"
|
||||||
|
|
||||||
|
def getCommitsURL(self, branch):
|
||||||
|
return "https://api.github.com/repos/" + self.user + "/" + self.repo + "/commits?sha" + urllib.parse.quote_plus(branch)
|
||||||
|
|
||||||
|
def getCommitDownload(self, commit):
|
||||||
|
return "https://github.com/" + self.user + "/" + self.repo + "/archive/" + commit + ".zip"
|
||||||
|
|
||||||
|
|
||||||
def parseConf(string):
|
def parseConf(string):
|
||||||
retval = {}
|
retval = {}
|
||||||
for line in string.split("\n"):
|
for line in string.split("\n"):
|
||||||
@ -49,10 +64,11 @@ def getMeta(urlstr):
|
|||||||
urlmaker = None
|
urlmaker = None
|
||||||
if url.netloc == "github.com":
|
if url.netloc == "github.com":
|
||||||
urlmaker = GithubURLMaker(url)
|
urlmaker = GithubURLMaker(url)
|
||||||
|
else:
|
||||||
|
raise TaskError("Unsupported repo")
|
||||||
|
|
||||||
if not urlmaker.isValid():
|
if not urlmaker.isValid():
|
||||||
print("Error! Url maker not valid")
|
raise TaskError("Error! Url maker not valid")
|
||||||
return
|
|
||||||
|
|
||||||
print(urlmaker.getModConfURL())
|
print(urlmaker.getModConfURL())
|
||||||
|
|
||||||
@ -79,3 +95,35 @@ def getMeta(urlstr):
|
|||||||
print("description.txt does not exist!")
|
print("description.txt does not exist!")
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
@celery.task()
|
||||||
|
def makeVCSRelease(id, branch):
|
||||||
|
release = PackageRelease.query.get(id)
|
||||||
|
if release is None:
|
||||||
|
raise TaskError("No such release!")
|
||||||
|
|
||||||
|
if release.package is None:
|
||||||
|
raise TaskError("No package attached to release")
|
||||||
|
|
||||||
|
url = urlparse(release.package.repo)
|
||||||
|
|
||||||
|
urlmaker = None
|
||||||
|
if url.netloc == "github.com":
|
||||||
|
urlmaker = GithubURLMaker(url)
|
||||||
|
else:
|
||||||
|
raise TaskError("Unsupported repo")
|
||||||
|
|
||||||
|
if not urlmaker.isValid():
|
||||||
|
raise TaskError("Invalid github repo URL")
|
||||||
|
|
||||||
|
contents = urllib.request.urlopen(urlmaker.getCommitsURL(branch)).read().decode("utf-8")
|
||||||
|
commits = json.loads(contents)
|
||||||
|
|
||||||
|
if len(commits) == 0:
|
||||||
|
raise TaskError("No commits found")
|
||||||
|
|
||||||
|
release.url = urlmaker.getCommitDownload(commits[0]["sha"])
|
||||||
|
release.task_id = None
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
return release.url
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>{% block title %}title{% endblock %} - {{ config.USER_APP_NAME }}</title>
|
<title>{% block title %}title{% endblock %} - {{ config.USER_APP_NAME }}</title>
|
||||||
<link rel="stylesheet" type="text/css" href="/static/main.css">
|
<link rel="stylesheet" type="text/css" href="/static/main.css">
|
||||||
|
{% block headextra %}{% endblock %}
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
@ -78,25 +78,29 @@
|
|||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
{% for rel in releases %}
|
{% for rel in releases %}
|
||||||
<li>
|
{% if rel.approved or package.checkPerm(current_user, "MAKE_RELEASE") or package.checkPerm(current_user, "APPROVE_RELEASE") %}
|
||||||
{% if not rel.approved %}<i>{% endif %}
|
<li>
|
||||||
|
{% if not rel.approved %}<i>{% endif %}
|
||||||
|
|
||||||
<a href="{{ rel.url }}">{{ rel.title }}</a>,
|
<a href="{{ rel.url }}">{{ rel.title }}</a>,
|
||||||
created {{ rel.releaseDate }}.
|
created {{ rel.releaseDate }}.
|
||||||
{% if not rel.approved %}
|
{% if rel.task_id %}
|
||||||
Waiting for approval.
|
<a href="{{ url_for('check_task', id=rel.task_id, r=package.getDetailsURL()) }}">Importing</a>
|
||||||
{% endif %}
|
{% elif not rel.approved %}
|
||||||
|
Waiting for approval.
|
||||||
{% if package.checkPerm(current_user, "MAKE_RELEASE") or package.checkPerm(current_user, "APPROVE_RELEASE") %}
|
|
||||||
<a href="{{ rel.getEditURL() }}">Edit
|
|
||||||
{% if not rel.approved and package.checkPerm(current_user, "APPROVE_RELEASE") %}
|
|
||||||
/ Approve
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</a>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if not rel.approved %}</i>{% endif %}
|
{% if not rel.task_id and (package.checkPerm(current_user, "MAKE_RELEASE") or package.checkPerm(current_user, "APPROVE_RELEASE")) %}
|
||||||
</li>
|
<a href="{{ rel.getEditURL() }}">Edit
|
||||||
|
{% if not rel.approved and package.checkPerm(current_user, "APPROVE_RELEASE") %}
|
||||||
|
/ Approve
|
||||||
|
{% endif %}
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if not rel.approved %}</i>{% endif %}
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
{% else %}
|
{% else %}
|
||||||
<li>No releases available.</li>
|
<li>No releases available.</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
21
app/templates/tasks/view.html
Normal file
21
app/templates/tasks/view.html
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block title %}
|
||||||
|
Working
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block headextra %}
|
||||||
|
{% if not "error" in info %}
|
||||||
|
<meta http-equiv="refresh" content="1;URL=">
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
{% if "error" in info %}
|
||||||
|
<h1>Task Failed</h1>
|
||||||
|
|
||||||
|
<p>{{ info. error }}</p>
|
||||||
|
{% else %}
|
||||||
|
<h1>Working…</h1>
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
@ -30,4 +30,4 @@ def home_page():
|
|||||||
packages = Package.query.filter_by(approved=True).all()
|
packages = Package.query.filter_by(approved=True).all()
|
||||||
return render_template("index.html", packages=packages)
|
return render_template("index.html", packages=packages)
|
||||||
|
|
||||||
from . import users, githublogin, packages, sass, api
|
from . import users, githublogin, packages, sass, tasks
|
||||||
|
@ -1,35 +0,0 @@
|
|||||||
from flask import *
|
|
||||||
from flask_user import *
|
|
||||||
from flask.ext import menu
|
|
||||||
from app import app
|
|
||||||
from app.models import *
|
|
||||||
from app.tasks import celery
|
|
||||||
from app.tasks.importtasks import getMeta
|
|
||||||
# from celery.result import AsyncResult
|
|
||||||
|
|
||||||
from .utils import *
|
|
||||||
|
|
||||||
@app.route("/tasks/getmeta/new/")
|
|
||||||
def new_getmeta_page():
|
|
||||||
aresult = getMeta.delay(request.args.get("url"))
|
|
||||||
return jsonify({
|
|
||||||
"poll_url": url_for("check_task", id=aresult.id),
|
|
||||||
})
|
|
||||||
|
|
||||||
@app.route("/tasks/<id>/")
|
|
||||||
def check_task(id):
|
|
||||||
result = celery.AsyncResult(id)
|
|
||||||
status = result.status
|
|
||||||
traceback = result.traceback
|
|
||||||
result = result.result
|
|
||||||
if isinstance(result, Exception):
|
|
||||||
return jsonify({
|
|
||||||
'status': status,
|
|
||||||
'error': str(result),
|
|
||||||
# 'traceback': traceback,
|
|
||||||
})
|
|
||||||
else:
|
|
||||||
return jsonify({
|
|
||||||
'status': status,
|
|
||||||
'result': result,
|
|
||||||
})
|
|
@ -3,6 +3,7 @@ from flask_user import *
|
|||||||
from flask.ext import menu
|
from flask.ext import menu
|
||||||
from app import app
|
from app import app
|
||||||
from app.models import *
|
from app.models import *
|
||||||
|
from app.tasks.importtasks import makeVCSRelease
|
||||||
|
|
||||||
from .utils import *
|
from .utils import *
|
||||||
|
|
||||||
@ -369,16 +370,17 @@ def create_release_page(type, author, name):
|
|||||||
# Initial form class from post data and default data
|
# Initial form class from post data and default data
|
||||||
form = CreatePackageReleaseForm()
|
form = CreatePackageReleaseForm()
|
||||||
if request.method == "POST" and form.validate():
|
if request.method == "POST" and form.validate():
|
||||||
for key, value in request.files.items() :
|
|
||||||
print (key, value)
|
|
||||||
if form["uploadOpt"].data == "vcs":
|
if form["uploadOpt"].data == "vcs":
|
||||||
rel = PackageRelease()
|
rel = PackageRelease()
|
||||||
rel.package = package
|
rel.package = package
|
||||||
rel.title = form["title"].data
|
rel.title = form["title"].data
|
||||||
rel.url = form["vcsLabel"].data
|
rel.url = ""
|
||||||
# TODO: get URL to commit from branch name
|
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
return redirect(package.getDetailsURL())
|
|
||||||
|
rel.task_id = makeVCSRelease.delay(rel.id, form["vcsLabel"].data).id
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
return redirect(url_for("check_task", id=rel.task_id, r=package.getDetailsURL()))
|
||||||
else:
|
else:
|
||||||
uploadedPath = doFileUpload(form.fileUpload.data, ["zip"], "a zip file")
|
uploadedPath = doFileUpload(form.fileUpload.data, ["zip"], "a zip file")
|
||||||
if uploadedPath is not None:
|
if uploadedPath is not None:
|
||||||
@ -412,6 +414,9 @@ def edit_release_page(type, author, name, id):
|
|||||||
if not (canEdit or canApprove):
|
if not (canEdit or canApprove):
|
||||||
return redirect(package.getDetailsURL())
|
return redirect(package.getDetailsURL())
|
||||||
|
|
||||||
|
if release.task_id is not None:
|
||||||
|
return redirect(url_for("check_task", id=release.task_id, r=release.getEditURL()))
|
||||||
|
|
||||||
# Initial form class from post data and default data
|
# Initial form class from post data and default data
|
||||||
form = EditPackageReleaseForm(formdata=request.form, obj=release)
|
form = EditPackageReleaseForm(formdata=request.form, obj=release)
|
||||||
if request.method == "POST" and form.validate():
|
if request.method == "POST" and form.validate():
|
||||||
|
50
app/views/tasks.py
Normal file
50
app/views/tasks.py
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
from flask import *
|
||||||
|
from flask_user import *
|
||||||
|
from flask.ext import menu
|
||||||
|
from app import app
|
||||||
|
from app.models import *
|
||||||
|
from app.tasks import celery
|
||||||
|
from app.tasks.importtasks import getMeta
|
||||||
|
from .utils import shouldReturnJson
|
||||||
|
# from celery.result import AsyncResult
|
||||||
|
|
||||||
|
from .utils import *
|
||||||
|
|
||||||
|
@app.route("/tasks/getmeta/new/")
|
||||||
|
def new_getmeta_page():
|
||||||
|
aresult = getMeta.delay(request.args.get("url"))
|
||||||
|
return jsonify({
|
||||||
|
"poll_url": url_for("check_task", id=aresult.id),
|
||||||
|
})
|
||||||
|
|
||||||
|
@app.route("/tasks/<id>/")
|
||||||
|
def check_task(id):
|
||||||
|
result = celery.AsyncResult(id)
|
||||||
|
status = result.status
|
||||||
|
traceback = result.traceback
|
||||||
|
result = result.result
|
||||||
|
|
||||||
|
info = None
|
||||||
|
if isinstance(result, Exception):
|
||||||
|
info = {
|
||||||
|
'status': status,
|
||||||
|
'error': str(result),
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
info = {
|
||||||
|
'status': status,
|
||||||
|
'result': result,
|
||||||
|
}
|
||||||
|
|
||||||
|
if shouldReturnJson():
|
||||||
|
return jsonify(info)
|
||||||
|
else:
|
||||||
|
r = request.args.get("r")
|
||||||
|
if r is None:
|
||||||
|
abort(422)
|
||||||
|
|
||||||
|
if status == "SUCCESS":
|
||||||
|
flash("Task complete!", "success")
|
||||||
|
return redirect(r)
|
||||||
|
else:
|
||||||
|
return render_template("tasks/view.html", info=info)
|
Loading…
Reference in New Issue
Block a user