#!/usr/bin/python3
# -*- coding: utf-8 -*-
# Copyright (C) 2018 SUSE LLC
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
# USA.
"""
Script to insert new patches in series.conf according to the upstream order of
commits that the patches backport.
"""
import argparse
import collections
import sys
import pygit2_wrapper as pygit2
import exc
import git_sort
import lib
import series_conf
if __name__ == "__main__":
parser = argparse.ArgumentParser(
description="Insert new patches in series.conf according to the "
"upstream order of commits that the patches backport.")
parser.add_argument("patches", nargs="+", metavar="PATCH",
help="Patch file to insert in series.conf")
args = parser.parse_args()
repo_path = lib.repo_path()
repo = pygit2.Repository(repo_path)
index = lib.git_sort.SortIndex(repo)
try:
with open("series.conf") as f:
lines = f.readlines()
except IOError as err:
print("Error: could not open series file, %s" % (err,), file=sys.stderr)
sys.exit(1)
try:
before, inside, after = series_conf.split(lines)
current_entries = lib.parse_inside(index, inside, False)
except exc.KSError as err:
print("Error: %s" % (err,), file=sys.stderr)
sys.exit(1)
if list(filter(lib.tag_needs_update, current_entries)):
print("Error: Some Git-repo tags for patches currently in series.conf "
"are outdated. Please run series_sort.py first and commit the "
"result before adding new patches.", file=sys.stderr)
sys.exit(1)
current_names = set([entry.name for entry in current_entries])
current_revs = {rev : entry.name
for entry in current_entries
if entry.dest_head != git_sort.oot
for rev in entry.revs}
new_lines = set()
new_entries = []
for name in args.patches:
if name in current_names:
print("Error: patch \"%s\" is already in series.conf." % (name,),
file=sys.stderr)
sys.exit(1)
entry = lib.InputEntry("\t%s\n" % (name,))
new_lines.add(entry.value)
try:
entry.from_patch(index, name, git_sort.oot, True)
except exc.KSError as err:
print("Error: %s" % (err,), file=sys.stderr)
sys.exit(1)
if entry.dest_head != git_sort.oot:
for rev in entry.revs:
try:
match = current_revs[rev]
except KeyError:
continue
else:
print("Warning: commit %s in new patch \"%s\" is already "
"present in patch \"%s\" from series.conf." % (
rev[12:], entry.name, match,), file=sys.stderr)
new_entries.append(entry)
try:
sorted_entries = lib.series_sort(index, current_entries + new_entries)
except exc.KSError as err:
print("Error: %s" % (err,), file=sys.stderr)
sys.exit(1)
cur_sorted_entries = collections.OrderedDict()
for head, lines in list(sorted_entries.items()):
current_lines = [line for line in lines if line not in new_lines]
if current_lines:
cur_sorted_entries[head] = current_lines
cur_inside = lib.flatten([
lib.series_header(inside),
lib.series_format(cur_sorted_entries),
lib.series_footer(inside),
])
if inside != cur_inside:
print("Error: Current series.conf is not sorted. "
"Please run series_sort.py first and commit the result before "
"adding new patches.", file=sys.stderr)
sys.exit(1)
new_inside = lib.flatten([
lib.series_header(inside),
lib.series_format(sorted_entries),
lib.series_footer(inside),
])
output = lib.flatten([
before,
new_inside,
after,
])
with open("series.conf", mode="w") as f:
f.writelines(output)
try:
lib.update_tags(index, list(filter(lib.tag_needs_update, new_entries)))
except exc.KSError as err:
print("Error: %s" % (err,), file=sys.stderr)
sys.exit(1)