diff options
-rwxr-xr-x | bin/repoman | 2 | ||||
-rw-r--r-- | pym/repoman/utilities.py | 164 |
2 files changed, 126 insertions, 40 deletions
diff --git a/bin/repoman b/bin/repoman index bec3b1e01..5b01825b7 100755 --- a/bin/repoman +++ b/bin/repoman @@ -2471,7 +2471,7 @@ else: new_changelog = utilities.UpdateChangeLog(checkdir_relative, \ catdir, pkgdir, \ clnew, clremoved, clchanged, \ - changelog_msg, options.pretend) + changelog_msg, options.pretend, repodir) if new_changelog is None: writemsg_level("!!! Updating the ChangeLog failed\n", \ level=logging.ERROR, noiselevel=-1) diff --git a/pym/repoman/utilities.py b/pym/repoman/utilities.py index c8cbba730..a3fdf12e0 100644 --- a/pym/repoman/utilities.py +++ b/pym/repoman/utilities.py @@ -523,8 +523,77 @@ def FindVCS(): return outvcs -def UpdateChangeLog(pkgdir, category, package, new, removed, changed, msg, pretend): - """ Write an entry to an existing ChangeLog, or create a new one. """ +def update_copyright(fn_path, year, pretend): + """ + 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. + """ + + try: + fn_hdl = io.open(_unicode_encode(fn_path, + encoding=_encodings['fs'], errors='strict'), + mode='r', encoding=_encodings['repo.content'], errors='replace') + 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] != '#': + new_header.append(line) + break + + # these two regexes are taken from + # echangelog update_copyright() + line = re.sub(r'^(# Copyright \d+) ', + r'\1-%s ' % year, line) + line = re.sub(r'^(# Copyright) \d\d\d\d-\d\d\d\d', + r'\1 1999-%s' % year, line) + new_header.append(line) + + difflines = 0 + for line in difflib.unified_diff(orig_header, new_header, + fromfile=fn_path, tofile=fn_path, n=0): + util.writemsg_stdout(line, 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='w', encoding=_encodings['repo.content'], + errors='backslashreplace') + 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() + +def UpdateChangeLog(pkgdir, category, package, new, removed, changed, \ + msg, pretend, repodir): + """ + Write an entry to an existing ChangeLog, or create a new one. + Updates copyright year on changed files, and updates the header of + ChangeLog with the contents of skel.ChangeLog. + """ # figure out who to write as if 'GENTOO_COMMITTER_NAME' in os.environ and \ @@ -547,10 +616,21 @@ def UpdateChangeLog(pkgdir, category, package, new, removed, changed, msg, prete logging.critical(err) return None + # ChangeLog times are in UTC + gmtime = time.gmtime() + year = time.strftime('%Y', gmtime) + date = time.strftime('%d %b %Y', gmtime) + + # check modified files and the ChangeLog for copyright updates + # patches and diffs (identified by .patch and .diff) are excluded + for fn in new + changed: + if fn.endswith('.diff') or fn.endswith('.patch'): + continue + update_copyright(os.path.join(pkgdir, fn), year, pretend) + cl_path = os.path.join(pkgdir, 'ChangeLog') clold_lines = [] clnew_lines = [] - old_header_lines = [] header_lines = [] try: @@ -560,42 +640,50 @@ def UpdateChangeLog(pkgdir, category, package, new, removed, changed, msg, prete except EnvironmentError: clold_file = None - # ChangeLog times are in UTC - gmtime = time.gmtime() + clskel_file = None + if clold_file is None: + # we will only need the ChangeLog skeleton if there is no + # ChangeLog yet + try: + clskel_path = os.path.join(repodir, 'skel.ChangeLog') + clskel_file = io.open(_unicode_encode(clskel_path, + encoding=_encodings['fs'], errors='strict'), + mode='r', encoding=_encodings['repo.content'], + errors='replace') + except EnvironmentError: + pass + f, clnew_path = mkstemp() - # create an empty ChangeLog.new with correct header first + # construct correct header first try: - f = io.open(f, mode='w', encoding=_encodings['repo.content'], - errors='backslashreplace') - - if clold_file is None: - header_lines.append(_unicode_decode('# ChangeLog for %s/%s\n' % - (category, package))) - year = time.strftime('%Y', gmtime) - header_lines.append(_unicode_decode('# Copyright 1999-' - '%s Gentoo Foundation; Distributed under the GPL v2\n' % year)) - header_lines.append(_unicode_decode('# $Header: $\n')) - header_lines.append(_unicode_decode('\n')) - else: + if clold_file is not None: + # retain header from old ChangeLog for line in clold_file: - line_strip = line.strip() - if line_strip and line[:1] != "#": - clold_lines.append(line) + line_strip = line.strip() + clold_lines.append(line) + if line_strip[:1] != '#': break - header_lines.append(line) + line = re.sub(r'^(# Copyright) \d\d\d\d-\d\d\d\d', + r'\1 1999-%s' % year, line) + clnew_lines.append(line) if not line_strip: break - - # update the copyright year - old_header_lines = header_lines[:] - if len(header_lines) >= 2: - header_lines[1] = re.sub(r'^(# Copyright \d\d\d\d)-\d\d\d\d ', - r'\1-%s ' % time.strftime('%Y', gmtime), header_lines[1]) + elif clskel_file is not None: + # read skel.ChangeLog up to first empty line + for line in clskel_file: + line_strip = line.strip() + if not line_strip: + break + line = line.replace('<CATEGORY>', category) + line = line.replace('<PACKAGE_NAME>', package) + line = re.sub(r'^(# Copyright \d\d\d\d)-\d\d\d\d ', + r'\1-%s ' % year, line) + clnew_lines.append(line) + clnew_lines.append(_unicode_decode('\n')) + clskel_file.close() # write new ChangeLog entry - clnew_lines.extend(header_lines) - date = time.strftime('%d %b %Y', gmtime) newebuild = False for fn in new: if not fn.endswith('.ebuild'): @@ -634,20 +722,18 @@ def UpdateChangeLog(pkgdir, category, package, new, removed, changed, msg, prete clnew_lines.append(_unicode_decode('%s\n' % line)) clnew_lines.append(_unicode_decode('\n')) + f = io.open(f, mode='w', encoding=_encodings['repo.content'], + errors='backslashreplace') + for line in clnew_lines: f.write(line) # append stuff from old ChangeLog if clold_file is not None: - # If the old ChangeLog didn't have a header, then # clold_lines may contain a saved non-header line # that we want to write first. - for line in clold_lines: - f.write(line) - - # Now prepend old_header_lines to clold_lines, for use - # in the unified_diff call below. - clold_lines = old_header_lines + clold_lines + if clold_lines and clold_lines[-1].strip(): + f.write(clold_lines[-1]) for line in clold_file: f.write(line) @@ -657,7 +743,7 @@ def UpdateChangeLog(pkgdir, category, package, new, removed, changed, msg, prete # show diff (do we want to keep on doing this, or only when # pretend?) for line in difflib.unified_diff(clold_lines, clnew_lines, - fromfile=cl_path, tofile=cl_path + '.new', n=0): + fromfile=cl_path, tofile=cl_path, n=0): util.writemsg_stdout(line, noiselevel=-1) util.writemsg_stdout("\n", noiselevel=-1) @@ -665,7 +751,7 @@ def UpdateChangeLog(pkgdir, category, package, new, removed, changed, msg, prete # remove what we've done os.remove(clnew_path) else: - # rename ChangeLog.new to ChangeLog, and set permissions + # rename to ChangeLog, and set permissions try: clold_stat = os.stat(cl_path) except OSError: |