By using this site, you agree to have cookies stored on your device, strictly for functional purposes, such as storing your session and preferences.

Dismiss

 celery_tasks.py

View raw Download
text/x-script.python • 6.6 kiB
Python script, ASCII text executable
        
            
1
import common
2
import time
3
import os
4
import config
5
import email_send
6
import shutil
7
from celery import shared_task
8
from app import db, _
9
from smtplib import SMTP
10
from celery.utils.log import get_task_logger
11
from sqlalchemy.orm import make_transient
12
from datetime import datetime
13
14
15
@shared_task(ignore_result=False)
16
def send_notification(user_notification_id):
17
from models import UserNotification
18
user_notification = db.session.get(UserNotification, user_notification_id)
19
user = user_notification.user
20
notification = user_notification.notification
21
22
if user.email:
23
with (SMTP(config.MAIL_SERVER) as mail):
24
if notification.data.get("type") == "welcome":
25
message = email_send.make_multipart_message(
26
"Welcome, {username}".format(username=user.username),
27
config.NOTIFICATION_EMAIL,
28
user.email,
29
"welcome",
30
username=user.username)
31
32
mail.sendmail(config.NOTIFICATION_EMAIL, user.email, message)
33
34
return 0 # notification sent successfully
35
36
37
@shared_task(ignore_result=False)
38
def merge_heads(head_route, head_branch, base_route, base_branch, simulate=True):
39
from models import Repo, Commit
40
server_repo_location = os.path.join(config.REPOS_PATH, base_route.lstrip("/"))
41
if not os.path.isdir(server_repo_location):
42
raise FileNotFoundError(f"Repo {server_repo_location} not found, cannot merge.")
43
44
if base_route == head_route:
45
common.git_command(server_repo_location, b"", "checkout", f"{base_branch}")
46
if simulate:
47
out, err, merge_exit = common.git_command(server_repo_location, b"", "merge", "--no-commit", "--no-ff", f"heads/{head_branch}",
48
return_err=True, return_exit=True)
49
50
# Undo the merge.
51
common.git_command(server_repo_location, b"", "merge", "--abort")
52
else:
53
out, err, merge_exit = common.git_command(server_repo_location, b"", "merge", f"heads/{head_branch}",
54
return_err=True, return_exit=True)
55
56
return "merge_simulator" if simulate else "merge", out, err, head_route, head_branch, base_route, base_branch, merge_exit
57
58
# Otherwise, we need to fetch the head repo.
59
remote_url = os.path.join(config.BASE_DOMAIN, "git", base_route.lstrip("/"))
60
61
out, err = b"", b""
62
part_out, part_err = common.git_command(server_repo_location, b"", "remote", "add", "NEW", remote_url, return_err=True)
63
out += part_out
64
err += part_err
65
part_out, part_err = common.git_command(server_repo_location, b"", "remote", "update", return_err=True)
66
out += part_out
67
err += part_err
68
part_out, part_err = common.git_command(server_repo_location, b"", "checkout", f"{base_branch}", return_err=True)
69
out += part_out
70
err += part_err
71
new_commits = common.git_command(server_repo_location, b"", "log", "--oneline", f"{base_branch}..{head_branch}")
72
73
if simulate:
74
part_out, part_err, merge_exit = common.git_command(server_repo_location, b"", "merge", "--allow-unrelated-histories",
75
"--no-commit", "--no-ff", f"NEW/{head_branch}", return_err=True, return_exit=True)
76
else:
77
part_out, part_err, merge_exit = common.git_command(server_repo_location, b"", "merge", "--allow-unrelated-histories",
78
f"NEW/{head_branch}", return_err=True, return_exit=True)
79
80
diff, diff_exit = common.git_command(server_repo_location, b"", "diff", "--check", return_exit=True)
81
82
out += part_out
83
err += part_err
84
part_out, part_err = common.git_command(server_repo_location, b"", "remote", "rm", "NEW", return_err=True)
85
out += part_out
86
err += part_err
87
if simulate:
88
# Undo the merge.
89
common.git_command(server_repo_location, b"", "merge", "--abort")
90
else:
91
# Copy the commits rows from the head repo to the base repo
92
for commit in new_commits:
93
commit_data = Commit.query.filter_by(repo_name=head_route, sha=commit.split())
94
95
db.session.expunge(commit_data)
96
make_transient(commit_data)
97
98
commit_data.repo_name = base_route
99
commit_data.identifier = f"{base_route}/{commit_data.sha}"
100
commit_data.receive_date = datetime.now()
101
db.session.add(commit_data)
102
103
return "merge_simulator" if simulate else "merge", out, err, head_route, head_branch, base_route, base_branch, merge_exit
104
105
106
@shared_task(ignore_result=False)
107
def copy_site(route):
108
from models import Repo
109
repo = db.session.get(Repo, route)
110
server_repo_location = os.path.join(config.REPOS_PATH, route.lstrip("/"))
111
subdomain = repo.owner.username
112
subpath = repo.name if repo.has_site != 2 else ""
113
site_location = os.path.join(config.SITE_PATH, subdomain, subpath)
114
# Get the branch to be used for the site; if it somehow doesn't exist, use the default branch.
115
branch = repo.site_branch or repo.default_branch
116
# Make a shallow clone of the repo; this prevents getting the full git database when it's not needed.
117
if os.path.isdir(site_location):
118
# Delete the old site.
119
shutil.rmtree(site_location)
120
121
common.git_command(config.SITE_PATH, b"", "clone", "--depth=1", f"--branch={branch}", os.path.join(os.getcwd(), server_repo_location), os.path.join(subdomain, subpath))
122
123
124
@shared_task(ignore_result=False)
125
def delete_site(route):
126
from models import Repo
127
repo = db.session.get(Repo, route)
128
subdomain = repo.owner.username
129
subpath = repo.name if repo.has_site != 2 else "."
130
site_location = os.path.join(config.SITE_PATH, subdomain, subpath)
131
if os.path.isdir(site_location):
132
shutil.rmtree(site_location)
133
134
# Redo the primary site.
135
primary_site = Repo.query.filter_by(owner=repo.owner, has_site=2).first()
136
if primary_site:
137
copy_site(primary_site.route)
138
139
140
@shared_task(ignore_result=False)
141
def request_email_change(username, email):
142
from models import User, EmailChangeRequest
143
user = db.session.get(User, username)
144
145
request = EmailChangeRequest(user, email)
146
147
db.session.add(request)
148
db.session.commit()
149
150
message = email_send.make_multipart_message(
151
"Email change request for {username}".format(username=username),
152
config.NOTIFICATION_EMAIL,
153
email,
154
"email-change",
155
username=username,
156
code=request.code,
157
new_email=email,
158
url="https://" if config.suggest_https else "http://" + config.BASE_DOMAIN + "/settings/confirm-email/" + request.code
159
)
160