repoIsAvailable check is the given repository is locked by a Cache. Note: this is a smart function that will clean the lock file if the corresponding process is not there anymore. If no error is returned, the repo is free to edit.
(repo repository.RepoStorage, events chan BuildEvent)
| 262 | // corresponding process is not there anymore. |
| 263 | // If no error is returned, the repo is free to edit. |
| 264 | func repoIsAvailable(repo repository.RepoStorage, events chan BuildEvent) error { |
| 265 | // Todo: this leave way for a racey access to the repo between the test |
| 266 | // if the file exist and the actual write. It's probably not a problem in |
| 267 | // practice because using a repository will be done from user interaction |
| 268 | // or in a context where a single instance of git-bug is already guaranteed |
| 269 | // (say, a server with the web UI running). But still, that might be nice to |
| 270 | // have a mutex or something to guard that. |
| 271 | |
| 272 | // Todo: this will fail if somehow the filesystem is shared with another |
| 273 | // computer. Should add a configuration that prevent the cleaning of the |
| 274 | // lock file |
| 275 | |
| 276 | f, err := repo.LocalStorage().Open(lockfile) |
| 277 | if err != nil && !os.IsNotExist(err) { |
| 278 | return err |
| 279 | } |
| 280 | |
| 281 | if err == nil { |
| 282 | // lock file already exist |
| 283 | buf, err := io.ReadAll(io.LimitReader(f, 10)) |
| 284 | if err != nil { |
| 285 | _ = f.Close() |
| 286 | return err |
| 287 | } |
| 288 | |
| 289 | err = f.Close() |
| 290 | if err != nil { |
| 291 | return err |
| 292 | } |
| 293 | |
| 294 | if len(buf) >= 10 { |
| 295 | return fmt.Errorf("the lock file should be < 10 bytes") |
| 296 | } |
| 297 | |
| 298 | pid, err := strconv.Atoi(string(buf)) |
| 299 | if err != nil { |
| 300 | return err |
| 301 | } |
| 302 | |
| 303 | if process.IsRunning(pid) { |
| 304 | return fmt.Errorf("the repository you want to access is already locked by the process pid %d", pid) |
| 305 | } |
| 306 | |
| 307 | // The lock file is just laying there after a crash, clean it |
| 308 | |
| 309 | events <- BuildEvent{Event: BuildEventRemoveLock} |
| 310 | |
| 311 | err = repo.LocalStorage().Remove(lockfile) |
| 312 | if err != nil { |
| 313 | return err |
| 314 | } |
| 315 | } |
| 316 | |
| 317 | return nil |
| 318 | } |