diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..8d40d8f --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @everettjf diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..dec9e19 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,66 @@ +name: Bug report +description: Report a reproducible problem in GrapeCompare +title: "[Bug]: " +body: + - type: markdown + attributes: + value: | + Thanks for helping improve GrapeCompare. Please remove private information from paths, filenames, screenshots, and sample files before posting. + + - type: textarea + id: summary + attributes: + label: What happened? + description: Tell us what you expected and what happened instead. + placeholder: A clear, concise description of the problem. + validations: + required: true + + - type: textarea + id: reproduce + attributes: + label: Steps to reproduce + placeholder: | + 1. Open ... + 2. Compare ... + 3. See ... + validations: + required: true + + - type: input + id: version + attributes: + label: GrapeCompare version + placeholder: "For example: 1.1.0 (5)" + validations: + required: true + + - type: input + id: macos + attributes: + label: macOS version and Mac model + placeholder: "For example: macOS 27.0, MacBook Pro with Apple silicon" + validations: + required: true + + - type: textarea + id: sample + attributes: + label: Minimal sample or screenshot + description: Attach the smallest non-sensitive sample that reproduces the issue, if possible. + + - type: textarea + id: context + attributes: + label: Additional context + description: Include logs, file counts, approximate file sizes, or anything else that may help. + + - type: checkboxes + id: checks + attributes: + label: Checklist + options: + - label: I searched existing issues and did not find a duplicate. + required: true + - label: I removed private or confidential data from this report. + required: true diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..31bb76f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +blank_issues_enabled: false +contact_links: + - name: Security vulnerability + url: https://github.com/everettjf/GrapeCompare/security/advisories/new + about: Report security problems privately instead of opening a public issue. + - name: App Store support + url: https://github.com/everettjf/GrapeCompare/blob/main/SUPPORT.md + about: Read the support guide before opening an issue. diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 0000000..22349e8 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,48 @@ +name: Feature request +description: Suggest an improvement or new capability +title: "[Feature]: " +body: + - type: textarea + id: problem + attributes: + label: What problem would this solve? + description: Describe the workflow or limitation behind the request. + validations: + required: true + + - type: textarea + id: proposal + attributes: + label: Proposed solution + description: Explain what you would like GrapeCompare to do. + validations: + required: true + + - type: textarea + id: alternatives + attributes: + label: Alternatives considered + description: Share any workarounds or alternative designs you tried. + + - type: dropdown + id: area + attributes: + label: Area + options: + - File comparison + - Folder comparison + - Performance + - User interface + - Accessibility + - Documentation + - Other + validations: + required: true + + - type: checkboxes + id: checks + attributes: + label: Checklist + options: + - label: I searched existing issues and did not find a duplicate. + required: true diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..0cfa1d7 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,24 @@ +## Summary + +Describe the problem and the approach taken. + +## Validation + +- [ ] `bash macos/Tests/run-tests.sh` +- [ ] I manually tested the affected file/folder comparison workflow. +- [ ] I added or updated tests for behavior changes. +- [ ] I updated documentation for user-visible changes. + +## Performance impact + +If this touches comparison, scanning, filtering, or rendering performance, include reproducible before/after benchmark commands and results. Otherwise write “Not applicable.” + +## Screenshots + +Include before/after screenshots for visible UI changes, or write “Not applicable.” + +## Privacy and compatibility + +- [ ] The change keeps comparison data on-device. +- [ ] The change does not broaden filesystem permissions without explanation. +- [ ] The change preserves current macOS deployment compatibility, or documents why it changes. diff --git a/.github/release.yml b/.github/release.yml new file mode 100644 index 0000000..eac1d8a --- /dev/null +++ b/.github/release.yml @@ -0,0 +1,19 @@ +changelog: + categories: + - title: New features + labels: + - enhancement + - feature + - title: Performance + labels: + - performance + - title: Fixes + labels: + - bug + - fix + - title: Documentation + labels: + - documentation + - title: Other changes + labels: + - "*" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..fd0b5dd --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,27 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + core-tests: + name: Core correctness and stress tests + runs-on: macos-26 + timeout-minutes: 10 + + steps: + - name: Check out repository + uses: actions/checkout@v4 + + - name: Run core tests + run: bash macos/Tests/run-tests.sh diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..3fc3efb --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,21 @@ +# Code of Conduct + +GrapeCompare is committed to a welcoming, respectful, and productive community. + +## Expected behavior + +- Be considerate and constructive when discussing ideas or reviewing work. +- Focus criticism on code, design, and observable behavior rather than people. +- Welcome different levels of experience and help others participate effectively. +- Respect privacy. Never publish another person's confidential files, paths, logs, or identifying information. +- Accept maintainers' decisions about project scope and moderation. + +## Unacceptable behavior + +Harassment, discrimination, threats, personal attacks, deliberate disruption, and publishing private information without permission are not tolerated in project spaces. + +## Reporting and enforcement + +Report conduct concerns privately using the contact information on [the maintainer's GitHub profile](https://github.com/everettjf). Do not open a public issue for a sensitive report. Reports will be reviewed fairly and kept confidential to the extent practical. Maintainers may edit or remove content and temporarily or permanently restrict participation when necessary. + +This policy applies to the repository, issue tracker, pull requests, discussions, and other spaces where someone is representing the project. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..e86bd18 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,51 @@ +# Contributing to GrapeCompare + +Thanks for helping make file and folder comparison faster, clearer, and more reliable. + +## Before you start + +- Search [existing issues](https://github.com/everettjf/GrapeCompare/issues) before opening a new one. +- Use the bug or feature issue form and include a minimal, non-sensitive example when possible. +- For a large behavioral or architectural change, open an issue first so the approach can be discussed before substantial implementation work. +- Report vulnerabilities privately according to [SECURITY.md](SECURITY.md). + +## Development setup + +The application currently requires macOS 27+ and Xcode 27+. Open `macos/GrapeCompare.xcodeproj`, select the `GrapeCompare` scheme, and run the app. + +The comparison engines and their tests can also be compiled directly with the Swift toolchain: + +```bash +bash macos/Tests/run-tests.sh +``` + +Run the reproducible Release benchmark with: + +```bash +bash macos/Benchmarks/run-benchmarks.sh +``` + +Optional arguments set generated line and file counts: + +```bash +bash macos/Benchmarks/run-benchmarks.sh 100000 50000 +``` + +## Pull requests + +Keep each pull request focused and explain the user-facing motivation. Before submitting: + +1. Run the full core test suite. +2. Add regression coverage for correctness fixes and edge cases. +3. Manually exercise affected SwiftUI workflows. +4. Update both English and Chinese READMEs for user-facing documentation changes. +5. Include screenshots for visible UI changes. +6. Include the exact fixture, command, and before/after timings for performance changes. + +Comparison accuracy takes priority over benchmark gains. An optimization should retain exact byte validation where required and must not silently discard stable diff structure. + +## Code style + +Follow the surrounding Swift style, favor small focused types and functions, and keep platform-independent comparison logic in `macos/GrapeCompare/Core`. Avoid unrelated formatting changes in the same pull request. + +By participating, you agree to follow the [Code of Conduct](CODE_OF_CONDUCT.md). diff --git a/README.md b/README.md index c824a6e..3e298b3 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,37 @@
+ GrapeCompare app icon # GrapeCompare **Fast, accurate file and folder comparison for macOS.**
-Native SwiftUI, no WebView, inspired by Beyond Compare. +A native SwiftUI app inspired by Beyond Compare — no WebView, no cloud upload. -[Download on the App Store](https://apps.apple.com/app/id6796778424) · [中文说明](README.zh-CN.md) · [Support](https://github.com/everettjf/GrapeCompare/issues) · [Privacy](docs/privacy.html) +[![Release](https://img.shields.io/github/v/release/everettjf/GrapeCompare?display_name=tag&sort=semver&style=flat-square&color=7c3aed)](https://github.com/everettjf/GrapeCompare/releases/latest) +[![CI](https://img.shields.io/github/actions/workflow/status/everettjf/GrapeCompare/ci.yml?branch=main&style=flat-square&label=tests)](https://github.com/everettjf/GrapeCompare/actions/workflows/ci.yml) +![macOS](https://img.shields.io/badge/macOS-27%2B-111827?style=flat-square&logo=apple) +![Swift](https://img.shields.io/badge/Swift-5-F05138?style=flat-square&logo=swift&logoColor=white) + +[Mac App Store](https://apps.apple.com/app/id6796778424) · [Website](https://xnu.app/GrapeCompare/) · [中文说明](README.zh-CN.md) · [Changelog](CHANGELOG.md) · [Contributing](CONTRIBUTING.md)
-| Folder comparison | File comparison | -| --- | --- | -| ![Folder comparison](docs/assets/folder-diff.png) | ![File comparison](docs/assets/file-diff.png) | +## See every difference clearly + +### Folder comparison + +Browse a recursive, filterable tree and jump directly from a changed file into its text diff. + +

+ GrapeCompare folder comparison showing a recursive result tree and status filters +

+ +### File comparison + +Review aligned lines, character-level edits, totals, and previous/next difference navigation side by side. + +

+ GrapeCompare side-by-side file comparison with inline highlights +

## Why GrapeCompare @@ -58,9 +78,11 @@ bash macos/Benchmarks/run-benchmarks.sh 100000 50000 The diff design builds on [Myers' O(ND) algorithm](https://doi.org/10.1007/BF01840446) and the low-occurrence anchoring ideas documented in [Git's diff algorithms](https://git-scm.com/docs/diff-algorithm-option.html). -## Install or build +## Install + +Install the signed release from the [Mac App Store](https://apps.apple.com/app/id6796778424). -Install the signed release from the [Mac App Store](https://apps.apple.com/app/id6796778424), or build from source with macOS 27+ and Xcode 27+: +To build from source, use macOS 27+ and Xcode 27+: ```bash xcodebuild -project macos/GrapeCompare.xcodeproj \ @@ -79,15 +101,15 @@ GrapeCompare Two folders open the folder comparison; other inputs open the file comparison. The App Store build is sandboxed and cannot read arbitrary command-line paths. Build with App Sandbox disabled if this workflow is required. -## Test +## Development + +Run the platform-independent core suite without launching Xcode: ```bash -macos/Tests/run-tests.sh +bash macos/Tests/run-tests.sh ``` -The core suite contains 45 focused checks, 300 randomized shortest-edit-script cases, large-text stress cases, and folder edge cases. No UI or Xcode test runner is required. - -## Project structure +The suite contains 45 focused checks, 300 randomized shortest-edit-script cases, large-text stress cases, and folder edge cases. Pull requests run the same suite in GitHub Actions. ```text macos/ @@ -101,6 +123,4 @@ macos/ └── Benchmarks/ # repeatable large-file/folder benchmarks ``` -## Support - -Use [GitHub Issues](https://github.com/everettjf/GrapeCompare/issues) for bugs and feature requests. +Contributions are welcome. Read [CONTRIBUTING.md](CONTRIBUTING.md) before opening a pull request. For help, use [GitHub Issues](https://github.com/everettjf/GrapeCompare/issues); report security problems according to [SECURITY.md](SECURITY.md). By participating, you agree to follow the [Code of Conduct](CODE_OF_CONDUCT.md). diff --git a/README.zh-CN.md b/README.zh-CN.md index fde1e26..9757c37 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -1,17 +1,37 @@
+ GrapeCompare 应用图标 # GrapeCompare **快速、准确的 macOS 文件与文件夹比较工具。**
-原生 SwiftUI,不使用 WebView,灵感来自 Beyond Compare。 +原生 SwiftUI,灵感来自 Beyond Compare——不使用 WebView,不上传云端。 -[从 App Store 下载](https://apps.apple.com/app/id6796778424) · [English](README.md) · [问题反馈](https://github.com/everettjf/GrapeCompare/issues) · [隐私政策](docs/privacy.html) +[![最新版本](https://img.shields.io/github/v/release/everettjf/GrapeCompare?display_name=tag&sort=semver&style=flat-square&color=7c3aed)](https://github.com/everettjf/GrapeCompare/releases/latest) +[![自动测试](https://img.shields.io/github/actions/workflow/status/everettjf/GrapeCompare/ci.yml?branch=main&style=flat-square&label=tests)](https://github.com/everettjf/GrapeCompare/actions/workflows/ci.yml) +![macOS](https://img.shields.io/badge/macOS-27%2B-111827?style=flat-square&logo=apple) +![Swift](https://img.shields.io/badge/Swift-5-F05138?style=flat-square&logo=swift&logoColor=white) + +[Mac App Store](https://apps.apple.com/app/id6796778424) · [官网](https://xnu.app/GrapeCompare/) · [English](README.md) · [更新记录](CHANGELOG.md) · [参与贡献](CONTRIBUTING.md)
-| 文件夹比较 | 文件比较 | -| --- | --- | -| ![文件夹比较](docs/assets/folder-diff.png) | ![文件比较](docs/assets/file-diff.png) | +## 每一处差异都清晰可见 + +### 文件夹比较 + +在可筛选的递归目录树中查看结果,并从不同的文件直接进入文本对比。 + +

+ GrapeCompare 文件夹比较界面,展示递归结果树和状态筛选 +

+ +### 文件比较 + +左右对齐查看行差异、字符级修改、差异统计,以及上一处/下一处导航。 + +

+ GrapeCompare 左右并排文件比较界面和行内高亮 +

## 为什么选择 GrapeCompare @@ -58,9 +78,11 @@ bash macos/Benchmarks/run-benchmarks.sh 100000 50000 Diff 设计基于 [Myers O(ND) 算法](https://doi.org/10.1007/BF01840446),并采纳了 [Git diff 算法文档](https://git-scm.com/docs/diff-algorithm-option.html)中的低频元素锚定思路。 -## 安装或构建 +## 安装 + +可以从 [Mac App Store](https://apps.apple.com/app/id6796778424) 安装已签名版本。 -可以从 [Mac App Store](https://apps.apple.com/app/id6796778424) 安装已签名版本,也可以使用 macOS 27+ 和 Xcode 27+ 从源码构建: +从源码构建需要 macOS 27+ 和 Xcode 27+: ```bash xcodebuild -project macos/GrapeCompare.xcodeproj \ @@ -79,15 +101,15 @@ GrapeCompare <左侧路径> <右侧路径> 两个输入都是文件夹时进入文件夹比较,其他情况进入文件比较。App Store 版本启用了沙盒,无法读取任意命令行路径;如需该工作流,请在自行构建时关闭 App Sandbox。 -## 测试 +## 开发 + +无需打开 Xcode 即可运行平台无关的核心测试: ```bash -macos/Tests/run-tests.sh +bash macos/Tests/run-tests.sh ``` -核心套件包含 45 项针对性检查、300 组随机最短编辑脚本用例、大文本压力场景和文件夹边界场景,不依赖 UI 或 Xcode 测试运行器。 - -## 项目结构 +测试套件包含 45 项针对性检查、300 组随机最短编辑脚本用例、大文本压力场景和文件夹边界场景;Pull Request 会在 GitHub Actions 中运行同一套测试。 ```text macos/ @@ -101,6 +123,4 @@ macos/ └── Benchmarks/ # 可重复的大文件/文件夹性能基准 ``` -## 支持 - -Bug 和功能建议请提交到 [GitHub Issues](https://github.com/everettjf/GrapeCompare/issues)。 +欢迎参与贡献。提交 Pull Request 前请阅读 [CONTRIBUTING.md](CONTRIBUTING.md)。问题与建议请使用 [GitHub Issues](https://github.com/everettjf/GrapeCompare/issues);安全问题请按 [SECURITY.md](SECURITY.md) 私下报告。参与本项目即表示同意遵守 [行为准则](CODE_OF_CONDUCT.md)。 diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..501de9e --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,22 @@ +# Security Policy + +## Supported versions + +Security fixes are provided for the latest released version of GrapeCompare. + +| Version | Supported | +| --- | --- | +| 1.1.x | Yes | +| 1.0.x and earlier | No | + +## Report a vulnerability + +Please use GitHub's private [Report a vulnerability](https://github.com/everettjf/GrapeCompare/security/advisories/new) form. Do not disclose a suspected vulnerability in a public issue, pull request, or discussion. + +Include the affected version, macOS version, impact, reproduction steps, and a minimal proof of concept when safe to share. Remove unrelated personal or confidential data. + +You should receive an acknowledgement within seven days. After validation, the maintainer will coordinate a fix and disclosure timeline with you. Please allow a reasonable remediation period before public disclosure. + +## Scope + +Security reports include unintended filesystem access, sandbox escapes, unsafe parsing, data disclosure, and supply-chain concerns. Ordinary crashes, comparison correctness bugs, and feature requests can use the public [issue tracker](https://github.com/everettjf/GrapeCompare/issues). diff --git a/SUPPORT.md b/SUPPORT.md new file mode 100644 index 0000000..63f5aa1 --- /dev/null +++ b/SUPPORT.md @@ -0,0 +1,13 @@ +# GrapeCompare Support + +GrapeCompare processes selected files locally and does not upload comparison contents. + +## Get help + +1. Update to the latest [App Store](https://apps.apple.com/app/id6796778424) or [GitHub release](https://github.com/everettjf/GrapeCompare/releases/latest). +2. Search [existing issues](https://github.com/everettjf/GrapeCompare/issues). +3. If the problem remains, open a bug report with the GrapeCompare version, macOS version, Mac model, reproduction steps, and approximate file sizes or folder counts. + +Use only non-sensitive sample data and redact private paths from screenshots and logs. + +Feature ideas are welcome through the feature request form. Security vulnerabilities must be reported privately according to [SECURITY.md](SECURITY.md).