• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

stacklok / toolhive-studio / 22182921017

19 Feb 2026 01:03PM UTC coverage: 56.052% (-0.07%) from 56.117%
22182921017

Pull #1670

github

web-flow
Merge 0485129a0 into 33881d979
Pull Request #1670: build: modernize flatpak build

2571 of 4797 branches covered (53.6%)

4 of 16 new or added lines in 1 file covered. (25.0%)

35 existing lines in 3 files now uncovered.

4037 of 6992 relevant lines covered (57.74%)

120.17 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

89.66
/main/src/cli/marker-file.ts
1
/**
2
 * Marker File Management
3
 * Manages ~/.toolhive/.cli-source marker file (THV-0020)
4
 */
5

6
import {
7
  existsSync,
8
  mkdirSync,
9
  readFileSync,
10
  writeFileSync,
11
  unlinkSync,
12
  chmodSync,
13
} from 'node:fs'
1✔
14
import path from 'node:path'
15
import { app } from 'electron'
16
import { getMarkerFilePath } from './constants'
17
import { isFlatpak } from './symlink-manager'
18
import type { CliSourceMarker, Platform } from './types'
19
import log from '../logger'
20

21
const CURRENT_SCHEMA_VERSION = 1 as const
1✔
22

23
export function readMarkerFile(): CliSourceMarker | null {
24
  const markerPath = getMarkerFilePath()
5✔
25

26
  if (!existsSync(markerPath)) {
5✔
27
    return null
1✔
28
  }
29

30
  try {
4✔
31
    const content = readFileSync(markerPath, 'utf8')
4✔
32
    const data = JSON.parse(content)
4✔
33

34
    if (data.schema_version !== CURRENT_SCHEMA_VERSION) {
4✔
35
      log.warn(`Marker file has invalid schema version: ${data.schema_version}`)
1✔
36
      return null
1✔
37
    }
38

39
    if (data.source !== 'desktop') {
2✔
40
      log.warn(`Marker file has invalid source: ${data.source}`)
1✔
41
      return null
1✔
42
    }
43

44
    return data as CliSourceMarker
1✔
45
  } catch (error) {
46
    log.warn(`Failed to read marker file: ${error}`)
1✔
47
    return null
1✔
48
  }
49
}
50

51
export function writeMarkerFile(
52
  marker: Omit<CliSourceMarker, 'schema_version'>
53
): boolean {
54
  const markerPath = getMarkerFilePath()
5✔
55
  const markerDir = path.dirname(markerPath)
5✔
56

57
  try {
5✔
58
    if (!existsSync(markerDir)) {
5!
59
      mkdirSync(markerDir, { recursive: true })
5✔
60
    }
61

62
    const fullMarker: CliSourceMarker = {
5✔
63
      schema_version: CURRENT_SCHEMA_VERSION,
64
      ...marker,
65
    }
66

67
    writeFileSync(markerPath, JSON.stringify(fullMarker, null, 2), 'utf8')
5✔
68

69
    if (process.platform !== 'win32') {
5✔
70
      try {
4✔
71
        chmodSync(markerPath, 0o600)
4✔
72
      } catch {
73
        // Ignore chmod errors
74
      }
75
    }
76

77
    log.info(`Marker file written successfully: ${markerPath}`)
5✔
78
    return true
5✔
79
  } catch (error) {
80
    log.error(`Failed to write marker file: ${error}`)
×
UNCOV
81
    return false
×
82
  }
83
}
84

85
export function deleteMarkerFile(): boolean {
86
  const markerPath = getMarkerFilePath()
2✔
87

88
  if (!existsSync(markerPath)) {
2✔
89
    return true
1✔
90
  }
91

92
  try {
1✔
93
    unlinkSync(markerPath)
1✔
94
    log.info('Marker file deleted successfully')
1✔
95
    return true
1✔
96
  } catch (error) {
97
    log.error(`Failed to delete marker file: ${error}`)
×
UNCOV
98
    return false
×
99
  }
100
}
101

102
export function createMarkerForDesktopInstall(
103
  cliVersion: string,
104
  symlinkTarget: string | undefined,
105
  cliChecksum: string | undefined,
106
  platform: Platform = process.platform as Platform
2✔
107
): boolean {
108
  return writeMarkerFile({
2✔
109
    source: 'desktop',
110
    install_method:
111
      platform === 'win32' ? 'copy' : isFlatpak() ? 'wrapper' : 'symlink',
3!
112
    cli_version: cliVersion,
113
    symlink_target: symlinkTarget,
114
    cli_checksum: cliChecksum,
115
    installed_at: new Date().toISOString(),
116
    desktop_version: app.getVersion(),
117
  })
118
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc