| Age | Commit message (Collapse) | Author |
|
errcheck ./... flagged unchecked HTTP response Close(), file Close(),
os.RemoveAll(), fmt.Scanln(), and fmt.Fprintf() calls across codeberg,
github, release, showcase, and sync. None of these were bugs causing
incorrect behavior today, but leaving them unchecked hid real failure
modes (e.g. a lagging NFS mount failing a file Close() after writes,
which this codebase has hit before per commit 23ecaa2).
- internal/codeberg/codeberg.go, internal/github/github.go,
internal/release/release.go: added a small closeResponseBody(resp)
helper per package and used it for all deferred resp.Body.Close()
calls. The body is always fully read (or abandoned on an earlier
error) by the time Close() runs, so the error is intentionally
discarded - matching the explicit `_ = ...` discard convention
already used elsewhere in this repo (e.g. showcase.go's
os.RemoveAll on the worktree-add failure path).
- internal/release/release.go: the two fmt.Scanln(&response) prompts
now explicitly discard the return values; a Scanln error already
leaves response == "", which the existing y/yes check already
treats as a safe decline, so behavior is unchanged.
- internal/showcase/code_extractor.go, images.go, language_detector.go:
added a shared closeFile(*os.File) helper (package showcase) for the
read-only file Close() calls, matching the same discard rationale.
copyFile's destination Close() is the one write-side case where a
close failure is real data-loss information, so it now uses a named
return to surface it via err without masking any earlier error.
- internal/showcase/showcase.go: the deferred os.RemoveAll(tempRoot)
now explicitly discards its error, matching the sibling `_ =` call
three lines above in the same function.
- internal/sync/branch_analyzer.go: GenerateDeleteScript's per-repository
fmt.Fprintf(file, ...) calls are now checked and wrapped with
fmt.Errorf(...: %w), matching the error-wrapping convention already
used by writeBranchDeletionBlock right below it in the same file
(the repeated repo-header writes were pulled into a new
writeDeleteScriptRepoHeader helper to keep this readable). The
script file's defer file.Close() now uses a named return so a close
failure is reported instead of silently discarded.
Added focused tests for the two behavior-relevant paths: copyFile's
missing-source/success paths after the named-return change, and
PromptConfirmation's empty-input-declines/explicit-yes behavior after
touching the Scanln call. Trivial defer-Close discards elsewhere are
not additionally unit tested per the task's guidance against
overengineering.
Verified: go build ./..., go vet ./..., errcheck ./... (clean), and
go test ./... all pass.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
|
Auditing a full bidirectional sync to the r0 git-server backup destination
showed a stale/missing-repo pattern that cgit idle times alone did not
explain: several public repos (rampage, ggaze, comicforge, fastforge, gonf,
quicklog, shuriken.sh) were entirely absent from r0 even though they synced
fine to GitHub/Codeberg.
Root cause #1: createSSHBareRepository provisions missing backup repos by
running `git init --bare` over a root SSH session directly on the r0
filesystem. That leaves the new repo directory at mode 0755 (root's
session umask), owner-write only. Pushes into it later go through the
git-server pod's own SSH endpoint as a different, non-root UID (1001,
GID 33/www-data per the git-server helm chart's docker-image/Dockerfile),
which then cannot write new objects into the 0755 tree ("unable to create
temporary object directory"). Fixed by initializing with
`git init --bare --shared=group` (mode 2775, matching the already-working
repos on r0).
Root cause #2: even with correct permissions, the push immediately
following repository creation can still fail transiently (the git-server's
own view of the newly created directory can lag behind, e.g. across an NFS
mount). handlePushError treats any backup push failure as fatal for the
remainder of that sync run and disables the backup destination entirely
(disableBackupForSession) - so one transient failure early in a shuffled
repo order silently skipped backup for every repo processed afterward in
that pass, explaining the fuller set of stale repos. Fixed by retrying the
post-creation push up to 3 times with a short backoff in the new
createAndPushSSHBackupRepo helper, and by capturing/propagating the actual
git stderr on failure (previously swallowed via cmd.Run()) so any future
failure is diagnosable instead of a bare "exit status 128".
Verified against the live r0 git-server (ssh://git@r0:30022/repos,
/data/nfs/k3svolumes/git-server/repos): reinstalled gitsyncer and reran
`sync bidirectional --force --backup --auto-create-releases` end to end
with zero backup-disable events across both passes; all previously
missing/broken repos (plus the pre-existing broken player.git and
irregular.ninja.git, repaired directly via chmod) now match GitHub/Codeberg
HEAD exactly and are browsable on c-git.f3s.buetow.org.
Adds a regression test for the --shared=group init command.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
|
forcePush/descriptionSync creation support
Backup failures now disable retries only for the failing remote instead of
the whole session, add an opt-in forcePush flag for backup organizations,
and allow repository creation to go through descriptionSyncHost/Root when
configured so the git remote endpoint can stay restricted. Also fixes the
AI release-notes cache being bypassed by --force, which is meant to control
sync scheduling, not cache invalidation.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
- Add amp as default AI tool for release notes and showcase generation
- Fallback chain: amp → hexai → claude → aichat
- Replace Taskfile.yaml with magefile.go for build automation
- Update all documentation (README.md, AGENTS.md, doc/development.md)
- Update version to 0.10.0
Amp-Thread-ID: https://ampcode.com/threads/T-735ba1e2-0255-4b43-8ed1-6c0d2f78301b
Co-authored-by: Amp <amp@ampcode.com>
|
|
- Add branch switching logic to prevent "refusing to delete current branch" error
- Check if we're on the branch to be deleted and switch to main/master first
- Skip deletion if no main/master branch exists to switch to
- Bump version to 0.8.2
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
|
|
- Check all organizations (not just active ones) to identify backup locations
- Skip fetching from backup remotes when backup is not enabled
- Remove duplicate "Fetching" message from fetchRemote function
- Prevents "Warning: Remote repository does not exist yet" for backup locations
This ensures backup locations are truly opt-in and don't interfere with
normal sync operations.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
|
|
- Add --check-releases flag for manual release checking
- Enable automatic release checking after sync operations by default
- Add --no-check-releases flag to disable automatic checking
- Add --auto-create-releases flag for unattended release creation
- Generate release notes from commit history
- Support version tag formats: vX.Y.Z, vX.Y, vX, X.Y.Z, X.Y, X
- Use tokens from gitsyncer config (with fallback to env vars and files)
- Show release notes preview before creating releases
- Group commits by type (features, fixes, other) in release notes
|
|
- Add warning notice for projects with avg commit age > 2 years AND last commit > 1 year
- Display "⚠️ Notice: This project appears to be finished, obsolete, or no longer maintained"
- Also update abandoned branch threshold from 1 to 3 years in branch analyzer
- Helps users identify potentially outdated or unmaintained projects
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
|
|
- Add --showcase flag to generate project showcases using Claude
- Extract repository metadata (languages, commits, LOC, dates, license)
- Support image extraction from README files (local and remote)
- Add caching with --force flag to regenerate
- Add exclude_from_showcase config option
- Add standalone showcase mode (--showcase without sync)
- Sort projects by recent activity (avg age of last 100 commits)
- Output in Gemini Gemtext template format (.gmi.tpl)
- Fix backup location fetching when --backup flag not set
🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
|
|
- Add support for SSH backup locations (e.g., paul@server:git/)
- Backup locations are one-way only (push only, never pull)
- Automatic bare repository creation on SSH servers
- Add --backup flag to opt-in to backup syncing
- Backup locations are disabled by default for offline resilience
- Update version to 0.2.0
This allows users to maintain private backups on home servers that may
be offline without affecting regular sync operations.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
|
|
|
|
|
|
|
|
Users can now exclude branches from synchronization using regex patterns
in the configuration file. This is useful for:
- Excluding temporary or experimental branches
- Skipping vendor or third-party branches
- Ignoring deployment-specific branches
Configuration example:
```json
{
"exclude_branches": [
"^codex/", // Exclude branches starting with "codex/"
"^temp-", // Exclude branches starting with "temp-"
"-wip$" // Exclude branches ending with "-wip"
]
}
```
Features:
- Regex pattern matching for flexible exclusion rules
- Clear reporting of excluded branches during sync
- Excluded branches are filtered from sync but still analyzed for abandonment
- Invalid regex patterns are reported but don't stop sync
The feature helps maintain cleaner synchronization by allowing users to
ignore branches that shouldn't be synchronized across all repositories.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
|
|
Automatically detects and reports abandoned branches during sync operations:
- Branches are considered abandoned if they have no commits for 6+ months
- Only reports on active repositories (main/master updated within last year)
- Shows individual reports during sync of each repository
- Displays comprehensive summary after sync-all operations
- Provides helpful cleanup commands for removing old branches
This helps maintain cleaner repositories by identifying stale branches
that may no longer be needed.
Example output:
🔍 Abandoned branches in dtail:
Main branch last updated: 2025-04-17
Found 1 abandoned branches (no commits for 6+ months):
- develop (last commit: 2023-10-05, No commits for 628 days)
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
|
|
Remove unused path/filepath import that was causing build errors.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
|
|
Major refactoring to improve code maintainability:
1. Split main.go (481 lines → 72 lines) into internal/cli package:
- flags.go: Command-line flag definitions and parsing
- handlers.go: General command handlers (version, config, list operations)
- sync_handlers.go: Sync-specific handlers for all sync operations
2. Refactored sync.go to extract logic into separate files:
- git_operations.go: Git command helpers (merge, push, fetch, etc.)
- repository_setup.go: Repository initialization and remote configuration
- branch_sync.go: Branch synchronization helpers
3. Reduced function sizes to meet 30-line guideline:
- syncBranch: 104 lines → 26 lines
- SyncRepository: 97 lines → 44 lines
- main(): 465 lines → 63 lines
- getAllBranches: 32 lines → 9 lines
All functionality remains the same, but the code is now more modular,
testable, and easier to understand. Each function has a single, clear
responsibility.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
|
|
- Add --full flag that enables both --sync-codeberg-public and --sync-github-public
- Also enables --create-github-repos and --create-codeberg-repos with --full
- Update module name from github.com/paul/gitsyncer to codeberg.org/snonux/gitsyncer
- Update all import statements to use new module name
- Fix sync operations to work together when both are enabled
- Add visual separator between sync operations in full mode
- Update README with full sync documentation
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
|
|
- Show full absolute path to the repository with conflicts
- Provide clear instructions on how to resolve or delete the directory
- Make error message more actionable for users
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
|
|
- Add --test-github-token flag to validate GitHub authentication
- Improve error messages for 401 authentication failures
- Add merge conflict detection before sync attempts
- Stop sync on first error for easier debugging
- Add GitHub repo creation support for --sync and --sync-all commands
- Add detailed token loading debug output
- Create test script for GitHub token validation
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
|
|
- Add --create-github-repos flag to automatically create missing GitHub repositories
- Implement GitHub API client with token support from config/env/file
- Add Codeberg API integration to sync all public repositories
- Make sync operations stop on first error for better debugging
- Support GitHub repo creation for all sync commands (--sync, --sync-all, --sync-codeberg-public)
- Add comprehensive error messages and debug logging
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
|
|
- Add optional 'repositories' array to configuration file
- Add --list-repos flag to list configured repositories
- Add --sync-all flag to sync all configured repositories at once
- Show progress when syncing multiple repositories
- Gracefully handle missing remote repositories with warnings
- Improve error handling to continue syncing other repos on failure
- Add comprehensive integration tests for all functionality
- Add test for multiple repository sync feature
Example usage:
gitsyncer --sync-all # Sync all configured repos
gitsyncer --list-repos # List configured repos
gitsyncer --sync repo-name # Sync specific repo (still works)
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
|
|
- Create sync package to handle git repository synchronization
- Implement multi-organization sync with branch tracking
- Add merge conflict detection and error handling
- Support cloning, fetching, merging, and pushing across all remotes
- Add --sync flag to synchronize repositories
- Add --work-dir flag for working directory specification
- Create test infrastructure with setup and conflict test scripts
- Update config validation to support file:// URLs
- Add comprehensive .gitignore entries for test artifacts
The sync package automatically:
- Clones repositories if not present
- Fetches updates from all configured organizations
- Merges changes from all remotes for each branch
- Pushes synchronized changes to all organizations
- Detects and reports merge conflicts for manual resolution
Test with: ./test/setup_test_repos.sh && ./gitsyncer --config test/test-config.json --sync test-repo
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
|