blob: 94257c942ff85d1583ccb669ba3e1aa226aed9b6 [file] [log] [blame]
# -*- coding:utf-8 -*-
import difflib
import io
import re
from tempfile import mkstemp
from portage import _encodings
from portage import _unicode_decode
from portage import _unicode_encode
from portage import os
from portage import shutil
from portage import util
_copyright_re1 = \
re.compile(br'^(# Copyright \d\d\d\d)-\d\d\d\d( Gentoo Foundation)\b')
_copyright_re2 = \
re.compile(br'^(# Copyright )(\d\d\d\d)( Gentoo Foundation)\b')
class _copyright_repl(object):
__slots__ = ('year',)
def __init__(self, year):
self.year = year
def __call__(self, matchobj):
if matchobj.group(2) == self.year:
return matchobj.group(0)
else:
return matchobj.group(1) + matchobj.group(2) + \
b'-' + self.year + matchobj.group(3)
def update_copyright_year(year, line):
"""
These two regexes are taken from echangelog
update_copyright(), except that we don't hardcode
1999 here (in order to be more generic).
"""
is_bytes = isinstance(line, bytes)
if is_bytes:
if not line.startswith(b'# Copyright '):
return line
else:
if not line.startswith('# Copyright '):
return line
year = _unicode_encode(year)
line = _unicode_encode(line)
line = _copyright_re1.sub(br'\1-' + year + br'\2', line)
line = _copyright_re2.sub(_copyright_repl(year), line)
if not is_bytes:
line = _unicode_decode(line)
return line
def update_copyright(fn_path, year, pretend=False):
"""
Check file for a Copyright statement, and update its year. The
patterns used for replacing copyrights are taken from echangelog.
Only the first lines of each file that start with a hash ('#') are
considered, until a line is found that doesn't start with a hash.
Files are read and written in binary mode, so that this function
will work correctly with files encoded in any character set, as
long as the copyright statements consist of plain ASCII.
"""
try:
fn_hdl = io.open(_unicode_encode(
fn_path, encoding=_encodings['fs'], errors='strict'),
mode='rb')
except EnvironmentError:
return
orig_header = []
new_header = []
for line in fn_hdl:
line_strip = line.strip()
orig_header.append(line)
if not line_strip or line_strip[:1] != b'#':
new_header.append(line)
break
line = update_copyright_year(year, line)
new_header.append(line)
difflines = 0
for diffline in difflib.unified_diff(
[_unicode_decode(diffline) for diffline in orig_header],
[_unicode_decode(diffline) for diffline in new_header],
fromfile=fn_path, tofile=fn_path, n=0):
util.writemsg_stdout(diffline, noiselevel=-1)
difflines += 1
util.writemsg_stdout("\n", noiselevel=-1)
# unified diff has three lines to start with
if difflines > 3 and not pretend:
# write new file with changed header
f, fnnew_path = mkstemp()
f = io.open(f, mode='wb')
for line in new_header:
f.write(line)
for line in fn_hdl:
f.write(line)
f.close()
try:
fn_stat = os.stat(fn_path)
except OSError:
fn_stat = None
shutil.move(fnnew_path, fn_path)
if fn_stat is None:
util.apply_permissions(fn_path, mode=0o644)
else:
util.apply_stat_permissions(fn_path, fn_stat)
fn_hdl.close()