Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Confirm that each journal can be parsed during upgrade, and abort upgrade if not #650

Merged
merged 5 commits into from
Aug 24, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 0 additions & 11 deletions features/encryption.feature
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,3 @@
When we run "jrnl simple -n 1"
Then we should not see the message "Password"
and the output should contain "2013-06-10 15:40 Life is good"

Scenario: Upgrading a journal encrypted with jrnl 1.x
Given we use the config "encrypted_old.json"
When we run "jrnl -n 1" and enter
"""
Y
bad doggie no biscuit
bad doggie no biscuit
"""
Then we should see the message "Password"
and the output should contain "2013-06-10 15:40 Life is good"
11 changes: 0 additions & 11 deletions features/regression.feature
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,6 @@ Feature: Zapped bugs should stay dead.
| Hope to get a lot of traffic.
"""

Scenario: Upgrade and parse journals with square brackets
Given we use the config "upgrade_from_195.json"
When we run "jrnl -9" and enter "Y"
Then the output should contain
"""
2010-06-10 15:00 A life without chocolate is like a bad analogy.

2013-06-10 15:40 He said "[this] is the best time to be alive".
"""
Then the journal should have 2 entries

Scenario: Integers in square brackets should not be read as dates
Given we use the config "brackets.yaml"
When we run "jrnl -1"
Expand Down
23 changes: 23 additions & 0 deletions features/upgrade.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
Feature: Upgrading Journals from 1.x.x to 2.x.x

Scenario: Upgrade and parse journals with square brackets
Given we use the config "upgrade_from_195.json"
When we run "jrnl -9" and enter "Y"
Then the output should contain
"""
2010-06-10 15:00 A life without chocolate is like a bad analogy.

2013-06-10 15:40 He said "[this] is the best time to be alive".
"""
Then the journal should have 2 entries

Scenario: Upgrading a journal encrypted with jrnl 1.x
Given we use the config "encrypted_old.json"
When we run "jrnl -n 1" and enter
"""
Y
bad doggie no biscuit
bad doggie no biscuit
"""
Then we should see the message "Password"
and the output should contain "2013-06-10 15:40 Life is good"
13 changes: 12 additions & 1 deletion jrnl/Journal.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,20 @@ def open(self, filename=None):
def write(self, filename=None):
"""Dumps the journal into the config file, overwriting it"""
filename = filename or self.config['journal']
text = "\n".join([e.__unicode__() for e in self.entries])
text = self._to_text()
self._store(filename, text)

def validate_parsing(self):
"""Confirms that the jrnl is still parsed correctly after being dumped to text."""
new_entries = self._parse(self._to_text())
for i, entry in enumerate(self.entries):
if entry != new_entries[i]:
return False
return True

def _to_text(self):
return "\n".join([e.__unicode__() for e in self.entries])

def _load(self, filename):
raise NotImplementedError

Expand Down
13 changes: 12 additions & 1 deletion jrnl/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from .EncryptedJournal import EncryptedJournal
import yaml
import logging
import sys

DEFAULT_CONFIG_NAME = 'jrnl.yaml'
DEFAULT_JOURNAL_NAME = 'journal.txt'
Expand Down Expand Up @@ -85,8 +86,18 @@ def load_or_install_jrnl():
if os.path.exists(config_path):
log.debug('Reading configuration from file %s', config_path)
config = util.load_config(config_path)
upgrade.upgrade_jrnl_if_necessary(config_path)

try:
upgrade.upgrade_jrnl_if_necessary(config_path)
except upgrade.UpgradeValidationException:
util.prompt("Aborting upgrade.")
util.prompt("Please tell us about this problem at the following URL:")
util.prompt("https://github.com/jrnl-org/jrnl/issues/new?title=UpgradeValidationException")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀

util.prompt("Exiting.")
sys.exit(1)

upgrade_config(config)

return config
else:
log.debug('Configuration file not found, installing jrnl...')
Expand Down
27 changes: 21 additions & 6 deletions jrnl/upgrade.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ def upgrade_jrnl_if_necessary(config_path):
encrypted_journals = {}
plain_journals = {}
other_journals = {}
all_journals = []

for journal_name, journal_conf in config['journals'].items():
if isinstance(journal_conf, dict):
Expand Down Expand Up @@ -85,19 +86,33 @@ def upgrade_jrnl_if_necessary(config_path):
util.prompt("\nUpgrading encrypted '{}' journal stored in {}...".format(journal_name, path))
backup(path, binary=True)
old_journal = Journal.open_journal(journal_name, util.scope_config(config, journal_name), legacy=True)
new_journal = EncryptedJournal.from_journal(old_journal)
new_journal.write()
util.prompt(" Done.")
all_journals.append(EncryptedJournal.from_journal(old_journal))

for journal_name, path in plain_journals.items():
util.prompt("\nUpgrading plain text '{}' journal stored in {}...".format(journal_name, path))
backup(path)
old_journal = Journal.open_journal(journal_name, util.scope_config(config, journal_name), legacy=True)
new_journal = Journal.PlainJournal.from_journal(old_journal)
new_journal.write()
util.prompt(" Done.")
all_journals.append(Journal.PlainJournal.from_journal(old_journal))

# loop through lists to validate
failed_journals = [j for j in all_journals if not j.validate_parsing()]

if len(failed_journals) > 0:
util.prompt("\nThe following journal{} failed to upgrade:\n{}".format(
's' if len(failed_journals) > 1 else '', "\n".join(j.name for j in failed_journals))
)

raise UpgradeValidationException

# write all journals - or - don't
for j in all_journals:
j.write()

util.prompt("\nUpgrading config...")
backup(config_path)

util.prompt("\nWe're all done here and you can start enjoying jrnl 2.".format(config_path))

class UpgradeValidationException(Exception):
"""Raised when the contents of an upgraded journal do not match the old journal"""
pass