Skip to content
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
7b49d2e
enhancement: cherry pick the readme.md for merge in dev
AriajSarkar Dec 6, 2025
7693a72
chore: reorder release workflow, exclude unnecessary files, rename CI
AriajSarkar Dec 8, 2025
79652b1
Merge branch 'main' into dev
AriajSarkar Dec 18, 2025
6b5be7a
feat(recurrence): add lazy OccurrenceIterator for memory-efficient it…
AriajSarkar Mar 6, 2026
604ad97
perf(gap_validation): replace O(N²) pair-check with O(N log N) sweep-…
AriajSarkar Mar 6, 2026
1a0335a
test: strengthen event validation and schedule analysis test coverage
AriajSarkar Mar 6, 2026
5674e0b
perf: add criterion benchmark suite and tidy dependency versions
AriajSarkar Mar 6, 2026
b21ea87
feat: add json_web example for JSON serialization workflows
AriajSarkar Mar 6, 2026
6bcbd94
ci: redesign release workflow with Cargo.toml-authoritative versioning
AriajSarkar Mar 6, 2026
282885b
chore: remove DEVELOPMENT.md and TESTING.md
AriajSarkar Mar 6, 2026
02d4947
docs: update CHANGELOG for v0.3.2
AriajSarkar Mar 6, 2026
bc9c7d6
refactor(recurrence): extract advance_by_frequency shared helper
AriajSarkar Mar 6, 2026
37c1b95
style(gap_validation): clarify checkpoint sort ordering
AriajSarkar Mar 6, 2026
a504af4
fix(ci): use python3 instead of python in release workflow
AriajSarkar Mar 6, 2026
70bf49d
fix(examples): remove recurrence from json_web examples
AriajSarkar Mar 6, 2026
9f9a776
fix: fmt error
AriajSarkar Mar 6, 2026
39321c1
test(recurrence): cover uncovered OccurrenceIterator branches
AriajSarkar Mar 6, 2026
fdf38f7
fix(gap_validation): use BTreeSet for deterministic overlap ordering
AriajSarkar Mar 6, 2026
05671b4
fix(recurrence): clamp day for Monthly/Yearly instead of terminating
AriajSarkar Mar 6, 2026
0fb25e9
fix(recurrence): guard interval==0 and implement weekdays filtering
AriajSarkar Mar 6, 2026
4f22e72
fix(recurrence): add TODO for handling silent drops of valid occurren…
AriajSarkar Mar 6, 2026
0aa7f17
fix(recurrence): count emitted results not scanned slots, fix DST drift
AriajSarkar Mar 6, 2026
d683b15
fix(event): use intersection filter in occurrences_between
AriajSarkar Mar 6, 2026
9b46252
chore: bump to v0.4.0, rewrite changelog for minor release
AriajSarkar Mar 6, 2026
19a78e0
fix(recurrence): DST gap fallback, lazy occurrences_between, weekly w…
AriajSarkar Mar 6, 2026
1d822e0
fix(recurrence): proper DST gap handling via pre-gap UTC offset, DRY …
AriajSarkar Mar 6, 2026
11f7552
Add full sub-daily recurrence and lazy capped occurrence filtering
AriajSarkar Mar 8, 2026
841b2ba
fmt
AriajSarkar Mar 8, 2026
d59160e
chore: update changelog and README for new eager cap helper and break…
AriajSarkar Mar 10, 2026
8c693ff
fix(recurrence): enforce bounded recurrences in generate_occurrences …
AriajSarkar Mar 10, 2026
b1a0c48
fmt
AriajSarkar Mar 10, 2026
7b5651d
fix(docs): clarify error type in generate_occurrences documentation
AriajSarkar Mar 10, 2026
83bb72a
ai review fixes
AriajSarkar Mar 10, 2026
13a876f
feat: enhance recurrence handling and documentation
AriajSarkar Mar 10, 2026
145554c
fix(recurrence): improve error handling for recurrence and exdates in…
AriajSarkar Mar 12, 2026
3291f08
fix(ics): improve error handling for EXDATE parsing and BYDAY validation
AriajSarkar Mar 12, 2026
9e0d939
fix(ics): enforce RFC 5545 rules by rejecting COUNT and UNTIL togethe…
AriajSarkar Mar 12, 2026
b47225e
fix(changelog): update `generate_occurrences()` to return an error fo…
AriajSarkar Mar 12, 2026
d78b7e1
fix(recurrence): improve error handling for interval overflow and val…
AriajSarkar Mar 12, 2026
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
2 changes: 1 addition & 1 deletion .github/workflows/rust.yml → .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Rust CI
name: EventixCI

on:
push:
Expand Down
119 changes: 95 additions & 24 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ jobs:

- name: Run all tests
run: |
set -euo pipefail
cargo test --all-features --verbose
cargo clippy --all-features -- -D warnings
cargo fmt -- --check
Expand All @@ -33,9 +34,48 @@ jobs:

- name: Security audit
run: |
set -euo pipefail
cargo install cargo-audit
cargo audit

- name: Resolve release version
id: release_meta
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
run: |
set -euo pipefail
PACKAGE_VERSION=$(python3 -c "import tomllib; print(tomllib.load(open('Cargo.toml', 'rb'))['package']['version'])")
TAG_VERSION="${GITHUB_REF#refs/tags/v}"

echo "Cargo.toml version: $PACKAGE_VERSION"
echo "Git tag version: $TAG_VERSION"

if [ "$PACKAGE_VERSION" != "$TAG_VERSION" ]; then
echo "⚠️ Tag v$TAG_VERSION does not match Cargo.toml version $PACKAGE_VERSION"
echo "⚠️ Using Cargo.toml version as the authoritative README/publish version"
fi

echo "version=$PACKAGE_VERSION" >> "$GITHUB_OUTPUT"

- name: Prepare README for publish
id: prepare_readme
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
run: |
set -euo pipefail
VERSION="${{ steps.release_meta.outputs.version }}"
echo "Ensuring README dependency snippets match Cargo.toml version $VERSION"

sed -i "s/^\([[:space:]]*\)eventix = \".*\"/\1eventix = \"$VERSION\"/" README.md

if git diff --quiet README.md; then
echo "README already matches Cargo.toml version $VERSION"
echo "changed=false" >> "$GITHUB_OUTPUT"
else
echo "README updated in working tree before publish"
echo "changed=true" >> "$GITHUB_OUTPUT"
git diff -- README.md
fi

# Publish the tagged source, with README normalized from Cargo.toml just before packaging
- name: Publish to crates.io
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
env:
Expand All @@ -53,41 +93,72 @@ jobs:
LICENSE-MIT
LICENSE-APACHE

- name: Update README version
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
- name: Persist README version on main
id: sync_readme_main
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') && steps.prepare_readme.outputs.changed == 'true'
run: |
# Checkout main branch for updates (release triggered on tag)
git checkout main
git pull origin main --rebase

# Configure Git
set -euo pipefail
VERSION="${{ steps.release_meta.outputs.version }}"

git config --global user.name 'github-actions[bot]'
git config --global user.email 'github-actions[bot]@users.noreply.github.com'

# Extract version from tag (e.g., v0.3.0 -> 0.3.0)
VERSION=${GITHUB_REF#refs/tags/v}
echo "Updating README to version $VERSION"

# Replace 'eventix = "..."' with 'eventix = "$VERSION"', preserving indentation

git checkout main
git pull origin main --rebase

sed -i "s/^\([[:space:]]*\)eventix = \".*\"/\1eventix = \"$VERSION\"/" README.md

# Check for changes

if git diff --quiet README.md; then
echo "No changes to README.md"
echo "README already up to date on main"
echo "commit_sha=" >> "$GITHUB_OUTPUT"
else
git commit -am "docs: update readme version to $VERSION [skip ci]"
git push origin main
echo "Pushed README update to main"

COMMIT_SHA=$(git rev-parse HEAD)
echo "commit_sha=$COMMIT_SHA" >> "$GITHUB_OUTPUT"
echo "Pushed README update to main ($COMMIT_SHA)"
fi

- name: Merge main into dev
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
- name: Sync README update to dev
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') && steps.sync_readme_main.outputs.commit_sha != ''
run: |
VERSION=${GITHUB_REF#refs/tags/v}
echo "Merging main into dev..."
set -euo pipefail
COMMIT_SHA="${{ steps.sync_readme_main.outputs.commit_sha }}"
echo "Syncing README commit $COMMIT_SHA to dev..."

git checkout dev
git pull origin dev --rebase
git merge origin/main -m "merge: sync main to dev after release $VERSION"
git push origin dev
echo "Merged main into dev"

# Check if commit is already on dev
if git merge-base --is-ancestor "$COMMIT_SHA" HEAD; then
echo "ℹ️ SKIPPED: Commit $COMMIT_SHA is already on dev branch"
exit 0
fi

# Attempt cherry-pick
echo "🍒 Cherry-picking commit $COMMIT_SHA..."
if git cherry-pick "$COMMIT_SHA"; then
git push origin dev
echo "✅ SUCCESS: Cherry-picked and pushed README update to dev"
else
# Cherry-pick failed (likely conflict)
echo "⚠️ Cherry-pick failed, checking for conflict..."

# Abort the failed cherry-pick
git cherry-pick --abort 2>/dev/null || true

# Reset to clean state
git reset --hard HEAD

echo "❌ CONFLICT: Could not cherry-pick README update to dev"
echo " The commit $COMMIT_SHA conflicts with current dev branch."
echo " Manual resolution required:"
echo " git checkout dev"
echo " git cherry-pick $COMMIT_SHA"
echo " # resolve conflicts"
echo " git push origin dev"

# Exit with error to make the conflict visible
exit 1
fi
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,19 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.3.2] - 2026-03-06

### Added
- **Lazy recurrence iteration**: Added `Recurrence::occurrences()` and the public `OccurrenceIterator` type for memory-efficient, on-demand occurrence generation.
- **Benchmark coverage**: Added a `criterion` benchmark suite covering overlap detection, gap detection, density analysis, recurrence generation, and slot availability.
- **JSON/web examples**: Added examples showing how to import/export calendars as JSON for API-style workflows without expanding the main public API surface.

### Changed
- **Faster overlap detection**: `gap_validation::find_overlaps()` now uses a sweep-line approach for much better scalability on larger calendars.
- **Correct boundary handling**: Back-to-back events that merely touch at the boundary are no longer reported as overlapping.
- **Safer edge-case handling**: Zero-duration events no longer interfere with overlap detection.
- **Stronger schedule-analysis validation**: Expanded integration and property-based test coverage for `gap_validation` invariants and edge cases.

## [0.3.1] - 2025-12-18

### Added
Expand Down
27 changes: 20 additions & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "eventix"
version = "0.3.1"
version = "0.3.2"
edition = "2021"
authors = ["Raj Sarkar <ariajsarkar@gmail.com>"]
description = "High-level calendar & recurrence crate with timezone-aware scheduling, exceptions, and ICS import/export"
Expand All @@ -10,21 +10,34 @@ readme = "README.md"
homepage = "https://github.com/AriajSarkar/eventix"
keywords = ["calendar", "scheduling", "booking", "availability", "ics"]
categories = ["date-and-time"]
exclude = ["usage-examples/"]
exclude = [
"usage-examples/",
"examples_output/",
".github/",
"target/",
"TODO.md",
"llms.txt",
"rustfmt.toml",
]

[dependencies]
chrono = { version = "0.4", features = ["serde"] }
chrono-tz = { version = "0.10", features = ["serde"] }
rrule = "0.14"
icalendar = "0.17"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
thiserror = "2.0"
uuid = { version = "1.0", features = ["v4"] }
serde_json = "1"
thiserror = "2"
uuid = { version = "1", features = ["v4"] }

[dev-dependencies]
anyhow = "1.0"
proptest = "1.0"
anyhow = "1"
proptest = "1.10"
criterion = { version = "0.8", features = ["html_reports"] }

[[bench]]
name = "performance"
harness = false

[lints.clippy]
unwrap_used = "warn"
Expand Down
Loading