Commit f9173f25 authored by Claude Paroz's avatar Claude Paroz

Add ability to commit new files when linguas_location is 'no'

parent a8d3bfc3
......@@ -52,6 +52,11 @@ BRANCH_HEAD_NAMES = (
class UnableToCommit(Exception):
class Module(models.Model):
name = models.CharField(max_length=50, unique=True, validators=[validate_slug])
homepage = models.URLField(blank=True,
......@@ -625,44 +630,36 @@ class Branch(models.Model):
def commit_po(self, po_file, domain, language, author):
""" Commit the file 'po_file' in the branch VCS repository """
if self.is_vcs_readonly():
raise Exception("This branch is in read-only mode. Unable to commit")
vcs_type = self.module.vcs_type
if vcs_type not in ("git",):
raise NotImplementedError("Commit is not implemented for '%s'" % vcs_type)
locale = language.locale
base_path = self.co_path
dest_path = domain.get_po_path(locale)
dest_full_path = base_path / dest_path
dest_full_path, existing, linguas_path = domain.commit_info(self, language)
with ModuleLock(self.module):
if vcs_type == "git":
already_exist = dest_full_path.exists()
if not already_exist:
linguas_path = domain.get_linguas_path(self)
if linguas_path is None:
raise Exception(
_("Sorry, adding new translations when the LINGUAS file is not known is not supported.")
base_path = self.co_path
# Copy file in repo
shutil.copyfile(str(po_file), str(dest_full_path))
# git add file.po
['git', 'add', dest_path], raise_on_error=True, cwd=base_path)
if not already_exist:
['git', 'add', str(dest_full_path.relative_to(base_path))],
raise_on_error=True, cwd=base_path
if linguas_path:
# Add locale to LINGUAS
utils.insert_locale_in_linguas(linguas_path, locale)
utils.insert_locale_in_linguas(linguas_path, language.locale)
['git', 'add', str(linguas_path.relative_to(base_path))],
raise_on_error=True, cwd=base_path
msg = "Add %s translation" %
if existing:
msg = "Update %s translation" %
msg = "Add %s translation" %
commit_cmd = ['git', 'commit', '-m', msg]
if author:
......@@ -683,7 +680,7 @@ class Branch(models.Model):
commit_hash = out.split()[0] if out else ''
# Finish by updating stats
if already_exist:
if existing:
stat = Statistics.objects.get(language=language, branch=self, domain=domain)
except Statistics.DoesNotExist:
......@@ -975,10 +972,28 @@ class Domain(models.Model):
pot_command.extend(['--msgid-bugs-address', bugs_url])
return pot_command, env
def get_linguas_path(self, branch):
"""Return a LINGUAS file path, or None."""
path = branch.co_path / self.base_dir / 'LINGUAS'
return path if path.exists() else None
def commit_info(self, branch, language):
Return a 3-tuple: (
absolute path to po file,
boolean telling if the file is new
linguas_path -> if linguas edition needed, else None
Raise an exception if file cannot be committed.
if branch.is_vcs_readonly():
raise UnableToCommit(_("The repository is read only"))
abs_po_path = branch.co_path / self.get_po_path(language.locale)
existing = abs_po_path.exists()
linguas = None
if not existing and self.linguas_location != 'no':
linguas = branch.co_path / self.base_dir / 'LINGUAS'
if not linguas.exists():
raise UnableToCommit(
_("Sorry, adding new translations when the LINGUAS file is not known is not supported.")
return abs_po_path, existing, linguas
def get_linguas(self, branch):
""" Return a linguas dict like this: {'langs':['lang1', lang2], 'error':"Error"} """
......@@ -17,7 +17,7 @@ from django.test.utils import override_settings
from common.utils import run_shell_command
from stats.models import (
Module, Domain, Branch, Release, CategoryName, Statistics, FakeLangStatistics,
Information, UnableToCommit
from stats import utils
from languages.models import Language
......@@ -279,13 +279,43 @@ class ModuleTestCase(TestCase):
response = self.client.get(dyn_url)
self.assertContains(response, """# Tamil translation for gnome-hello.""")
def test_commit_ability(self):
branch = self.mod.get_head_branch()
domain = self.mod.domain_set.get(name='po')
fr_lang = Language.objects.get(locale='fr')
with self.assertRaises(UnableToCommit):
# read-only VCS
domain.commit_info(branch, fr_lang)
# Setup as a writable repo
self.mod.vcs_root = '' %
linguas = branch.co_path / 'po' / 'LINGUAS'
bem_lang = Language.objects.get(locale='bem')
with self.assertRaises(UnableToCommit):
# unaccessible LINGUAS file for a new lang
domain.commit_info(branch, bem_lang)
domain.linguas_location = 'no'
domain.commit_info(branch, bem_lang),
(branch.co_path / 'po' / 'bem.po', False, None)
domain.commit_info(branch, fr_lang),
(branch.co_path / 'po' / 'fr.po', True, None)
def test_commit_po(self):
branch = self.mod.get_head_branch()
po_file = Path(__file__).parent / 'test.po'
domain = self.mod.domain_set.get(name='po')
fr_lang = Language.objects.get(locale='fr')
with self.assertRaisesRegex(Exception, 'read-only mode'):
with self.assertRaisesRegex(UnableToCommit, 'read only'):
branch.commit_po(po_file, domain, fr_lang, 'Author <>')
# Setup as a writable repo
self.mod.vcs_root = '' %
......@@ -11,7 +11,7 @@ from django.urls import reverse
from django.utils.translation import override, ugettext, ugettext_noop, ugettext_lazy as _
from common.utils import run_shell_command, send_mail
from stats.models import Branch, Domain, Statistics, PoFile
from stats.models import Branch, Domain, Statistics, PoFile, UnableToCommit
from stats.signals import pot_has_changed
from stats.utils import STATUS_OK, is_po_reduced, po_grep
from languages.models import Language
......@@ -74,11 +74,11 @@ class State(models.Model):
return None
def able_to_commit(self):
return (
not self.branch.is_vcs_readonly() and
self.get_latest_po_file_action() is not None and
(self.stats is not None or self.domain.get_linguas_path(self.branch) is not None)
self.domain.commit_info(self.branch, self.language)
except UnableToCommit:
return False
return self.get_latest_po_file_action() is not None
def change_state(self, state_class, person=None): = state_class._name
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment