refactor: perform cleanup
All checks were successful
Go CI Pipeline / ci (push) Successful in 28s
Release Builds / GoReleaser build (push) Successful in 1m7s

This commit is contained in:
Patryk Hegenberg 2025-06-30 08:07:53 +02:00
parent d8743e54c1
commit 54979319ff
7 changed files with 13 additions and 45 deletions

6
app.go
View file

@ -54,30 +54,24 @@ func (a *App) connect() (*SSHConnection, error) { // Rückgabetyp geändert
return nil, fmt.Errorf("failed to establish primary SSH connection: %w", err)
}
// slog.Info("SSH connection established. Setting up tunnels...")
slog.Info("SSH connection established. Setting up tunnels...")
sshForwarder := NewPortForwarder(sshCon.client, "2048", "22", a.cfg.WorkstationIP)
go func() {
// slog.Info("Starting SSH forwarder (local :2048 -> remote workstation:22)")
slog.Info("Starting SSH forwarder (local :2048 -> remote workstation:22)")
if err := sshForwarder.forward(); err != nil {
// slog.Error(fmt.Sprintf("SSH forwarder failed: %v", err)
slog.Error(fmt.Sprintf("SSH forwarder failed: %v", err))
}
// slog.Info("SSH forwarder stopped.")
slog.Info("SSH forwarder stopped.")
}()
rdpForwarder := NewPortForwarder(sshCon.client, "6000", "3389", a.cfg.WorkstationIP)
go func() {
// slog.Info("Starting RDP forwarder (local :6000 -> remote workstation:3389)")
slog.Info("Starting RDP forwarder (local :6000 -> remote workstation:3389)")
if err := rdpForwarder.forward(); err != nil {
// slog.Error(fmt.Sprintf("RDP forwarder failed: %v", err)
slog.Error(fmt.Sprintf("ERROR: RDP forwarder failed: %v", err))
}
// slog.Info("RDP forwarder stopped.")
slog.Info("RDP forwarder stopped.")
}()

4
cmd.go
View file

@ -155,7 +155,7 @@ This also stops any currently running timer.`,
if err := a.timeStore.LogFullDay(tagLower, today); err != nil {
return fmt.Errorf("could not log '%s' for today: %w", tagLower, err)
}
return nil // Erfolg
return nil
default:
fmt.Printf("Attempting to start tracking interval '%s'...\n", tag)
@ -163,7 +163,7 @@ This also stops any currently running timer.`,
slog.Error(fmt.Sprintf("Failed to start tracking '%s': %v", tag, err))
return fmt.Errorf("could not start tracking '%s': %w", tag, err)
}
return nil // Erfolg
return nil
}
},
}

View file

@ -441,11 +441,10 @@ func writeExcelSheet(entries []ExcelEntry, name string) error {
f.SetCellValue(sheetName, "D"+rowStr, "")
f.MergeCell(sheetName, "D"+rowStr, "I"+rowStr)
f.SetCellStyle(sheetName, "D"+rowStr, "I"+rowStr, centerStyle)
// J: Netto ist 0
f.SetCellValue(sheetName, "J"+rowStr, 0.0)
f.SetCellStyle(sheetName, "J"+rowStr, "J"+rowStr, saldoStyle)
default: // Unbekannte Tags oder Tage ohne Eintrag
default:
f.SetCellValue(sheetName, "J"+rowStr, 0.0)
f.SetCellStyle(sheetName, "J"+rowStr, "J"+rowStr, saldoStyle)
}

View file

@ -52,7 +52,7 @@ func (pf *PortForwarder) forward() error {
continue
}
pf.logf("INFO", "Accepted connection from %s on %s", localConn.RemoteAddr(), localAddr)
pf.logf("INFO", fmt.Sprintf("Accepted connection from %s on %s", localConn.RemoteAddr(), localAddr))
go pf.handleConnection(localConn, remoteAddr)
}
}

1
go.mod
View file

@ -33,7 +33,6 @@ require (
github.com/mattn/go-localereader v0.0.1 // indirect
github.com/mattn/go-runewidth v0.0.16 // indirect
github.com/mitchellh/hashstructure/v2 v2.0.2 // indirect
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
github.com/muesli/cancelreader v0.2.2 // indirect
github.com/muesli/termenv v0.15.3-0.20240618155329-98d742f6907a // indirect

26
go.sum
View file

@ -56,8 +56,6 @@ github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6T
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4=
github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE=
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI=
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo=
github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
@ -105,50 +103,34 @@ github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
github.com/tiendc/go-deepcopy v1.6.0 h1:0UtfV/imoCwlLxVsyfUd4hNHnB3drXsfle+wzSCA5Wo=
github.com/tiendc/go-deepcopy v1.6.0/go.mod h1:toXoeQoUqXOOS/X4sKuiAoSk6elIdqc0pN7MTgOOo2I=
github.com/xuri/efp v0.0.0-20240408161823-9ad904a10d6d h1:llb0neMWDQe87IzJLS4Ci7psK/lVsjIS2otl+1WyRyY=
github.com/xuri/efp v0.0.0-20240408161823-9ad904a10d6d/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI=
github.com/xuri/efp v0.0.1 h1:fws5Rv3myXyYni8uwj2qKjVaRP30PdjeYe2Y6FDsCL8=
github.com/xuri/efp v0.0.1/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI=
github.com/xuri/excelize/v2 v2.9.0 h1:1tgOaEq92IOEumR1/JfYS/eR0KHOCsRv/rYXXh6YJQE=
github.com/xuri/excelize/v2 v2.9.0/go.mod h1:uqey4QBZ9gdMeWApPLdhm9x+9o2lq4iVmjiLfBS5hdE=
github.com/xuri/excelize/v2 v2.9.1 h1:VdSGk+rraGmgLHGFaGG9/9IWu1nj4ufjJ7uwMDtj8Qw=
github.com/xuri/excelize/v2 v2.9.1/go.mod h1:x7L6pKz2dvo9ejrRuD8Lnl98z4JLt0TGAwjhW+EiP8s=
github.com/xuri/nfp v0.0.0-20240318013403-ab9948c2c4a7 h1:hPVCafDV85blFTabnqKgNhDCkJX25eik94Si9cTER4A=
github.com/xuri/nfp v0.0.0-20240318013403-ab9948c2c4a7/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ=
github.com/xuri/nfp v0.0.1 h1:MDamSGatIvp8uOmDP8FnmjuQpu90NzdJxo7242ANR9Q=
github.com/xuri/nfp v0.0.1/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ=
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ=
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 h1:nDVHiLt8aIbd/VzvPWN6kSOPE7+F/fNFDSXLVYkE/Iw=
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394/go.mod h1:sIifuuw/Yco/y6yb6+bDNfyeQ/MdPUy/hKEMYQV17cM=
golang.org/x/image v0.18.0 h1:jGzIakQa/ZXI1I0Fxvaa9W7yP25TqT6cHIHn+6CqvSQ=
golang.org/x/image v0.18.0/go.mod h1:4yyo5vMFQjVjUcVk4jEQcU9MGy/rulF5WvUILseCM2E=
golang.org/x/image v0.25.0 h1:Y6uW6rH1y5y/LK1J8BPWZtr6yZ7hrsy6hFrXjgsc2fQ=
golang.org/x/image v0.25.0/go.mod h1:tCAmOEGthTtkalusGp1g3xa2gke8J6c2N565dTyl9Rs=
golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU=
golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y=
golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g=
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg=
golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ=
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
golang.org/x/tools v0.31.0 h1:0EedkvKDbh+qistFTd0Bcwe/YLh4vHwWEkiI0toFIBU=

View file

@ -378,7 +378,7 @@ func (ts *TimeStore) ExportSummary(filename string) error {
}
slog.Info(fmt.Sprintf("Generated %d daily entries for the Excel export.", len(excelEntries)))
if err := writeExcelSheet(excelEntries, filename); err != nil { // Aufruf der geänderten Funktion
if err := writeExcelSheet(excelEntries, filename); err != nil {
return fmt.Errorf("failed to write excel sheet '%s': %w", filename, err)
}
@ -391,21 +391,17 @@ func (ts *TimeStore) LogFullDay(tag string, date time.Time) error {
if tag == "" {
return fmt.Errorf("cannot log full day with an empty tag")
}
tag = strings.ToLower(tag) // Stelle sicher, dass der Tag klein geschrieben ist
tag = strings.ToLower(tag)
location := date.Location() // Verwende die Zeitzone des übergebenen Datums
// Berechne Start (00:00:00 des Tages) und Ende (00:00:00 des nächsten Tages)
location := date.Location()
dayStart := time.Date(date.Year(), date.Month(), date.Day(), 0, 0, 0, 0, location)
dayEnd := dayStart.Add(24 * time.Hour)
dayStr := dayStart.Format("2006-01-02")
slog.Info(fmt.Sprintf("Attempting to log '%s' for the full day %s", tag, dayStr))
// 1. Stoppe den aktuell laufenden Timer (falls vorhanden)
// Wir verwenden dayStart als Zeitpunkt für das Stoppen, um Konsistenz zu wahren
stopped, err := ts.stopCurrentEntry(dayStart)
if err != nil {
// Nur loggen, weitermachen. Der Nutzer will diesen Tag ja explizit setzen.
slog.Warn(fmt.Sprintf("Failed to stop current entry before logging full day '%s': %v", tag, err))
} else if stopped {
slog.Info(fmt.Sprintf("Stopped active timer before logging '%s' for %s.", tag, dayStr))
@ -415,7 +411,7 @@ func (ts *TimeStore) LogFullDay(tag string, date time.Time) error {
if err != nil {
return fmt.Errorf("could not begin transaction to log full day: %w", err)
}
defer tx.Rollback() // Stellt sicher, dass bei Fehlern nichts gespeichert wird
defer tx.Rollback()
query := `INSERT INTO time_entries (tag, start_time, end_time) VALUES (?, ?, ?);`
stmt, err := tx.Prepare(query)
@ -426,17 +422,15 @@ func (ts *TimeStore) LogFullDay(tag string, date time.Time) error {
_, err = stmt.Exec(tag, dayStart, dayEnd)
if err != nil {
// Spezifischere Fehlermeldung, falls es UNIQUE Constraints gäbe
return fmt.Errorf("failed to insert full-day entry for tag '%s' on %s: %w", tag, dayStr, err)
}
// Transaktion erfolgreich abschließen
if err = tx.Commit(); err != nil {
return fmt.Errorf("failed to commit transaction for full-day entry: %w", err)
}
titleCaser := cases.Title(language.English)
slog.Info(fmt.Sprintf("Successfully logged full day entry: Tag='%s', Start='%s', End='%s'", tag, dayStart.Format(time.RFC3339), dayEnd.Format(time.RFC3339)))
fmt.Printf("Successfully logged '%s' for %s.\n", titleCaser.String(tag), dayStr) // Benutzerfeedback
fmt.Printf("Successfully logged '%s' for %s.\n", titleCaser.String(tag), dayStr)
return nil
}