powerful but friendly backup program that runs in your tray, powered by restic devins.page/restray
go restic system-tray
2

Configure Feed

Select the types of activity you want to include in your feed.

revert: unlock after cancel

probably not needed, figured out what the actual issue i was having was

intergrav (Jul 2, 2026, 12:33 AM EDT) 0d164de0 77c4e58d

-17
-6
cmd/restray/operations.go
··· 99 99 log.Printf("[%s] %s killed by system, retrying once", prof.displayName(), args[0]) 100 100 msg, err = runResticOnce(idx, prof, mStatus, args...) 101 101 } 102 - if err != nil && takeCancelled(idx) && retryLockEnabled(prof) { 103 - retryUnlock(idx, prof, mStatus) 104 - } 105 102 return msg, err 106 103 } 107 104 ··· 193 190 mStatus.SetTitle("Backing up...") 194 191 setProfileFailed(idx, "") 195 192 ok, code = doBackupOnce(idx, mStatus, prof, args) 196 - } 197 - if !ok && takeCancelled(idx) && retryLockEnabled(prof) { 198 - retryUnlock(idx, prof, mStatus) 199 193 } 200 194 if ok { 201 195 setLastBackup(idx, time.Now())
-11
cmd/restray/restic.go
··· 184 184 notifications string 185 185 failStatus map[int]string 186 186 lastBackup map[int]time.Time 187 - cancelled map[int]bool 188 187 } 189 188 190 189 var state = appState{ ··· 193 192 mountStopping: make(map[int]bool), 194 193 failStatus: make(map[int]string), 195 194 lastBackup: make(map[int]time.Time), 196 - cancelled: make(map[int]bool), 197 - } 198 - 199 - func takeCancelled(idx int) bool { 200 - state.mu.Lock() 201 - defer state.mu.Unlock() 202 - was := state.cancelled[idx] 203 - delete(state.cancelled, idx) 204 - return was 205 195 } 206 196 207 197 func setLastBackup(idx int, t time.Time) { ··· 272 262 state.mu.Lock() 273 263 defer state.mu.Unlock() 274 264 if cmd := state.busyProfiles[idx]; cmd != nil && cmd.Process != nil { 275 - state.cancelled[idx] = true 276 265 interruptProcess(cmd.Process) 277 266 } 278 267 }