mirror of
https://github.com/nix-community/home-manager
synced 2024-11-23 05:03:09 +00:00
isync/mbsync: replace master/slave with far/near (#1776)
* isync/mbsync: replace master/slave with far/near isync/mbsync: update tests to match new changes * isync/mbsync: use mkRenamedOptionModule to alert user to near/far change * isync/mbsync: use warnings to alert about master/slave far/near change Fix capitalization isync/mbsync: fix nitpicks * isync/mbsync: run format script * isync/mbsync: include new test for expected master/slave warnings * isync/mbsync: add news about changes
This commit is contained in:
parent
4f70f49cec
commit
64607f58b7
6 changed files with 239 additions and 87 deletions
|
@ -2029,6 +2029,23 @@ in
|
|||
A new module is available: 'programs.foot'.
|
||||
'';
|
||||
}
|
||||
|
||||
{
|
||||
time = "2021-04-13T07:19:36+00:00";
|
||||
message = ''
|
||||
mbsync channels no longer accepts the masterPattern or slavePattern
|
||||
attribute keys. This is due to an upstream change.
|
||||
They have been renamed: masterPattern -> farPattern, and
|
||||
slavePattern -> nearPattern.
|
||||
This is a stateful change, where the database file(s) used to keep track
|
||||
of mail are silently upgraded once you upgrade both your configuration file
|
||||
and the mbsync program.
|
||||
|
||||
Note that this change is non-reversible, meaning once you choose to switch to
|
||||
near/farPattern, you can no longer use your previous slave/masterPattern
|
||||
configuration file.
|
||||
'';
|
||||
}
|
||||
];
|
||||
};
|
||||
}
|
||||
|
|
|
@ -50,13 +50,13 @@ let
|
|||
'';
|
||||
};
|
||||
|
||||
masterPattern = mkOption {
|
||||
farPattern = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
example = "[Gmail]/Sent Mail";
|
||||
description = ''
|
||||
IMAP4 patterns for which mailboxes on the remote mail server to sync.
|
||||
If <literal>Patterns</literal> are specified, <literal>masterPattern</literal>
|
||||
If <literal>Patterns</literal> are specified, <literal>farPattern</literal>
|
||||
is interpreted as a prefix which is not matched against the patterns,
|
||||
and is not affected by mailbox list overrides.
|
||||
</para><para>
|
||||
|
@ -65,14 +65,14 @@ let
|
|||
'';
|
||||
};
|
||||
|
||||
slavePattern = mkOption {
|
||||
nearPattern = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
example = "Sent";
|
||||
description = ''
|
||||
Name for where mail coming from the master mail server will end up
|
||||
locally. The mailbox specified by the master's pattern will be placed
|
||||
in this directory.
|
||||
Name for where mail coming from the remote (far) mail server will end up
|
||||
locally. The mailbox specified by the far pattern will be placed in
|
||||
this directory.
|
||||
</para><para>
|
||||
If this is left as the default, then mbsync will default to the pattern
|
||||
<literal>INBOX</literal>.
|
||||
|
@ -85,7 +85,7 @@ let
|
|||
example = [ "INBOX" ];
|
||||
description = ''
|
||||
Instead of synchronizing <emphasis>just</emphasis> the mailboxes that
|
||||
match the <literal>masterPattern</literal>, use it as a prefix which is
|
||||
match the <literal>farPattern</literal>, use it as a prefix which is
|
||||
not matched against the patterns, and is not affected by mailbox list
|
||||
overrides.
|
||||
'';
|
||||
|
|
|
@ -10,6 +10,24 @@ let
|
|||
mbsyncAccounts =
|
||||
filter (a: a.mbsync.enable) (attrValues config.accounts.email.accounts);
|
||||
|
||||
# Given a SINGLE group's channels attribute set, return true if ANY of the channel's
|
||||
# patterns use the invalidOption attribute set value name.
|
||||
channelInvalidOption = channels: invalidOption:
|
||||
any (c: c) (mapAttrsToList (c: hasAttr invalidOption) channels);
|
||||
|
||||
# Given a SINGLE account's groups attribute set, return true if ANY of the account's group's channel's patterns use the invalidOption attribute set value name.
|
||||
groupInvalidOption = groups: invalidOption:
|
||||
any (g: g) (mapAttrsToList (groupName: groupVals:
|
||||
channelInvalidOption groupVals.channels invalidOption) groups);
|
||||
|
||||
# Given all accounts (ensure that accounts passed in here ARE mbsync-using accounts)
|
||||
# return true if ANY of the account's groups' channels' patterns use the
|
||||
# invalidOption attribute set value name.
|
||||
accountInvalidOption = accounts: invalidOption:
|
||||
any (a: a)
|
||||
(map (account: groupInvalidOption account.mbsync.groups invalidOption)
|
||||
mbsyncAccounts);
|
||||
|
||||
genTlsConfig = tls:
|
||||
{
|
||||
SSLType = if !tls.enable then
|
||||
|
@ -22,10 +40,18 @@ let
|
|||
CertificateFile = toString tls.certificatesFile;
|
||||
};
|
||||
|
||||
masterSlaveMapping = {
|
||||
imports = [
|
||||
(mkRenamedOptionModule [ "programs" "mbsync" "masterSlaveMapping" ] [
|
||||
"programs"
|
||||
"mbsync"
|
||||
"nearFarMapping"
|
||||
])
|
||||
];
|
||||
|
||||
nearFarMapping = {
|
||||
none = "None";
|
||||
imap = "Master";
|
||||
maildir = "Slave";
|
||||
imap = "Far";
|
||||
maildir = "Near";
|
||||
both = "Both";
|
||||
};
|
||||
|
||||
|
@ -88,18 +114,18 @@ let
|
|||
genAccountWideChannel = account:
|
||||
with account;
|
||||
genSection "Channel ${name}" ({
|
||||
Master = ":${name}-remote:";
|
||||
Slave = ":${name}-local:";
|
||||
Far = ":${name}-remote:";
|
||||
Near = ":${name}-local:";
|
||||
Patterns = mbsync.patterns;
|
||||
Create = masterSlaveMapping.${mbsync.create};
|
||||
Remove = masterSlaveMapping.${mbsync.remove};
|
||||
Expunge = masterSlaveMapping.${mbsync.expunge};
|
||||
Create = nearFarMapping.${mbsync.create};
|
||||
Remove = nearFarMapping.${mbsync.remove};
|
||||
Expunge = nearFarMapping.${mbsync.expunge};
|
||||
SyncState = "*";
|
||||
} // mbsync.extraConfig.channel) + "\n";
|
||||
|
||||
# Given the attr set of groups, return a string of channels that will direct
|
||||
# mail to the proper directories, according to the pattern used in channel's
|
||||
# master pattern definition.
|
||||
# "far" pattern definition.
|
||||
genGroupChannelConfig = storeName: groups:
|
||||
let
|
||||
# Given the name of the group this channel is part of and the channel
|
||||
|
@ -118,8 +144,8 @@ let
|
|||
else
|
||||
"";
|
||||
in genSection "Channel ${groupName}-${channel.name}" ({
|
||||
Master = ":${storeName}-remote:${channel.masterPattern}";
|
||||
Slave = ":${storeName}-local:${channel.slavePattern}";
|
||||
Far = ":${storeName}-remote:${channel.farPattern}";
|
||||
Near = ":${storeName}-local:${channel.nearPattern}";
|
||||
} // channel.extraConfig) + genChannelPatterns channel.patterns;
|
||||
# Given the group name, and a attr set of channels within that group,
|
||||
# Generate a list of strings for each channels' configuration.
|
||||
|
@ -206,50 +232,66 @@ in {
|
|||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
assertions = let
|
||||
checkAccounts = pred: msg:
|
||||
let badAccounts = filter pred mbsyncAccounts;
|
||||
in {
|
||||
assertion = badAccounts == [ ];
|
||||
message = "mbsync: ${msg} for accounts: "
|
||||
+ concatMapStringsSep ", " (a: a.name) badAccounts;
|
||||
};
|
||||
in [
|
||||
(checkAccounts (a: a.maildir == null) "Missing maildir configuration")
|
||||
(checkAccounts (a: a.imap == null) "Missing IMAP configuration")
|
||||
(checkAccounts (a: a.passwordCommand == null) "Missing passwordCommand")
|
||||
(checkAccounts (a: a.userName == null) "Missing username")
|
||||
];
|
||||
config = mkIf cfg.enable (mkMerge [
|
||||
{
|
||||
assertions = let
|
||||
checkAccounts = pred: msg:
|
||||
let badAccounts = filter pred mbsyncAccounts;
|
||||
in {
|
||||
assertion = badAccounts == [ ];
|
||||
message = "mbsync: ${msg} for accounts: "
|
||||
+ concatMapStringsSep ", " (a: a.name) badAccounts;
|
||||
};
|
||||
in [
|
||||
(checkAccounts (a: a.maildir == null) "Missing maildir configuration")
|
||||
(checkAccounts (a: a.imap == null) "Missing IMAP configuration")
|
||||
(checkAccounts (a: a.passwordCommand == null) "Missing passwordCommand")
|
||||
(checkAccounts (a: a.userName == null) "Missing username")
|
||||
];
|
||||
}
|
||||
|
||||
home.packages = [ cfg.package ];
|
||||
(mkIf (accountInvalidOption mbsyncAccounts "masterPattern") {
|
||||
warnings = [
|
||||
"mbsync channels no longer use masterPattern. Use farPattern in its place."
|
||||
];
|
||||
})
|
||||
|
||||
programs.notmuch.new.ignore = [ ".uidvalidity" ".mbsyncstate" ];
|
||||
(mkIf (accountInvalidOption mbsyncAccounts "slavePattern") {
|
||||
warnings = [
|
||||
"mbsync channels no longer use slavePattern. Use nearPattern in its place."
|
||||
];
|
||||
})
|
||||
|
||||
home.file.".mbsyncrc".text = let
|
||||
accountsConfig = map genAccountConfig mbsyncAccounts;
|
||||
# Only generate this kind of Group configuration if there are ANY accounts
|
||||
# that do NOT have a per-account groups/channels option(s) specified.
|
||||
groupsConfig =
|
||||
if any (account: account.mbsync.groups == { }) mbsyncAccounts then
|
||||
mapAttrsToList genGroupConfig cfg.groups
|
||||
else
|
||||
[ ];
|
||||
in ''
|
||||
# Generated by Home Manager.
|
||||
{
|
||||
home.packages = [ cfg.package ];
|
||||
|
||||
''
|
||||
+ concatStringsSep "\n" (optional (cfg.extraConfig != "") cfg.extraConfig)
|
||||
+ concatStringsSep "\n\n" accountsConfig
|
||||
+ concatStringsSep "\n" groupsConfig;
|
||||
programs.notmuch.new.ignore = [ ".uidvalidity" ".mbsyncstate" ];
|
||||
|
||||
home.activation = mkIf (mbsyncAccounts != [ ]) {
|
||||
createMaildir =
|
||||
hm.dag.entryBetween [ "linkGeneration" ] [ "writeBoundary" ] ''
|
||||
$DRY_RUN_CMD mkdir -m700 -p $VERBOSE_ARG ${
|
||||
concatMapStringsSep " " (a: a.maildir.absPath) mbsyncAccounts
|
||||
}
|
||||
'';
|
||||
};
|
||||
};
|
||||
home.file.".mbsyncrc".text = let
|
||||
accountsConfig = map genAccountConfig mbsyncAccounts;
|
||||
# Only generate this kind of Group configuration if there are ANY accounts
|
||||
# that do NOT have a per-account groups/channels option(s) specified.
|
||||
groupsConfig =
|
||||
if any (account: account.mbsync.groups == { }) mbsyncAccounts then
|
||||
mapAttrsToList genGroupConfig cfg.groups
|
||||
else
|
||||
[ ];
|
||||
in ''
|
||||
# Generated by Home Manager.
|
||||
|
||||
''
|
||||
+ concatStringsSep "\n" (optional (cfg.extraConfig != "") cfg.extraConfig)
|
||||
+ concatStringsSep "\n\n" accountsConfig
|
||||
+ concatStringsSep "\n" groupsConfig;
|
||||
|
||||
home.activation = mkIf (mbsyncAccounts != [ ]) {
|
||||
createMaildir =
|
||||
hm.dag.entryBetween [ "linkGeneration" ] [ "writeBoundary" ] ''
|
||||
$DRY_RUN_CMD mkdir -m700 -p $VERBOSE_ARG ${
|
||||
concatMapStringsSep " " (a: a.maildir.absPath) mbsyncAccounts
|
||||
}
|
||||
'';
|
||||
};
|
||||
}
|
||||
]);
|
||||
}
|
||||
|
|
|
@ -16,30 +16,30 @@ Path /home/hm-user/Mail/hm-account/
|
|||
SubFolders Verbatim
|
||||
|
||||
Channel emptyChannels-empty1
|
||||
Master :hm-account-remote:
|
||||
Slave :hm-account-local:
|
||||
Far :hm-account-remote:
|
||||
Near :hm-account-local:
|
||||
|
||||
Channel emptyChannels-empty2
|
||||
Master :hm-account-remote:
|
||||
Slave :hm-account-local:
|
||||
Far :hm-account-remote:
|
||||
Near :hm-account-local:
|
||||
|
||||
Channel hm-account-earlierPatternMatch
|
||||
Master :hm-account-remote:Label
|
||||
Slave :hm-account-local:SomethingUnderLabel
|
||||
Far :hm-account-remote:Label
|
||||
Near :hm-account-local:SomethingUnderLabel
|
||||
Pattern ThingUnderLabel !NotThisMaildirThough "[Weird] Label?"
|
||||
|
||||
Channel hm-account-inbox
|
||||
Master :hm-account-remote:Inbox
|
||||
Slave :hm-account-local:Inbox
|
||||
Far :hm-account-remote:Inbox
|
||||
Near :hm-account-local:Inbox
|
||||
|
||||
Channel hm-account-patternMatch
|
||||
Master :hm-account-remote:Label
|
||||
Slave :hm-account-local:SomethingUnderLabel
|
||||
Far :hm-account-remote:Label
|
||||
Near :hm-account-local:SomethingUnderLabel
|
||||
Pattern ThingUnderLabel !NotThisMaildirThough "[Weird] Label?"
|
||||
|
||||
Channel hm-account-strangeHostBoxName
|
||||
Master ":hm-account-remote:[Weird]/Label Mess"
|
||||
Slave :hm-account-local:[AnotherWeird]/Label
|
||||
Far ":hm-account-remote:[Weird]/Label Mess"
|
||||
Near :hm-account-local:[AnotherWeird]/Label
|
||||
|
||||
Group emptyChannels
|
||||
Channel emptyChannels-empty1
|
||||
|
@ -68,12 +68,12 @@ Path /home/hm-user/Mail/hm@example.com/
|
|||
SubFolders Verbatim
|
||||
|
||||
Channel inboxes-inbox1
|
||||
Master :hm@example.com-remote:Inbox1
|
||||
Slave :hm@example.com-local:Inboxes
|
||||
Far :hm@example.com-remote:Inbox1
|
||||
Near :hm@example.com-local:Inboxes
|
||||
|
||||
Channel inboxes-inbox2
|
||||
Master :hm@example.com-remote:Inbox2
|
||||
Slave :hm@example.com-local:Inboxes
|
||||
Far :hm@example.com-remote:Inbox2
|
||||
Near :hm@example.com-local:Inboxes
|
||||
|
||||
Group inboxes
|
||||
Channel inboxes-inbox1
|
||||
|
|
93
tests/modules/programs/mbsync/mbsync-master-slave-change.nix
Normal file
93
tests/modules/programs/mbsync/mbsync-master-slave-change.nix
Normal file
|
@ -0,0 +1,93 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
{
|
||||
imports = [ ../../accounts/email-test-accounts.nix ];
|
||||
|
||||
test.asserts.warnings.expected = [
|
||||
"mbsync channels no longer use masterPattern. Use farPattern in its place."
|
||||
"mbsync channels no longer use slavePattern. Use nearPattern in its place."
|
||||
];
|
||||
|
||||
config = {
|
||||
programs.mbsync = {
|
||||
enable = true;
|
||||
# programs.mbsync.groups and
|
||||
# accounts.email.accounts.<name>.mbsync.groups should NOT be used at the
|
||||
# same time.
|
||||
# If they are, then the new version will take precendence.
|
||||
groups.inboxes = {
|
||||
"hm@example.com" = [ "Inbox1" "Inbox2" ];
|
||||
hm-account = [ "Inbox" ];
|
||||
};
|
||||
};
|
||||
|
||||
accounts.email.accounts = {
|
||||
"hm@example.com".mbsync = {
|
||||
enable = true;
|
||||
groups.inboxes = {
|
||||
channels = {
|
||||
inbox1 = {
|
||||
farPattern = "Inbox1";
|
||||
nearPattern = "Inboxes";
|
||||
};
|
||||
inbox2 = {
|
||||
farPattern = "Inbox2";
|
||||
nearPattern = "Inboxes";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
hm-account.mbsync = {
|
||||
enable = true;
|
||||
groups.hm-account = {
|
||||
channels.earlierPatternMatch = {
|
||||
farPattern = "Label";
|
||||
nearPattern = "SomethingUnderLabel";
|
||||
patterns = [
|
||||
"ThingUnderLabel"
|
||||
"!NotThisMaildirThough"
|
||||
''"[Weird] Label?"''
|
||||
];
|
||||
};
|
||||
channels.inbox = {
|
||||
farPattern = "Inbox";
|
||||
nearPattern = "Inbox";
|
||||
};
|
||||
channels.strangeHostBoxName = {
|
||||
farPattern = "[Weird]/Label Mess";
|
||||
nearPattern = "[AnotherWeird]/Label";
|
||||
};
|
||||
channels.patternMatch = {
|
||||
farPattern = "Label";
|
||||
nearPattern = "SomethingUnderLabel";
|
||||
patterns = [
|
||||
"ThingUnderLabel"
|
||||
"!NotThisMaildirThough"
|
||||
''"[Weird] Label?"''
|
||||
];
|
||||
};
|
||||
};
|
||||
# No group should be printed.
|
||||
groups.emptyGroup = { };
|
||||
# Group should be printed, but left with default channels.
|
||||
groups.emptyChannels = {
|
||||
channels.empty1 = { };
|
||||
channels.empty2 = { };
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
test.asserts.warnings.expected = [
|
||||
"mbsync channels no longer use masterPattern. use farPattern in its place."
|
||||
"mbsync channels no longer use slavePattern. Use nearPattern in its place."
|
||||
];
|
||||
|
||||
nmt.script = ''
|
||||
assertFileExists home-files/.mbsyncrc
|
||||
assertFileContent home-files/.mbsyncrc ${./mbsync-expected.conf}
|
||||
'';
|
||||
};
|
||||
}
|
|
@ -24,12 +24,12 @@ with lib;
|
|||
groups.inboxes = {
|
||||
channels = {
|
||||
inbox1 = {
|
||||
masterPattern = "Inbox1";
|
||||
slavePattern = "Inboxes";
|
||||
farPattern = "Inbox1";
|
||||
nearPattern = "Inboxes";
|
||||
};
|
||||
inbox2 = {
|
||||
masterPattern = "Inbox2";
|
||||
slavePattern = "Inboxes";
|
||||
farPattern = "Inbox2";
|
||||
nearPattern = "Inboxes";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -39,8 +39,8 @@ with lib;
|
|||
enable = true;
|
||||
groups.hm-account = {
|
||||
channels.earlierPatternMatch = {
|
||||
masterPattern = "Label";
|
||||
slavePattern = "SomethingUnderLabel";
|
||||
farPattern = "Label";
|
||||
nearPattern = "SomethingUnderLabel";
|
||||
patterns = [
|
||||
"ThingUnderLabel"
|
||||
"!NotThisMaildirThough"
|
||||
|
@ -48,16 +48,16 @@ with lib;
|
|||
];
|
||||
};
|
||||
channels.inbox = {
|
||||
masterPattern = "Inbox";
|
||||
slavePattern = "Inbox";
|
||||
farPattern = "Inbox";
|
||||
nearPattern = "Inbox";
|
||||
};
|
||||
channels.strangeHostBoxName = {
|
||||
masterPattern = "[Weird]/Label Mess";
|
||||
slavePattern = "[AnotherWeird]/Label";
|
||||
farPattern = "[Weird]/Label Mess";
|
||||
nearPattern = "[AnotherWeird]/Label";
|
||||
};
|
||||
channels.patternMatch = {
|
||||
masterPattern = "Label";
|
||||
slavePattern = "SomethingUnderLabel";
|
||||
farPattern = "Label";
|
||||
nearPattern = "SomethingUnderLabel";
|
||||
patterns = [
|
||||
"ThingUnderLabel"
|
||||
"!NotThisMaildirThough"
|
||||
|
|
Loading…
Reference in a new issue