From 6d40eaf17414446e096444c2a8ed1ceee1728742 Mon Sep 17 00:00:00 2001 From: RyuJongJin <266630912+RyuJongJin@users.noreply.github.com> Date: Mon, 19 Oct 2026 22:34:20 +0900 Subject: [PATCH] =?UTF-8?q?WIP=20177=20=EB=B3=B4=EC=B6=A9=204=20(28=20?= =?UTF-8?q?=ED=99=95=EC=9D=B8):=20=EB=B6=99=EC=97=AC=20=EC=93=B4=20-f"+=20?= =?UTF-8?q?*.txt"=20=EB=8F=84=20=EA=B7=9C=EC=B9=99=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EC=9D=BD=EC=9D=8C=20(=EC=98=88=EC=A0=84=EC=97=90=EB=8A=94=20?= =?UTF-8?q?=EB=A7=90=EC=97=86=EC=9D=B4=20=EB=B2=84=EB=A0=A4=20=EC=A7=80?= =?UTF-8?q?=EC=9A=B8=20=EB=AA=A9=EB=A1=9D=EC=9D=B4=20=EC=A0=81=EA=B2=8C=20?= =?UTF-8?q?=EB=B3=B4=EC=98=80=EB=8B=A4)=20=C2=B7=20--files-from=20?= =?UTF-8?q?=EC=9D=80=20"=EB=AF=B8=EB=A6=AC=20=EB=B3=BC=20=EC=88=98=20?= =?UTF-8?q?=EC=97=86=EC=9D=8C"=20(=EA=B2=80=ED=86=A0=20=EB=8C=80=EA=B8=B0)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 --- lib/core/rsync_filter.dart | 7 +++++++ test/rsync_filter_test.dart | 8 ++++++++ 2 files changed, 15 insertions(+) diff --git a/lib/core/rsync_filter.dart b/lib/core/rsync_filter.dart index ce5eee3..1a3a9f6 100644 --- a/lib/core/rsync_filter.dart +++ b/lib/core/rsync_filter.dart @@ -95,6 +95,13 @@ class RsyncFilter { filterRule(v!); } else if (o == '-f' && i + 1 < t.length) { filterRule(t[++i]); + } else if (o.startsWith('-f') && !o.startsWith('--')) { + // 28 확인: -f"+ *.txt" 처럼 붙여 쓴 것 (따옴표가 벗겨져 "-f+ *.txt" 한 낱말) - 예전에는 말없이 버렸다 + filterRule(o.substring(2)); + } else if (o == '--files-from' || o.startsWith('--files-from=')) { + // 28 확인: 고른 파일만 보내므로 미리 보기와 다르다 (미리 보기는 더 많이 보임) - 알린다 + if (o == '--files-from' && i + 1 < t.length) i++; + unsupported.add(o); } else if (o == '--delete-excluded') { deleteExcluded = true; } else if (o == '--cvs-exclude' || o == '-F' || (o.startsWith('-') && !o.startsWith('--') && (o.contains('C') || o.contains('F')))) { diff --git a/test/rsync_filter_test.dart b/test/rsync_filter_test.dart index 8a4f117..d7b8a9a 100644 --- a/test/rsync_filter_test.dart +++ b/test/rsync_filter_test.dart @@ -53,6 +53,11 @@ void main() { expect(ex('--exclude="My Folder/"', 'My Folder', dir: true), isTrue); expect(ex('--filter="- *.bak"', 'x.bak'), isTrue); expect(ex('-f "+ keep.bak" -f "- *.bak"', 'keep.bak'), isFalse); + // 28 확인: 붙여 쓴 -f"…" 도 읽는다 · --files-from 은 미리 볼 수 없음 + expect(ex('-f"+ *.txt" --exclude=*', 'gone.txt'), isFalse); + expect(ex('-f"+ *.txt" --exclude=*', 'old.log'), isTrue); + expect(ex('-f"- *.log"', 'c.log'), isTrue); + expect(RsyncFilter.parse('--files-from=list.txt').unsupported, ['--files-from=list.txt']); }); test('--exclude-from 파일 (빈 줄 · # · + / - 머리) · 못 읽으면 알림 목록', () { final f = RsyncFilter.parse('--exclude-from=list.txt', @@ -272,6 +277,9 @@ void main() { '-a --delete-after --exclude=*.log', '-a --delete --exclude=**/x/', '-a --delete --include=*.txt --exclude=*.log --exclude=*/', + // 28 확인 (63ef362): 붙여 쓴 -f + '-a --delete -f"+ *.txt" --exclude=*', + '-a --delete -f"- *.log"', ].indexed) { test('${i + 1}: $opts', () async { if (!Platform.isWindows || !File(rsync).existsSync()) return markTestSkipped('앱에 든 rsync 가 없음');