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
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ gitstreams
| `-db` | Path to SQLite database (default: `~/.gitstreams/gitstreams.db`) |
| `-report` | Path to write HTML report (default: temp file) |
| `-sync-lookback-days` | How far back to fetch GitHub data (1-365 days, default: 30) |
| `-report-since` | Generate report from historical data starting from this date (e.g., `2026-01-15` or `7d` for 7 days ago) |
| `-offline` | Skip GitHub API sync and use cached data |
| `-no-notify` | Skip desktop notification |
| `-no-open` | Don't open report in browser |
Expand All @@ -58,6 +59,12 @@ gitstreams -v -db /path/to/my.db
# Fetch GitHub data from the last 7 days
gitstreams -sync-lookback-days 7

# Generate report from historical cached data (last 7 days)
gitstreams -report-since 7d

# Generate report from a specific date using cached data
gitstreams -report-since 2026-01-15 -offline

# Use cached data without hitting GitHub API (fast, but may be stale)
gitstreams -offline
```
Expand Down
36 changes: 18 additions & 18 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,15 @@ var (

// Config holds the runtime configuration for gitstreams.
type Config struct {
DBPath string
Token string
ReportPath string
Since string // Generate report from this date (e.g., '2026-01-15' or '7d')
Days int // How far back to fetch GitHub data (API sync lookback, default 30)
NoNotify bool
NoOpen bool
Verbose bool
Offline bool // Use only cached data, skip GitHub API calls
DBPath string
Token string
ReportPath string
ReportSince string // Generate report from this date (e.g., '2026-01-15' or '7d')
Days int // How far back to fetch GitHub data (API sync lookback, default 30)
NoNotify bool
NoOpen bool
Verbose bool
Offline bool // Use only cached data, skip GitHub API calls
}

// Dependencies holds injectable dependencies for testing.
Expand Down Expand Up @@ -134,11 +134,11 @@ func run(stdout, stderr io.Writer, args []string, deps *Dependencies) int {
var currentSnapshot, previousSnapshot *diff.Snapshot

// Historical mode: generate report from cached data
if cfg.Since != "" {
if cfg.ReportSince != "" {
var sinceDate time.Time
sinceDate, err = parseSinceDate(cfg.Since, deps.Now())
sinceDate, err = parseSinceDate(cfg.ReportSince, deps.Now())
if err != nil {
_, _ = fmt.Fprintf(stderr, "Error parsing --since date: %v\n", err)
_, _ = fmt.Fprintf(stderr, "Error parsing --report-since date: %v\n", err)
return 1
}

Expand All @@ -150,11 +150,11 @@ func run(stdout, stderr io.Writer, args []string, deps *Dependencies) int {
var sinceSnapshots []*storage.Snapshot
sinceSnapshots, err = store.GetByTimeRange(snapshotUserID, sinceDate.Add(-24*time.Hour), sinceDate.Add(24*time.Hour))
if err != nil {
_, _ = fmt.Fprintf(stderr, "Error querying snapshots for --since date: %v\n", err)
_, _ = fmt.Fprintf(stderr, "Error querying snapshots for --report-since date: %v\n", err)
return 1
}
if len(sinceSnapshots) == 0 {
_, _ = fmt.Fprintf(stderr, "No cached snapshot found for date %s (try running without --since first to build cache)\n", sinceDate.Format("2006-01-02"))
_, _ = fmt.Fprintf(stderr, "No cached snapshot found for date %s (try running without --report-since first to build cache)\n", sinceDate.Format("2006-01-02"))
return 1
}
previousSnapshot, err = storageToSnapshot(sinceSnapshots[0])
Expand Down Expand Up @@ -279,11 +279,11 @@ func run(stdout, stderr io.Writer, args []string, deps *Dependencies) int {
// Filter results by since date if specified
// This is needed because snapshots contain historical data (e.g., 30 days),
// so we need to filter out activities that occurred before the since date
if cfg.Since != "" {
if cfg.ReportSince != "" {
var filterDate time.Time
filterDate, err = parseSinceDate(cfg.Since, deps.Now())
filterDate, err = parseSinceDate(cfg.ReportSince, deps.Now())
if err != nil {
_, _ = fmt.Fprintf(stderr, "Error parsing --since date for filtering: %v\n", err)
_, _ = fmt.Fprintf(stderr, "Error parsing --report-since date for filtering: %v\n", err)
return 1
}
result = filterResultBySinceDate(result, filterDate)
Expand Down Expand Up @@ -374,7 +374,7 @@ func parseFlags(args []string) (*Config, error) {
fs.BoolVar(&cfg.Verbose, "v", false, "Verbose output")
fs.BoolVar(&showVersion, "version", false, "Print version and exit")
fs.IntVar(&cfg.Days, "sync-lookback-days", 30, "How far back to fetch GitHub data (1-365 days, doesn't affect report filtering)")
fs.StringVar(&cfg.Since, "since", "", "Generate report from historical data (e.g., '2026-01-15' or '7d' for 7 days ago)")
fs.StringVar(&cfg.ReportSince, "report-since", "", "Generate report from historical data starting from this date (e.g., '2026-01-15' or '7d' for 7 days ago)")
fs.BoolVar(&cfg.Offline, "offline", false, "Use only cached data, skip GitHub API calls")

if err := fs.Parse(args); err != nil {
Expand Down
8 changes: 4 additions & 4 deletions main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1281,7 +1281,7 @@ func TestRun_HistoricalMode(t *testing.T) {
}

var stdout, stderr bytes.Buffer
args := []string{"-since", "7d", "-token", "test-token", "-no-notify", "-no-open", "-v"}
args := []string{"-report-since", "7d", "-token", "test-token", "-no-notify", "-no-open", "-v"}

exitCode := run(&stdout, &stderr, args, deps)

Expand Down Expand Up @@ -1354,7 +1354,7 @@ func TestRun_OfflineMode(t *testing.T) {
}

var stdout, stderr bytes.Buffer
args := []string{"-since", "7d", "-offline", "-no-notify", "-no-open", "-v"}
args := []string{"-report-since", "7d", "-offline", "-no-notify", "-no-open", "-v"}

exitCode := run(&stdout, &stderr, args, deps)

Expand All @@ -1372,9 +1372,9 @@ func TestRun_OfflineMode(t *testing.T) {
}
}

// TestRun_OfflineWithoutSince - --offline can be used standalone or with --since
// TestRun_OfflineWithoutSince - --offline can be used standalone or with --report-since
// Standalone --offline mode uses cached data for a quick report without GitHub API calls
// This test is removed as --offline is now supported both with and without --since
// This test is removed as --offline is now supported both with and without --report-since

func TestRun_BrowserError_DoesNotFail(t *testing.T) {
var stdout, stderr bytes.Buffer
Expand Down
Loading