Skip to content

Commit 83f15a5

Browse files
committed
feat: initial public release of drift
Fast, interactive file comparison tool with a terminal UI. Compare directories, archives (IPA, APK, JAR, tar), Mach-O binaries, plists, and text files — with structured JSON output for CI pipelines. Architecture: - compare/ — pure-Go comparison engine (tree, binary, plist, text modes) - tui/ — Bubbletea-based interactive terminal UI with split-pane layout - cmd/drift/ — CLI entry point with kong Cross-platform: macOS, Linux, Windows. Binary analysis and plist conversion degrade gracefully when platform tools are unavailable.
1 parent b2d4841 commit 83f15a5

58 files changed

Lines changed: 6798 additions & 69 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 11 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,21 @@
11
---
2-
name: 🐛 Bug Report
3-
about: Thank you for taking the time, please report a reproducible bug
4-
title: "[Bug] <Bug Title Here>"
2+
name: Bug Report
3+
about: Report a bug with drift
54
labels: bug
6-
assignees: add codeowner's @name here
7-
5+
assignees: luispadron
86
---
97

10-
**Describe the bug**
11-
*A clear and concise description of what the bug is.*
8+
**What happened?**
129

13-
**To Reproduce:**
14-
*Steps to reproduce the behavior:*
15-
1. Go to '...'
16-
2. Click on '....'
17-
3. Scroll down to '....'
18-
4. See error
10+
**Command run:**
11+
```
12+
drift ...
13+
```
1914

2015
**Expected behavior:**
21-
*A clear and concise description of what you expected to happen.*
22-
23-
**Supporting Material**
24-
*If applicable, add screenshots, output log and/or other documentation to help explain your problem.*
2516

26-
**Environment (please complete the following information):**
27-
- OS: [ex: iOS]
28-
- Version
17+
**Environment:**
18+
- OS:
19+
- drift version (`drift --version`):
2920

3021
**Additional context**
31-
Add any other context that you feel is relevant about the problem here.

.github/ISSUE_TEMPLATE/config.yml

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1 @@
1-
contact_links:
2-
- name: ❓ Questions and Help 🤔
3-
url: https://discord.gg/block-opensource (/add your discord channel if applicable)
4-
about: This issue tracker is not for support questions. Please refer to the community for more help.
1+
blank_issues_enabled: false

.github/assets/drift_logo.png

121 KB
Loading

.github/workflows/ci.yml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
8+
jobs:
9+
build-and-test:
10+
runs-on: macos-latest
11+
steps:
12+
- uses: actions/checkout@v6
13+
14+
- uses: actions/setup-go@v6
15+
with:
16+
go-version-file: go.mod
17+
18+
- name: Build
19+
run: go build -o drift ./cmd/drift
20+
21+
- name: Test
22+
run: go test ./...
23+
24+
- name: Vet
25+
run: go vet ./...

.github/workflows/release.yml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
name: Release
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
version:
7+
description: "Release version (e.g. 0.1.0, without 'v' prefix)"
8+
required: true
9+
type: string
10+
11+
permissions:
12+
contents: write
13+
14+
jobs:
15+
release:
16+
runs-on: ubuntu-latest
17+
steps:
18+
- uses: actions/checkout@v6
19+
with:
20+
fetch-depth: 0
21+
22+
- uses: actions/setup-go@v6
23+
with:
24+
go-version-file: go.mod
25+
26+
- name: Create and push tag
27+
run: |
28+
git tag "v${{ inputs.version }}"
29+
git push origin "v${{ inputs.version }}"
30+
31+
- name: Run GoReleaser
32+
uses: goreleaser/goreleaser-action@v7
33+
with:
34+
version: latest
35+
args: release --clean
36+
env:
37+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/drift
2+
.agents/
3+
.DS_Store

.goreleaser.yaml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
version: 2
2+
3+
builds:
4+
- main: ./cmd/drift
5+
binary: drift
6+
ldflags:
7+
- -s -w -X main.Version={{.Version}}
8+
goos:
9+
- linux
10+
- darwin
11+
- windows
12+
goarch:
13+
- amd64
14+
- arm64
15+
16+
archives:
17+
- name_template: "{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}"
18+
format_overrides:
19+
- goos: windows
20+
formats: ["zip"]
21+
22+
checksum:
23+
name_template: "checksums.txt"
24+
25+
changelog:
26+
sort: asc

CLAUDE.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# CLAUDE.md
2+
3+
## Build & Test
4+
5+
- **Build:** `go build -o drift ./cmd/drift`
6+
- **Test:** `go test ./...` or `go test ./compare -run TestName`
7+
- **Vet:** `go vet ./...`
8+
9+
## Architecture
10+
11+
`drift` is a two-layer tool: a comparison engine and an interactive TUI.
12+
13+
### Compare engine (`compare/`)
14+
15+
Pure-Go diffing logic. `Compare(pathA, pathB, mode)` returns a `*Result` with a tree of `Node`s representing the comparison. `Detail(result, node)` produces the detailed diff for a single node.
16+
17+
Supported modes: tree (directories/archives), binary (Mach-O), plist, text. Mode is auto-detected from inputs.
18+
19+
Key files:
20+
- `compare.go` - entry point, mode detection, tree comparison
21+
- `directory.go` - directory walking and tree building
22+
- `archive.go` - archive extraction (zip, tar, tar.gz, tar.bz2)
23+
- `binary.go` - Mach-O analysis via nm/size/otool
24+
- `plist.go` - plist conversion via plutil
25+
- `text.go` - line-by-line unified diff
26+
- `types.go` - `Result`, `Node`, `DetailResult` types
27+
- `hash.go` - content hashing for change detection
28+
29+
### TUI (`tui/`)
30+
31+
Bubbletea-based interactive terminal UI. Three-tier component model:
32+
33+
1. **App** (`app.go`) - root model, layout, keyboard dispatch
34+
2. **Components** (`tree.go`, `detail.go`, `search.go`, `overlay.go`, `alert.go`) - stateful sub-models
35+
3. **Views** (`view_*.go`, `summary.go`, `render.go`) - pure render functions, no state
36+
37+
- `styles.go` - all lipgloss styles
38+
- `help.go` - keybinding definitions
39+
- `components.go` - detail content builder
40+
41+
### Entry point
42+
43+
- `cmd/drift/main.go` - CLI struct, kong parser, `run()` method
44+
45+
## Code style
46+
47+
- Views are pure functions: `func renderX(width int, data T) string`
48+
- Components own state and implement `Update`/`View`
49+
- Use lipgloss for all styling - no raw ANSI

CODEOWNERS

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,4 @@
11
# This CODEOWNERS file denotes the project leads
22
# and encodes their responsibilities for code review.
33

4-
# Instructions: At a minimum, replace the '@GITHUB_USER_NAME_GOES_HERE'
5-
# here with at least one project lead.
6-
7-
# Lines starting with '#' are comments.
8-
# Each line is a file pattern followed by one or more owners.
9-
# The format is described: https://github.blog/2017-07-06-introducing-code-owners/
10-
11-
# These owners will be the default owners for everything in the repo.
124
* @luispadron
13-
14-
15-
# -----------------------------------------------
16-
# BELOW THIS LINE ARE TEMPLATES, UNUSED
17-
# -----------------------------------------------
18-
# Order is important. The last matching pattern has the most precedence.
19-
# So if a pull request only touches javascript files, only these owners
20-
# will be requested to review.
21-
# *.js @octocat @github/js
22-
23-
# You can also use email addresses if you prefer.
24-
# docs/* docs@example.com

0 commit comments

Comments
 (0)