devutils/platform_patches: preserve generic series changes on unmerge (#1550)

now if we add some patch to the middle of generic series, it should be
moved to generic repo instead of staying at the top of the series file
This commit is contained in:
jj authored and GitHub committed 2026-05-02 10:50:40 +02:00
1 parent 24d8d010d8
commit a50bc6fddd
1 file changed
+72 -35
+72 -35
View File
@@ -1,6 +1,10 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright (c) 2026 The Helium Authors
# You can use, redistribute, and/or modify this source code under
# the terms of the GPL-3.0 license that can be found in the LICENSE file.
# Copyright (c) 2019 The ungoogled-chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE.ungoogled_chromium file.
@@ -73,6 +77,7 @@ def _rename_files_with_dirs(root_dir, source_dir, sorted_file_iter):
complete_path = Path(root_dir, partial_path)
complete_source_path = Path(source_dir, partial_path)
try:
complete_source_path.parent.mkdir(parents=True, exist_ok=True)
complete_path.rename(complete_source_path)
except FileNotFoundError:
get_logger().warning('Could not move prepended patch: %s', complete_path)
@@ -87,6 +92,44 @@ def _rename_files_with_dirs(root_dir, source_dir, sorted_file_iter):
complete_path = complete_path.parent
def _series_path(series_line):
return series_line.split(' #', maxsplit=1)[0]
def _parse_series_metadata(series_lines):
paths = set()
# patch path -> list of lines after patch path and before next patch path
path_comments = {}
# patch path -> inline comment for patch
path_inline_comments = {}
previous_path = None
for partial_path in series_lines:
if not partial_path or partial_path.startswith('#'):
if previous_path not in path_comments:
path_comments[previous_path] = []
path_comments[previous_path].append(partial_path)
else:
previous_path = _series_path(partial_path)
paths.add(previous_path)
path_parts = partial_path.split(' #', maxsplit=1)
if len(path_parts) == 2:
path_inline_comments[previous_path] = path_parts[1]
return paths, path_comments, path_inline_comments
def _restore_series_metadata(series, path_comments, path_inline_comments):
series_index = 0
while series_index < len(series):
current_path = series[series_index]
clean_path = _series_path(current_path)
if clean_path in path_inline_comments:
series[series_index] = clean_path + ' #' + path_inline_comments[clean_path]
if clean_path in path_comments:
series.insert(series_index + 1, '\n'.join(path_comments[clean_path]))
series_index += 1
series_index += 1
def unmerge_platform_patches(platform_patches_dir, prepend_patches_dir):
'''
Undo merge_platform_patches(), adding any new patches from series.merged as necessary
@@ -97,54 +140,48 @@ def unmerge_platform_patches(platform_patches_dir, prepend_patches_dir):
get_logger().error('Unable to find series.prepend at: %s',
platform_patches_dir / _SERIES_PREPEND)
return False
prepend_series = set(
filter(len,
(platform_patches_dir / _SERIES_PREPEND).read_text(encoding=ENCODING).splitlines()))
# Move prepended files back to original location, preserving changes
_rename_files_with_dirs(platform_patches_dir, prepend_patches_dir, sorted(prepend_series))
prepend_series, prepend_path_comments, prepend_path_inline_comments = _parse_series_metadata(
(platform_patches_dir / _SERIES_PREPEND).read_text(encoding=ENCODING).splitlines())
# Determine positions of blank spaces in series.orig
if not (platform_patches_dir / _SERIES_ORIG).exists():
get_logger().error('Unable to find series.orig at: %s', platform_patches_dir / _SERIES_ORIG)
return False
orig_series = (platform_patches_dir / _SERIES_ORIG).read_text(encoding=ENCODING).splitlines()
# patch path -> list of lines after patch path and before next patch path
path_comments = {}
# patch path -> inline comment for patch
path_inline_comments = {}
previous_path = None
for partial_path in orig_series:
if not partial_path or partial_path.startswith('#'):
if partial_path not in path_comments:
path_comments[previous_path] = []
path_comments[previous_path].append(partial_path)
else:
path_parts = partial_path.split(' #', maxsplit=1)
previous_path = path_parts[0]
if len(path_parts) == 2:
path_inline_comments[path_parts[0]] = path_parts[1]
orig_series_paths, path_comments, path_inline_comments = _parse_series_metadata(
(platform_patches_dir / _SERIES_ORIG).read_text(encoding=ENCODING).splitlines())
# Apply changes on series.merged into a modified version of series.orig
if not (platform_patches_dir / _SERIES_MERGED).exists():
get_logger().error('Unable to find series.merged at: %s',
platform_patches_dir / _SERIES_MERGED)
return False
new_series = filter(len, (platform_patches_dir /
_SERIES_MERGED).read_text(encoding=ENCODING).splitlines())
new_series = filter((lambda x: x not in prepend_series), new_series)
new_series = list(new_series)
series_index = 0
while series_index < len(new_series):
current_path = new_series[series_index]
if current_path in path_inline_comments:
new_series[series_index] = current_path + ' #' + path_inline_comments[current_path]
if current_path in path_comments:
new_series.insert(series_index + 1, '\n'.join(path_comments[current_path]))
series_index += 1
series_index += 1
merged_series = filter(len, (platform_patches_dir /
_SERIES_MERGED).read_text(encoding=ENCODING).splitlines())
generic_series = []
new_series = []
in_platform_series = False
for current_path in merged_series:
clean_path = _series_path(current_path)
if clean_path in orig_series_paths:
in_platform_series = True
if clean_path in prepend_series or not in_platform_series:
generic_series.append(current_path)
else:
new_series.append(current_path)
# Move prepended files back to original location, preserving changes
# including any new patches added before the platform patch block.
_rename_files_with_dirs(
platform_patches_dir, prepend_patches_dir,
sorted(prepend_series.union(_series_path(patch_path) for patch_path in generic_series)))
_restore_series_metadata(generic_series, prepend_path_comments, prepend_path_inline_comments)
_restore_series_metadata(new_series, path_comments, path_inline_comments)
# Write series file
with (prepend_patches_dir / _SERIES).open('w', encoding=ENCODING) as series_file:
series_file.write('\n'.join(generic_series))
series_file.write('\n')
with (platform_patches_dir / _SERIES).open('w', encoding=ENCODING) as series_file:
series_file.write('\n'.join(new_series))
series_file.write('\n')