Use XDG config directory as default config path
- Look for config at $XDG_CONFIG_HOME/converge/config.yaml by default - --config still overrides to an explicit path - Falls back to single-repo --repo mode if no config file found - New defaultConfigPath and configFileExists helpers in Converge module
This commit is contained in:
@@ -6,41 +6,47 @@ Converge notifies the user via libnotify / `notify-send` whenever a merge confli
|
|||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
### Single repository
|
### Configuration
|
||||||
|
|
||||||
|
Converge looks for its config file at `$XDG_CONFIG_HOME/converge/config.yaml` (typically `~/.config/converge/config.yaml`). If found, it uses that file automatically.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Watch the current directory (defaults)
|
# Run with the default XDG config file
|
||||||
./scripts/run
|
./scripts/run
|
||||||
|
|
||||||
# Watch a specific repo
|
|
||||||
./scripts/run -- --repo /path/to/repo --branch master --debounce 10000
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Multiple repositories (config file)
|
You can also specify a config file explicitly:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Create a config file
|
./scripts/run -- --config /path/to/converge.yaml
|
||||||
cp converge.example.yaml converge.yaml
|
```
|
||||||
# Edit to list your repos
|
|
||||||
vim converge.yaml
|
|
||||||
|
|
||||||
# Run with config
|
### Single repository (no config file)
|
||||||
./scripts/run -- --config converge.yaml
|
|
||||||
|
If no config file exists, converge falls back to watching a single repository:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Watch the current directory
|
||||||
|
./scripts/run
|
||||||
|
|
||||||
|
# Watch a specific repo with options
|
||||||
|
./scripts/run -- --repo /path/to/repo --branch master --debounce 10000
|
||||||
```
|
```
|
||||||
|
|
||||||
### Options
|
### Options
|
||||||
|
|
||||||
| Option | Default | Description |
|
| Option | Default | Description |
|
||||||
|--------|---------|-------------|
|
|--------|---------|-------------|
|
||||||
| `-c`, `--config FILE` | — | Path to YAML config file listing repositories |
|
| `-c`, `--config FILE` | `$XDG_CONFIG_HOME/converge/config.yaml` | Path to YAML config file listing repositories |
|
||||||
| `-r`, `--repo PATH` | `.` (cwd) | Path to a single git repository |
|
| `-r`, `--repo PATH` | `.` (cwd) | Path to a single git repository (single-repo fallback mode) |
|
||||||
| `-d`, `--debounce MS` | `5000` | Debounce window in milliseconds (overrides config) |
|
| `-d`, `--debounce MS` | `5000` | Debounce window in milliseconds (overrides config file) |
|
||||||
| `--remote NAME` | `origin` | Remote name (single-repo mode) |
|
| `--remote NAME` | `origin` | Remote name (single-repo fallback mode) |
|
||||||
| `-b`, `--branch NAME` | `main` | Branch to pull (single-repo mode) |
|
| `-b`, `--branch NAME` | `main` | Branch to pull (single-repo fallback mode) |
|
||||||
|
|
||||||
### Config file format
|
### Config file format
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
|
# ~/.config/converge/config.yaml (XDG default)
|
||||||
repos:
|
repos:
|
||||||
- path: /absolute/or/relative/path
|
- path: /absolute/or/relative/path
|
||||||
remote: origin # optional, defaults to "origin"
|
remote: origin # optional, defaults to "origin"
|
||||||
@@ -74,5 +80,5 @@ All development tools run inside Docker via the `hs` wrapper script.
|
|||||||
- **File watching**: [fsnotify](https://hackage.haskell.org/package/fsnotify)
|
- **File watching**: [fsnotify](https://hackage.haskell.org/package/fsnotify)
|
||||||
- **Concurrency**: one watcher thread per repository via `async`
|
- **Concurrency**: one watcher thread per repository via `async`
|
||||||
- **Notifications**: shell out to `notify-send` (libnotify)
|
- **Notifications**: shell out to `notify-send` (libnotify)
|
||||||
- **Configuration**: YAML config file for multi-repo, CLI flags for single-repo
|
- **Configuration**: YAML config file at XDG config path for multi-repo, CLI flags for single-repo fallback
|
||||||
- **Daemonization**: TBD (likely systemd service)
|
- **Daemonization**: TBD (likely systemd service)
|
||||||
|
|||||||
+34
-17
@@ -76,27 +76,40 @@ main :: IO ()
|
|||||||
main = do
|
main = do
|
||||||
cli <- execParser parserInfo
|
cli <- execParser parserInfo
|
||||||
let mDebounceOverride = cliDebounce cli
|
let mDebounceOverride = cliDebounce cli
|
||||||
options <- case cliConfig cli of
|
(options, configSource) <- case cliConfig cli of
|
||||||
Just cfgPath -> do
|
Just cfgPath -> do
|
||||||
cfg <- loadConfig cfgPath
|
cfg <- loadConfig cfgPath
|
||||||
let opts = configToOptions cfg
|
let opts = applyDebounce mDebounceOverride (configToOptions cfg)
|
||||||
pure $ case mDebounceOverride of
|
pure (opts, Just cfgPath)
|
||||||
Just ms -> opts{optDebounceMs = ms}
|
Nothing -> do
|
||||||
Nothing -> opts
|
exists <- configFileExists
|
||||||
Nothing ->
|
if exists
|
||||||
pure $
|
then do
|
||||||
defaultOptions
|
cfgPath <- defaultConfigPath
|
||||||
{ optRepos =
|
cfg <- loadConfig cfgPath
|
||||||
[ defaultRepoConfig
|
let opts = applyDebounce mDebounceOverride (configToOptions cfg)
|
||||||
{ rcPath = fromMaybe "." (cliRepo cli)
|
pure (opts, Just cfgPath)
|
||||||
, rcRemote = cliRemote cli
|
else
|
||||||
, rcBranch = cliBranch cli
|
pure
|
||||||
|
( defaultOptions
|
||||||
|
{ optRepos =
|
||||||
|
[ defaultRepoConfig
|
||||||
|
{ rcPath = fromMaybe "." (cliRepo cli)
|
||||||
|
, rcRemote = cliRemote cli
|
||||||
|
, rcBranch = cliBranch cli
|
||||||
|
}
|
||||||
|
]
|
||||||
|
, optDebounceMs = fromMaybe 5000 mDebounceOverride
|
||||||
}
|
}
|
||||||
]
|
, Nothing
|
||||||
, optDebounceMs = fromMaybe 5000 mDebounceOverride
|
)
|
||||||
}
|
case configSource of
|
||||||
|
Just path ->
|
||||||
|
hPutStrLn stderr ("Using config: " <> path)
|
||||||
|
Nothing ->
|
||||||
|
hPutStrLn stderr "No config file found, using single-repo mode"
|
||||||
hPutStrLn stderr $
|
hPutStrLn stderr $
|
||||||
"Converge watching "
|
"Watching "
|
||||||
<> show (length (optRepos options))
|
<> show (length (optRepos options))
|
||||||
<> " repo(s)"
|
<> " repo(s)"
|
||||||
<> " (debounce: "
|
<> " (debounce: "
|
||||||
@@ -104,3 +117,7 @@ main = do
|
|||||||
<> "ms)"
|
<> "ms)"
|
||||||
mapM_ (\r -> hPutStrLn stderr (" - " <> rcPath r)) (optRepos options)
|
mapM_ (\r -> hPutStrLn stderr (" - " <> rcPath r)) (optRepos options)
|
||||||
runConverge options
|
runConverge options
|
||||||
|
|
||||||
|
applyDebounce :: Maybe Int -> Options -> Options
|
||||||
|
applyDebounce (Just ms) opts = opts{optDebounceMs = ms}
|
||||||
|
applyDebounce Nothing opts = opts
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
# Example converge configuration file.
|
# Example converge configuration file.
|
||||||
# Usage: converge --config converge.yaml
|
# Place at ~/.config/converge/config.yaml to use by default,
|
||||||
|
# or pass explicitly with: converge --config converge.yaml
|
||||||
|
|
||||||
repos:
|
repos:
|
||||||
- path: /home/jbrechtel/org
|
- path: /home/jbrechtel/org
|
||||||
|
|||||||
+11
-1
@@ -9,6 +9,8 @@ module Converge (
|
|||||||
Config (..),
|
Config (..),
|
||||||
loadConfig,
|
loadConfig,
|
||||||
configToOptions,
|
configToOptions,
|
||||||
|
defaultConfigPath,
|
||||||
|
configFileExists,
|
||||||
|
|
||||||
-- * Running
|
-- * Running
|
||||||
runConverge,
|
runConverge,
|
||||||
@@ -31,7 +33,7 @@ import Data.Maybe (fromMaybe)
|
|||||||
import Data.Text (Text)
|
import Data.Text (Text)
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
import Data.Yaml (FromJSON (..), decodeFileThrow, withObject, (.:), (.:?))
|
import Data.Yaml (FromJSON (..), decodeFileThrow, withObject, (.:), (.:?))
|
||||||
import System.Directory (getCurrentDirectory)
|
import System.Directory (XdgDirectory (XdgConfig), doesFileExist, getCurrentDirectory, getXdgDirectory)
|
||||||
import System.Exit (ExitCode (..))
|
import System.Exit (ExitCode (..))
|
||||||
import System.FSNotify
|
import System.FSNotify
|
||||||
import System.FilePath (isAbsolute, (</>))
|
import System.FilePath (isAbsolute, (</>))
|
||||||
@@ -114,6 +116,14 @@ configToOptions cfg =
|
|||||||
, optDebounceMs = fromMaybe 5000 (cfgDebounceMs cfg)
|
, optDebounceMs = fromMaybe 5000 (cfgDebounceMs cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
-- | The default XDG config file path: @$XDG_CONFIG_HOME/converge/config.yaml@.
|
||||||
|
defaultConfigPath :: IO FilePath
|
||||||
|
defaultConfigPath = (</> "converge/config.yaml") <$> getXdgDirectory XdgConfig ""
|
||||||
|
|
||||||
|
-- | Check whether the default config file exists.
|
||||||
|
configFileExists :: IO Bool
|
||||||
|
configFileExists = defaultConfigPath >>= doesFileExist
|
||||||
|
|
||||||
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
-- Running
|
-- Running
|
||||||
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
|
|||||||
Reference in New Issue
Block a user