Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* @everettjf
66 changes: 66 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
@@ -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
8 changes: 8 additions & 0 deletions .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -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.
48 changes: 48 additions & 0 deletions .github/ISSUE_TEMPLATE/feature_request.yml
Original file line number Diff line number Diff line change
@@ -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
24 changes: 24 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -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.
19 changes: 19 additions & 0 deletions .github/release.yml
Original file line number Diff line number Diff line change
@@ -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:
- "*"
27 changes: 27 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -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
21 changes: 21 additions & 0 deletions CODE_OF_CONDUCT.md
Original file line number Diff line number Diff line change
@@ -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.
51 changes: 51 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -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).
50 changes: 35 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,37 @@
<div align="center">
<img src="macos/GrapeCompare/Assets.xcassets/GrapeIcon.imageset/grape-icon.png" width="112" alt="GrapeCompare app icon">

# GrapeCompare

**Fast, accurate file and folder comparison for macOS.**<br>
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)

</div>

| 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.

<p align="center">
<img src="docs/assets/folder-diff.png" width="100%" alt="GrapeCompare folder comparison showing a recursive result tree and status filters">
</p>

### File comparison

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

<p align="center">
<img src="docs/assets/file-diff.png" width="100%" alt="GrapeCompare side-by-side file comparison with inline highlights">
</p>

## Why GrapeCompare

Expand Down Expand Up @@ -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 \
Expand All @@ -79,15 +101,15 @@ GrapeCompare <left> <right>

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/
Expand All @@ -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).
Loading
Loading