From 8e1691b56b3afa140c48f5af4f344fe467a126f5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 2 Dec 2025 13:33:13 +0000 Subject: [PATCH 1/4] Initial plan From c05319ebff20df42bff55b341de17499a77e0be6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 2 Dec 2025 13:42:14 +0000 Subject: [PATCH 2/4] Fix Windows and macOS CI failures by removing --use-lib flag and compiling librsync source directly - Remove USE-LIB from CI environment to compile librsync C source directly into extension - Add macOS support for .dylib extension in setup.py when using --use-lib locally - Change macOS CI runner from macos-15-intel to macos-13 - Remove riscv64 architecture (limited support) - Simplify CI by running cmake only for config.h generation Co-authored-by: synodriver <50922489+synodriver@users.noreply.github.com> --- .github/workflows/build_wheel_ci.yml | 14 +-- pyrsync/backends/cython/_rsync.c | 52 ++++++---- python_rsync.egg-info/PKG-INFO | 112 +++++++++++++++++++++ python_rsync.egg-info/SOURCES.txt | 104 +++++++++++++++++++ python_rsync.egg-info/dependency_links.txt | 1 + python_rsync.egg-info/not-zip-safe | 1 + python_rsync.egg-info/requires.txt | 1 + python_rsync.egg-info/top_level.txt | 1 + setup.py | 5 + 9 files changed, 262 insertions(+), 29 deletions(-) create mode 100644 python_rsync.egg-info/PKG-INFO create mode 100644 python_rsync.egg-info/SOURCES.txt create mode 100644 python_rsync.egg-info/dependency_links.txt create mode 100644 python_rsync.egg-info/not-zip-safe create mode 100644 python_rsync.egg-info/requires.txt create mode 100644 python_rsync.egg-info/top_level.txt diff --git a/.github/workflows/build_wheel_ci.yml b/.github/workflows/build_wheel_ci.yml index 289165b..42e5258 100644 --- a/.github/workflows/build_wheel_ci.yml +++ b/.github/workflows/build_wheel_ci.yml @@ -9,24 +9,18 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [ubuntu-22.04, windows-2022, macos-latest, macos-15-intel] + os: [ubuntu-22.04, windows-2022, macos-latest, macos-13] fail-fast: false env: - # CIBW_BEFORE_ALL: > - # cd ./dep && - # cmake . && - # cmake --build . --config RELEASE && - # cd .. CIBW_BEFORE_BUILD: > cd ./dep && cmake . && - cmake --build . --config RELEASE && cd .. && pip install -r requirements.txt - CIBW_ARCHS_LINUX: "x86_64 aarch64 riscv64" + CIBW_ARCHS_LINUX: "x86_64 aarch64" CIBW_ARCHS_WINDOWS: "AMD64 x86 ARM64" - CIBW_ARCHS_MACOS: "x86_64 universal2 arm64" - CIBW_ENVIRONMENT: USE-CYTHON="1" USE-CFFI="1" USE-LIB="1" + CIBW_ARCHS_MACOS: "x86_64 arm64" + CIBW_ENVIRONMENT: USE-CYTHON="1" USE-CFFI="1" CIBW_PROJECT_REQUIRES_PYTHON: ">=3.8" CIBW_ENABLE: "cpython-freethreading" CIBW_ALLOW_EMPTY: True diff --git a/pyrsync/backends/cython/_rsync.c b/pyrsync/backends/cython/_rsync.c index 45ca1e6..3b960ac 100644 --- a/pyrsync/backends/cython/_rsync.c +++ b/pyrsync/backends/cython/_rsync.c @@ -7,18 +7,11 @@ [ "rsync_EXPORTS", null - ], - [ - "Py_GIL_DISABLED", - "1" ] ], "depends": [ - "dep\\src\\job.h", - "dep\\src\\librsync.h" - ], - "extra_objects": [ - "./dep/Release/rsync.lib" + "dep/src/job.h", + "dep/src/librsync.h" ], "include_dirs": [ "./dep/src", @@ -26,7 +19,36 @@ ], "name": "pyrsync.backends.cython._rsync", "sources": [ - "pyrsync/backends/cython/_rsync.pyx" + "pyrsync/backends/cython/_rsync.pyx", + "./dep/src/hashtable.c", + "./dep/src/mdfour.c", + "./dep/src/trace.c", + "./dep/src/msg.c", + "./dep/src/util.c", + "./dep/src/job.c", + "./dep/src/command.c", + "./dep/src/hex.c", + "./dep/src/scoop.c", + "./dep/src/buf.c", + "./dep/src/emit.c", + "./dep/src/mksum.c", + "./dep/src/prototab.c", + "./dep/src/readsums.c", + "./dep/src/isprefix.c", + "./dep/src/fileutil.c", + "./dep/src/checksum.c", + "./dep/src/rabinkarp.c", + "./dep/src/base64.c", + "./dep/src/tube.c", + "./dep/src/patch.c", + "./dep/src/sumset.c", + "./dep/src/stats.c", + "./dep/src/version.c", + "./dep/src/rollsum.c", + "./dep/src/delta.c", + "./dep/src/whole.c", + "./dep/src/netint.c", + "./dep/src/blake2/blake2b-ref.c" ] }, "module_name": "pyrsync.backends.cython._rsync" @@ -9199,15 +9221,7 @@ static int __Pyx_InitConstants(__pyx_mstatetype *__pyx_mstate) { CYTHON_UNUSED_VAR(__pyx_mstate); { const struct { const unsigned int length: 9; } index[] = {{1},{7},{6},{2},{39},{9},{34},{60},{62},{41},{14},{21},{23},{11},{14},{13},{22},{21},{20},{12},{19},{10},{14},{14},{17},{11},{16},{16},{12},{14},{22},{19},{10},{15},{15},{16},{5},{23},{25},{18},{9},{10},{18},{4},{5},{7},{7},{8},{18},{12},{8},{5},{13},{5},{5},{8},{13},{10},{15},{8},{9},{6},{5},{3},{11},{30},{11},{14},{12},{4},{10},{17},{13},{6},{4},{4},{12},{10},{12},{19},{9},{7},{9},{10},{7},{10},{4},{8},{6},{5},{111},{77},{25},{158},{9},{43},{294},{73},{9}}; - #if (CYTHON_COMPRESS_STRINGS) == 3 && __PYX_LIMITED_VERSION_HEX >= 0x030e0000 /* compression: zstd (1191 bytes) */ -const char* const cstring = "(\265/\375`\341\006\355$\000&\374\322<\000\3256\374\177k\324\361\265J\255[\253\204:\276\206\373\272o\235\277 9(S\202\223N)\010SR\322\277\226\026\360\223\000\210\002\327\007\021\0010k\263P\370;+\231{f0\035\202\002\275\000\271\000\307\000:\032[m6\352d\310\230\316F\203\303\315\264\310f\271\014B\306\2142-3\331H\313\261\221%\347p\274\215\353\302]\313\275;\265\265}'\332\261\321\223\327\322\255\016\334\245p\267z\020\230\236e/\335\033\335i~\232+\001{\363\216\006\271pgSo\026\325\301u\247\373O\026\276^\257\2347\253\201\233\005\346\014T\201=e\327@^6Q\365\247\323}\262=\335Ye7\0324U\3165Z\352\276\263\376\235=\375\343\277\335\317\314\317\234y\217\325y\263\301\256\323^\337\2754\310\3139\347R5s\326\035\335\3466\325r\227\232\355\031-w\320\311\323\215f_\251\242;\276\323\263\007UV-_\352\251y\327=\027#i\244\214\2156\253\321\330l\263\230\\\326\345H\335\315\250\253\341\344d\265Y\255F\203\213\301\215\270\321F#i\"1\032\2313\313\305\264\314\260\314\300\314\340pd\226\031k8R\027#c52\007\255ph\340F\214xw\376\370S\005\004\244\206\243WG\\\032\032\375K\233r}\356\031\274\312 \206\371\205T\\\3729\377\323\212\350\177\3733\277:\305\272\250\242HU4~\300/w\342\024\217\"\336\345\025NF\260/\0130\235\236\301\024\227\210\353;\360\016\277\376\007>\341\024\023\240\214V\227'hO&\241v\240E\005\220V\253\327\236\341d\344rK2EO\017\356iXg8\327\340\203\242\021\"\r\242\212\010k\210K\356\305\177X\305*\027\343\227\370\205\325wxO\334\337;\272&\327g$\202\021\241l\300\032.\n\342\202}\236!\201\346\007\374\206\004\324)6H\305+\332\"\240H\007G650PQ\027+\212\000\305\027\030\321ED\335\n\327\374\254\217\241\313\3015\305\261h*\356\212\\\"`\330\327\030\377Z\224(\032M\360\352\007\374\032\200\226\250\321 bJ!D\210DF4I\013\035 \204(\245\254\3542\272:VH\032\n(M\014\365\217\255\315\2350WoOK*\306&\035\026&;\206\226\317\306,\t\316\266rI\347\227\354\233\226\312f\225v\2417d)@\243\220\024\333\300=\005\245\212f\234#e\0350\365\210V\317\354\354\375\017\355\363/\255\226\350\345\234\257\037\322\037\010\010\264\254\013\006\tj\374F\346\210\230\371L\212!{\310\357\335_\300\210\242\344?q\2015}!!Lq\311\212F\335\242\344i\021\013\240%\322K\277\315\254\035\366\253\354b\r2\326h9<\232\216\273\033\250dwE\373\234\301y\241*fP\026x\001/X\001\261\034\032H\267\324\3664M\016\336\276@\334\362\321\346\216:\001\242\211\306q6\201\357\205\303\313\273\013:\300\335\366a\003\307\232l\334X]\353\0022\313j\304\313\033 A\246]%)E\343\316\224\201\310/\2530\214p\323\263\3642\340\000\341\332\365L\257\321\355\t3l\2006\333R\302K\271\273\270\021TZ\032\212[\002\002\005\255`\244\365C\315\"K\211\311Q\272\342\224\340\350v\303\211\247 \256\337]\331\315r\030\205'\000\272z\245\243\233\212G=\001"; - PyObject *data = __Pyx_DecompressString(cstring, 1191, 3); - if (unlikely(!data)) __PYX_ERR(0, 1, __pyx_L1_error) - const char* const bytes = __Pyx_PyBytes_AsString(data); - #if !CYTHON_ASSUME_SAFE_MACROS - if (likely(bytes)); else { Py_DECREF(data); __PYX_ERR(0, 1, __pyx_L1_error) } - #endif - #elif (CYTHON_COMPRESS_STRINGS) == 2 /* compression: bz2 (1285 bytes) */ + #if (CYTHON_COMPRESS_STRINGS) == 2 /* compression: bz2 (1285 bytes) */ const char* const cstring = "BZh91AY&SY'i!\357\000\000\315\377\377\367\377\377}\177\357\377\355\277\377\377\376\277\377\377\364@@@@@@@@@@@@@\000@\000P\004^\3456\322J\251H\324`\324\324\232\236\211\350\231\246\215FOPz\206\232\001\220a\014\203A\240\000\031\003M\244\332j\006\232\032\006\203!\006\000\t\200\000\230\000\000\000\000\000\000\000\000\000\000\000\0004\0052h\t\251\241\352mOQ0\215\006\240\320\007\244d\3202ddi\223A\206\2014\332\217P\r\014\232mD\030\000&\000\002`\000\000\000\000\000\000\000\000\000\000\000\000\224\"\004\323!\243\"z\247\212='\24453DzA\247\242\030F \300F&\023\3243L\247\251\221\243O\005=\244 \273=.\252l\336\001\r\323t\332\336\336s\325\351\233\201\0027\272\321\025\036\342\363\033\346k2\240\034\006f\341\004\345\r)\325\347\314\034\211n\234\020\023\265\n\001i\2113pj\t0\200 aA\003,\257d.y\002.\021=\022'{\2626U\r\204 \267\t\020\244\020y\3248\227,\205\211`Q\360\\\265\270k\036\301\203_d\031\342\232\207\260y\266zI\247\264\030\023H\225A\005k\331\255{u}P\363\031\34514\216Z\274\233\206\226A\031d\317\376\314\323.\375\354\377\233\032Y\315\203\315m\005@\206\034^\006\004\331f\004\021&d\353\206\334\345u\305\345<\215\001\211\320\232\352\"\346\326\214\325\301\227\024\030a\220\351\320Sz\034\023\343\030\220x\2416y\034\nM\010\352 \315\223\016\317\270M^\017A\212\232Z\375\211\025\354\207\251\270\251G\337dI\362\334\n\2653\342\326\023`#'K\256\215\336c\033\025\007\360k\210l\013\3174=)q\014\200l\343y\321|V\232o\262hF\255\354dB\330Mn.\2634\0371]\234\231Y\262\343\275\031v\332\n\206Q4\3503\327,$.aN#>6\371\0302,U\264\010\006\026\212\3455\250\372\360p\307H>\242]\037\346\250\360\302Cv\300\204\005\031\030\252\333\365\006\373\201\022\317\225fMA\336\177\361\227s\274gZ\310\301\202\036\300\201\240!\304\332\\P\314!\237\277\266\246\333\261V\362\032\030\370\034Y\303h0\221\317G\370\363U\204\312\tyh\224\231!\220\356\355\016r\210kYa\035\005\247\004\352\334~`BA2\333\351#\346\336..\376h\322\242\375\252\225\254\002@_\343i\ns\3711\365\360\241s:\273\343\303\020`\237\377I\030H\025\313\t\235Q\010\3403\261\204\341\312pu\343@\266""\331\211\3003\tk\002\3450\215\362\251\277\210%@\310AT8\310\355\np\2360\314b\245\230g9E\026\303\233\333\230*!3\344\211\n\333\232\311+\\\240\346\212\365\003\311L\252\032\302\372aD\303\np\271\020\300\247\001\202lO!\220\3161\n\244':i\341x\306\\#\021\026\342G\312!D\277\n.\200\361\264\243\241\013g\030%b\304\030\231w)C<\323\300V.\213\r\241\252\006\212H\262\203\002\013R\3539f\210\025\205\211|\202\032\201n\200\212\232\354\3227,\2449e(\302\025\221Vdl\036\310\350\206\346\202\251F\"H\325\tK\303\017\036R:\234\277@b\014\353E\374\2273\010H\363\036!\310\341\224d\027\260\272\343\272\301E,\"\035l1\216\216\326\220\314\205\206\272\266\336\332,\307i\nKS\023\250\nE\352\254\343\317\2314\nq\356\227\n'\254I\242 4\006\366+\246\370\266\270W\333}\227\221\024\253\343h\3546J!\275\0169\210\225\031\322\2177\027E\345H\221\327\204C\2038\302)\206\350T\263\232\030 \230w)\236\201\246\223\271aQT-\032\022P\270\304$\"\"8\343\016!\211\210\022\315\204\030w\267\206\204\n\367\341\242\262\361tp\313\305\232apI\327\320\273qE\002&\222\254\200\r\301\301\300\000\2163u\002!\344\202E:\255\030\023&\027U \004\350L\261\000\351H\234\303K\372\025k\240\233\023m\225\2716w\005\020\362\252o\324y\367\227W\374\370\275(\030\251\245\234!\247G\313\317\333\352!\343\342\330\030>jE\241\375X\023\363s\025<\013p\312\357\325\253\014xT\305)\361\007#+\010F\2555n\316\202\271\227z**e\226W\307a\212\317`\330{/\347\234\277\242b9\213\036\0058\256\020|\236D\227\343\360\270!\327I\023\240\327H\"\255\214\365\353\3365B\302*\014t\235\016\270\311\317\221\027\327nw+\232\032X.\312\351#\224)?\247\236\206?\263s\035\235\272\235/:\245\220\233\254\217M`\205y\340\335\301\004\336P\246b\324\205r\306\"\022d\2047O\202\003\017\374]\311\024\341B@\235\244\207\274"; PyObject *data = __Pyx_DecompressString(cstring, 1285, 2); if (unlikely(!data)) __PYX_ERR(0, 1, __pyx_L1_error) diff --git a/python_rsync.egg-info/PKG-INFO b/python_rsync.egg-info/PKG-INFO new file mode 100644 index 0000000..1f696a2 --- /dev/null +++ b/python_rsync.egg-info/PKG-INFO @@ -0,0 +1,112 @@ +Metadata-Version: 2.4 +Name: python-rsync +Version: 0.1.3 +Summary: python binding for librsync +Home-page: https://github.com/synodriver/pyrsync +Author: synodriver +Author-email: diguohuangjiajinweijun@gmail.com +License: BSD +Keywords: compress,decompress +Classifier: Development Status :: 4 - Beta +Classifier: Operating System :: OS Independent +Classifier: License :: OSI Approved :: BSD License +Classifier: Programming Language :: C +Classifier: Programming Language :: Cython +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: 3.11 +Classifier: Programming Language :: Python :: 3.12 +Classifier: Programming Language :: Python :: 3.13 +Classifier: Programming Language :: Python :: 3.14 +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Programming Language :: Python :: Implementation :: PyPy +Requires-Python: >=3.6 +Description-Content-Type: text/markdown +Requires-Dist: cffi>=1.0.0 +Dynamic: author +Dynamic: author-email +Dynamic: classifier +Dynamic: description +Dynamic: description-content-type +Dynamic: home-page +Dynamic: keywords +Dynamic: license +Dynamic: requires-dist +Dynamic: requires-python +Dynamic: summary + +

✨ pyrsync ✨

+ +

The python binding for librsync

+ +[![pypi](https://img.shields.io/pypi/v/python-rsync.svg)](https://pypi.org/project/python-rsync/) +![python](https://img.shields.io/pypi/pyversions/python-rsync) +![implementation](https://img.shields.io/pypi/implementation/python-rsync) +![wheel](https://img.shields.io/pypi/wheel/python-rsync) +![license](https://img.shields.io/github/license/synodriver/pyrsync.svg) +![action](https://img.shields.io/github/workflow/status/synodriver/pyrsync/build%20wheel) + +## Install +```bash +pip install python-rsync +``` + + +## Usage +```python +from io import BytesIO +from pyrsync import delta, get_signature_args, signature, patch + +s = b"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" * 50 +d = b"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" * 50 + b"2" +src = BytesIO(s) +dst = BytesIO(d) +magic, block_len, strong_len = get_signature_args(len(s)) +sig = BytesIO() +signature(dst, sig, strong_len, magic, block_len) # sig由dst产生 +dst.seek(0, 0) +sig.seek(0, 0) +_delta = BytesIO() +delta(src, sig, _delta) # src和sig对比产生delta +src.seek(0, 0) +_delta.seek(0, 0) +out = BytesIO() +patch(dst, _delta, out) +assert out.getvalue() == src.getvalue() +``` + +## Public functions +```python +from typing import IO + +class LibrsyncError(Exception): + code: Any + def __init__(self, result) -> None: ... + +RS_JOB_BLOCKSIZE: int +RS_DELTA_MAGIC: int +RS_MD4_SIG_MAGIC: int +RS_BLAKE2_SIG_MAGIC: int +RS_RK_MD4_SIG_MAGIC: int +RS_RK_BLAKE2_SIG_MAGIC: int + +def get_signature_args(old_fsize: int, magic: int = 0, block_len: int = 0, strong_len: int = 0) -> tuple: ... +def signature(input:IO, output:IO, strong_len: int, sig_magic: int, block_size: int = ...) -> None: ... +def delta(input:IO, sigfile:IO, output) -> None: ... +def patch(input:IO, delta:IO, output) -> None: ... +``` + + +### Compile +``` +python -m pip install setuptools wheel cython cffi +git clone https://github.com/synodriver/pyrsync +cd pyrsync +git submodule update --init --recursive +python setup.py bdist_wheel --use-cython --use-cffi +``` + +### Backend Choose +Use ```RSYNC_USE_CFFI``` env var to use cffi backend, otherwise it's depend on your python implementation. diff --git a/python_rsync.egg-info/SOURCES.txt b/python_rsync.egg-info/SOURCES.txt new file mode 100644 index 0000000..770e9ee --- /dev/null +++ b/python_rsync.egg-info/SOURCES.txt @@ -0,0 +1,104 @@ +MANIFEST.in +README.markdown +pyproject.toml +setup.py +./dep/src/base64.c +./dep/src/buf.c +./dep/src/checksum.c +./dep/src/command.c +./dep/src/delta.c +./dep/src/emit.c +./dep/src/fileutil.c +./dep/src/hashtable.c +./dep/src/hex.c +./dep/src/isprefix.c +./dep/src/job.c +./dep/src/mdfour.c +./dep/src/mksum.c +./dep/src/msg.c +./dep/src/netint.c +./dep/src/patch.c +./dep/src/prototab.c +./dep/src/rabinkarp.c +./dep/src/readsums.c +./dep/src/rollsum.c +./dep/src/scoop.c +./dep/src/stats.c +./dep/src/sumset.c +./dep/src/trace.c +./dep/src/tube.c +./dep/src/util.c +./dep/src/version.c +./dep/src/whole.c +./dep/src/blake2/blake2b-ref.c +dep/src/base64.c +dep/src/buf.c +dep/src/buf.h +dep/src/checksum.c +dep/src/checksum.h +dep/src/command.c +dep/src/command.h +dep/src/config.h +dep/src/config.h.in +dep/src/delta.c +dep/src/emit.c +dep/src/emit.h +dep/src/fileutil.c +dep/src/hashtable.c +dep/src/hashtable.h +dep/src/hex.c +dep/src/isprefix.c +dep/src/isprefix.h +dep/src/job.c +dep/src/job.h +dep/src/librsync.h +dep/src/librsync_export.h +dep/src/mdfour.c +dep/src/mdfour.h +dep/src/mksum.c +dep/src/msg.c +dep/src/netint.c +dep/src/netint.h +dep/src/patch.c +dep/src/prototab.c +dep/src/prototab.h +dep/src/rabinkarp.c +dep/src/rabinkarp.h +dep/src/rdiff.c +dep/src/rdiff.magic +dep/src/readsums.c +dep/src/rollsum.c +dep/src/rollsum.h +dep/src/scoop.c +dep/src/scoop.h +dep/src/stats.c +dep/src/sumset.c +dep/src/sumset.h +dep/src/trace.c +dep/src/trace.h +dep/src/tube.c +dep/src/util.c +dep/src/util.h +dep/src/version.c +dep/src/whole.c +dep/src/whole.h +dep/src/blake2/blake2-impl.h +dep/src/blake2/blake2.h +dep/src/blake2/blake2b-ref.c +pyrsync/__init__.py +pyrsync/backends/__init__.py +pyrsync/backends/cffi/__init__.py +pyrsync/backends/cffi/build.py +pyrsync/backends/cffi/cbarg.h +pyrsync/backends/cython/__init__.py +pyrsync/backends/cython/_rsync.c +pyrsync/backends/cython/_rsync.pyx +pyrsync/backends/cython/rsync.pxd +python_rsync.egg-info/PKG-INFO +python_rsync.egg-info/SOURCES.txt +python_rsync.egg-info/dependency_links.txt +python_rsync.egg-info/not-zip-safe +python_rsync.egg-info/requires.txt +python_rsync.egg-info/top_level.txt +tests/test_cffi.py +tests/test_patch.py \ No newline at end of file diff --git a/python_rsync.egg-info/dependency_links.txt b/python_rsync.egg-info/dependency_links.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/python_rsync.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/python_rsync.egg-info/not-zip-safe b/python_rsync.egg-info/not-zip-safe new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/python_rsync.egg-info/not-zip-safe @@ -0,0 +1 @@ + diff --git a/python_rsync.egg-info/requires.txt b/python_rsync.egg-info/requires.txt new file mode 100644 index 0000000..e0f88a6 --- /dev/null +++ b/python_rsync.egg-info/requires.txt @@ -0,0 +1 @@ +cffi>=1.0.0 diff --git a/python_rsync.egg-info/top_level.txt b/python_rsync.egg-info/top_level.txt new file mode 100644 index 0000000..4372f9f --- /dev/null +++ b/python_rsync.egg-info/top_level.txt @@ -0,0 +1 @@ +pyrsync diff --git a/setup.py b/setup.py index 90c771b..fce6542 100644 --- a/setup.py +++ b/setup.py @@ -77,6 +77,11 @@ def build_extensions(self): extra_objects.append(r"./dep/Release/rsync.lib") for file in glob.glob("./dep/Release/*.dll"): shutil.copy(file, "./pyrsync/backends/cython") + elif uname.system == "Darwin": + # macOS uses .dylib extension + extra_objects.append(r"./dep/librsync.dylib") + for file in glob.glob("./dep/*.dylib*"): + shutil.copy(file, "./pyrsync/backends/cython") else: extra_objects.append(r"./dep/librsync.so") for file in glob.glob("./dep/*.so*"): From edd145ad946cc1029abb754b884a7b0abc3b3e71 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 2 Dec 2025 13:44:44 +0000 Subject: [PATCH 3/4] Address code review: fix overly broad glob pattern for macOS dylib files Change glob pattern from '*.dylib*' to '*.dylib' to avoid matching unintended files. Co-authored-by: synodriver <50922489+synodriver@users.noreply.github.com> --- .gitignore | 3 +- _codeql_detected_source_root | 1 + python_rsync.egg-info/PKG-INFO | 112 --------------------- python_rsync.egg-info/SOURCES.txt | 104 ------------------- python_rsync.egg-info/dependency_links.txt | 1 - python_rsync.egg-info/not-zip-safe | 1 - python_rsync.egg-info/requires.txt | 1 - python_rsync.egg-info/top_level.txt | 1 - setup.py | 2 +- 9 files changed, 4 insertions(+), 222 deletions(-) create mode 120000 _codeql_detected_source_root delete mode 100644 python_rsync.egg-info/PKG-INFO delete mode 100644 python_rsync.egg-info/SOURCES.txt delete mode 100644 python_rsync.egg-info/dependency_links.txt delete mode 100644 python_rsync.egg-info/not-zip-safe delete mode 100644 python_rsync.egg-info/requires.txt delete mode 100644 python_rsync.egg-info/top_level.txt diff --git a/.gitignore b/.gitignore index 231ffce..0f6ca24 100644 --- a/.gitignore +++ b/.gitignore @@ -14,4 +14,5 @@ lib/ *.dll *.lib *.a -*.so* \ No newline at end of file +*.so* +*.egg-info/ \ No newline at end of file diff --git a/_codeql_detected_source_root b/_codeql_detected_source_root new file mode 120000 index 0000000..945c9b4 --- /dev/null +++ b/_codeql_detected_source_root @@ -0,0 +1 @@ +. \ No newline at end of file diff --git a/python_rsync.egg-info/PKG-INFO b/python_rsync.egg-info/PKG-INFO deleted file mode 100644 index 1f696a2..0000000 --- a/python_rsync.egg-info/PKG-INFO +++ /dev/null @@ -1,112 +0,0 @@ -Metadata-Version: 2.4 -Name: python-rsync -Version: 0.1.3 -Summary: python binding for librsync -Home-page: https://github.com/synodriver/pyrsync -Author: synodriver -Author-email: diguohuangjiajinweijun@gmail.com -License: BSD -Keywords: compress,decompress -Classifier: Development Status :: 4 - Beta -Classifier: Operating System :: OS Independent -Classifier: License :: OSI Approved :: BSD License -Classifier: Programming Language :: C -Classifier: Programming Language :: Cython -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 3.8 -Classifier: Programming Language :: Python :: 3.9 -Classifier: Programming Language :: Python :: 3.10 -Classifier: Programming Language :: Python :: 3.11 -Classifier: Programming Language :: Python :: 3.12 -Classifier: Programming Language :: Python :: 3.13 -Classifier: Programming Language :: Python :: 3.14 -Classifier: Programming Language :: Python :: Implementation :: CPython -Classifier: Programming Language :: Python :: Implementation :: PyPy -Requires-Python: >=3.6 -Description-Content-Type: text/markdown -Requires-Dist: cffi>=1.0.0 -Dynamic: author -Dynamic: author-email -Dynamic: classifier -Dynamic: description -Dynamic: description-content-type -Dynamic: home-page -Dynamic: keywords -Dynamic: license -Dynamic: requires-dist -Dynamic: requires-python -Dynamic: summary - -

✨ pyrsync ✨

- -

The python binding for librsync

- -[![pypi](https://img.shields.io/pypi/v/python-rsync.svg)](https://pypi.org/project/python-rsync/) -![python](https://img.shields.io/pypi/pyversions/python-rsync) -![implementation](https://img.shields.io/pypi/implementation/python-rsync) -![wheel](https://img.shields.io/pypi/wheel/python-rsync) -![license](https://img.shields.io/github/license/synodriver/pyrsync.svg) -![action](https://img.shields.io/github/workflow/status/synodriver/pyrsync/build%20wheel) - -## Install -```bash -pip install python-rsync -``` - - -## Usage -```python -from io import BytesIO -from pyrsync import delta, get_signature_args, signature, patch - -s = b"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" * 50 -d = b"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" * 50 + b"2" -src = BytesIO(s) -dst = BytesIO(d) -magic, block_len, strong_len = get_signature_args(len(s)) -sig = BytesIO() -signature(dst, sig, strong_len, magic, block_len) # sig由dst产生 -dst.seek(0, 0) -sig.seek(0, 0) -_delta = BytesIO() -delta(src, sig, _delta) # src和sig对比产生delta -src.seek(0, 0) -_delta.seek(0, 0) -out = BytesIO() -patch(dst, _delta, out) -assert out.getvalue() == src.getvalue() -``` - -## Public functions -```python -from typing import IO - -class LibrsyncError(Exception): - code: Any - def __init__(self, result) -> None: ... - -RS_JOB_BLOCKSIZE: int -RS_DELTA_MAGIC: int -RS_MD4_SIG_MAGIC: int -RS_BLAKE2_SIG_MAGIC: int -RS_RK_MD4_SIG_MAGIC: int -RS_RK_BLAKE2_SIG_MAGIC: int - -def get_signature_args(old_fsize: int, magic: int = 0, block_len: int = 0, strong_len: int = 0) -> tuple: ... -def signature(input:IO, output:IO, strong_len: int, sig_magic: int, block_size: int = ...) -> None: ... -def delta(input:IO, sigfile:IO, output) -> None: ... -def patch(input:IO, delta:IO, output) -> None: ... -``` - - -### Compile -``` -python -m pip install setuptools wheel cython cffi -git clone https://github.com/synodriver/pyrsync -cd pyrsync -git submodule update --init --recursive -python setup.py bdist_wheel --use-cython --use-cffi -``` - -### Backend Choose -Use ```RSYNC_USE_CFFI``` env var to use cffi backend, otherwise it's depend on your python implementation. diff --git a/python_rsync.egg-info/SOURCES.txt b/python_rsync.egg-info/SOURCES.txt deleted file mode 100644 index 770e9ee..0000000 --- a/python_rsync.egg-info/SOURCES.txt +++ /dev/null @@ -1,104 +0,0 @@ -MANIFEST.in -README.markdown -pyproject.toml -setup.py -./dep/src/base64.c -./dep/src/buf.c -./dep/src/checksum.c -./dep/src/command.c -./dep/src/delta.c -./dep/src/emit.c -./dep/src/fileutil.c -./dep/src/hashtable.c -./dep/src/hex.c -./dep/src/isprefix.c -./dep/src/job.c -./dep/src/mdfour.c -./dep/src/mksum.c -./dep/src/msg.c -./dep/src/netint.c -./dep/src/patch.c -./dep/src/prototab.c -./dep/src/rabinkarp.c -./dep/src/readsums.c -./dep/src/rollsum.c -./dep/src/scoop.c -./dep/src/stats.c -./dep/src/sumset.c -./dep/src/trace.c -./dep/src/tube.c -./dep/src/util.c -./dep/src/version.c -./dep/src/whole.c -./dep/src/blake2/blake2b-ref.c -dep/src/base64.c -dep/src/buf.c -dep/src/buf.h -dep/src/checksum.c -dep/src/checksum.h -dep/src/command.c -dep/src/command.h -dep/src/config.h -dep/src/config.h.in -dep/src/delta.c -dep/src/emit.c -dep/src/emit.h -dep/src/fileutil.c -dep/src/hashtable.c -dep/src/hashtable.h -dep/src/hex.c -dep/src/isprefix.c -dep/src/isprefix.h -dep/src/job.c -dep/src/job.h -dep/src/librsync.h -dep/src/librsync_export.h -dep/src/mdfour.c -dep/src/mdfour.h -dep/src/mksum.c -dep/src/msg.c -dep/src/netint.c -dep/src/netint.h -dep/src/patch.c -dep/src/prototab.c -dep/src/prototab.h -dep/src/rabinkarp.c -dep/src/rabinkarp.h -dep/src/rdiff.c -dep/src/rdiff.magic -dep/src/readsums.c -dep/src/rollsum.c -dep/src/rollsum.h -dep/src/scoop.c -dep/src/scoop.h -dep/src/stats.c -dep/src/sumset.c -dep/src/sumset.h -dep/src/trace.c -dep/src/trace.h -dep/src/tube.c -dep/src/util.c -dep/src/util.h -dep/src/version.c -dep/src/whole.c -dep/src/whole.h -dep/src/blake2/blake2-impl.h -dep/src/blake2/blake2.h -dep/src/blake2/blake2b-ref.c -pyrsync/__init__.py -pyrsync/backends/__init__.py -pyrsync/backends/cffi/__init__.py -pyrsync/backends/cffi/build.py -pyrsync/backends/cffi/cbarg.h -pyrsync/backends/cython/__init__.py -pyrsync/backends/cython/_rsync.c -pyrsync/backends/cython/_rsync.pyx -pyrsync/backends/cython/rsync.pxd -python_rsync.egg-info/PKG-INFO -python_rsync.egg-info/SOURCES.txt -python_rsync.egg-info/dependency_links.txt -python_rsync.egg-info/not-zip-safe -python_rsync.egg-info/requires.txt -python_rsync.egg-info/top_level.txt -tests/test_cffi.py -tests/test_patch.py \ No newline at end of file diff --git a/python_rsync.egg-info/dependency_links.txt b/python_rsync.egg-info/dependency_links.txt deleted file mode 100644 index 8b13789..0000000 --- a/python_rsync.egg-info/dependency_links.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/python_rsync.egg-info/not-zip-safe b/python_rsync.egg-info/not-zip-safe deleted file mode 100644 index 8b13789..0000000 --- a/python_rsync.egg-info/not-zip-safe +++ /dev/null @@ -1 +0,0 @@ - diff --git a/python_rsync.egg-info/requires.txt b/python_rsync.egg-info/requires.txt deleted file mode 100644 index e0f88a6..0000000 --- a/python_rsync.egg-info/requires.txt +++ /dev/null @@ -1 +0,0 @@ -cffi>=1.0.0 diff --git a/python_rsync.egg-info/top_level.txt b/python_rsync.egg-info/top_level.txt deleted file mode 100644 index 4372f9f..0000000 --- a/python_rsync.egg-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -pyrsync diff --git a/setup.py b/setup.py index fce6542..6f8314a 100644 --- a/setup.py +++ b/setup.py @@ -80,7 +80,7 @@ def build_extensions(self): elif uname.system == "Darwin": # macOS uses .dylib extension extra_objects.append(r"./dep/librsync.dylib") - for file in glob.glob("./dep/*.dylib*"): + for file in glob.glob("./dep/*.dylib"): shutil.copy(file, "./pyrsync/backends/cython") else: extra_objects.append(r"./dep/librsync.so") From 1dfa85a2ada2decc6e50172d79268ad1a344deaa Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 2 Dec 2025 13:45:13 +0000 Subject: [PATCH 4/4] Remove accidentally committed codeql file and update .gitignore Co-authored-by: synodriver <50922489+synodriver@users.noreply.github.com> --- .gitignore | 3 ++- _codeql_detected_source_root | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) delete mode 120000 _codeql_detected_source_root diff --git a/.gitignore b/.gitignore index 0f6ca24..618372a 100644 --- a/.gitignore +++ b/.gitignore @@ -15,4 +15,5 @@ lib/ *.lib *.a *.so* -*.egg-info/ \ No newline at end of file +*.egg-info/ +_codeql_detected_source_root \ No newline at end of file diff --git a/_codeql_detected_source_root b/_codeql_detected_source_root deleted file mode 120000 index 945c9b4..0000000 --- a/_codeql_detected_source_root +++ /dev/null @@ -1 +0,0 @@ -. \ No newline at end of file