Merge pull request #2503 from JojoBoulix/stable

Extend SOURCE_DATE_EPOCH support
This commit is contained in:
Takeshi KOMIYA 2016-05-05 22:15:19 +09:00
commit 20719f0b00
6 changed files with 76 additions and 4 deletions

View File

@ -11,7 +11,7 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from os import path, walk from os import path, walk, getenv
from codecs import open from codecs import open
from time import time from time import time
from datetime import datetime, tzinfo, timedelta from datetime import datetime, tzinfo, timedelta
@ -130,6 +130,12 @@ class I18nBuilder(Builder):
timestamp = time() timestamp = time()
tzdelta = datetime.fromtimestamp(timestamp) - \ tzdelta = datetime.fromtimestamp(timestamp) - \
datetime.utcfromtimestamp(timestamp) datetime.utcfromtimestamp(timestamp)
# set timestamp from SOURCE_DATE_EPOCH if set
# see https://reproducible-builds.org/specs/source-date-epoch/
source_date_epoch = getenv('SOURCE_DATE_EPOCH')
if source_date_epoch is not None:
timestamp = float(source_date_epoch)
tzdelta = 0
class LocalTimeZone(tzinfo): class LocalTimeZone(tzinfo):

View File

@ -10,7 +10,7 @@
""" """
import re import re
from os import path, environ from os import path, environ, getenv
import shlex import shlex
from six import PY2, PY3, iteritems, string_types, binary_type, text_type, integer_types from six import PY2, PY3, iteritems, string_types, binary_type, text_type, integer_types
@ -19,8 +19,10 @@ from sphinx.errors import ConfigError
from sphinx.locale import l_ from sphinx.locale import l_
from sphinx.util.osutil import make_filename, cd from sphinx.util.osutil import make_filename, cd
from sphinx.util.pycompat import execfile_, NoneType from sphinx.util.pycompat import execfile_, NoneType
from sphinx.util.i18n import format_date
nonascii_re = re.compile(br'[\x80-\xff]') nonascii_re = re.compile(br'[\x80-\xff]')
copyright_year_re = re.compile(r'^((\d{4}-)?)(\d{4})(?=[ ,])')
CONFIG_SYNTAX_ERROR = "There is a syntax error in your configuration file: %s" CONFIG_SYNTAX_ERROR = "There is a syntax error in your configuration file: %s"
if PY3: if PY3:
@ -298,6 +300,15 @@ class Config(object):
self.setup = config.get('setup', None) self.setup = config.get('setup', None)
self.extensions = config.get('extensions', []) self.extensions = config.get('extensions', [])
# correct values of copyright year that are not coherent with
# the SOURCE_DATE_EPOCH environment variable (if set)
# See https://reproducible-builds.org/specs/source-date-epoch/
if getenv('SOURCE_DATE_EPOCH') is not None:
for k in ('copyright', 'epub_copyright'):
if k in config:
config[k] = copyright_year_re.sub('\g<1>%s' % format_date('%Y'),
config[k])
def check_types(self, warn): def check_types(self, warn):
# check all values for deviation from the default value's type, since # check all values for deviation from the default value's type, since
# that can result in TypeErrors all over the place # that can result in TypeErrors all over the place

View File

@ -14,7 +14,6 @@ import os
import re import re
import warnings import warnings
from os import path from os import path
from time import gmtime
from datetime import datetime from datetime import datetime
from collections import namedtuple from collections import namedtuple
@ -188,7 +187,7 @@ def format_date(format, date=None, language=None, warn=None):
# See https://wiki.debian.org/ReproducibleBuilds/TimestampsProposal # See https://wiki.debian.org/ReproducibleBuilds/TimestampsProposal
source_date_epoch = os.getenv('SOURCE_DATE_EPOCH') source_date_epoch = os.getenv('SOURCE_DATE_EPOCH')
if source_date_epoch is not None: if source_date_epoch is not None:
date = gmtime(float(source_date_epoch)) date = datetime.utcfromtimestamp(float(source_date_epoch))
else: else:
date = datetime.now() date = datetime.now()

View File

@ -0,0 +1,3 @@
copyright = u'2006-2009, Author'

View File

@ -0,0 +1,4 @@
=================
test-correct-year
=================

View File

@ -0,0 +1,49 @@
# -*- coding: utf-8 -*-
"""
test_correct_year
~~~~~~~~~~~~~~~~~
Test copyright year adjustment
:copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import os
from util import TestApp
def test_correct_year():
try:
# save current value of SOURCE_DATE_EPOCH
sde = os.environ.pop('SOURCE_DATE_EPOCH',None)
# test with SOURCE_DATE_EPOCH unset: no modification
app = TestApp(buildername='html',testroot='correct-year')
app.builder.build_all()
content = (app.outdir / 'contents.html').text()
app.cleanup()
assert '2006-2009' in content
# test with SOURCE_DATE_EPOCH set: copyright year should be
# updated
os.environ['SOURCE_DATE_EPOCH'] = "1293840000"
app = TestApp(buildername='html',testroot='correct-year')
app.builder.build_all()
content = (app.outdir / 'contents.html').text()
app.cleanup()
assert '2006-2011' in content
os.environ['SOURCE_DATE_EPOCH'] = "1293839999"
app = TestApp(buildername='html',testroot='correct-year')
app.builder.build_all()
content = (app.outdir / 'contents.html').text()
app.cleanup()
assert '2006-2010' in content
finally:
# Restores SOURCE_DATE_EPOCH
if sde == None:
os.environ.pop('SOURCE_DATE_EPOCH',None)
else:
os.environ['SOURCE_DATE_EPOCH'] = sde