Skip to content

Commit 78bc675

Browse files
authored
Synchronize release 1.19 changes over master branch (#49)
* Mark 1.19 as stable version Signed-off-by: Uilian Ries <[email protected]> * Add workflow to validate patch-ng with Conan Signed-off-by: Uilian Ries <[email protected]> * Install Conan requirements for testing Signed-off-by: Uilian Ries <[email protected]> * Add CCI validation Signed-off-by: Uilian Ries <[email protected]> * Refer repo in a separte folder Signed-off-by: Uilian Ries <[email protected]> * Move test script Signed-off-by: Uilian Ries <[email protected]> * Try to fix test script path Signed-off-by: Uilian Ries <[email protected]> * Exclude recipe with system requirements Signed-off-by: Uilian Ries <[email protected]> * Trigger CI Signed-off-by: Uilian Ries <[email protected]> * Support a few non patch related errors Signed-off-by: Uilian Ries <[email protected]> * Allow missing binaries as an error Signed-off-by: Uilian Ries <[email protected]> * Fix condition Signed-off-by: Uilian Ries <[email protected]> * Exclude conans import Signed-off-by: Uilian Ries <[email protected]> * Update allowed errors Signed-off-by: Uilian Ries <[email protected]> * Fix quoted file paths Signed-off-by: Uilian Ries <[email protected]> --------- Signed-off-by: Uilian Ries <[email protected]>
1 parent 32364f4 commit 78bc675

File tree

7 files changed

+239
-2
lines changed

7 files changed

+239
-2
lines changed
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
#!/usr/bin/env bash
2+
3+
set -euo pipefail
4+
5+
# Get TEST_ALL_RECIPES from environment variable, default to 0 (false)
6+
PYTHON_NG_TEST_ALL_RECIPES=${PYTHON_NG_TEST_ALL_RECIPES:-0}
7+
8+
SAMPLE_RECIPES_NUM=30
9+
RECIPES_BUILD_NUM=10
10+
RECIPES_BUILT_COUNT=0
11+
12+
# Ensure required tools are installed
13+
COMMANDS=("conan" "yq" "jq")
14+
for cmd in "${COMMANDS[@]}"; do
15+
if ! which $cmd &> /dev/null; then
16+
echo "ERROR: $cmd is not installed. Please install $cmd to proceed."
17+
exit 1
18+
fi
19+
done
20+
21+
# Find all conanfile.py files that use apply_conandata_patches
22+
RECIPES=$(find . -type f -name "conanfile.py" -exec grep -l "apply_conandata_patches(self)" {} + | sort | uniq)
23+
# And does not need system requirement
24+
RECIPES=$(grep -L "/system" $RECIPES)
25+
# And does not contain Conan 1 imports
26+
RECIPES=$(grep -L "from conans" $RECIPES)
27+
28+
echo "Found $(echo "$RECIPES" | wc -l) recipes using apply_conandata_patches."
29+
30+
if [ "${PYTHON_NG_TEST_ALL_RECIPES}" -eq "1" ]; then
31+
SAMPLE_RECIPES_NUM=$(echo "$RECIPES" | wc -l)
32+
RECIPES_BUILD_NUM=$SAMPLE_RECIPES_NUM
33+
echo "PYTHON_NG_TEST_ALL_RECIPES is set to 1, testing all $SAMPLE_RECIPES_NUM recipes."
34+
else
35+
RECIPES=$(shuf -e ${RECIPES[@]} -n $SAMPLE_RECIPES_NUM)
36+
echo "Pick $SAMPLE_RECIPES_NUM random recipes to test:"
37+
echo "$RECIPES"
38+
fi
39+
40+
# Run conan create for each sampled recipe
41+
for it in $RECIPES; do
42+
43+
if [ $RECIPES_BUILT_COUNT -ge $RECIPES_BUILD_NUM ]; then
44+
echo "Reached the limit of $RECIPES_BUILD_NUM recipes built, stopping. All done."
45+
break
46+
fi
47+
48+
recipe_dir=$(dirname "${it}")
49+
pushd "$recipe_dir" > /dev/null
50+
echo "Testing recipe in directory: ${recipe_dir}"
51+
# Get a version from conandata.yml that uses a patch
52+
version=$(yq '.patches | keys | .[0]' conandata.yml 2>/dev/null)
53+
if [ -z "$version" ]; then
54+
echo "ERROR: No patches found in conandata.yml for $recipe_dir, skipping."
55+
popd > /dev/null
56+
continue
57+
fi
58+
version=$(echo ${version} | tr -d '"')
59+
# Replace apply_conandata_patches to exit just after applying patches
60+
sed -i -e 's/apply_conandata_patches(self)/apply_conandata_patches(self); import sys; sys.exit(0)/g' conanfile.py
61+
62+
# Allow conan create to fail without stopping the script, we will handle errors manually
63+
set +e
64+
65+
# Create the package with the specified version
66+
output=$(conan create . --version=${version} 2>&1)
67+
# Accept some errors as non-fatal
68+
if [ $? -ne 0 ]; then
69+
echo "WARNING: conan create failed for $recipe_dir"
70+
allowed_errors=(
71+
"ERROR: There are invalid packages"
72+
"ERROR: Version conflict"
73+
"ERROR: Missing binary"
74+
"Failed to establish a new connection"
75+
"ConanException: sha256 signature failed"
76+
"ConanException: Error downloading file"
77+
"ConanException: Cannot find"
78+
"certificate verify failed: certificate has expired"
79+
"NotFoundException: Not found"
80+
)
81+
# check if any allowed error is in the output
82+
if printf '%s\n' "${allowed_errors[@]}" | grep -q -f - <(echo "$output"); then
83+
echo "WARNING: Could not apply patches, skipping build:"
84+
echo "$output" | tail -n 10
85+
echo "-------------------------------------------------------"
86+
else
87+
echo "ERROR: Fatal error during conan create command execution:"
88+
echo "$output"
89+
popd > /dev/null
90+
exit 1
91+
fi
92+
else
93+
echo "INFO: Successfully patched $recipe_dir."
94+
echo "$output" | tail -n 10
95+
echo "-------------------------------------------------------"
96+
RECIPES_BUILT_COUNT=$((RECIPES_BUILT_COUNT + 1))
97+
fi
98+
popd > /dev/null
99+
done
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
name: Validate Applying Patch in Conan Center Index
2+
3+
on:
4+
push:
5+
paths-ignore:
6+
- 'doc/**'
7+
- '**/*.md'
8+
- 'LICENSE'
9+
- 'example/**'
10+
- '.gitignore'
11+
- 'tests/**'
12+
workflow_dispatch:
13+
pull_request:
14+
paths-ignore:
15+
- 'doc/**'
16+
- '**/*.md'
17+
- 'LICENSE'
18+
- 'example/**'
19+
- '.gitignore'
20+
- 'tests/**'
21+
22+
jobs:
23+
conan-center-index-validate:
24+
name: "Validate Patche-NG in Conan Center Index"
25+
runs-on: ubuntu-22.04
26+
steps:
27+
- name: Checkout repository
28+
uses: actions/checkout@v5
29+
with:
30+
path: python-ng
31+
32+
- name: Setup Conan client
33+
uses: conan-io/setup-conan@v1
34+
35+
- name: Setup Python NG
36+
run: pip install -e ./python-ng
37+
38+
- name: Checkout conan-center-index
39+
uses: actions/checkout@v5
40+
with:
41+
repository: conan-io/conan-center-index
42+
path: conan-center-index
43+
ref: 'd8efbb6f3c51b134205f01d3f8d90bdad1a67fe6'
44+
45+
- name: Validate Python-NG patch application
46+
working-directory: conan-center-index/recipes
47+
run: bash "${GITHUB_WORKSPACE}/python-ng/.github/scripts/validate-cci-patch-ng.sh"

.github/workflows/conan.yml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
name: Validate Conan client
2+
3+
on:
4+
push:
5+
paths-ignore:
6+
- 'doc/**'
7+
- '**/*.md'
8+
- 'LICENSE'
9+
- 'example/**'
10+
- '.gitignore'
11+
- 'tests/**'
12+
workflow_dispatch:
13+
pull_request:
14+
paths-ignore:
15+
- 'doc/**'
16+
- '**/*.md'
17+
- 'LICENSE'
18+
- 'example/**'
19+
- '.gitignore'
20+
- 'tests/**'
21+
22+
jobs:
23+
conan-client-validate:
24+
name: "Validate Conan client"
25+
runs-on: ubuntu-22.04
26+
steps:
27+
- uses: actions/checkout@v5
28+
29+
- name: Setup python
30+
uses: actions/setup-python@v6
31+
with:
32+
python-version: 3.12
33+
architecture: x64
34+
35+
- name: Clone conan client
36+
run: |
37+
git clone --depth 1 https://github.com/conan-io/conan.git
38+
cd conan/
39+
pip install -r conans/requirements_dev.txt
40+
pip install -r conans/requirements.txt
41+
42+
- name: Run Conan client tests involving patch-ng
43+
run: |
44+
pip install -e .
45+
cd conan/
46+
pytest -v test/functional/test_third_party_patch_flow.py
47+
pytest -v test/functional/tools/test_files.py
48+
pytest -v test/unittests/tools/files/test_patches.py

.github/workflows/workflow.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Main workflow
1+
name: Python Patch-NG Tests
22

33
on:
44
push:

patch_ng.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
SOFTWARE.
3030
"""
3131
__author__ = "Conan.io <[email protected]>"
32-
__version__ = "1.19.0-dev"
32+
__version__ = "1.19.0"
3333
__license__ = "MIT"
3434
__url__ = "https://github.com/conan-io/python-patch"
3535

@@ -900,6 +900,9 @@ def _normalize_filenames(self):
900900
p.source = xnormpath(p.source)
901901
p.target = xnormpath(p.target)
902902

903+
p.source = p.source.strip(b'"')
904+
p.target = p.target.strip(b'"')
905+
903906
sep = b'/' # sep value can be hardcoded, but it looks nice this way
904907

905908
# references to parent are not allowed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
diff '--color=auto' -ruN "b/Wrapper/FreeImage.NET/cs/Samples/Sample 01 - Loading and saving/Program.cs" "a/Wrapper/FreeImage.NET/cs/Samples/Sample 01 - Loading and saving/Program.cs"
2+
--- "b/Wrapper/FreeImage.NET/cs/Samples/Sample 01 - Loading and saving/Program.cs" 2025-10-08 15:56:02.302486070 +0200
3+
+++ "a/Wrapper/FreeImage.NET/cs/Samples/Sample 01 - Loading and saving/Program.cs" 2025-10-08 15:21:46.283174211 +0200
4+
@@ -1 +1 @@
5+
-feriunt summos, fulmina montes.
6+
+lux oculorum laetificat animam.

tests/run_tests.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -589,6 +589,40 @@ def test_add_move_and_update_file(self):
589589
content = f.read()
590590
self.assertTrue(b'dum tempus habemus, operemur bonum' in content)
591591

592+
class TestPatchFileWithSpaces(unittest.TestCase):
593+
594+
def setUp(self):
595+
self.save_cwd = os.getcwd()
596+
self.tmpdir = mkdtemp(prefix=self.__class__.__name__)
597+
shutil.copytree(join(TESTS, 'filewithspace'), join(self.tmpdir, 'filewithspace'))
598+
patch_folder = join(self.tmpdir, "a", "Wrapper", "FreeImage.NET", "cs", "Samples", "Sample 01 - Loading and saving")
599+
os.makedirs(patch_folder, exist_ok=True)
600+
self.program_cs = join(patch_folder, "Program.cs")
601+
with open(self.program_cs, 'w') as fd:
602+
fd.write("feriunt summos, fulmina montes.")
603+
604+
def tearDown(self):
605+
os.chdir(self.save_cwd)
606+
remove_tree_force(self.tmpdir)
607+
608+
def test_patch_with_white_space(self):
609+
"""When a patch file is generated using `diff -ruN b/ a/` command, and
610+
contains white spaces in the file path, the patch should be applied correctly.
611+
612+
Reported by https://github.com/conan-io/conan/issues/16727
613+
"""
614+
615+
os.chdir(self.tmpdir)
616+
print("TMPDIR:", self.tmpdir)
617+
pto = patch_ng.fromfile(join(self.tmpdir, 'filewithspace', '0001-quote.diff'))
618+
self.assertEqual(len(pto), 1)
619+
self.assertEqual(pto.items[0].type, patch_ng.PLAIN)
620+
self.assertTrue(pto.apply())
621+
with open(self.program_cs, 'rb') as f:
622+
content = f.read()
623+
self.assertTrue(b'lux oculorum laetificat animam.' in content)
624+
625+
592626
class TestHelpers(unittest.TestCase):
593627
# unittest setting
594628
longMessage = True

0 commit comments

Comments
 (0)