Skip to content

Commit 9ec3db8

Browse files
authored
Bug 1318960 - Migrate files only when their messages change (#26)
1 parent fee4c63 commit 9ec3db8

File tree

6 files changed

+75
-29
lines changed

6 files changed

+75
-29
lines changed

fluent/migrate/context.py

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,14 @@
22
from __future__ import unicode_literals
33

44
import os
5-
import sys
65
import codecs
76
import logging
87

8+
try:
9+
from itertools import zip_longest
10+
except ImportError:
11+
from itertools import izip_longest as zip_longest
12+
913
import fluent.syntax.ast as FTL
1014
from fluent.syntax.parser import FluentParser
1115
from fluent.syntax.serializer import FluentSerializer
@@ -202,6 +206,29 @@ def get_source(self, path, key):
202206
resource = self.localization_resources[path]
203207
return resource.get(key, None)
204208

209+
def messages_equal(self, res1, res2):
210+
"""Compare messages of two FTL resources.
211+
212+
Uses FTL.BaseNode.equals to compare all messages in two FTL resources.
213+
If the order or number of messages differ, the result is also False.
214+
"""
215+
def message_id(message):
216+
"Return the message's identifer name for sorting purposes."
217+
return message.id.name
218+
219+
messages1 = sorted(
220+
(entry for entry in res1.body if isinstance(entry, FTL.Message)),
221+
key=message_id)
222+
messages2 = sorted(
223+
(entry for entry in res2.body if isinstance(entry, FTL.Message)),
224+
key=message_id)
225+
for msg1, msg2 in zip_longest(messages1, messages2):
226+
if msg1 is None or msg2 is None:
227+
return False
228+
if not msg1.equals(msg2):
229+
return False
230+
return True
231+
205232
def merge_changeset(self, changeset=None):
206233
"""Return a generator of FTL ASTs for the changeset.
207234
@@ -256,16 +283,14 @@ def in_changeset(ident):
256283
self, reference, current, transforms, in_changeset
257284
)
258285

259-
# Skip this path if the merged snapshot is identical to the current
260-
# state of the localization file. This may happen when:
286+
# Skip this path if the messages in the merged snapshot are
287+
# identical to those in the current state of the localization file.
288+
# This may happen when:
261289
#
262290
# - none of the transforms is in the changset, or
263291
# - all messages which would be migrated by the context's
264292
# transforms already exist in the current state.
265-
#
266-
# We compare JSON trees rather then use filtering by `in_changeset`
267-
# to account for translations removed from `reference`.
268-
if snapshot.to_json() == current.to_json():
293+
if self.messages_equal(current, snapshot):
269294
continue
270295

271296
# Store the merged snapshot on the context so that the next merge
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
foo = foo
2+
bar = Bar
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<!ENTITY foo "FOO">
2+
<!ENTITY bar "BAR">
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
bar = BAR
2+
foo = FOO

tests/migrate/test_context.py

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -292,25 +292,16 @@ def tearDown(self):
292292
logging.disable(logging.NOTSET)
293293

294294
def test_missing_localization_file(self):
295-
expected = {
296-
'toolbar.ftl': ftl_resource_to_json('''
297-
// This Source Code Form is subject to the terms of the Mozilla Public
298-
// License, v. 2.0. If a copy of the MPL was not distributed with this
299-
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
300-
301-
302-
[[ Toolbar items ]]
303-
''')
304-
}
305-
306295
self.maxDiff = None
307296
self.assertDictEqual(
308297
to_json(self.ctx.merge_changeset()),
309-
expected
298+
{}
310299
)
311300

312301

313302
class TestExistingTarget(unittest.TestCase):
303+
maxDiff = None
304+
314305
def setUp(self):
315306
# Silence all logging.
316307
logging.disable(logging.CRITICAL)
@@ -415,6 +406,33 @@ def test_existing_target_ftl_with_all_messages(self):
415406
{}
416407
)
417408

409+
def test_existing_target_ftl_with_all_messages_reordered(self):
410+
self.ctx.add_transforms('existing.ftl', 'existing.ftl', [
411+
FTL.Message(
412+
id=FTL.Identifier('foo'),
413+
value=COPY(
414+
'existing.dtd',
415+
'foo'
416+
)
417+
),
418+
FTL.Message(
419+
id=FTL.Identifier('bar'),
420+
value=COPY(
421+
'existing.dtd',
422+
'bar'
423+
)
424+
),
425+
])
426+
427+
# All migrated messages are already in the target FTL but in a
428+
# different order. The order of messages is explicitly ignored in the
429+
# snapshot equality check. Consequently, the result of merge_changeset
430+
# is an empty iterator.
431+
self.assertDictEqual(
432+
to_json(self.ctx.merge_changeset()),
433+
{}
434+
)
435+
418436

419437
class TestNotSupportedError(unittest.TestCase):
420438
def test_add_ftl(self):

tools/migrate/README.md

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,13 @@ Then run migrations passing the `examples` directory as the reference:
2020
Here's what the output should look like:
2121

2222
Annotating /home/stas/moz/l10n-central/it
23+
Running migration examples.bug_1291693
24+
Writing to /home/stas/moz/l10n-central/it/browser/branding/official/brand.ftl
25+
Committing changeset: Bug 1291693 - Migrate the menubar to FTL, part 1
26+
Writing to /home/stas/moz/l10n-central/it/browser/menubar.ftl
27+
Writing to /home/stas/moz/l10n-central/it/browser/toolbar.ftl
28+
Writing to /home/stas/moz/l10n-central/it/browser/branding/official/brand.ftl
29+
Committing changeset: Bug 1291693 - Migrate the menubar to FTL, part 2
2330
Running migration examples.about_dialog
2431
Writing to /home/stas/moz/l10n-central/it/browser/about_dialog.ftl
2532
Committing changeset: Migrate about:dialog, part 1
@@ -30,13 +37,3 @@ Here's what the output should look like:
3037
Committing changeset: Migrate about:download in Firefox for Android, part 2
3138
Writing to /home/stas/moz/l10n-central/it/mobile/about_downloads.ftl
3239
Committing changeset: Migrate about:download in Firefox for Android, part 3
33-
Running migration examples.bug_1291693
34-
Writing to /home/stas/moz/l10n-central/it/browser/menubar.ftl
35-
Writing to /home/stas/moz/l10n-central/it/browser/toolbar.ftl
36-
Committing changeset: Bug 1291693 - Migrate the menubar to FTL, part 1
37-
Writing to /home/stas/moz/l10n-central/it/browser/branding/official/brand.ftl
38-
Committing changeset: Bug 1291693 - Migrate the menubar to FTL, part 2
39-
Writing to /home/stas/moz/l10n-central/it/browser/menubar.ftl
40-
Writing to /home/stas/moz/l10n-central/it/browser/toolbar.ftl
41-
Writing to /home/stas/moz/l10n-central/it/browser/branding/official/brand.ftl
42-
Committing changeset: Bug 1291693 - Migrate the menubar to FTL, part 3

0 commit comments

Comments
 (0)