Skip to content

Commit 23f06f7

Browse files
committed
Refactor patch, status, close, and commiter to leverage Workflow
Make getting a POC while only having a patchid a single Workflow call. Patch and committer use the committer lookup and change interface. Status and close use the updatePOCStatus interface used by transition. All four leverage PoC as their main hook for patch and commitfest info.
1 parent d714ada commit 23f06f7

File tree

2 files changed

+51
-87
lines changed

2 files changed

+51
-87
lines changed

pgcommitfest/commitfest/models.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ class Patch(models.Model, DiffableModel):
179179
"authors": "authors_string",
180180
"reviewers": "reviewers_string",
181181
}
182+
182183
# XXX probably should just encourage using PoC.commitfest since most places
183184
# dealing with the Patch need the PoC anyway.
184185
def current_commitfest(self):
@@ -559,6 +560,10 @@ class CfbotTask(models.Model):
559560
# the workflow this application is built for. These elements exist
560561
# independent of what the user is presently seeing on their page.
561562
class Workflow(models.Model):
563+
564+
def get_poc_for_patchid_or_404(patchid):
565+
return get_object_or_404(Patch.objects.select_related(), pk=patchid).current_patch_on_commitfest()
566+
562567
# At most a single Open CommitFest is allowed and this function returns it.
563568
def open_cf():
564569
cfs = list(CommitFest.objects.filter(status=CommitFest.STATUS_OPEN))

pgcommitfest/commitfest/views.py

Lines changed: 46 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -674,29 +674,18 @@ def patch(request, patchid):
674674
)
675675
cf = patch_commitfests[0].commitfest
676676

677-
committers = Committer.objects.filter(active=True).order_by(
678-
"user__last_name", "user__first_name"
679-
)
680-
681677
cfbot_branch = getattr(patch, "cfbot_branch", None)
682678
cfbot_tasks = patch.cfbot_tasks.order_by("position") if cfbot_branch else []
683679

684680
# XXX: this creates a session, so find a smarter way. Probably handle
685681
# it in the callback and just ask the user then?
686682
if request.user.is_authenticated:
687-
committer = [c for c in committers if c.user == request.user]
688-
if len(committer) > 0:
689-
is_committer = True
690-
is_this_committer = committer[0] == patch.committer
691-
else:
692-
is_committer = is_this_committer = False
693-
683+
is_committer, is_this_committer, all_committers = Workflow.isCommitter(request.user, patch)
694684
is_author = request.user in patch.authors.all()
695685
is_reviewer = request.user in patch.reviewers.all()
696686
is_subscribed = patch.subscribers.filter(id=request.user.id).exists()
697687
else:
698-
is_committer = False
699-
is_this_committer = False
688+
is_committer, is_this_committer, all_committers = Workflow.isCommitter(None, None)
700689
is_author = False
701690
is_reviewer = False
702691
is_subscribed = False
@@ -718,7 +707,7 @@ def patch(request, patchid):
718707
"is_subscribed": is_subscribed,
719708
"authors": patch.authors.all(),
720709
"reviewers": patch.reviewers.all(),
721-
"committers": committers,
710+
"committers": all_committers,
722711
"attachnow": "attachthreadnow" in request.GET,
723712
"title": patch.name,
724713
"breadcrumbs": [
@@ -987,14 +976,7 @@ def comment(request, patchid, what):
987976
@login_required
988977
@transaction.atomic
989978
def status(request, patchid, status):
990-
patch = get_object_or_404(Patch.objects.select_related(), pk=patchid)
991-
cf = patch.current_commitfest()
992-
poc = get_object_or_404(
993-
PatchOnCommitFest.objects.select_related(),
994-
commitfest__id=cf.id,
995-
patch__id=patchid,
996-
)
997-
979+
# Active status only since those can be freely swapped between.
998980
if status == "review":
999981
newstatus = PatchOnCommitFest.STATUS_REVIEW
1000982
elif status == "author":
@@ -1004,64 +986,46 @@ def status(request, patchid, status):
1004986
else:
1005987
raise Exception("Can't happen")
1006988

1007-
if newstatus != poc.status:
1008-
# Only save it if something actually changed
1009-
poc.status = newstatus
1010-
poc.patch.set_modified()
1011-
poc.patch.save()
1012-
poc.save()
989+
poc = Workflow.get_poc_for_patchid_or_404(patchid)
1013990

1014-
PatchHistory(
1015-
patch=poc.patch, by=request.user, what="New status: %s" % poc.statusstring
1016-
).save_and_notify()
991+
try:
992+
if (Workflow.updatePOCStatus(poc, newstatus, request.user)):
993+
messages.info(request, "Updated status to %s" % poc.statusstring)
994+
except Exception as e:
995+
messages.error(request, "Failed to update status of patch: {}".format(e))
1017996

1018997
return HttpResponseRedirect("/patch/%s/" % (poc.patch.id))
1019998

1020999

10211000
@login_required
10221001
@transaction.atomic
10231002
def close(request, patchid, status):
1024-
patch = get_object_or_404(Patch.objects.select_related(), pk=patchid)
1025-
poc = patch.current_patch_on_commitfest()
1026-
1027-
poc.leavedate = datetime.now()
1003+
poc = Workflow.get_poc_for_patchid_or_404(patchid)
1004+
committer = None
10281005

1029-
# We know the status can't be one of the ones below, since we
1030-
# have checked that we're not closed yet. Therefor, we don't
1031-
# need to check if the individual status has changed.
1006+
# Inactive statuses only, except moved (next), which is handled by /transition
10321007
if status == "reject":
1033-
poc.status = PatchOnCommitFest.STATUS_REJECTED
1008+
newstatus = PatchOnCommitFest.STATUS_REJECTED
10341009
elif status == "withdrawn":
1035-
poc.status = PatchOnCommitFest.STATUS_WITHDRAWN
1010+
newstatus = PatchOnCommitFest.STATUS_WITHDRAWN
10361011
elif status == "feedback":
1037-
poc.status = PatchOnCommitFest.STATUS_RETURNED
1012+
newstatus = PatchOnCommitFest.STATUS_RETURNED
10381013
elif status == "committed":
10391014
committer = get_object_or_404(Committer, user__username=request.GET["c"])
1040-
if committer != poc.patch.committer:
1041-
# Committer changed!
1042-
prevcommitter = poc.patch.committer
1043-
poc.patch.committer = committer
1044-
PatchHistory(
1045-
patch=poc.patch,
1046-
by=request.user,
1047-
what="Changed committer to %s" % committer,
1048-
).save_and_notify(prevcommitter=prevcommitter)
1049-
poc.status = PatchOnCommitFest.STATUS_COMMITTED
1015+
newstatus = PatchOnCommitFest.STATUS_COMMITTED
10501016
else:
10511017
raise Exception("Can't happen")
10521018

1053-
poc.patch.set_modified()
1054-
poc.patch.save()
1055-
poc.save()
1056-
1057-
PatchHistory(
1058-
patch=poc.patch,
1059-
by=request.user,
1060-
what="Closed in commitfest %s with status: %s"
1061-
% (poc.commitfest, poc.statusstring),
1062-
).save_and_notify()
1019+
try:
1020+
if (committer):
1021+
Workflow.setCommitter(poc, committer, request.user)
1022+
messages.info(request, "Committed by %s" % committer.user)
1023+
if (Workflow.updatePOCStatus(poc, newstatus, request.user)):
1024+
messages.info(request, "Closed. Updated status to %s" % poc.statusstring)
1025+
except Exception as e:
1026+
messages.error(request, "Failed to close patch: {}".format(e))
10631027

1064-
return HttpResponseRedirect("/%s/%s/" % (poc.commitfest.id, poc.patch.id))
1028+
return HttpResponseRedirect("/patch/%s/" % poc.patch.id)
10651029

10661030

10671031
@login_required
@@ -1073,7 +1037,7 @@ def transition(request, patchid):
10731037
messages.error(request, "Unknown from commitfest id {}".format(request.GET.get("fromcfid", None)))
10741038
return HttpResponseRedirect("/patch/%s/" % (patchid))
10751039

1076-
cur_poc = get_object_or_404(Patch.objects.select_related(), pk=patchid).current_patch_on_commitfest()
1040+
cur_poc = Workflow.get_poc_for_patchid_or_404(patchid)
10771041

10781042
if from_cf != cur_poc.commitfest:
10791043
messages.error(request, "Transition aborted, Redirect performed. Commitfest for patch already changed.")
@@ -1124,33 +1088,28 @@ def reviewer(request, patchid, status):
11241088
@login_required
11251089
@transaction.atomic
11261090
def committer(request, patchid, status):
1127-
patch = get_object_or_404(Patch, pk=patchid)
1091+
poc = Workflow.get_poc_for_patchid_or_404(patchid)
11281092

1129-
committer = list(Committer.objects.filter(user=request.user, active=True))
1130-
if len(committer) == 0:
1093+
find_me = list(Committer.objects.filter(user=request.user, active=True))
1094+
if len(find_me) == 0:
11311095
return HttpResponseForbidden("Only committers can do that!")
1132-
committer = committer[0]
1096+
me = find_me[0]
1097+
1098+
# At this point it doesn't matter who the existing committer, if any, is.
1099+
# If someone else is one we are permitted to become the new one, then
1100+
# remove ourselves. So removing them is acceptable, and desireable for admin.
1101+
# So we just need to know whether we are leaving the patch with ourselves
1102+
# as the commiter, or None.
1103+
if status == "become":
1104+
new_committer = me
1105+
elif status == "remove":
1106+
new_committer = None
1107+
1108+
# We could ignore a no-op become...but we expect the application to
1109+
# prevent such things on this particular interface.
1110+
if (not Workflow.setCommitter(poc, new_committer, request.user)):
1111+
raise Exception("Not expecting a no-op: toggling committer")
11331112

1134-
is_committer = committer == patch.committer
1135-
1136-
prevcommitter = patch.committer
1137-
if status == "become" and not is_committer:
1138-
patch.committer = committer
1139-
patch.set_modified()
1140-
PatchHistory(
1141-
patch=patch,
1142-
by=request.user,
1143-
what="Added %s as committer" % request.user.username,
1144-
).save_and_notify(prevcommitter=prevcommitter)
1145-
elif status == "remove" and is_committer:
1146-
patch.committer = None
1147-
patch.set_modified()
1148-
PatchHistory(
1149-
patch=patch,
1150-
by=request.user,
1151-
what="Removed %s from committers" % request.user.username,
1152-
).save_and_notify(prevcommitter=prevcommitter)
1153-
patch.save()
11541113
return HttpResponseRedirect("../../")
11551114

11561115

0 commit comments

Comments
 (0)