Repository: translate/pootle

Issue:
sync_stores/update_stores
For 2.9.0 we're making Pootle FS the main path into Pootle, but `sync_stores` and `update_stores` are kept for backward compatibility.

But we have situations where Pootle FS can't do what sync/update does in that it may do more or may touch the db/file when sync/update would only do it on one side.

So we need to warn:
1. That this mode is deprecated
2. Where there are conflicts e.g. we should warn and bail or warn and allow it to continue

Essentially, we want people to know when we can't do what they expect.


Discussion:

Resolving patch:
diff --git a/pootle/apps/pootle_app/management/commands/sync_stores.py b/pootle/apps/pootle_app/management/commands/sync_stores.py
--- a/pootle/apps/pootle_app/management/commands/sync_stores.py
+++ b/pootle/apps/pootle_app/management/commands/sync_stores.py
@@ -6,6 +6,7 @@
 # or later license. See the LICENSE file for a copy of the license and the
 # AUTHORS file for copyright and authorship information.
 
+import logging
 import os
 os.environ['DJANGO_SETTINGS_MODULE'] = 'pootle.settings'
 
@@ -13,6 +14,9 @@
 from pootle_fs.utils import FSPlugin
 
 
+logger = logging.getLogger(__name__)
+
+
 class Command(PootleCommand):
     help = "Save new translations to disk manually."
     process_disabled_projects = True
@@ -42,10 +46,22 @@ def add_arguments(self, parser):
             help="Don't ignore stores synced after last change",
         )
 
+    warn_on_conflict = []
+
     def handle_all_stores(self, translation_project, **options):
         path_glob = "%s*" % translation_project.pootle_path
         plugin = FSPlugin(translation_project.project)
         plugin.fetch()
+        if translation_project.project.pk not in self.warn_on_conflict:
+            state = plugin.state()
+            if any(k in state for k in ["conflict", "conflict_untracked"]):
+                logger.warn(
+                    "The project '%s' has conflicting changes in the database "
+                    "and translation files. Use `pootle fs resolve` to tell "
+                    "pootle how to merge",
+                    translation_project.project.code)
+                self.warn_on_conflict.append(
+                    translation_project.project.pk)
         if not options["skip_missing"]:
             plugin.add(pootle_path=path_glob, update="fs")
         if options["overwrite"]:


Test patch:
diff --git a/tests/commands/sync_stores.py b/tests/commands/sync_stores.py
--- a/tests/commands/sync_stores.py
+++ b/tests/commands/sync_stores.py
@@ -6,6 +6,8 @@
 # or later license. See the LICENSE file for a copy of the license and the
 # AUTHORS file for copyright and authorship information.
 
+import os
+
 import pytest
 
 from django.core.management import call_command
@@ -26,3 +28,24 @@ def test_sync_stores_noargs(capfd, tmpdir):
     # FIXME we should work out how to get something here
     assert out == ''
     assert err == ''
+
+
+@pytest.mark.cmd
+@pytest.mark.django_db
+def test_sync_stores_warn_on_conflict(caplog, project0, language0,
+                                      tmpdir, settings):
+    """Check warning if there are conflicting store/files"""
+    settings.POOTLE_FS_WORKING_PATH = str(tmpdir.mkdir("__fs_tmp__"))
+    fs_tmp = tmpdir.mkdir(project0.code)
+    project0.config["pootle_fs.fs_url"] = str(fs_tmp)
+    tp_tmp = fs_tmp.mkdir(language0.code)
+    conflict_po = os.path.join(str(tp_tmp), "complex.po")
+    with open(conflict_po, "w") as f:
+        f.write("this file should conflict with complex.po in db")
+
+    # the above code will create a conflict, if env changes this
+    # test will need to be updated
+    call_command('sync_stores', "--project=%s" % project0.code)
+    rec = caplog.records[-1]
+    assert rec.levelname == "WARNING"
+    assert "tell pootle how to merge" in rec.message