Skip to content

Commit 69069d1

Browse files
committed
Merged in [17027] from rcross@amsl.com:
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. - Legacy-Id: 17032 Note: SVN reference [17027] has been migrated to Git commit 9882d7f
2 parents 873494b + 9882d7f commit 69069d1

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)