git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
* [PATCH v2 0/5] extend describe and name-rev pattern matching
@ 2016-12-17  1:24 Jacob Keller
  2016-12-17  1:24 ` [PATCH v2 1/5] doc: add documentation for OPT_STRING_LIST Jacob Keller
                   ` (4 more replies)
  0 siblings, 5 replies; 9+ messages in thread
From: Jacob Keller @ 2016-12-17  1:24 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Jacob Keller

From: Jacob Keller <jacob.keller@gmail.com>

This series adds support for extending describe and name-rev pattern
matching to allow (a) taking multiple patterns and (b) negative patterns
which discard instead of keep. These changes increase the flexibility of
the describe mechanism so that searching for specific tag formats can be
done more easily.

Changes since v1
* add new patches for negative pattern matching
* tweak the documentation slightly

-- interdiff since v1 --
diff --git c/Documentation/git-describe.txt w/Documentation/git-describe.txt
index c85f2811ce28..a89bbde207b2 100644
--- c/Documentation/git-describe.txt
+++ w/Documentation/git-describe.txt
@@ -83,11 +83,18 @@ OPTIONS
 --match <pattern>::
	Only consider tags matching the given `glob(7)` pattern,
	excluding the "refs/tags/" prefix.  This can be used to avoid
-	leaking private tags from the repository, or to shrink the scope of
-	searched tags to avoid -rc tags or similar. If given multiple a list
-	of patterns will be accumulated, and tags matching any of the patterns
-	will be considered. Use `--no-match` to clear and reset the list of
-	patterns.
+	leaking private tags from the repository. If given multiple times, a
+	list of patterns will be accumulated, and tags matching any of the
+	patterns will be considered. Use `--no-match` to clear and reset the
+	list of patterns.
+
+--discard <pattern>::
+	Do not consider tags matching the given `glob(7)` pattern, excluding
+	the "refs/tags/" prefix. This can be used to narrow the tag space and
+	find only tags matching some meaningful criteria. If given multiple
+	times, a list of patterns will be accumulated and tags matching any
+	of the patterns will be discarded. Use `--no-discard` to clear and
+	reset the list of patterns.
 
 --always::
	Show uniquely abbreviated commit object as fallback.
diff --git c/Documentation/git-name-rev.txt w/Documentation/git-name-rev.txt
index 7433627db12d..9b46e5ea9aae 100644
--- c/Documentation/git-name-rev.txt
+++ w/Documentation/git-name-rev.txt
@@ -30,6 +30,13 @@ OPTIONS
	given multiple times, use refs whose names match any of the given shell
	patterns. Use `--no-refs` to clear any previous ref patterns given.
 
+--discard=<pattern>::
+	Do not use any ref whose name matches a given shell pattern. The
+	pattern can be one of branch name, tag name or fully qualified ref
+	name. If given multiple times, discard refs that match any of the given
+	shell patterns. Use `--no-discards` to clear the list of discard
+	patterns.
+
 --all::
	List all commits reachable from all refs
 
diff --git c/builtin/describe.c w/builtin/describe.c
index e3ceab65e273..c09288ee6321 100644
--- c/builtin/describe.c
+++ w/builtin/describe.c
@@ -29,6 +29,7 @@ static int max_candidates = 10;
 static struct hashmap names;
 static int have_util;
 static struct string_list patterns = STRING_LIST_INIT_NODUP;
+static struct string_list discard_patterns = STRING_LIST_INIT_NODUP;
 static int always;
 static const char *dirty;
 
@@ -130,6 +131,22 @@ static int get_name(const char *path, const struct object_id *oid, int flag, voi
		return 0;
 
	/*
+	 * If we're given discard patterns, first discard any tag which match
+	 * any of the discard pattern.
+	 */
+	if (discard_patterns.nr) {
+		struct string_list_item *item;
+
+		if (!is_tag)
+			return 0;
+
+		for_each_string_list_item(item, &discard_patterns) {
+			if (!wildmatch(item->string, path + 10, 0, NULL))
+				return 0;
+		}
+	}
+
+	/*
	 * If we're given patterns, accept only tags which match at least one
	 * pattern.
	 */
@@ -140,9 +157,8 @@ static int get_name(const char *path, const struct object_id *oid, int flag, voi
			return 0;
 
		for_each_string_list_item(item, &patterns) {
-			if (!wildmatch(item->string, path + 10, 0, NULL)) {
+			if (!wildmatch(item->string, path + 10, 0, NULL))
				break;
-			}
 
			/* If we get here, no pattern matched. */
			return 0;
@@ -422,6 +438,8 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
			    N_("consider <n> most recent tags (default: 10)")),
		OPT_STRING_LIST(0, "match", &patterns, N_("pattern"),
			   N_("only consider tags matching <pattern>")),
+		OPT_STRING_LIST(0, "discard", &discard_patterns, N_("pattern"),
+			   N_("do not consider tags matching <pattern>")),
		OPT_BOOL(0, "always",        &always,
			N_("show abbreviated commit object as fallback")),
		{OPTION_STRING, 0, "dirty",  &dirty, N_("mark"),
@@ -459,6 +477,8 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
			argv_array_push(&args, "--tags");
			for_each_string_list_item(item, &patterns)
				argv_array_pushf(&args, "--refs=refs/tags/%s", item->string);
+			for_each_string_list_item(item, &discard_patterns)
+				argv_array_pushf(&args, "--discard=refs/tags/%s", item->string);
		}
		if (argc)
			argv_array_pushv(&args, argv);
diff --git c/builtin/name-rev.c w/builtin/name-rev.c
index 000a2a700ed3..86479c17a7c9 100644
--- c/builtin/name-rev.c
+++ w/builtin/name-rev.c
@@ -109,6 +109,7 @@ struct name_ref_data {
	int tags_only;
	int name_only;
	struct string_list ref_filters;
+	struct string_list discard_filters;
 };
 
 static struct tip_table {
@@ -150,6 +151,15 @@ static int name_ref(const char *path, const struct object_id *oid, int flags, vo
	if (data->tags_only && !starts_with(path, "refs/tags/"))
		return 0;
 
+	if (data->discard_filters.nr) {
+		struct string_list_item *item;
+
+		for_each_string_list_item(item, &data->discard_filters) {
+			if (subpath_matches(path, item->string) >= 0)
+				return 0;
+		}
+	}
+
	if (data->ref_filters.nr) {
		struct string_list_item *item;
		int matched = 0;
@@ -323,12 +333,14 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix)
 {
	struct object_array revs = OBJECT_ARRAY_INIT;
	int all = 0, transform_stdin = 0, allow_undefined = 1, always = 0, peel_tag = 0;
-	struct name_ref_data data = { 0, 0, STRING_LIST_INIT_NODUP };
+	struct name_ref_data data = { 0, 0, STRING_LIST_INIT_NODUP, STRING_LIST_INIT_NODUP };
	struct option opts[] = {
		OPT_BOOL(0, "name-only", &data.name_only, N_("print only names (no SHA-1)")),
		OPT_BOOL(0, "tags", &data.tags_only, N_("only use tags to name the commits")),
		OPT_STRING_LIST(0, "refs", &data.ref_filters, N_("pattern"),
				   N_("only use refs matching <pattern>")),
+		OPT_STRING_LIST(0, "discard", &data.discard_filters, N_("pattern"),
+				   N_("ignore refs matching <pattern>")),
		OPT_GROUP(""),
		OPT_BOOL(0, "all", &all, N_("list all commits reachable from all refs")),
		OPT_BOOL(0, "stdin", &transform_stdin, N_("read from stdin")),
diff --git c/t/t6007-rev-list-cherry-pick-file.sh w/t/t6007-rev-list-cherry-pick-file.sh
index d072ec43b016..8a4c35f6ffee 100755
--- c/t/t6007-rev-list-cherry-pick-file.sh
+++ w/t/t6007-rev-list-cherry-pick-file.sh
@@ -118,6 +118,13 @@ test_expect_success 'name-rev --refs excludes non-matched patterns' '
	test_cmp actual.named expect
 '
 
+test_expect_success 'name-rev --discard excludes matched patterns' '
+	git rev-list --left-right --cherry-pick F...E -- bar > actual &&
+	git name-rev --stdin --name-only --refs="*tags/*" --discard="*E" \
+		< actual > actual.named &&
+	test_cmp actual.named expect
+'
+
 cat >expect <<EOF
 $(git rev-list --left-right --cherry-pick F...E -- bar)
 EOF
diff --git c/t/t6120-describe.sh w/t/t6120-describe.sh
index 9e5db9b87a1f..4e4a9f2e5305 100755
--- c/t/t6120-describe.sh
+++ w/t/t6120-describe.sh
@@ -218,6 +218,14 @@ test_expect_success 'describe --contains and --match' '
	test_cmp expect actual
 '
 
+test_expect_success 'describe --discard' '
+	echo "c~1" >expect &&
+	tagged_commit=$(git rev-parse "refs/tags/A^0") &&
+	test_must_fail git describe --contains --match="B" $tagged_commit &&
+	git describe --contains --match="?" --discard="A" $tagged_commit >actual &&
+	test_cmp expect actual
+'
+
 test_expect_success 'describe --contains and --no-match' '
	echo "A^0" >expect &&
	tagged_commit=$(git rev-parse "refs/tags/A^0") &&

Jacob Keller (5):
  doc: add documentation for OPT_STRING_LIST
  name-rev: extend --refs to accept multiple patterns
  name-rev: add support to discard refs by pattern match
  describe: teach --match to accept multiple patterns
  describe: teach describe negative pattern matches

 Documentation/git-describe.txt                | 13 ++++++-
 Documentation/git-name-rev.txt                | 11 +++++-
 Documentation/technical/api-parse-options.txt |  5 +++
 builtin/describe.c                            | 51 ++++++++++++++++++++++----
 builtin/name-rev.c                            | 53 +++++++++++++++++++++------
 t/t6007-rev-list-cherry-pick-file.sh          | 30 +++++++++++++++
 t/t6120-describe.sh                           | 19 ++++++++++
 7 files changed, 161 insertions(+), 21 deletions(-)

-- 
2.11.0.rc2.152.g4d04e67


^ permalink raw reply related	[flat|nested] 9+ messages in thread
* [PATCH v2 0/5] extend git-describe pattern matching
@ 2017-01-18  0:03 Jacob Keller
  2017-01-18  0:03 ` [PATCH v2 1/5] doc: add documentation for OPT_STRING_LIST Jacob Keller
  0 siblings, 1 reply; 9+ messages in thread
From: Jacob Keller @ 2017-01-18  0:03 UTC (permalink / raw)
  To: git; +Cc: Johannes Sixt, Johannes Schindelin, Junio C Hamano, Jacob Keller

From: Jacob Keller <jacob.keller@gmail.com>

Teach git describe and git name-rev the ability to match multiple
patterns inclusively. Additionally, teach these commands to also accept
negative patterns to exclude any refs which match.

The pattern lists for positive and negative patterns are inclusive. This
means that for the positive patterns, a reference will be considered as
long as it matches at least one of the match patterns. It need not match
all given patterns. Additionally for negative patterns, we will not
consider any ref which matches any negative pattern, even if it matches
one of the positive patterns.

Together this allows the ability to express far more sets of tags than a
single match pattern alone. It does not provide quite the same depth as
would teaching full regexp but it is simpler and easy enough to
understand.

- v2
* use --exclude instead of --discard
* use modern style in tests

I chose *not* to implement the suggestion of ordered values for exclude
and match, since this is not how the current implementation of
git-describe worked, and it didn't really make sense to me what was
being requested. I looked at the interface for git-log, and it appears
that the command accepts multiple invocations of --branches, --remotes,
and similar. I do not believe these need to be identical interfaces. I
welcome feedback on this decision, but I am not convinced yet that the
ordered arguments are worth the trouble.

diff --git c/Documentation/git-describe.txt w/Documentation/git-describe.txt
index a89bbde207b2..21a43b78924a 100644
--- c/Documentation/git-describe.txt
+++ w/Documentation/git-describe.txt
@@ -88,12 +88,12 @@ OPTIONS
	patterns will be considered. Use `--no-match` to clear and reset the
	list of patterns.
 
---discard <pattern>::
+--exclude <pattern>::
	Do not consider tags matching the given `glob(7)` pattern, excluding
	the "refs/tags/" prefix. This can be used to narrow the tag space and
	find only tags matching some meaningful criteria. If given multiple
	times, a list of patterns will be accumulated and tags matching any
-	of the patterns will be discarded. Use `--no-discard` to clear and
+	of the patterns will be excluded. Use `--no-exclude` to clear and
	reset the list of patterns.
 
 --always::
diff --git c/Documentation/git-name-rev.txt w/Documentation/git-name-rev.txt
index 9b46e5ea9aae..301b4a8d55e6 100644
--- c/Documentation/git-name-rev.txt
+++ w/Documentation/git-name-rev.txt
@@ -30,11 +30,11 @@ OPTIONS
	given multiple times, use refs whose names match any of the given shell
	patterns. Use `--no-refs` to clear any previous ref patterns given.
 
---discard=<pattern>::
+--exclude=<pattern>::
	Do not use any ref whose name matches a given shell pattern. The
	pattern can be one of branch name, tag name or fully qualified ref
-	name. If given multiple times, discard refs that match any of the given
-	shell patterns. Use `--no-discards` to clear the list of discard
+	name. If given multiple times, exclude refs that match any of the given
+	shell patterns. Use `--no-exclude` to clear the list of exclude
	patterns.
 
 --all::
diff --git c/Documentation/technical/api-parse-options.txt w/Documentation/technical/api-parse-options.txt
index 15e876e4c804..6914f54f5f44 100644
--- c/Documentation/technical/api-parse-options.txt
+++ w/Documentation/technical/api-parse-options.txt
@@ -169,9 +169,9 @@ There are some macros to easily define options:
	The string argument is put into `str_var`.
 
 `OPT_STRING_LIST(short, long, &list, arg_str, description)`::
-	Introduce an option with a string argument. Repeated invocations
-	accumulate into a list of strings. Reset and clear the list with
-	`--no-option`.
+	Introduce an option with string argument.
+	The string argument is stored as an element in `&list` which must be a
+	struct string_list. Reset the list using `--no-option`.
 
 `OPT_INTEGER(short, long, &int_var, description)`::
	Introduce an option with integer argument.
diff --git c/builtin/describe.c w/builtin/describe.c
index c09288ee6321..6769446e1f57 100644
--- c/builtin/describe.c
+++ w/builtin/describe.c
@@ -29,7 +29,7 @@ static int max_candidates = 10;
 static struct hashmap names;
 static int have_util;
 static struct string_list patterns = STRING_LIST_INIT_NODUP;
-static struct string_list discard_patterns = STRING_LIST_INIT_NODUP;
+static struct string_list exclude_patterns = STRING_LIST_INIT_NODUP;
 static int always;
 static const char *dirty;
 
@@ -131,16 +131,16 @@ static int get_name(const char *path, const struct object_id *oid, int flag, voi
		return 0;
 
	/*
-	 * If we're given discard patterns, first discard any tag which match
-	 * any of the discard pattern.
+	 * If we're given exclude patterns, first exclude any tag which match
+	 * any of the exclude pattern.
	 */
-	if (discard_patterns.nr) {
+	if (exclude_patterns.nr) {
		struct string_list_item *item;
 
		if (!is_tag)
			return 0;
 
-		for_each_string_list_item(item, &discard_patterns) {
+		for_each_string_list_item(item, &exclude_patterns) {
			if (!wildmatch(item->string, path + 10, 0, NULL))
				return 0;
		}
@@ -438,7 +438,7 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
			    N_("consider <n> most recent tags (default: 10)")),
		OPT_STRING_LIST(0, "match", &patterns, N_("pattern"),
			   N_("only consider tags matching <pattern>")),
-		OPT_STRING_LIST(0, "discard", &discard_patterns, N_("pattern"),
+		OPT_STRING_LIST(0, "exclude", &exclude_patterns, N_("pattern"),
			   N_("do not consider tags matching <pattern>")),
		OPT_BOOL(0, "always",        &always,
			N_("show abbreviated commit object as fallback")),
@@ -477,8 +477,8 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
			argv_array_push(&args, "--tags");
			for_each_string_list_item(item, &patterns)
				argv_array_pushf(&args, "--refs=refs/tags/%s", item->string);
-			for_each_string_list_item(item, &discard_patterns)
-				argv_array_pushf(&args, "--discard=refs/tags/%s", item->string);
+			for_each_string_list_item(item, &exclude_patterns)
+				argv_array_pushf(&args, "--exclude=refs/tags/%s", item->string);
		}
		if (argc)
			argv_array_pushv(&args, argv);
diff --git c/builtin/name-rev.c w/builtin/name-rev.c
index 86479c17a7c9..da4a0d7c0fdf 100644
--- c/builtin/name-rev.c
+++ w/builtin/name-rev.c
@@ -109,7 +109,7 @@ struct name_ref_data {
	int tags_only;
	int name_only;
	struct string_list ref_filters;
-	struct string_list discard_filters;
+	struct string_list exclude_filters;
 };
 
 static struct tip_table {
@@ -151,10 +151,10 @@ static int name_ref(const char *path, const struct object_id *oid, int flags, vo
	if (data->tags_only && !starts_with(path, "refs/tags/"))
		return 0;
 
-	if (data->discard_filters.nr) {
+	if (data->exclude_filters.nr) {
		struct string_list_item *item;
 
-		for_each_string_list_item(item, &data->discard_filters) {
+		for_each_string_list_item(item, &data->exclude_filters) {
			if (subpath_matches(path, item->string) >= 0)
				return 0;
		}
@@ -339,7 +339,7 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix)
		OPT_BOOL(0, "tags", &data.tags_only, N_("only use tags to name the commits")),
		OPT_STRING_LIST(0, "refs", &data.ref_filters, N_("pattern"),
				   N_("only use refs matching <pattern>")),
-		OPT_STRING_LIST(0, "discard", &data.discard_filters, N_("pattern"),
+		OPT_STRING_LIST(0, "exclude", &data.exclude_filters, N_("pattern"),
				   N_("ignore refs matching <pattern>")),
		OPT_GROUP(""),
		OPT_BOOL(0, "all", &all, N_("list all commits reachable from all refs")),
diff --git c/t/t6007-rev-list-cherry-pick-file.sh w/t/t6007-rev-list-cherry-pick-file.sh
index 8a4c35f6ffee..83838d0da208 100755
--- c/t/t6007-rev-list-cherry-pick-file.sh
+++ w/t/t6007-rev-list-cherry-pick-file.sh
@@ -100,42 +100,43 @@ test_expect_success '--cherry-pick bar does not come up empty (II)' '
 '
 
 test_expect_success 'name-rev multiple --refs combine inclusive' '
-	git rev-list --left-right --cherry-pick F...E -- bar > actual &&
+	git rev-list --left-right --cherry-pick F...E -- bar >actual &&
	git name-rev --stdin --name-only --refs="*tags/F" --refs="*tags/E" \
-		< actual > actual.named &&
+		<actual >actual.named &&
	test_cmp actual.named expect
 '
 
 cat >expect <<EOF
 <tags/F
-$(git rev-list --left-right --right-only --cherry-pick F...E -- bar)
 EOF
 
 test_expect_success 'name-rev --refs excludes non-matched patterns' '
-	git rev-list --left-right --cherry-pick F...E -- bar > actual &&
+	git rev-list --left-right --right-only --cherry-pick F...E -- bar >>expect &&
+	git rev-list --left-right --cherry-pick F...E -- bar >actual &&
	git name-rev --stdin --name-only --refs="*tags/F" \
-		< actual > actual.named &&
-	test_cmp actual.named expect
-'
-
-test_expect_success 'name-rev --discard excludes matched patterns' '
-	git rev-list --left-right --cherry-pick F...E -- bar > actual &&
-	git name-rev --stdin --name-only --refs="*tags/*" --discard="*E" \
-		< actual > actual.named &&
+		<actual >actual.named &&
	test_cmp actual.named expect
 '
 
 cat >expect <<EOF
-$(git rev-list --left-right --cherry-pick F...E -- bar)
+<tags/F
 EOF
 
-test_expect_success 'name-rev --no-refs clears the refs list' '
-	git rev-list --left-right --cherry-pick F...E -- bar > actual &&
-	git name-rev --stdin --name-only --refs="*tags/F" --refs="*tags/E" --no-refs --refs="*tags/G" \
-		< actual > actual.named &&
+test_expect_success 'name-rev --exclude excludes matched patterns' '
+	git rev-list --left-right --right-only --cherry-pick F...E -- bar >>expect &&
+	git rev-list --left-right --cherry-pick F...E -- bar >actual &&
+	git name-rev --stdin --name-only --refs="*tags/*" --exclude="*E" \
+		<actual >actual.named &&
	test_cmp actual.named expect
 '
 
+test_expect_success 'name-rev --no-refs clears the refs list' '
+	git rev-list --left-right --cherry-pick F...E -- bar >expect &&
+	git name-rev --stdin --name-only --refs="*tags/F" --refs="*tags/E" --no-refs --refs="*tags/G" \
+		<actual >actual &&
+	test_cmp actual expect
+'
+
 cat >expect <<EOF
 +tags/F
 =tags/D
diff --git c/t/t6120-describe.sh w/t/t6120-describe.sh
index 4e4a9f2e5305..167491fd5b0d 100755
--- c/t/t6120-describe.sh
+++ w/t/t6120-describe.sh
@@ -218,11 +218,11 @@ test_expect_success 'describe --contains and --match' '
	test_cmp expect actual
 '
 
-test_expect_success 'describe --discard' '
+test_expect_success 'describe --exclude' '
	echo "c~1" >expect &&
	tagged_commit=$(git rev-parse "refs/tags/A^0") &&
	test_must_fail git describe --contains --match="B" $tagged_commit &&
-	git describe --contains --match="?" --discard="A" $tagged_commit >actual &&
+	git describe --contains --match="?" --exclude="A" $tagged_commit >actual &&
	test_cmp expect actual
 '
 

Jacob Keller (5):
  doc: add documentation for OPT_STRING_LIST
  name-rev: extend --refs to accept multiple patterns
  name-rev: add support to exclude refs by pattern match
  describe: teach --match to accept multiple patterns
  describe: teach describe negative pattern matches

 Documentation/git-describe.txt                | 13 ++++++-
 Documentation/git-name-rev.txt                | 11 +++++-
 Documentation/technical/api-parse-options.txt |  5 +++
 builtin/describe.c                            | 51 ++++++++++++++++++++++----
 builtin/name-rev.c                            | 53 +++++++++++++++++++++------
 t/t6007-rev-list-cherry-pick-file.sh          | 38 +++++++++++++++++++
 t/t6120-describe.sh                           | 27 ++++++++++++++
 7 files changed, 177 insertions(+), 21 deletions(-)

-- 
2.11.0.403.g196674b8396b


^ permalink raw reply related	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2017-01-18  0:04 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-12-17  1:24 [PATCH v2 0/5] extend describe and name-rev pattern matching Jacob Keller
2016-12-17  1:24 ` [PATCH v2 1/5] doc: add documentation for OPT_STRING_LIST Jacob Keller
2016-12-17 11:56   ` Philip Oakley
2016-12-18 12:19     ` Jacob Keller
2016-12-17  1:24 ` [PATCH v2 2/5] name-rev: extend --refs to accept multiple patterns Jacob Keller
2016-12-17  1:24 ` [PATCH v2 3/5] name-rev: add support to discard refs by pattern match Jacob Keller
2016-12-17  1:24 ` [PATCH v2 4/5] describe: teach --match to accept multiple patterns Jacob Keller
2016-12-17  1:24 ` [PATCH v2 5/5] describe: teach describe negative pattern matches Jacob Keller
  -- strict thread matches above, loose matches on Subject: below --
2017-01-18  0:03 [PATCH v2 0/5] extend git-describe pattern matching Jacob Keller
2017-01-18  0:03 ` [PATCH v2 1/5] doc: add documentation for OPT_STRING_LIST Jacob Keller

Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).