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
6 changes: 4 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,15 @@ jobs:
run: cd server && go test ./...

- name: Lint
uses: golangci/golangci-lint-action@v6
uses: golangci/golangci-lint-action@v7
with:
version: v2.11.4
working-directory: tracksync

- name: Lint server
uses: golangci/golangci-lint-action@v6
uses: golangci/golangci-lint-action@v7
with:
version: v2.11.4
working-directory: server

nix:
Expand Down
7 changes: 7 additions & 0 deletions nixos/tracksync.nix
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,14 @@ let

# Wait for device to be mounted or udisks2 to be ready (up to 60s)
MOUNT=""
SELF_MOUNTED=0
for i in $(seq 1 60); do
MOUNT=$(${pkgs.util-linux}/bin/findmnt -n -o TARGET "$DEV" 2>/dev/null || true)
[ -n "$MOUNT" ] && break
if ${pkgs.udisks2}/bin/udisksctl info -b "$DEV" >/dev/null 2>&1; then
${pkgs.udisks2}/bin/udisksctl mount -b "$DEV" --no-user-interaction 2>&1
MOUNT=$(${pkgs.util-linux}/bin/findmnt -n -o TARGET "$DEV" 2>/dev/null || true)
SELF_MOUNTED=1
break
fi
sleep 1
Expand All @@ -70,6 +72,11 @@ let
SKIPPED=$(echo "$SUMMARY" | ${pkgs.jq}/bin/jq -r '.skipped // 0')
ERRORS=$(echo "$SUMMARY" | ${pkgs.jq}/bin/jq -r '.errors // 0')

# Only unmount if we mounted it ourselves
if [ "$SELF_MOUNTED" = 1 ]; then
${pkgs.udisks2}/bin/udisksctl unmount -b "$DEV" --no-user-interaction 2>/dev/null || true
fi

if [ "$RC" = 0 ]; then
${pkgs.libnotify}/bin/notify-send -i emblem-ok "Tracksync" "$UPLOADED uploaded, $SKIPPED skipped" 2>/dev/null || true
else
Expand Down
4 changes: 2 additions & 2 deletions server/internal/migrations/migrations.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,12 @@ func Run(db *sql.DB) error {
}

if _, err := tx.Exec(string(data)); err != nil {
tx.Rollback()
_ = tx.Rollback()
return fmt.Errorf("applying migration %s: %w", name, err)
}

if _, err := tx.Exec("INSERT INTO schema_migrations (version) VALUES (?)", name); err != nil {
tx.Rollback()
_ = tx.Rollback()
return fmt.Errorf("recording migration %s: %w", name, err)
}

Expand Down
10 changes: 5 additions & 5 deletions server/internal/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ func (s *Server) authenticate(r *http.Request) *config.Client {

func (s *Server) handleHealth(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
fmt.Fprintln(w, "ok")
_, _ = fmt.Fprintln(w, "ok")
}

func (s *Server) handleUpload(w http.ResponseWriter, r *http.Request) {
Expand Down Expand Up @@ -95,7 +95,7 @@ func (s *Server) handleUpload(w http.ResponseWriter, r *http.Request) {
http.Error(w, "missing file field", http.StatusBadRequest)
return
}
defer file.Close()
defer func() { _ = file.Close() }()

data, err := io.ReadAll(file)
if err != nil {
Expand All @@ -117,7 +117,7 @@ func (s *Server) handleUpload(w http.ResponseWriter, r *http.Request) {
if exists {
slog.Info("duplicate", "file", header.Filename, "sha256", hashHex[:12], "client", client.ID)
w.WriteHeader(http.StatusOK)
fmt.Fprintln(w, "duplicate")
_, _ = fmt.Fprintln(w, "duplicate")
return
}

Expand Down Expand Up @@ -150,11 +150,11 @@ func (s *Server) handleUpload(w http.ResponseWriter, r *http.Request) {
if rows == 0 {
slog.Info("duplicate (concurrent)", "file", header.Filename, "sha256", hashHex[:12], "client", client.ID)
w.WriteHeader(http.StatusOK)
fmt.Fprintln(w, "duplicate")
_, _ = fmt.Fprintln(w, "duplicate")
return
}

slog.Info("uploaded", "file", header.Filename, "sha256", hashHex[:12], "client", client.ID, "device", deviceID)
w.WriteHeader(http.StatusCreated)
fmt.Fprintln(w, "uploaded")
_, _ = fmt.Fprintln(w, "uploaded")
}
12 changes: 6 additions & 6 deletions server/internal/server/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func setupTestServer(t *testing.T, targetErr error) *Server {
db, err := sql.Open("sqlite", ":memory:")
require.NoError(t, err)
require.NoError(t, InitDB(db))
t.Cleanup(func() { db.Close() })
t.Cleanup(func() { _ = db.Close() })

cfg := &config.Config{
Clients: []config.Client{
Expand All @@ -58,8 +58,8 @@ func uploadRequest(token, deviceID, filename string, body []byte) *http.Request
var buf bytes.Buffer
writer := multipart.NewWriter(&buf)
part, _ := writer.CreateFormFile("file", filename)
part.Write(body)
writer.Close()
_, _ = part.Write(body)
_ = writer.Close()

req := httptest.NewRequest("POST", "/upload", &buf)
req.Header.Set("Content-Type", writer.FormDataContentType())
Expand Down Expand Up @@ -153,7 +153,7 @@ func TestUpload_TargetNotForwarded_OnDuplicate(t *testing.T) {
db, err := sql.Open("sqlite", ":memory:")
require.NoError(t, err)
require.NoError(t, InitDB(db))
t.Cleanup(func() { db.Close() })
t.Cleanup(func() { _ = db.Close() })

cfg := &config.Config{
Clients: []config.Client{{ID: "c", Token: "tok", AllowedDeviceIDs: []string{"dev"}}},
Expand All @@ -172,8 +172,8 @@ func TestUpload_MissingFileField(t *testing.T) {

var buf bytes.Buffer
writer := multipart.NewWriter(&buf)
writer.WriteField("other", "value")
writer.Close()
_ = writer.WriteField("other", "value")
_ = writer.Close()

req := httptest.NewRequest("POST", "/upload", &buf)
req.Header.Set("Content-Type", writer.FormDataContentType())
Expand Down
2 changes: 1 addition & 1 deletion server/internal/target/dawarich/dawarich.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ func (d *Dawarich) Send(filename string, data []byte) error {
if err != nil {
return fmt.Errorf("sending to dawarich: %w", err)
}
defer resp.Body.Close()
defer func() { _ = resp.Body.Close() }()

if resp.StatusCode < 200 || resp.StatusCode >= 300 {
body, _ := io.ReadAll(resp.Body)
Expand Down
6 changes: 3 additions & 3 deletions server/internal/target/dawarich/dawarich_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,14 @@ func TestSend_PostsToImportsEndpoint(t *testing.T) {
cfg: target.Config{URL: ts.URL, APIKey: "k"},
client: &http.Client{Timeout: 5 * time.Second},
}
d.Send("f.gpx", []byte("data"))
_ = d.Send("f.gpx", []byte("data"))
assert.Equal(t, "/api/v1/imports", gotPath)
}

func TestSend_ErrorOnNon2xx(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte("something broke"))
_, _ = w.Write([]byte("something broke"))
}))
defer ts.Close()

Expand All @@ -80,7 +80,7 @@ func TestReadAPIKey_Inline(t *testing.T) {

func TestReadAPIKey_File(t *testing.T) {
path := filepath.Join(t.TempDir(), "api-key")
os.WriteFile(path, []byte(" file-key\n"), 0600)
require.NoError(t, os.WriteFile(path, []byte(" file-key\n"), 0600))

d := &Dawarich{cfg: target.Config{APIKeyFile: path}}
key, err := d.readAPIKey()
Expand Down
2 changes: 1 addition & 1 deletion server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ func main() {
slog.Error("failed to open database", "error", err)
os.Exit(1)
}
defer db.Close()
defer func() { _ = db.Close() }()

if err := server.InitDB(db); err != nil {
slog.Error("failed to init database", "error", err)
Expand Down
22 changes: 11 additions & 11 deletions tracksync/internal/device/columbus/columbus_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import (

func TestFindFiles_GPX(t *testing.T) {
dir := t.TempDir()
os.WriteFile(filepath.Join(dir, "track1.gpx"), []byte("<gpx/>"), 0644)
os.WriteFile(filepath.Join(dir, "track2.gpx"), []byte("<gpx/>"), 0644)
require.NoError(t, os.WriteFile(filepath.Join(dir, "track1.gpx"), []byte("<gpx/>"), 0644))
require.NoError(t, os.WriteFile(filepath.Join(dir, "track2.gpx"), []byte("<gpx/>"), 0644))

files, err := (&P10Pro{}).FindFiles(dir)
require.NoError(t, err)
Expand All @@ -21,9 +21,9 @@ func TestFindFiles_GPX(t *testing.T) {

func TestFindFiles_CaseInsensitive(t *testing.T) {
dir := t.TempDir()
os.WriteFile(filepath.Join(dir, "lower.gpx"), []byte("<gpx/>"), 0644)
os.WriteFile(filepath.Join(dir, "UPPER.GPX"), []byte("<gpx/>"), 0644)
os.WriteFile(filepath.Join(dir, "Mixed.Gpx"), []byte("<gpx/>"), 0644)
require.NoError(t, os.WriteFile(filepath.Join(dir, "lower.gpx"), []byte("<gpx/>"), 0644))
require.NoError(t, os.WriteFile(filepath.Join(dir, "UPPER.GPX"), []byte("<gpx/>"), 0644))
require.NoError(t, os.WriteFile(filepath.Join(dir, "Mixed.Gpx"), []byte("<gpx/>"), 0644))

files, err := (&P10Pro{}).FindFiles(dir)
require.NoError(t, err)
Expand All @@ -32,9 +32,9 @@ func TestFindFiles_CaseInsensitive(t *testing.T) {

func TestFindFiles_SkipsNonGPX(t *testing.T) {
dir := t.TempDir()
os.WriteFile(filepath.Join(dir, "track.gpx"), []byte("<gpx/>"), 0644)
os.WriteFile(filepath.Join(dir, "photo.jpg"), []byte("jpeg"), 0644)
os.WriteFile(filepath.Join(dir, "notes.txt"), []byte("text"), 0644)
require.NoError(t, os.WriteFile(filepath.Join(dir, "track.gpx"), []byte("<gpx/>"), 0644))
require.NoError(t, os.WriteFile(filepath.Join(dir, "photo.jpg"), []byte("jpeg"), 0644))
require.NoError(t, os.WriteFile(filepath.Join(dir, "notes.txt"), []byte("text"), 0644))

files, err := (&P10Pro{}).FindFiles(dir)
require.NoError(t, err)
Expand All @@ -45,8 +45,8 @@ func TestFindFiles_Recursive(t *testing.T) {
dir := t.TempDir()
sub := filepath.Join(dir, "subdir", "nested")
require.NoError(t, os.MkdirAll(sub, 0755))
os.WriteFile(filepath.Join(dir, "root.gpx"), []byte("<gpx/>"), 0644)
os.WriteFile(filepath.Join(sub, "nested.gpx"), []byte("<gpx/>"), 0644)
require.NoError(t, os.WriteFile(filepath.Join(dir, "root.gpx"), []byte("<gpx/>"), 0644))
require.NoError(t, os.WriteFile(filepath.Join(sub, "nested.gpx"), []byte("<gpx/>"), 0644))

files, err := (&P10Pro{}).FindFiles(dir)
require.NoError(t, err)
Expand All @@ -68,7 +68,7 @@ func TestFindFiles_EmptyDir(t *testing.T) {

func TestFindFiles_AbsolutePaths(t *testing.T) {
dir := t.TempDir()
os.WriteFile(filepath.Join(dir, "track.gpx"), []byte("<gpx/>"), 0644)
require.NoError(t, os.WriteFile(filepath.Join(dir, "track.gpx"), []byte("<gpx/>"), 0644))

files, err := (&P10Pro{}).FindFiles(dir)
require.NoError(t, err)
Expand Down
4 changes: 2 additions & 2 deletions tracksync/internal/migrations/migrations.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,12 @@ func Run(db *sql.DB) error {
}

if _, err := tx.Exec(string(data)); err != nil {
tx.Rollback()
_ = tx.Rollback()
return fmt.Errorf("applying migration %s: %w", name, err)
}

if _, err := tx.Exec("INSERT INTO schema_migrations (version) VALUES (?)", name); err != nil {
tx.Rollback()
_ = tx.Rollback()
return fmt.Errorf("recording migration %s: %w", name, err)
}

Expand Down
6 changes: 3 additions & 3 deletions tracksync/internal/sync/sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ func OpenStateDB(path string) (*sql.DB, error) {
return nil, err
}
if _, err := db.Exec("PRAGMA journal_mode=wal"); err != nil {
db.Close()
_ = db.Close()
return nil, err
}
if err := migrations.Run(db); err != nil {
db.Close()
_ = db.Close()
return nil, err
}
return db, nil
Expand Down Expand Up @@ -98,7 +98,7 @@ func Upload(client *http.Client, serverURL, token, deviceID, hostname, filename
if err != nil {
return "", fmt.Errorf("sending request: %w", err)
}
defer resp.Body.Close()
defer func() { _ = resp.Body.Close() }()

body, _ := io.ReadAll(resp.Body)
status := strings.TrimSpace(string(body))
Expand Down
14 changes: 7 additions & 7 deletions tracksync/internal/sync/sync_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ func openTestDB(t *testing.T) *sql.DB {
t.Helper()
db, err := OpenStateDB(filepath.Join(t.TempDir(), "state.db"))
require.NoError(t, err)
t.Cleanup(func() { db.Close() })
t.Cleanup(func() { _ = db.Close() })
return db
}

Expand All @@ -45,14 +45,14 @@ func TestRecordUpload_Idempotent(t *testing.T) {
require.NoError(t, RecordUpload(db, "hash1", "a.gpx", "dev"), "INSERT OR IGNORE should not error")

var count int
db.QueryRow("SELECT COUNT(*) FROM uploaded WHERE sha256 = ?", "hash1").Scan(&count)
require.NoError(t, db.QueryRow("SELECT COUNT(*) FROM uploaded WHERE sha256 = ?", "hash1").Scan(&count))
assert.Equal(t, 1, count)
}

func TestClearUploads(t *testing.T) {
db := openTestDB(t)
for i := 0; i < 5; i++ {
RecordUpload(db, fmt.Sprintf("hash-%d", i), fmt.Sprintf("file-%d.gpx", i), "dev")
require.NoError(t, RecordUpload(db, fmt.Sprintf("hash-%d", i), fmt.Sprintf("file-%d.gpx", i), "dev"))
}

n, err := ClearUploads(db)
Expand Down Expand Up @@ -101,7 +101,7 @@ func TestUpload_Created(t *testing.T) {
assert.Equal(t, "dev-1", r.Header.Get("X-Device-ID"))
assert.Equal(t, "myhost", r.Header.Get("X-Client-Host"))
w.WriteHeader(http.StatusCreated)
fmt.Fprintln(w, "uploaded")
_, _ = fmt.Fprintln(w, "uploaded")
}))
defer ts.Close()

Expand All @@ -114,7 +114,7 @@ func TestUpload_Created(t *testing.T) {
func TestUpload_Duplicate(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
fmt.Fprintln(w, "duplicate")
_, _ = fmt.Fprintln(w, "duplicate")
}))
defer ts.Close()

Expand All @@ -127,7 +127,7 @@ func TestUpload_Duplicate(t *testing.T) {
func TestUpload_ServerError(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusInternalServerError)
fmt.Fprintln(w, "internal error")
_, _ = fmt.Fprintln(w, "internal error")
}))
defer ts.Close()

Expand All @@ -140,7 +140,7 @@ func TestOpenStateDB_CreatesDirectory(t *testing.T) {
path := filepath.Join(t.TempDir(), "nested", "dir", "state.db")
db, err := OpenStateDB(path)
require.NoError(t, err)
db.Close()
_ = db.Close()

_, err = os.Stat(path)
assert.NoError(t, err, "database file should exist")
Expand Down
6 changes: 3 additions & 3 deletions tracksync/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func main() {
slog.Error("failed to open state db", "error", err)
os.Exit(1)
}
defer db.Close()
defer func() { _ = db.Close() }()
n, err := sync.ClearUploads(db)
if err != nil {
slog.Error("failed to clear uploads", "error", err)
Expand Down Expand Up @@ -85,7 +85,7 @@ func main() {
slog.Error("failed to open state db", "error", err)
os.Exit(1)
}
defer db.Close()
defer func() { _ = db.Close() }()

dev, ok := device.Get(*deviceType)
if !ok {
Expand Down Expand Up @@ -171,7 +171,7 @@ func main() {

// writeSummary outputs the summary as JSON to stdout for machine consumption.
func writeSummary(s Summary) {
json.NewEncoder(os.Stdout).Encode(s)
_ = json.NewEncoder(os.Stdout).Encode(s)
}

func defaultStateDB() string {
Expand Down
Loading