Skip to content

Commit 9882d7f

Browse files
committed
Fix issue where draft resurrect feature does not move most recent draft file from the archive directory back to the current draft directory. Fixes ietf-tools#2646. Commit ready for merge
- Legacy-Id: 17027
1 parent 34f9393 commit 9882d7f

2 files changed

Lines changed: 60 additions & 30 deletions

File tree

ietf/doc/tests_draft.py

Lines changed: 39 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
import debug # pyflakes:ignore
1818

19+
from ietf.doc.expire import get_expired_drafts, send_expire_notice_for_draft, expire_draft
1920
from ietf.doc.factories import IndividualDraftFactory, WgDraftFactory, RgDraftFactory, DocEventFactory
2021
from ietf.doc.models import ( Document, DocReminder, DocEvent,
2122
ConsensusDocEvent, LastCallDocEvent, RelatedDocument, State, TelechatDocEvent,
@@ -492,7 +493,33 @@ def test_edit_consensus(self):
492493
self.assertEqual(draft.latest_event(ConsensusDocEvent, type="changed_consensus").consensus, None)
493494

494495

495-
class ResurrectTests(TestCase):
496+
class DraftFileMixin():
497+
'''A mixin to setup temporary draft directories and files'''
498+
def setUp(self):
499+
self.saved_id_dir = settings.INTERNET_DRAFT_PATH
500+
self.saved_archive_dir = settings.INTERNET_DRAFT_ARCHIVE_DIR
501+
self.id_dir = self.tempdir('id')
502+
self.archive_dir = self.tempdir('id-archive')
503+
os.mkdir(os.path.join(self.archive_dir, "unknown_ids"))
504+
os.mkdir(os.path.join(self.archive_dir, "deleted_tombstones"))
505+
os.mkdir(os.path.join(self.archive_dir, "expired_without_tombstone"))
506+
507+
settings.INTERNET_DRAFT_PATH = self.id_dir
508+
settings.INTERNET_DRAFT_ARCHIVE_DIR = self.archive_dir
509+
510+
def tearDown(self):
511+
shutil.rmtree(self.id_dir)
512+
shutil.rmtree(self.archive_dir)
513+
settings.INTERNET_DRAFT_PATH = self.saved_id_dir
514+
settings.INTERNET_DRAFT_ARCHIVE_DIR = self.saved_archive_dir
515+
516+
def write_draft_file(self, name, size):
517+
f = io.open(os.path.join(self.id_dir, name), 'w')
518+
f.write("a" * size)
519+
f.close()
520+
521+
522+
class ResurrectTests(DraftFileMixin, TestCase):
496523
def test_request_resurrect(self):
497524
draft = WgDraftFactory(states=[('draft','expired')])
498525

@@ -526,14 +553,17 @@ def test_request_resurrect(self):
526553

527554
def test_resurrect(self):
528555
ad = Person.objects.get(name="Areað Irector")
529-
draft = WgDraftFactory(ad=ad,states=[('draft','expired')])
556+
draft = WgDraftFactory(ad=ad,states=[('draft','active')])
530557
DocEventFactory(doc=draft,type="requested_resurrect",by=ad)
531558

532-
url = urlreverse('ietf.doc.views_draft.resurrect', kwargs=dict(name=draft.name))
533-
534-
login_testing_unauthorized(self, "secretary", url)
559+
# create file and expire draft
560+
txt = "%s-%s.txt" % (draft.name, draft.rev)
561+
self.write_draft_file(txt, 5000)
562+
expire_draft(draft)
535563

536564
# normal get
565+
url = urlreverse('ietf.doc.views_draft.resurrect', kwargs=dict(name=draft.name))
566+
login_testing_unauthorized(self, "secretary", url)
537567
r = self.client.get(url)
538568
self.assertEqual(r.status_code, 200)
539569
q = PyQuery(r.content)
@@ -556,31 +586,12 @@ def test_resurrect(self):
556586
self.assertTrue('iesg-secretary' in outbox[-1]['To'])
557587
self.assertTrue('aread' in outbox[-1]['To'])
558588

589+
# ensure file restored from archive directory
590+
self.assertTrue(os.path.exists(os.path.join(self.id_dir, txt)))
591+
self.assertTrue(not os.path.exists(os.path.join(self.archive_dir, txt)))
559592

560-
class ExpireIDsTests(TestCase):
561-
def setUp(self):
562-
self.saved_id_dir = settings.INTERNET_DRAFT_PATH
563-
self.saved_archive_dir = settings.INTERNET_DRAFT_ARCHIVE_DIR
564-
self.id_dir = self.tempdir('id')
565-
self.archive_dir = self.tempdir('id-archive')
566-
os.mkdir(os.path.join(self.archive_dir, "unknown_ids"))
567-
os.mkdir(os.path.join(self.archive_dir, "deleted_tombstones"))
568-
os.mkdir(os.path.join(self.archive_dir, "expired_without_tombstone"))
569-
570-
settings.INTERNET_DRAFT_PATH = self.id_dir
571-
settings.INTERNET_DRAFT_ARCHIVE_DIR = self.archive_dir
572-
573-
def tearDown(self):
574-
shutil.rmtree(self.id_dir)
575-
shutil.rmtree(self.archive_dir)
576-
settings.INTERNET_DRAFT_PATH = self.saved_id_dir
577-
settings.INTERNET_DRAFT_ARCHIVE_DIR = self.saved_archive_dir
578593

579-
def write_draft_file(self, name, size):
580-
f = io.open(os.path.join(self.id_dir, name), 'w')
581-
f.write("a" * size)
582-
f.close()
583-
594+
class ExpireIDsTests(DraftFileMixin, TestCase):
584595
def test_in_draft_expire_freeze(self):
585596
from ietf.doc.expire import in_draft_expire_freeze
586597

@@ -623,8 +634,6 @@ def test_warn_expirable_drafts(self):
623634
self.assertTrue('aread@' in outbox[-1]['Cc'])
624635

625636
def test_expire_drafts(self):
626-
from ietf.doc.expire import get_expired_drafts, send_expire_notice_for_draft, expire_draft
627-
628637
mars = GroupFactory(type_id='wg',acronym='mars')
629638
ad_role = RoleFactory(group=mars, name_id='ad', person=Person.objects.get(user__username='ad'))
630639
draft = WgDraftFactory(name='draft-ietf-mars-test',group=mars)

ietf/doc/views_draft.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
# changing state and metadata on Internet Drafts
88

99
import datetime
10+
import os
11+
import glob
12+
import shutil
1013

1114
from django import forms
1215
from django.conf import settings
@@ -47,6 +50,7 @@
4750
from ietf.person.models import Person, Email
4851
from ietf.utils.mail import send_mail, send_mail_message, on_behalf_of
4952
from ietf.utils.textupload import get_cleaned_text_file_content
53+
from ietf.utils import log
5054
from ietf.mailtrigger.utils import gather_address_lists
5155

5256
class ChangeStateForm(forms.Form):
@@ -835,13 +839,30 @@ def resurrect(request, name):
835839
doc.expires = datetime.datetime.now() + datetime.timedelta(settings.INTERNET_DRAFT_DAYS_TO_EXPIRE)
836840
doc.save_with_history(events)
837841

842+
restore_draft_file(request, doc)
843+
838844
return HttpResponseRedirect(doc.get_absolute_url())
839845

840846
return render(request, 'doc/draft/resurrect.html',
841847
dict(doc=doc,
842848
resurrect_requested_by=resurrect_requested_by,
843849
back_url=doc.get_absolute_url()))
844850

851+
852+
def restore_draft_file(request, draft):
853+
'''restore latest revision document file from archive'''
854+
basename = '{}-{}'.format(draft.name, draft.rev)
855+
files = glob.glob(os.path.join(settings.INTERNET_DRAFT_ARCHIVE_DIR, basename) + '.*')
856+
log.log("Resurrecting %s. Moving files:" % draft.name)
857+
for file in files:
858+
try:
859+
shutil.move(file, settings.INTERNET_DRAFT_PATH)
860+
log.log(" Moved file %s to %s" % (file, settings.INTERNET_DRAFT_PATH))
861+
except shutil.Error as ex:
862+
messages.warning(request, 'There was an error restoring the draft file: {} ({})'.format(file, ex))
863+
log.log(" Exception %s when attempting to move %s" % (ex, file))
864+
865+
845866
class IESGNoteForm(forms.Form):
846867
note = forms.CharField(widget=forms.Textarea, label="IESG note", required=False, strip=False)
847868

0 commit comments

Comments
 (0)