Recent changes to this wiki:

comment
diff --git a/doc/bugs/crippled_filesystem__58___SQLite3_returned_ErrorBusy/comment_11_9356da08c06aeae254fc84e44b0b3d14._comment b/doc/bugs/crippled_filesystem__58___SQLite3_returned_ErrorBusy/comment_11_9356da08c06aeae254fc84e44b0b3d14._comment
new file mode 100644
index 0000000000..46951f8c5a
--- /dev/null
+++ b/doc/bugs/crippled_filesystem__58___SQLite3_returned_ErrorBusy/comment_11_9356da08c06aeae254fc84e44b0b3d14._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 11"""
+ date="2022-08-11T21:15:29Z"
+ content="""
+I have mostly implemented an annex.dbdir to relocate the sqlite databases.
+It's in the `dbdir` branch until I get it fully working.
+"""]]

comment
diff --git a/doc/forum/__39__wget_--mirror__39___like_behaviour/comment_1_9c874a74f25fa06b8e515482b4706032._comment b/doc/forum/__39__wget_--mirror__39___like_behaviour/comment_1_9c874a74f25fa06b8e515482b4706032._comment
new file mode 100644
index 0000000000..95cd6f075d
--- /dev/null
+++ b/doc/forum/__39__wget_--mirror__39___like_behaviour/comment_1_9c874a74f25fa06b8e515482b4706032._comment
@@ -0,0 +1,24 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2022-08-11T17:54:16Z"
+ content="""
+There is not, but if you can find a way to get wget or something to
+generate a list of urls and the files it downloaded them to, you can
+feed that into `git-annex addurl --batch` to teach git-annex what the urls
+are.
+
+There is a subsystem in git-annex that could in theory be used for this,
+[[git-annex-import]] can import trees of files from a special remote.
+
+But the complexity of mirroring a website makes me think I would not want
+to try to support it in the web special remote. I mean, just look at how
+many options wget has that you might use to control how the mirroring
+works.
+
+Other special remotes can support importing from specific types of websites
+though. Currently this is limited to built-in special remotes, such as S3,
+but it would be possible to expand it to support external special remotes
+as well. See [[todo/importtree_only_remotes]] for discussion about doing
+that.
+"""]]

diff --git a/doc/forum/__39__wget_--mirror__39___like_behaviour.mdwn b/doc/forum/__39__wget_--mirror__39___like_behaviour.mdwn
new file mode 100644
index 0000000000..d13f3c2974
--- /dev/null
+++ b/doc/forum/__39__wget_--mirror__39___like_behaviour.mdwn
@@ -0,0 +1,7 @@
+Hi, is there a quick way to implement a 'wget --mirror' like behaviour with git-annex?
+
+I.e., I'd like to clone an entire website and adding it with original urls to my annex.
+
+I've tried 'git-annex addurl http://website.tld' only, but of course it downloads a single page, it does not descend recursively.
+
+Thanks

close
diff --git a/doc/bugs/bup_often_errors_out_when_-J___62___1.mdwn b/doc/bugs/bup_often_errors_out_when_-J___62___1.mdwn
index efc3b60030..f98a123b72 100644
--- a/doc/bugs/bup_often_errors_out_when_-J___62___1.mdwn
+++ b/doc/bugs/bup_often_errors_out_when_-J___62___1.mdwn
@@ -40,3 +40,5 @@ local repository version: 8
 ### Have you had any luck using git-annex before? (Sometimes we get tired of reading bug reports all day and a lil' positive end note does wonders)
 
 It's amazing and I use it every day :)
+
+> [[fixed|done]] --[[Joey]]

Added a comment
diff --git a/doc/bugs/Copying_many_files_to_bup_remotes_is_very_slow/comment_4_d2896b544d6d26663b532735c3924134._comment b/doc/bugs/Copying_many_files_to_bup_remotes_is_very_slow/comment_4_d2896b544d6d26663b532735c3924134._comment
new file mode 100644
index 0000000000..4e52bc45ad
--- /dev/null
+++ b/doc/bugs/Copying_many_files_to_bup_remotes_is_very_slow/comment_4_d2896b544d6d26663b532735c3924134._comment
@@ -0,0 +1,11 @@
+[[!comment format=mdwn
+ username="Atemu"
+ avatar="http://cdn.libravatar.org/avatar/d1f0f4275931c552403f4c6707bead7a"
+ subject="comment 4"
+ date="2022-08-10T12:35:27Z"
+ content="""
+Indeed it does. I assumed it'd concatenate the files internally for efficiency but is still able to output them separately later but that is not the case. I guess you could store the offsets externally and skip/seek but that'd be inefficient. 
+Perhaps bup could add an option for batching multiple singular-file splits in one invocation to avoid overhead.
+
+Alternatively, git-annex could index+save using excludes. That could be quite complicated (especially tracking which object exists inside which batches) but it could work.
+"""]]

Added a comment
diff --git a/doc/bugs/add_--dry-run_seems_have_introduced_a___34__regression__34__/comment_7_c8f6ee2cb993b22b2531d1a4b7c3da8e._comment b/doc/bugs/add_--dry-run_seems_have_introduced_a___34__regression__34__/comment_7_c8f6ee2cb993b22b2531d1a4b7c3da8e._comment
new file mode 100644
index 0000000000..c73080b432
--- /dev/null
+++ b/doc/bugs/add_--dry-run_seems_have_introduced_a___34__regression__34__/comment_7_c8f6ee2cb993b22b2531d1a4b7c3da8e._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="yarikoptic"
+ avatar="http://cdn.libravatar.org/avatar/f11e9c84cb18d26a1748c33b48c924b4"
+ subject="comment 7"
+ date="2022-08-09T19:12:40Z"
+ content="""
+BTW -- well done on:
+
+> For future reference, I was able to run the test suite by cloning datalad, and settup up the virtualenv like in the README, except then running \"pip install .\" in the datalad directory.
+
+FTR: There is also [CONTRIBUTING.md](https://github.com/datalad/datalad/blob/HEAD/CONTRIBUTING.md#development-environment) with more \"development oriented\" instructions for installation etc.  Might come handy.
+"""]]

Added a comment
diff --git a/doc/bugs/add_--dry-run_seems_have_introduced_a___34__regression__34__/comment_6_2455f440750a285768746e764fbfb9cd._comment b/doc/bugs/add_--dry-run_seems_have_introduced_a___34__regression__34__/comment_6_2455f440750a285768746e764fbfb9cd._comment
new file mode 100644
index 0000000000..6277a04f30
--- /dev/null
+++ b/doc/bugs/add_--dry-run_seems_have_introduced_a___34__regression__34__/comment_6_2455f440750a285768746e764fbfb9cd._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="yarikoptic"
+ avatar="http://cdn.libravatar.org/avatar/f11e9c84cb18d26a1748c33b48c924b4"
+ subject="comment 6"
+ date="2022-08-09T18:02:32Z"
+ content="""
+Thank you Joey! FTR, fixed in [10.20220724-96-g21cfd0ea9](https://git.kitenet.net/index.cgi/git-annex.git/commit/?id=21cfd0ea980feaec8875380707c1a1ddb91de5dc)
+"""]]

Added a comment
diff --git a/doc/bugs/add_--dry-run_seems_have_introduced_a___34__regression__34__/comment_5_3fb410419608d725ea15a4849266396e._comment b/doc/bugs/add_--dry-run_seems_have_introduced_a___34__regression__34__/comment_5_3fb410419608d725ea15a4849266396e._comment
new file mode 100644
index 0000000000..c447f64031
--- /dev/null
+++ b/doc/bugs/add_--dry-run_seems_have_introduced_a___34__regression__34__/comment_5_3fb410419608d725ea15a4849266396e._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="yarikoptic"
+ avatar="http://cdn.libravatar.org/avatar/f11e9c84cb18d26a1748c33b48c924b4"
+ subject="comment 5"
+ date="2022-08-09T18:02:08Z"
+ content="""
+Thank you Joey! FTR, fixed in [10.20220724-96-g21cfd0ea9](https://git.kitenet.net/index.cgi/git-annex.git/commit/?id=21cfd0ea980feaec8875380707c1a1ddb91de5dc)
+"""]]

fix reversion
3a513cfe73ed873aeeabbc17d2c458b62dd4198c caused a reversion in addurl.
The type of addSmall changed, but the void prevented the type checker
from helping notice this. Since it now returns a CommandPerform, the
cleanup action has to be run.
Sponsored-by: Dartmouth College's Datalad project
diff --git a/Command/AddUrl.hs b/Command/AddUrl.hs
index 805e72a0e7..830cc09251 100644
--- a/Command/AddUrl.hs
+++ b/Command/AddUrl.hs
@@ -476,7 +476,8 @@ addWorkTree _ addunlockedmatcher u url file key mtmp = case mtmp of
 					(fromRawFilePath file)
 					(fromRawFilePath tmp)
 				go
-			else void $ Command.Add.addSmall (DryRun False) file s
+			else Command.Add.addSmall (DryRun False) file s
+				>>= maybe noop void
   where
 	go = do
 		maybeShowJSON $ JSONChunk [("key", serializeKey key)]
diff --git a/doc/bugs/add_--dry-run_seems_have_introduced_a___34__regression__34__.mdwn b/doc/bugs/add_--dry-run_seems_have_introduced_a___34__regression__34__.mdwn
index 4c2b432777..c22436a01d 100644
--- a/doc/bugs/add_--dry-run_seems_have_introduced_a___34__regression__34__.mdwn
+++ b/doc/bugs/add_--dry-run_seems_have_introduced_a___34__regression__34__.mdwn
@@ -59,3 +59,4 @@ I will try to dig deeper some time later, unless you Joey immediately see what c
 [[!meta author=yoh]]
 [[!tag projects/datalad]]
 
+> [[fixed|done]] --[[Joey]]
diff --git a/doc/bugs/add_--dry-run_seems_have_introduced_a___34__regression__34__/comment_4_ee9f695290b1bcaf2c9320d8042047cc._comment b/doc/bugs/add_--dry-run_seems_have_introduced_a___34__regression__34__/comment_4_ee9f695290b1bcaf2c9320d8042047cc._comment
new file mode 100644
index 0000000000..8ef220c9f4
--- /dev/null
+++ b/doc/bugs/add_--dry-run_seems_have_introduced_a___34__regression__34__/comment_4_ee9f695290b1bcaf2c9320d8042047cc._comment
@@ -0,0 +1,11 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 4"""
+ date="2022-08-09T17:35:46Z"
+ content="""
+Found the bug.. it is in the change to Command.AddUrl. Since addSmall
+changed to a CommandPerform, `void $ Command.Add.addSmall ...` only
+now runs the first part of it, but not the action that returns that
+actually adds the file to git! The `void` causes that to get thrown
+away. Easily fixed.
+"""]]

comment
diff --git a/doc/bugs/add_--dry-run_seems_have_introduced_a___34__regression__34__/comment_3_38baec012d7ebc95f92df59c85c6d525._comment b/doc/bugs/add_--dry-run_seems_have_introduced_a___34__regression__34__/comment_3_38baec012d7ebc95f92df59c85c6d525._comment
new file mode 100644
index 0000000000..57f2c8d5b0
--- /dev/null
+++ b/doc/bugs/add_--dry-run_seems_have_introduced_a___34__regression__34__/comment_3_38baec012d7ebc95f92df59c85c6d525._comment
@@ -0,0 +1,11 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 3"""
+ date="2022-08-09T17:22:52Z"
+ content="""
+In particular, the test runs:
+
+	git-annex addurl -c annex.largefiles=exclude=*.txt --with-files --json --json-error-messages --batch
+
+It never runs git-annex add.
+"""]]

comment
diff --git a/doc/bugs/add_--dry-run_seems_have_introduced_a___34__regression__34__/comment_2_ecc658185b485a5ccaf592ab8a255241._comment b/doc/bugs/add_--dry-run_seems_have_introduced_a___34__regression__34__/comment_2_ecc658185b485a5ccaf592ab8a255241._comment
new file mode 100644
index 0000000000..9756e69a13
--- /dev/null
+++ b/doc/bugs/add_--dry-run_seems_have_introduced_a___34__regression__34__/comment_2_ecc658185b485a5ccaf592ab8a255241._comment
@@ -0,0 +1,14 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 2"""
+ date="2022-08-09T17:19:56Z"
+ content="""
+For future reference, I was able to run the test suite by cloning datalad,
+and settup up the virtualenv like in the README, except then running "pip
+install ." in the datalad directory.
+
+I reproduced the datalad test failure. Then I wrapped git-annex with a
+script that logs the paramters it was run with. It seems the test is 
+running git-annex addurl, not git-annex add at all. So maybe that commit
+broke addurl?
+"""]]

comment
diff --git a/doc/bugs/add_--dry-run_seems_have_introduced_a___34__regression__34__/comment_1_0bc5a3d36900d9bd8c978a08383d409d._comment b/doc/bugs/add_--dry-run_seems_have_introduced_a___34__regression__34__/comment_1_0bc5a3d36900d9bd8c978a08383d409d._comment
new file mode 100644
index 0000000000..59f1771bae
--- /dev/null
+++ b/doc/bugs/add_--dry-run_seems_have_introduced_a___34__regression__34__/comment_1_0bc5a3d36900d9bd8c978a08383d409d._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2022-08-09T16:41:59Z"
+ content="""
+Unable to reproduce such a problem using git-annex so far. (I don't know how
+to set up an enviroment to run that case of the datalad test suite.)
+
+Also I don't see any obvious logic error in the code of that commit.
+"""]]

comment
diff --git a/doc/bugs/Copying_many_files_to_bup_remotes_is_very_slow/comment_3_7150178b47a15857d5eece0fbe57a971._comment b/doc/bugs/Copying_many_files_to_bup_remotes_is_very_slow/comment_3_7150178b47a15857d5eece0fbe57a971._comment
new file mode 100644
index 0000000000..3fcd26ce91
--- /dev/null
+++ b/doc/bugs/Copying_many_files_to_bup_remotes_is_very_slow/comment_3_7150178b47a15857d5eece0fbe57a971._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 3"""
+ date="2022-08-09T16:28:16Z"
+ content="""
+While `bup split` can run on multiple files at once, it concacenates the
+files together and stores a single object. That is not useful for git-annex.
+
+Using the borg pattern with bup is a good idea.
+"""]]

initial report on possible regression due to --dry-run
diff --git a/doc/bugs/add_--dry-run_seems_have_introduced_a___34__regression__34__.mdwn b/doc/bugs/add_--dry-run_seems_have_introduced_a___34__regression__34__.mdwn
new file mode 100644
index 0000000000..4c2b432777
--- /dev/null
+++ b/doc/bugs/add_--dry-run_seems_have_introduced_a___34__regression__34__.mdwn
@@ -0,0 +1,61 @@
+### Please describe the problem.
+
+Our datalad tests started to fail on 04 Aug 2022  build of git-annex.  `git bisect` brought me to the [10.20220724-56-g3a513cfe7](https://git.kitenet.net/index.cgi/git-annex.git/commit/?id=3a513cfe73ed873aeeabbc17d2c458b62dd4198c) change which added `--dry-run` to `annex add`.  The "regression" manifests in that we end up with a file not added/committed.  Unfortunately I do not have yet more details or git-annex minimal reproducer.
+
+Meanwhile - the full log from running `DATALAD_LOG_OUTPUTS=1 DATALAD_LOG_LEVEL=DEBUG python -m pytest -s -v datalad/local/tests/test_add_archive_content.py::test_add_archive_content `
+
+[http://www.onerussian.com/tmp/test_add_archive_content-fail.log](http://www.onerussian.com/tmp/test_add_archive_content-fail.log)
+
+and it has
+
+
+```shell
+$> grep '2/1_f.txt\>' /tmp/test_add_archive_content-fail.log                                                                                                                                       
+[DEBUG] Adding /home/yoh/.tmp/datalad_temp_test_add_archive_contentxyf002ii/2/1_f.txt to annex pointing to dl+archive:MD5E-s151--eb922c8b7151d0c53f56e03c10bb0e70.tar.gz#path=1/1+f.txt&size=8 and with options ['-c', 'annex.largefiles=exclude=*.txt'] 
+[DEBUG] File /home/yoh/.tmp/datalad_temp_test_add_archive_contentxyf002ii/2/1_f.txt was added to git, not adding url 
+first = '2/1_f.txt'
+E           AssertionError: assert '2/1_f.txt' in ['.datalad/.gitattributes', '.datalad/config', '.gitattributes', '1/1 f-1.1.txt', '1/1 f-1.2.txt', '1/1 f-1.txt', ...]
+DEBUG    datalad.local.add_archive_content:add_archive_content.py:609 Adding /home/yoh/.tmp/datalad_temp_test_add_archive_contentxyf002ii/2/1_f.txt to annex pointing to dl+archive:MD5E-s151--eb922c8b7151d0c53f56e03c10bb0e70.tar.gz#path=1/1+f.txt&size=8 and with options ['-c', 'annex.largefiles=exclude=*.txt']
+DEBUG    datalad.local.add_archive_content:add_archive_content.py:627 File /home/yoh/.tmp/datalad_temp_test_add_archive_contentxyf002ii/2/1_f.txt was added to git, not adding url
+```
+
+so git-annex seems reported that it was added to `git` but if we stop in (another run) at that point and look at the repo we see that it was not added:
+
+```
+$> DATALAD_TESTS_TEMP_KEEP=1 DATALAD_LOG_OUTPUTS=1 DATALAD_LOG_LEVEL=DEBUG python -m pytest -s -v --pdb datalad/local/tests/test_add_archive_content.py::test_add_archive_content
+...
+DEBUG    datalad.runner.runner:runner.py:171 Run ['git', '-c', 'diff.ignoreSubmodules=none', 'annex', 'addurl', '-c', 'annex.largefiles=exclude=*.txt', '--with-files', '--json', '--json-error-messages', '--batch'] (protocol_class=BatchedCommandProtocol) (cwd=/home/yoh/.tmp/datalad_temp_test_add_archive_content0r8qsr6l)
+DEBUG    datalad.local.add_archive_content:add_archive_content.py:627 File /home/yoh/.tmp/datalad_temp_test_add_archive_content0r8qsr6l/2/1_f.txt was added to git, not adding url
+INFO     datalad.local.add_archive_content:log.py:431 Files to extract 0 
+DEBUG    datalad.local.add_archive_content:add_archive_content.py:506 Skipping 1/d/1d since contains d pattern
+DEBUG    datalad.local.add_archive_content:add_archive_content.py:641 Removing the original archive 1.tar.gz
+...
+
+```
+
+and if we go to that folder -- we see that `2/` was not added to git:
+
+```
+(git-annex)lena:~/.tmp/datalad_temp_test_add_archive_content0r8qsr6l[dl-test-branch]
+$> git status
+On branch dl-test-branch
+Untracked files:
+  (use "git add <file>..." to include in what will be committed)
+	2/
+
+nothing added to commit but untracked files present (use "git add" to track)
+
+$> ls 2/
+1_f.txt
+
+$> ls .git/annex/journal/
+# came out empty, FWIW
+```
+
+Versions: annexremote=1.6.0 boto=2.49.0 cmd:7z=16.02 cmd:annex=10.20220724+git77-ga24ae0814-1~ndall+1 cmd:bundled-git=2.30.2 cmd:git=2.30.2 cmd:ssh=9.0p1 cmd:system-git=2.35.1 cmd:system-ssh=9.0p1 datalad=0.17.2+75.g3bc853bb2 exifread=3.0.0 humanize=4.2.3 iso8601=1.0.2 keyring=23.6.0 keyrings.alt=UNKNOWN msgpack=1.0.4 mutagen=1.45.1 platformdirs=2.5.2 requests=2.28.1 tqdm=4.64.0
+
+I will try to dig deeper some time later, unless you Joey immediately see what could be a culprit or recommend something specific to try
+
+[[!meta author=yoh]]
+[[!tag projects/datalad]]
+

Added a comment
diff --git a/doc/bugs/bup_often_errors_out_when_-J___62___1/comment_5_90d280582d71f77d75aeedcd30c7c437._comment b/doc/bugs/bup_often_errors_out_when_-J___62___1/comment_5_90d280582d71f77d75aeedcd30c7c437._comment
new file mode 100644
index 0000000000..5ccfcb5fae
--- /dev/null
+++ b/doc/bugs/bup_often_errors_out_when_-J___62___1/comment_5_90d280582d71f77d75aeedcd30c7c437._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="Atemu"
+ avatar="http://cdn.libravatar.org/avatar/d1f0f4275931c552403f4c6707bead7a"
+ subject="comment 5"
+ date="2022-08-09T06:22:50Z"
+ content="""
+Thank you!
+
+That's sad to hear as it means bup will perform even worse where it wasn't performing well to begin with but unsafe is unsafe.
+
+I'd consider this issue solved as bup performance problems are tracked in https://git-annex.branchable.com/bugs/Copying_many_files_to_bup_remotes_is_very_slow/ already.
+"""]]

Added a comment
diff --git a/doc/bugs/Copying_many_files_to_bup_remotes_is_very_slow/comment_2_0f5ff10d84450a6df35cb974cdb4739e._comment b/doc/bugs/Copying_many_files_to_bup_remotes_is_very_slow/comment_2_0f5ff10d84450a6df35cb974cdb4739e._comment
new file mode 100644
index 0000000000..c82b5371e9
--- /dev/null
+++ b/doc/bugs/Copying_many_files_to_bup_remotes_is_very_slow/comment_2_0f5ff10d84450a6df35cb974cdb4739e._comment
@@ -0,0 +1,15 @@
+[[!comment format=mdwn
+ username="Atemu"
+ avatar="http://cdn.libravatar.org/avatar/d1f0f4275931c552403f4c6707bead7a"
+ subject="comment 2"
+ date="2022-08-09T06:14:05Z"
+ content="""
+Agreed.
+
+I see two potential ways to improve performance:
+
+* Batching:
+  Bup can split multiple files at once. If it's given 10, 20, 100 files at a time, the per-split overhead matters less. Batching is something git-annex might need to learn sooner or later anyways because file transfer generally doesn't scale well currently (bup's slowness just exacerbates the problem).
+* Bup index+save:
+  Use the same pattern as Borg. Back up the whole git-annex repo at a time and selectively restore in order to `get`. Not sure this would be a great idea but it should improve performance in my use-case (copy everything).
+"""]]

Added a comment
diff --git a/doc/bugs/GIN_is_not_recognized_as_a_git-annex_enabled_repos/comment_5_cf4130cb932d3d884e605d7c6447e61e._comment b/doc/bugs/GIN_is_not_recognized_as_a_git-annex_enabled_repos/comment_5_cf4130cb932d3d884e605d7c6447e61e._comment
new file mode 100644
index 0000000000..dba4af574b
--- /dev/null
+++ b/doc/bugs/GIN_is_not_recognized_as_a_git-annex_enabled_repos/comment_5_cf4130cb932d3d884e605d7c6447e61e._comment
@@ -0,0 +1,15 @@
+[[!comment format=mdwn
+ username="rinomizu5@5ead4c82685c65d7717dbd5591b80425036ae9e3"
+ nickname="rinomizu5"
+ avatar="http://cdn.libravatar.org/avatar/62478823018c68821064febcda7e5d4f"
+ subject="comment 5"
+ date="2022-08-09T00:33:55Z"
+ content="""
+Thank you joey for the additional help.  
+
+I see that I need to use the SSH protocol to upload the file contents to GIN with git annex.  
+And I also understand why it showed (not found).
+
+I appreciate your advice.
+RIno Mizuguchi
+"""]]

Avoid running multiple bup split processes concurrently
Since bup split is not concurrency safe.
Used a lock file so that 2 git-annex processes only run one bup split
between them (per bup repo).
(Concurrent writes from different git-annex repository clones to the same
bup repo could still have concurrency problems.)
Sponsored-by: Noam Kremen on Patreon
diff --git a/CHANGELOG b/CHANGELOG
index f0232c45b7..0f01833622 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -15,6 +15,8 @@ git-annex (10.20220725) UNRELEASED; urgency=medium
     when when core.untrackedCache is set, and broke git-annex init.
   * Improve output when storing to bup.
   * When bup split fails, display its stderr.
+  * Avoid running multiple bup split processes concurrently, since
+    bup is not concurrency safe.
 
  -- Joey Hess <id@joeyh.name>  Mon, 25 Jul 2022 15:35:45 -0400
 
diff --git a/Remote/Bup.hs b/Remote/Bup.hs
index 4d007243d3..c46dda4bf1 100644
--- a/Remote/Bup.hs
+++ b/Remote/Bup.hs
@@ -5,13 +5,14 @@
  - Licensed under the GNU AGPL version 3 or higher.
  -}
 
-{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE RankNTypes, OverloadedStrings #-}
 
 module Remote.Bup (remote) where
 
 import qualified Data.Map as M
 import qualified Data.ByteString as S
 import qualified Data.ByteString.Lazy as L
+import qualified System.FilePath.ByteString as P
 import Data.ByteString.Lazy.UTF8 (fromString)
 import Control.Concurrent.Async
 
@@ -35,6 +36,8 @@ import Utility.Hash
 import Utility.UserInfo
 import Annex.UUID
 import Annex.Ssh
+import Annex.LockFile
+import Annex.Perms
 import Utility.Metered
 import Types.ProposedAccepted
 
@@ -155,7 +158,7 @@ bupSplitParams r buprepo k src =
 		(os ++ [Param "-q", Param "-n", Param (bupRef k)] ++ src)
 
 store :: Remote -> BupRepo -> Storer
-store r buprepo = byteStorer $ \k b p -> do
+store r buprepo = byteStorer $ \k b p -> lockBup r $ do
 	liftIO $ withNullHandle $ \nullh ->
 		let params = bupSplitParams r buprepo k []
 		    cmd = (proc "bup" (toCommand params))
@@ -183,6 +186,17 @@ store r buprepo = byteStorer $ \k b p -> do
 					" (stderr output: " ++ erroutput ++ ")"
 	go _ _ _ _ _ _ = error "internal"
 
+{- Bup is not concurrency safe, so use a lock file to prevent more than
+ - one process from running. -}
+lockBup :: Remote -> Annex a -> Annex a
+lockBup r a = do
+	dir <- fromRepo gitAnnexRemotesDir
+	unlessM (liftIO $ doesDirectoryExist (fromRawFilePath dir)) $
+		createAnnexDirectory dir
+	let remoteid = fromUUID (uuid r)
+	let lck = dir P.</> remoteid <> ".lck"
+	withExclusiveLock (const lck) a
+
 retrieve :: BupRepo -> Retriever
 retrieve buprepo = byteRetriever $ \k sink -> do
 	let params = bupParams "join" buprepo [Param $ bupRef k]
diff --git a/doc/bugs/bup_often_errors_out_when_-J___62___1/comment_4_d7156224245542f5468783c1b5763154._comment b/doc/bugs/bup_often_errors_out_when_-J___62___1/comment_4_d7156224245542f5468783c1b5763154._comment
new file mode 100644
index 0000000000..dcae1ea760
--- /dev/null
+++ b/doc/bugs/bup_often_errors_out_when_-J___62___1/comment_4_d7156224245542f5468783c1b5763154._comment
@@ -0,0 +1,13 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 4"""
+ date="2022-08-08T20:13:24Z"
+ content="""
+Got confirmation that bup is generally not concurrency safe.
+
+I've made git-annex limit the number of bup-split it runs to 1.
+
+It may be that this will also need to be done with bup-join, but I think
+probably not since it probably does not write to the repo, and a bup-split
+is unlikely to get in its way.
+"""]]

avoid surprising "not found" error when copying to a http remote
git-annex copy --to a http remote will of course fail, as that's not
supported. But git-annex copy first checks if the content is already
present in the remote, and that threw a "not found".
Looks to me like other remotes that use Url.checkBoth in their checkPresent
do just return false when it fails. And Url.checkBoth does display
errors when unusual errors occur. So I'm pretty sure removing this error
message is ok.
Sponsored-by: Jarkko Kniivilä on Patreon
diff --git a/Remote/Git.hs b/Remote/Git.hs
index 0af5a3eb98..48f2422cd8 100644
--- a/Remote/Git.hs
+++ b/Remote/Git.hs
@@ -407,10 +407,9 @@ inAnnex' repo rmt st@(State connpool duc _ _ _) key
   where
 	checkhttp = do
 		gc <- Annex.getGitConfig
-		ifM (Url.withUrlOptionsPromptingCreds $ \uo -> anyM (\u -> Url.checkBoth u (fromKey keySize key) uo) (keyUrls gc repo rmt key))
-			( return True
-			, giveup "not found"
-			)
+		Url.withUrlOptionsPromptingCreds $ \uo -> 
+			anyM (\u -> Url.checkBoth u (fromKey keySize key) uo)
+				(keyUrls gc repo rmt key)
 	checkremote = P2PHelper.checkpresent (Ssh.runProto rmt connpool (cantCheck rmt)) key
 	checklocal = ifM duc
 		( guardUsable repo (cantCheck repo) $
diff --git a/doc/bugs/GIN_is_not_recognized_as_a_git-annex_enabled_repos/comment_4_f97de485f97d8016a5ab4e276799d230._comment b/doc/bugs/GIN_is_not_recognized_as_a_git-annex_enabled_repos/comment_4_f97de485f97d8016a5ab4e276799d230._comment
new file mode 100644
index 0000000000..d2d44cd9cd
--- /dev/null
+++ b/doc/bugs/GIN_is_not_recognized_as_a_git-annex_enabled_repos/comment_4_f97de485f97d8016a5ab4e276799d230._comment
@@ -0,0 +1,36 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 4"""
+ date="2022-08-08T15:27:21Z"
+ content="""
+Well, that is a different problem than the problem you reported, isn't it?
+You seem to have shown that git-annex does in fact recognize your GIN
+remote as a git-annex repo.
+
+git-annex does not support uploading files to a git repo on GIN using http.
+
+The datalad documentation says to add a remote using the ssh url of the GIN
+repository, which git-annex can store files on. See 
+<http://handbook.datalad.org/en/0.13_a/basics/101-139-gin.html#publishing-your-dataset-to-gin>
+
+Without using datalad, the equivilant commands would be something like:
+
+	git remote add gin git@gin.g-node.org:/ivis-mizuguchi/https.git
+	git-annex copy --to gin
+
+---
+
+So this leaves the question of why git-annex tries to do a http request
+when you ask it to copy the content to the http repo. That http request
+failing is what results in the "(not found)" message.
+
+Looks like that is due to `git-annex copy` checking to see if the content
+exists on the remote. It does not. So it ought to try to send it,
+which would fail with a better "copying to non-ssh repo not supported" error message.
+However, intstead it displays the error.
+
+I've fixed this bug, and now it fails with this message:
+
+	copy test3.txt (to origin...) 
+	  copying to non-ssh repo not supported
+"""]]

comment
diff --git a/doc/bugs/Copying_many_files_to_bup_remotes_is_very_slow/comment_1_d81f94dfdb1b15b8bc0d9c243ef748db._comment b/doc/bugs/Copying_many_files_to_bup_remotes_is_very_slow/comment_1_d81f94dfdb1b15b8bc0d9c243ef748db._comment
new file mode 100644
index 0000000000..75f8eaec6c
--- /dev/null
+++ b/doc/bugs/Copying_many_files_to_bup_remotes_is_very_slow/comment_1_d81f94dfdb1b15b8bc0d9c243ef748db._comment
@@ -0,0 +1,15 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2022-08-08T15:24:36Z"
+ content="""
+I don't think that git-annex is doing anything particularly slow with the
+bup special remote. Other than actually running bup, that special remote
+should run about as fast as other similar special remotes, like say
+the directory special remote.
+
+So, this is probably a performance problem in bup. Now, git-annex does
+use bup in an unusual way, running one bup-split per file to store in it.
+That was the only way to shoehorn what git-annex needs to do into bup
+though.
+"""]]

comment
diff --git a/doc/bugs/bup_often_errors_out_when_-J___62___1/comment_3_ca2b909c54a772e1eea58b7cbc07bf39._comment b/doc/bugs/bup_often_errors_out_when_-J___62___1/comment_3_ca2b909c54a772e1eea58b7cbc07bf39._comment
index e1f8649f96..d726ca75c2 100644
--- a/doc/bugs/bup_often_errors_out_when_-J___62___1/comment_3_ca2b909c54a772e1eea58b7cbc07bf39._comment
+++ b/doc/bugs/bup_often_errors_out_when_-J___62___1/comment_3_ca2b909c54a772e1eea58b7cbc07bf39._comment
@@ -7,8 +7,8 @@ Looks like bup-midx is at fault, and that makes sense; it converts git pack
 files into "midx" files, so is reading and deleting pack files. So it seems
 likely that two of those running at the same time would fail like this.
 
-I'm going to post to bup's mailing list (its github repo does not have
-issues turned on).
+I've posted to bup's mailing list about this:
+<https://groups.google.com/g/bup-list/c/SJg6rQ2XWy8>
 
 git-annex may need to work around this by only running one bup-split at a
 time.

comment
diff --git a/doc/bugs/bup_often_errors_out_when_-J___62___1/comment_3_ca2b909c54a772e1eea58b7cbc07bf39._comment b/doc/bugs/bup_often_errors_out_when_-J___62___1/comment_3_ca2b909c54a772e1eea58b7cbc07bf39._comment
new file mode 100644
index 0000000000..e1f8649f96
--- /dev/null
+++ b/doc/bugs/bup_often_errors_out_when_-J___62___1/comment_3_ca2b909c54a772e1eea58b7cbc07bf39._comment
@@ -0,0 +1,15 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 3"""
+ date="2022-08-08T15:11:53Z"
+ content="""
+Looks like bup-midx is at fault, and that makes sense; it converts git pack
+files into "midx" files, so is reading and deleting pack files. So it seems
+likely that two of those running at the same time would fail like this.
+
+I'm going to post to bup's mailing list (its github repo does not have
+issues turned on).
+
+git-annex may need to work around this by only running one bup-split at a
+time.
+"""]]

Added a comment: Additional Questions: git annex copy failed
diff --git a/doc/bugs/GIN_is_not_recognized_as_a_git-annex_enabled_repos/comment_3_07460def4969896c87e8696955740fa9._comment b/doc/bugs/GIN_is_not_recognized_as_a_git-annex_enabled_repos/comment_3_07460def4969896c87e8696955740fa9._comment
new file mode 100644
index 0000000000..1bb92766de
--- /dev/null
+++ b/doc/bugs/GIN_is_not_recognized_as_a_git-annex_enabled_repos/comment_3_07460def4969896c87e8696955740fa9._comment
@@ -0,0 +1,75 @@
+[[!comment format=mdwn
+ username="rinomizu5@5ead4c82685c65d7717dbd5591b80425036ae9e3"
+ nickname="rinomizu5"
+ avatar="http://cdn.libravatar.org/avatar/62478823018c68821064febcda7e5d4f"
+ subject="Additional Questions: git annex copy failed"
+ date="2022-08-08T10:31:26Z"
+ content="""
+Thanks for the advice, joey.  
+ 
+I understand that the URL in the browser bar needs to be set to remote.  
+Then, after modifying the remote URL, I am trying to sync the contents of the git annex file to GIN using the https protocol.  
+But git annex copy command failed.  
+<pre>(base) <font color=\"#8AE234\"><b>mizuguchi@ubuntu</b></font>:<font color=\"#729FCF\"><b>~/https</b></font>$ git annex copy --to=origin test2.txt
+copy test2.txt (not found) failed
+copy: 1 failed
+</pre>  
+I checked the origin remote has annex-uuid, and it's the same as uuid of [annex] in https://gin.g-node.org/ivis-mizuguchi/https/config.   
+I would like to know why git annex cannot find test2.txt.  
+
+### The version of the tool used in my environment is below.  
+- git version 2.24.0  
+- git-annex version: 8.20211123+git12-g02e3756bd-1~ndall+1  
+
+### The repository in GIN
+[https://gin.g-node.org/ivis-mizuguchi/https](https://gin.g-node.org/ivis-mizuguchi/https)
+
+### I have done the following process and failed.  
+1. Create a repository named [https](https://gin.g-node.org/ivis-mizuguchi/https) in GIN with initialization.  And set the repository to public.   
+2. git clone https://gin.g-node.org/ivis-mizuguchi/https  
+3. cd https  
+4. git annex init  
+5. echo \"test\" > test.txt  
+6. git annex add test.txt  
+7. git commit -m \"test\"  
+8. git annex sync origin  
+9. echo \"test\" > test2.txt  
+10. git annex add 'test2.txt'  
+11. git commit -m 'test2'  
+12. git push origin master  
+13. git annex copy --to=origin test2.txt
+  <pre>(base) <font color=\"#8AE234\"><b>mizuguchi@ubuntu</b></font>:<font color=\"#729FCF\"><b>~/https</b></font>$ git annex copy --to=origin test2.txt
+copy test2.txt (not found) failed
+copy: 1 failed
+</pre>
+14. cat .git/config
+  <pre>(base) <font color=\"#8AE234\"><b>mizuguchi@ubuntu</b></font>:<font color=\"#729FCF\"><b>~/https</b></font>$ cat .git/config
+[core]
+	repositoryformatversion = 0
+	filemode = true
+	bare = false
+	logallrefupdates = true
+[remote &quot;origin&quot;]
+	url = https://gin.g-node.org/ivis-mizuguchi/https
+	fetch = +refs/heads/*:refs/remotes/origin/*
+	annex-uuid = c7a50190-9146-44de-8f1d-288551fa32e3
+[branch &quot;master&quot;]
+	remote = origin
+	merge = refs/heads/master
+[annex]
+	uuid = 80f0adc3-3144-4bba-a288-09a9ab009cef
+	version = 8
+[filter &quot;annex&quot;]
+	smudge = git-annex smudge -- %f
+	clean = git-annex smudge --clean -- %f
+</pre>
+
+Any advice would be appreciated.  
+Sincerely,   
+Rino Mizuguchi
+
+
+
+
+
+"""]]

Added a comment: Additional Questions: git annex copy failed
diff --git a/doc/bugs/GIN_is_not_recognized_as_a_git-annex_enabled_repos/comment_2_3e2f01eaaf717710a08ba092856af193._comment b/doc/bugs/GIN_is_not_recognized_as_a_git-annex_enabled_repos/comment_2_3e2f01eaaf717710a08ba092856af193._comment
new file mode 100644
index 0000000000..0cc75496da
--- /dev/null
+++ b/doc/bugs/GIN_is_not_recognized_as_a_git-annex_enabled_repos/comment_2_3e2f01eaaf717710a08ba092856af193._comment
@@ -0,0 +1,75 @@
+[[!comment format=mdwn
+ username="rinomizu5@5ead4c82685c65d7717dbd5591b80425036ae9e3"
+ nickname="rinomizu5"
+ avatar="http://cdn.libravatar.org/avatar/62478823018c68821064febcda7e5d4f"
+ subject="Additional Questions: git annex copy failed"
+ date="2022-08-08T10:31:04Z"
+ content="""
+Thanks for the advice, joey.  
+ 
+I understand that the URL in the browser bar needs to be set to remote.  
+Then, after modifying the remote URL, I am trying to sync the contents of the git annex file to GIN using the https protocol.  
+But git annex copy command failed.  
+<pre>(base) <font color=\"#8AE234\"><b>mizuguchi@ubuntu</b></font>:<font color=\"#729FCF\"><b>~/https</b></font>$ git annex copy --to=origin test2.txt
+copy test2.txt (not found) failed
+copy: 1 failed
+</pre>  
+I checked the origin remote has annex-uuid, and it's the same as uuid of [annex] in https://gin.g-node.org/ivis-mizuguchi/https/config.   
+I would like to know why git annex cannot find test2.txt.  
+
+### The version of the tool used in my environment is below.  
+- git version 2.24.0  
+- git-annex version: 8.20211123+git12-g02e3756bd-1~ndall+1  
+
+### The repository in GIN
+[https://gin.g-node.org/ivis-mizuguchi/https](https://gin.g-node.org/ivis-mizuguchi/https)
+
+### I have done the following process and failed.  
+1. Create a repository named [https](https://gin.g-node.org/ivis-mizuguchi/https) in GIN with initialization.  And set the repository to public.   
+2. git clone https://gin.g-node.org/ivis-mizuguchi/https  
+3. cd https  
+4. git annex init  
+5. echo \"test\" > test.txt  
+6. git annex add test.txt  
+7. git commit -m \"test\"  
+8. git annex sync origin  
+9. echo \"test\" > test2.txt  
+10. git annex add 'test2.txt'  
+11. git commit -m 'test2'  
+12. git push origin master  
+13. git annex copy --to=origin test2.txt
+  <pre>(base) <font color=\"#8AE234\"><b>mizuguchi@ubuntu</b></font>:<font color=\"#729FCF\"><b>~/https</b></font>$ git annex copy --to=origin test2.txt
+copy test2.txt (not found) failed
+copy: 1 failed
+</pre>
+14. cat .git/config
+  <pre>(base) <font color=\"#8AE234\"><b>mizuguchi@ubuntu</b></font>:<font color=\"#729FCF\"><b>~/https</b></font>$ cat .git/config
+[core]
+	repositoryformatversion = 0
+	filemode = true
+	bare = false
+	logallrefupdates = true
+[remote &quot;origin&quot;]
+	url = https://gin.g-node.org/ivis-mizuguchi/https
+	fetch = +refs/heads/*:refs/remotes/origin/*
+	annex-uuid = c7a50190-9146-44de-8f1d-288551fa32e3
+[branch &quot;master&quot;]
+	remote = origin
+	merge = refs/heads/master
+[annex]
+	uuid = 80f0adc3-3144-4bba-a288-09a9ab009cef
+	version = 8
+[filter &quot;annex&quot;]
+	smudge = git-annex smudge -- %f
+	clean = git-annex smudge --clean -- %f
+</pre>
+
+Any advice would be appreciated.  
+Sincerely,   
+Rino Mizuguchi
+
+
+
+
+
+"""]]

Added a comment
diff --git a/doc/special_remotes/rsync/comment_16_509514d6e3d790a80a2125068f499a72._comment b/doc/special_remotes/rsync/comment_16_509514d6e3d790a80a2125068f499a72._comment
new file mode 100644
index 0000000000..3d46b00945
--- /dev/null
+++ b/doc/special_remotes/rsync/comment_16_509514d6e3d790a80a2125068f499a72._comment
@@ -0,0 +1,11 @@
+[[!comment format=mdwn
+ username="aurelia@b44312a63326710de6cea9c43290e5debbd55607"
+ nickname="aurelia"
+ avatar="http://cdn.libravatar.org/avatar/818bf579caf9992f9123bd9b58321b2b"
+ subject="comment 16"
+ date="2022-08-07T10:28:09Z"
+ content="""
+turns out that if you get into the habit of writing rsync remotes like rclone remotes, git annex breaks
+
+I had a SSH config entry with the name `annex` and set the rsync URL to `annex:`. The works for moving content in, but fsck and get will fail and undo the content tracking.
+"""]]

Added a comment
diff --git a/doc/bugs/bup_often_errors_out_when_-J___62___1/comment_2_f0f87b7a2c60afba609072566b0048ac._comment b/doc/bugs/bup_often_errors_out_when_-J___62___1/comment_2_f0f87b7a2c60afba609072566b0048ac._comment
new file mode 100644
index 0000000000..1b5e98c3ba
--- /dev/null
+++ b/doc/bugs/bup_often_errors_out_when_-J___62___1/comment_2_f0f87b7a2c60afba609072566b0048ac._comment
@@ -0,0 +1,190 @@
+[[!comment format=mdwn
+ username="Atemu"
+ avatar="http://cdn.libravatar.org/avatar/d1f0f4275931c552403f4c6707bead7a"
+ subject="comment 2"
+ date="2022-08-07T08:05:23Z"
+ content="""
+Thanks for looking into this!
+
+> However, I have not been able to reproduce it so far. I tried making 8 different files each 100 mb, and was able to copy them all to a bup repository concurrently with no failures.
+
+You need more than that; 8 Files might randomly work without error.
+
+Perhaps it only really manifests itself on smaller files? That's mainly what I've been copying.
+
+Here's an example output of git-annex 6d762fafae45cb1f6a6106ac25f347631d6d0ca8 `git-annex copy --not --in bup --to bup -J2 --all`:
+
+```
+...
+copy SHA256E-s227509--23bcff8394a16cb8ae090ac9f67e7cccb8a2c4354788b11426bfc14d01c136c6.csv (to bup...) 
+  bup [\"split\",\"-r\",\"/tmp/bup\",\"-q\",\"-n\",\"SHA256E-s227509--23bcff8394a16cb8ae090ac9f67e7cccb8a2c4354788b11426bfc14d01c136c6.csv\"] exited 1 (stderr output: Traceback (most recent call last):
+    File \"/nix/store/xqgy6d53wbazvkjcgqwdpbww4s87b69z-bup-0.32/lib/bup/cmd/bup-midx\", line 298, in <module>
+      do_midx_dir(path, opt.output, byte_stream(sys.stdout))
+    File \"/nix/store/xqgy6d53wbazvkjcgqwdpbww4s87b69z-bup-0.32/lib/bup/cmd/bup-midx\", line 192, in do_midx_dir
+      m = git.open_idx(mname)
+    File \"/nix/store/xqgy6d53wbazvkjcgqwdpbww4s87b69z-bup-0.32/lib/bup/cmd/../bup/git.py\", line 668, in open_idx
+      return midx.PackMidx(filename)
+    File \"/nix/store/xqgy6d53wbazvkjcgqwdpbww4s87b69z-bup-0.32/lib/bup/cmd/../bup/midx.py\", line 29, in __init__
+      self.map = mmap_read(open(filename))
+  FileNotFoundError: [Errno 2] No such file or directory: b'/tmp/bup/index-cache/None__tmp_bup/midx-5bfad00d8c17012ca48231b22dd894649c385b15.midx'
+  [b'/nix/store/xqgy6d53wbazvkjcgqwdpbww4s87b69z-bup-0.32/lib/bup/cmd/bup', b'midx', b'--auto', b'--dir', b'/tmp/bup/index-cache/None__tmp_bup']: returned 1
+  WARNING: 1 errors encountered while saving.
+  )
+ok
+copy SHA256E-s6061--b57b1e42ee05102f095d700c9bcb12b48142a9c57879573d3fd128d181b60f5f.txt.user (to bup...) ok
+copy SHA256E-s1861--86988a46008289c58943f2e59f4e543fdec3fc9853ce8b53375e11f9ccbd4138.cpp (to bup...) 
+  bup [\"split\",\"-r\",\"/tmp/bup\",\"-q\",\"-n\",\"SHA256E-s1861--86988a46008289c58943f2e59f4e543fdec3fc9853ce8b53375e11f9ccbd4138.cpp\"] exited 1 (stderr output: Traceback (most recent call last):
+    File \"/nix/store/xqgy6d53wbazvkjcgqwdpbww4s87b69z-bup-0.32/lib/bup/cmd/bup-server\", line 320, in <module>
+      cmd(conn, rest)
+    File \"/nix/store/xqgy6d53wbazvkjcgqwdpbww4s87b69z-bup-0.32/lib/bup/cmd/bup-server\", line 137, in receive_objects_v2
+      oldpack = w.exists(shar, want_source=True)
+    File \"/nix/store/xqgy6d53wbazvkjcgqwdpbww4s87b69z-bup-0.32/lib/bup/cmd/../bup/git.py\", line 804, in exists
+      self._require_objcache()
+    File \"/nix/store/xqgy6d53wbazvkjcgqwdpbww4s87b69z-bup-0.32/lib/bup/cmd/../bup/git.py\", line 797, in _require_objcache
+      self.objcache = self.objcache_maker()
+    File \"/nix/store/xqgy6d53wbazvkjcgqwdpbww4s87b69z-bup-0.32/lib/bup/cmd/../bup/git.py\", line 686, in _make_objcache
+      return PackIdxList(repo(b'objects/pack'))
+    File \"/nix/store/xqgy6d53wbazvkjcgqwdpbww4s87b69z-bup-0.32/lib/bup/cmd/../bup/git.py\", line 517, in __init__
+      self.refresh()
+    File \"/nix/store/xqgy6d53wbazvkjcgqwdpbww4s87b69z-bup-0.32/lib/bup/cmd/../bup/git.py\", line 607, in refresh
+      midxl.sort(key=lambda ix:
+    File \"/nix/store/xqgy6d53wbazvkjcgqwdpbww4s87b69z-bup-0.32/lib/bup/cmd/../bup/git.py\", line 608, in <lambda>
+      (-len(ix), -xstat.stat(ix.name).st_mtime))
+    File \"/nix/store/xqgy6d53wbazvkjcgqwdpbww4s87b69z-bup-0.32/lib/bup/cmd/../bup/xstat.py\", line 131, in stat
+      return stat_result.from_xstat_rep(_helpers.stat(path))
+  FileNotFoundError: [Errno 2] No such file or directory: '/tmp/bup/objects/pack/midx-13188bb9c81006e5bc683627ee9fe186c09a9104.midx'
+  Traceback (most recent call last):
+    File \"/nix/store/xqgy6d53wbazvkjcgqwdpbww4s87b69z-bup-0.32/lib/bup/cmd/bup-split\", line 232, in <module>
+      pack_writer.close()  # must close before we can update the ref
+    File \"/nix/store/xqgy6d53wbazvkjcgqwdpbww4s87b69z-bup-0.32/lib/bup/cmd/../bup/client.py\", line 520, in close
+      id = self._end()
+    File \"/nix/store/xqgy6d53wbazvkjcgqwdpbww4s87b69z-bup-0.32/lib/bup/cmd/../bup/client.py\", line 517, in _end
+      return self.suggest_packs() # Returns last idx received
+    File \"/nix/store/xqgy6d53wbazvkjcgqwdpbww4s87b69z-bup-0.32/lib/bup/cmd/../bup/client.py\", line 285, in _suggest_packs
+      self.check_ok()
+    File \"/nix/store/xqgy6d53wbazvkjcgqwdpbww4s87b69z-bup-0.32/lib/bup/cmd/../bup/client.py\", line 155, in check_ok
+      raise ClientError('server exited unexpectedly with code %r'
+  bup.client.ClientError: server exited unexpectedly with code 1
+  )
+ok
+copy SHA256E-s247--598ca11afb6b5a92fb0539d5e51b5933986a02b9af76c306ed0e3d123eba7f73.org (to bup...) ok
+copy SHA256E-s17120--e883a44474fb01cb2598a35de65bb8f149e8a86f0edad9e769c29cb47738f1d7.org (to bup...) ok
+copy SHA256E-s51256--6a45e5a834b84467ca8730b19d11997b1fda618e8264f3052466b0c0d9df33fb (to bup...) ok
+copy SHA256E-s138590--273323cbd322923f9d19280b6b4fa73bfa3638d2982b685b9efcaee43c988a07.pdf (to bup...) ok
+copy SHA256E-s1142--68e432e17b706adc8fed0c6e573957ebf3fdb3c2ed52152e8e11ff68742a964c.cpp (to bup...) ok
+copy SHA256E-s2357--88f5bd074dce62a99f67a2fcb89f69edc323f5b781c43f75e2266caa75f452a8.nix (to bup...) ok
+copy SHA256E-s17167--f1a52bf34dc0c09bd05ea76c129bca1edf01cb1634967facddc87ceed030ac0e.org (to bup...) ok
+copy SHA256E-s20152--ec24a0a718ff33a20fd18a672e7f8e8d29358a4930a0cb668fc023c6319acff2.cpp (to bup...) ok
+copy SHA256E-s74935712--48a36e91a03d46fe73ec361454b9cd3808ae0a6d5372df089c2400ea135269e1.pptx (to bup...) ok
+copy SHA256E-s32801--33568e97fb3c67d5646698a3157d2387ccbd447dbe846604e21f135962b7a82a.org (to bup...) ok
+copy SHA256E-s1112--08efad2257400abb2a011b7a2bcee115ad69a7c5f8fe622df94f9252e767f4b1.cpp (to bup...) ok
+copy SHA256E-s4--af489f7170eaf213b960628333c4752e3907304303ed0b052b43d864d2653c2e (to bup...) ok
+copy SHA256E-s270--fd3d6db55c73971d25b7a12211f618ee0f5b9185329974e15a71b8c7313b71d3.org (to bup...) ok
+copy SHA256E-s26781--66ff44f139d2f825d6202437078e2a6652214f2d4841f618268a39cb25919c52.org (to bup...) ok
+copy SHA256E-s267--5face6a2e6cf04634542c17626cfb273b5cd6d1ff8cad644bb3dfd50b5b26c10 (to bup...) ok
+copy SHA256E-s1117802--d9b03b85205196237df6bdcaaa74642db77da46fbea35d1e0de4034f24387cf4.pdf (to bup...) ok
+copy SHA256E-s265--fc2aec4bcb3af72e043a2f892440a1370ed19704cf4fb4a3cc26114441b6f8d0.org (to bup...) ok
+copy SHA256E-s34783--ad8860a118f942f58672a95c2df3dcfbfd2cc8ee3f5930f52bfbb88dc0a90132.org (to bup...) ok
+copy SHA256E-s56184--30106a0f9dd300f8a88e2eb88b2a184a1342874afa2cb4aaa64404a187f1e8c4 (to bup...) ok
+copy SHA256E-s74919040--86dcfa59caa040dcfc512bc41b8fe652abc0814324f8fe18d88043a14ecf4402.pptx (to bup...) ok
+copy SHA256E-s26013--0bae4beaba4bdf971bd79061a215e2835953b3bb00e532fb0341e6628b796008.org (to bup...) ok
+copy SHA256E-s58752--e03f8dc86ed2dc218612022331323a2f5cac319a250b4a24fc15d7312ee9e607 (to bup...) ok
+copy SHA256E-s8847--cc7aa3b84e82f7aa197d653f41b545a1e807c98f16187210ded3d2463b41ea86.csv (to bup...) ok
+copy SHA256E-s21189--8ffdc40240a69693c596b70a94dd58258cd753b41f34e0c16c38d8dbd89f698e.org (to bup...) ok
+copy SHA256E-s24137--9a5c833a7f70f53ba26aa26e3dd2faf22b16e1c4ce33c5733d0a2109560b7c71.org (to bup...) ok
+copy SHA256E-s359450--0d0ec93306f455d231ede0e8f2f6c047dd94e0de9a16639e1a7f0b3d86203ac3.pdf (to bup...) 
+  bup [\"split\",\"-r\",\"/tmp/bup\",\"-q\",\"-n\",\"SHA256E-s359450--0d0ec93306f455d231ede0e8f2f6c047dd94e0de9a16639e1a7f0b3d86203ac3.pdf\"] exited 1 (stderr output: Traceback (most recent call last):
+    File \"/nix/store/xqgy6d53wbazvkjcgqwdpbww4s87b69z-bup-0.32/lib/bup/cmd/bup-midx\", line 298, in <module>
+      do_midx_dir(path, opt.output, byte_stream(sys.stdout))
+    File \"/nix/store/xqgy6d53wbazvkjcgqwdpbww4s87b69z-bup-0.32/lib/bup/cmd/bup-midx\", line 198, in do_midx_dir
+      midxs.sort(key=lambda ix: (-sizes[ix], -xstat.stat(ix).st_mtime))
+    File \"/nix/store/xqgy6d53wbazvkjcgqwdpbww4s87b69z-bup-0.32/lib/bup/cmd/bup-midx\", line 198, in <lambda>
+      midxs.sort(key=lambda ix: (-sizes[ix], -xstat.stat(ix).st_mtime))
+    File \"/nix/store/xqgy6d53wbazvkjcgqwdpbww4s87b69z-bup-0.32/lib/bup/cmd/../bup/xstat.py\", line 131, in stat
+      return stat_result.from_xstat_rep(_helpers.stat(path))
+  FileNotFoundError: [Errno 2] No such file or directory: '/tmp/bup/index-cache/None__tmp_bup/midx-3da3384b3acf53204d7890e1bc78030c8b46b3a9.midx'
+  [b'/nix/store/xqgy6d53wbazvkjcgqwdpbww4s87b69z-bup-0.32/lib/bup/cmd/bup', b'midx', b'--auto', b'--dir', b'/tmp/bup/index-cache/None__tmp_bup']: returned 1
+  WARNING: 1 errors encountered while saving.
+  )
+ok
+copy SHA256E-s1433--20e8793d98da9272424818b56c28af028c1568ec3e82967d6f07ff81015c4108.cpp (to bup...) ok
+copy SHA256E-s91176--46ebe34cba131ea6ced189768edccfbf7eb4b7e33fa0be53c36c7888e2bff4a5 (to bup...) 
+  bup [\"split\",\"-r\",\"/tmp/bup\",\"-q\",\"-n\",\"SHA256E-s91176--46ebe34cba131ea6ced189768edccfbf7eb4b7e33fa0be53c36c7888e2bff4a5\"] exited 1 (stderr output: Traceback (most recent call last):
+    File \"/nix/store/xqgy6d53wbazvkjcgqwdpbww4s87b69z-bup-0.32/lib/bup/cmd/bup-server\", line 320, in <module>
+      cmd(conn, rest)
+    File \"/nix/store/xqgy6d53wbazvkjcgqwdpbww4s87b69z-bup-0.32/lib/bup/cmd/bup-server\", line 137, in receive_objects_v2
+      oldpack = w.exists(shar, want_source=True)
+    File \"/nix/store/xqgy6d53wbazvkjcgqwdpbww4s87b69z-bup-0.32/lib/bup/cmd/../bup/git.py\", line 804, in exists
+      self._require_objcache()
+    File \"/nix/store/xqgy6d53wbazvkjcgqwdpbww4s87b69z-bup-0.32/lib/bup/cmd/../bup/git.py\", line 797, in _require_objcache
+      self.objcache = self.objcache_maker()
+    File \"/nix/store/xqgy6d53wbazvkjcgqwdpbww4s87b69z-bup-0.32/lib/bup/cmd/../bup/git.py\", line 686, in _make_objcache
+      return PackIdxList(repo(b'objects/pack'))
+    File \"/nix/store/xqgy6d53wbazvkjcgqwdpbww4s87b69z-bup-0.32/lib/bup/cmd/../bup/git.py\", line 517, in __init__
+      self.refresh()
+    File \"/nix/store/xqgy6d53wbazvkjcgqwdpbww4s87b69z-bup-0.32/lib/bup/cmd/../bup/git.py\", line 607, in refresh
+      midxl.sort(key=lambda ix:
+    File \"/nix/store/xqgy6d53wbazvkjcgqwdpbww4s87b69z-bup-0.32/lib/bup/cmd/../bup/git.py\", line 608, in <lambda>
+      (-len(ix), -xstat.stat(ix.name).st_mtime))
+    File \"/nix/store/xqgy6d53wbazvkjcgqwdpbww4s87b69z-bup-0.32/lib/bup/cmd/../bup/xstat.py\", line 131, in stat
+      return stat_result.from_xstat_rep(_helpers.stat(path))
+  FileNotFoundError: [Errno 2] No such file or directory: '/tmp/bup/objects/pack/midx-4b7dfbb64132c6a9e65912f5d75a49fcc27dfc14.midx'
+  Traceback (most recent call last):
+    File \"/nix/store/xqgy6d53wbazvkjcgqwdpbww4s87b69z-bup-0.32/lib/bup/cmd/bup-split\", line 232, in <module>
+      pack_writer.close()  # must close before we can update the ref
+    File \"/nix/store/xqgy6d53wbazvkjcgqwdpbww4s87b69z-bup-0.32/lib/bup/cmd/../bup/client.py\", line 520, in close
+      id = self._end()
+    File \"/nix/store/xqgy6d53wbazvkjcgqwdpbww4s87b69z-bup-0.32/lib/bup/cmd/../bup/client.py\", line 517, in _end
+      return self.suggest_packs() # Returns last idx received
+    File \"/nix/store/xqgy6d53wbazvkjcgqwdpbww4s87b69z-bup-0.32/lib/bup/cmd/../bup/client.py\", line 285, in _suggest_packs
+      self.check_ok()
+    File \"/nix/store/xqgy6d53wbazvkjcgqwdpbww4s87b69z-bup-0.32/lib/bup/cmd/../bup/client.py\", line 155, in check_ok
+      raise ClientError('server exited unexpectedly with code %r'
+  bup.client.ClientError: server exited unexpectedly with code 1
+  )
+ok
+copy SHA256E-s84648--95ced533e6e0117e09eb0c6e887e3258ccd85e7c14b376a48683028d1959e6f4 (to bup...) ok
+copy SHA256E-s33116--1c7622be0217bef8b345d7a2d741a1ea7140df79fb69ee966d0e2596aedd9b92.org (to bup...) ok
+copy SHA256E-s1405--707992e818ada3dcf8ddee86d0bf01db6206e1cd9354c8b32bd760a842757890.cpp (to bup...) ok
+copy SHA256E-s34172--5ae202572227ab6df161298ab61c4bfe5ebca4b710e8646602c910996c9c4229.org (to bup...) ok
+copy SHA256E-s1406289--7462f1e3ca02e796090fe2ba18a50168a24f5cabc66bb8bf949836d4c81774cb.csv (to bup...) ok
+copy SHA256E-s263520--1ae605c38fb827de59f90fe304ad20c673a2d8fcbf8166a4cf44bfc45320fb43 (to bup...) ok
+copy SHA256E-s57968--830ff82c9c697a29a7cdf1f4765aadb532e42c932a01c45eafe3d66b254dc30b (to bup...) ok
+copy SHA256E-s16350--45d12a82d07c62c00fbb211b3cfbc7abea2fb8b4b1777140b56ebee9244ef7af.org (to bup...) 
+  bup [\"split\",\"-r\",\"/tmp/bup\",\"-q\",\"-n\",\"SHA256E-s16350--45d12a82d07c62c00fbb211b3cfbc7abea2fb8b4b1777140b56ebee9244ef7af.org\"] exited 1 (stderr output: Traceback (most recent call last):
+    File \"/nix/store/xqgy6d53wbazvkjcgqwdpbww4s87b69z-bup-0.32/lib/bup/cmd/bup-midx\", line 298, in <module>
+      do_midx_dir(path, opt.output, byte_stream(sys.stdout))
+    File \"/nix/store/xqgy6d53wbazvkjcgqwdpbww4s87b69z-bup-0.32/lib/bup/cmd/bup-midx\", line 198, in do_midx_dir
+      midxs.sort(key=lambda ix: (-sizes[ix], -xstat.stat(ix).st_mtime))
+    File \"/nix/store/xqgy6d53wbazvkjcgqwdpbww4s87b69z-bup-0.32/lib/bup/cmd/bup-midx\", line 198, in <lambda>
+      midxs.sort(key=lambda ix: (-sizes[ix], -xstat.stat(ix).st_mtime))
+    File \"/nix/store/xqgy6d53wbazvkjcgqwdpbww4s87b69z-bup-0.32/lib/bup/cmd/../bup/xstat.py\", line 131, in stat
+      return stat_result.from_xstat_rep(_helpers.stat(path))
+  FileNotFoundError: [Errno 2] No such file or directory: '/tmp/bup/index-cache/None__tmp_bup/midx-fef6f07a351680cef8630a1c0ba203f2ed8c0e72.midx'
+  [b'/nix/store/xqgy6d53wbazvkjcgqwdpbww4s87b69z-bup-0.32/lib/bup/cmd/bup', b'midx', b'--auto', b'--dir', b'/tmp/bup/index-cache/None__tmp_bup']: returned 1
+  WARNING: 1 errors encountered while saving.
+  )
+ok
+copy SHA256E-s2--9a271f2a916b0b6ee6cecb2426f0b3206ef074578be55d9bc94f6f3fe3ab86aa (to bup...) 
+  bup [\"split\",\"-r\",\"/tmp/bup\",\"-q\",\"-n\",\"SHA256E-s2--9a271f2a916b0b6ee6cecb2426f0b3206ef074578be55d9bc94f6f3fe3ab86aa\"] exited 1 (stderr output: Traceback (most recent call last):
+    File \"/nix/store/xqgy6d53wbazvkjcgqwdpbww4s87b69z-bup-0.32/lib/bup/cmd/bup-midx\", line 298, in <module>
+      do_midx_dir(path, opt.output, byte_stream(sys.stdout))
+    File \"/nix/store/xqgy6d53wbazvkjcgqwdpbww4s87b69z-bup-0.32/lib/bup/cmd/bup-midx\", line 198, in do_midx_dir
+      midxs.sort(key=lambda ix: (-sizes[ix], -xstat.stat(ix).st_mtime))
+    File \"/nix/store/xqgy6d53wbazvkjcgqwdpbww4s87b69z-bup-0.32/lib/bup/cmd/bup-midx\", line 198, in <lambda>
+      midxs.sort(key=lambda ix: (-sizes[ix], -xstat.stat(ix).st_mtime))
+    File \"/nix/store/xqgy6d53wbazvkjcgqwdpbww4s87b69z-bup-0.32/lib/bup/cmd/../bup/xstat.py\", line 131, in stat
+      return stat_result.from_xstat_rep(_helpers.stat(path))
+  FileNotFoundError: [Errno 2] No such file or directory: '/tmp/bup/index-cache/None__tmp_bup/midx-fef6f07a351680cef8630a1c0ba203f2ed8c0e72.midx'
+  [b'/nix/store/xqgy6d53wbazvkjcgqwdpbww4s87b69z-bup-0.32/lib/bup/cmd/bup', b'midx', b'--auto', b'--dir', b'/tmp/bup/index-cache/None__tmp_bup']: returned 1
+  WARNING: 1 errors encountered while saving.
+  )
+ok
+^C
+```
+
+(Ran this on aarch64-darwin because that's all I have access to ATM but x86_64-linux will probably have the same errors.)
+
+Given the error, it indeed looks like a concurrency issue in `bup` itself. Version is 0.32 which is the newest.
+
+"""]]

idea
diff --git a/doc/bugs/crippled_filesystem__58___SQLite3_returned_ErrorBusy/comment_10_b96755e44bedf262cbb32403f8edaf0b._comment b/doc/bugs/crippled_filesystem__58___SQLite3_returned_ErrorBusy/comment_10_b96755e44bedf262cbb32403f8edaf0b._comment
new file mode 100644
index 0000000000..22dddc60bb
--- /dev/null
+++ b/doc/bugs/crippled_filesystem__58___SQLite3_returned_ErrorBusy/comment_10_b96755e44bedf262cbb32403f8edaf0b._comment
@@ -0,0 +1,21 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 10"""
+ date="2022-08-05T18:42:34Z"
+ content="""
+Another way this could be dealt with is to move the sqlite databases to
+a local filesystem.
+
+Since git-annex only ever uses them for caching information from git, it
+can rebuild them, so even a tempfs would work. And it would also be ok if
+two git-annex processes accessing the same repo used different sqlite
+databases, since they would both build up the same information.
+(Even if they were on different computers using a network filesystem.)
+
+This could be done with a git config. And perhaps get `git-annex init`
+to somehow probe for this problem and set the git config. Although, what
+path would it set it to?
+
+(Note that gitAnnexKeysDbIndexCache would also need to be moved since it
+contains information about the content of a sqlite database.)
+"""]]

tag datalad since they have an issue about this
diff --git a/doc/bugs/crippled_filesystem__58___SQLite3_returned_ErrorBusy.mdwn b/doc/bugs/crippled_filesystem__58___SQLite3_returned_ErrorBusy.mdwn
index cce24684ab..b22f15cb79 100644
--- a/doc/bugs/crippled_filesystem__58___SQLite3_returned_ErrorBusy.mdwn
+++ b/doc/bugs/crippled_filesystem__58___SQLite3_returned_ErrorBusy.mdwn
@@ -85,3 +85,4 @@ add file1 ok
 
 When initializing the repo with v5 git-annex (git annex init --version=5 test), then the legacy direct mode is used and file addition works well.
 
+[[!tag projects/datalad]]

comment
diff --git a/doc/bugs/crippled_filesystem__58___SQLite3_returned_ErrorBusy/comment_9_d0d441c94af2fe63ed1b20fb031181a3._comment b/doc/bugs/crippled_filesystem__58___SQLite3_returned_ErrorBusy/comment_9_d0d441c94af2fe63ed1b20fb031181a3._comment
new file mode 100644
index 0000000000..d27ad40762
--- /dev/null
+++ b/doc/bugs/crippled_filesystem__58___SQLite3_returned_ErrorBusy/comment_9_d0d441c94af2fe63ed1b20fb031181a3._comment
@@ -0,0 +1,15 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 9"""
+ date="2022-08-05T18:05:45Z"
+ content="""
+@yoh Mounting the cifs filesystem with nobrl should avoid the problem.
+To make that safe, you *also* need to set annex.pidlock.
+
+Setting annex.pidlock on its own will not help.
+
+I don't think that git-annex can be changed in any way that makes sqlite
+work on this filesystem in its default state. What I discussed in comment
+#7 seems like the only feasible improvement to git-annex and would only
+help the user learn about the mount option.
+"""]]

When bup split fails, display its stderr
It seems worth noting here that I emailed bup's author about bup split
being noisy on stderr even with -q in approximately 2011. That never got
fixed. Its current repo on github only accepts pull requests, not bug
reports. Needing to add such complexity to deal with such a longstanding
unfixed issue is not fun.
Sponsored-by: Kevin Mueller on Patreon
diff --git a/CHANGELOG b/CHANGELOG
index 45991265a9..f0232c45b7 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -14,6 +14,7 @@ git-annex (10.20220725) UNRELEASED; urgency=medium
   * Work around bug in git 2.37 that causes a segfault
     when when core.untrackedCache is set, and broke git-annex init.
   * Improve output when storing to bup.
+  * When bup split fails, display its stderr.
 
  -- Joey Hess <id@joeyh.name>  Mon, 25 Jul 2022 15:35:45 -0400
 
diff --git a/Remote/Bup.hs b/Remote/Bup.hs
index 35e95e6bbe..4d007243d3 100644
--- a/Remote/Bup.hs
+++ b/Remote/Bup.hs
@@ -1,6 +1,6 @@
 {- Using bup as a remote.
  -
- - Copyright 2011-2020 Joey Hess <id@joeyh.name>
+ - Copyright 2011-2022 Joey Hess <id@joeyh.name>
  -
  - Licensed under the GNU AGPL version 3 or higher.
  -}
@@ -13,6 +13,7 @@ import qualified Data.Map as M
 import qualified Data.ByteString as S
 import qualified Data.ByteString.Lazy as L
 import Data.ByteString.Lazy.UTF8 (fromString)
+import Control.Concurrent.Async
 
 import Annex.Common
 import qualified Annex
@@ -160,19 +161,26 @@ store r buprepo = byteStorer $ \k b p -> do
 		    cmd = (proc "bup" (toCommand params))
 			{ std_in = CreatePipe
 			, std_out = UseHandle nullh
-			-- bup split is noisy to stderr even with the -q
-			-- option.
-			, std_err = UseHandle nullh
+			, std_err = CreatePipe
 			}
 		    feeder = \h -> do
 			meteredWrite p (S.hPut h) b
 			hClose h
 		in withCreateProcess cmd (go feeder cmd)
   where
-	go feeder p (Just h) _ _ pid =
-		forceSuccessProcess p pid
-			`after`
-		feeder h
+	go feeder p (Just inh) _ (Just errh) pid = do
+		-- bup split is noisy to stderr even with the -q
+		-- option. But when bup fails, the stderr needs
+		-- to be displayed.
+		(feedresult, erroutput) <- tryNonAsync (feeder inh)
+			`concurrently` hGetContentsStrict errh
+		waitForProcess pid >>= \case
+			ExitSuccess -> case feedresult of
+				Right () -> return ()
+				Left e -> throwM e
+			ExitFailure n -> giveup $ 
+				showCmd p ++ " exited " ++ show n ++
+					" (stderr output: " ++ erroutput ++ ")"
 	go _ _ _ _ _ _ = error "internal"
 
 retrieve :: BupRepo -> Retriever
diff --git a/Utility/Process.hs b/Utility/Process.hs
index 4cf61054b4..e768c13367 100644
--- a/Utility/Process.hs
+++ b/Utility/Process.hs
@@ -31,6 +31,7 @@ module Utility.Process (
 	stdoutHandle,
 	stderrHandle,
 	processHandle,
+	showCmd,
 	devNull,
 ) where
 
diff --git a/doc/bugs/bup_often_errors_out_when_-J___62___1/comment_1_1731cfb2662890299ca6daeacdd4bb47._comment b/doc/bugs/bup_often_errors_out_when_-J___62___1/comment_1_1731cfb2662890299ca6daeacdd4bb47._comment
new file mode 100644
index 0000000000..6659b61e8d
--- /dev/null
+++ b/doc/bugs/bup_often_errors_out_when_-J___62___1/comment_1_1731cfb2662890299ca6daeacdd4bb47._comment
@@ -0,0 +1,22 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2022-08-05T15:57:26Z"
+ content="""
+This seems most likely to be a concurrency issue in bup itself, or in how
+it uses git.
+
+However, I have not been able to reproduce it so far. I tried making 8
+different files each 100 mb, and was able to copy them all to a bup repository
+concurrently with no failures.
+
+That was with bup 0.32. What is your bup version?
+
+It would be good to know what error message bup outputs.
+Unfortunately, since `bup split -q` is noisy on stderr, git-annex
+sinks it to /dev/null and so you don't see it.
+
+I've changed git-annex to display the stderr when `bup split` fails.
+So if you can get an updated build of git-annex, and reproduce this problem,
+we'll be able to see if this is a bug in bup, or what.
+"""]]

Added a comment
diff --git a/doc/bugs/crippled_filesystem__58___SQLite3_returned_ErrorBusy/comment_8_0d34bfeab48421e35c6880bca639cbb2._comment b/doc/bugs/crippled_filesystem__58___SQLite3_returned_ErrorBusy/comment_8_0d34bfeab48421e35c6880bca639cbb2._comment
new file mode 100644
index 0000000000..8e059a15ea
--- /dev/null
+++ b/doc/bugs/crippled_filesystem__58___SQLite3_returned_ErrorBusy/comment_8_0d34bfeab48421e35c6880bca639cbb2._comment
@@ -0,0 +1,16 @@
+[[!comment format=mdwn
+ username="yarikoptic"
+ avatar="http://cdn.libravatar.org/avatar/f11e9c84cb18d26a1748c33b48c924b4"
+ subject="comment 8"
+ date="2022-08-05T16:17:09Z"
+ content="""
+We have got user of cifs filesystem mount [reprorting](https://github.com/datalad/datalad/issues/6917#issuecomment-1206358866) that setting pidlock didn't help while using git-annex 10.20220504-g35cafb7 and cifs mount with options 
+
+```
+type cifs (rw,relatime,vers=default,sec=krb5,cache=strict,multiuser,uid=164445,noforceuid,gid=100513,noforcegid,addr=172.19
+```
+
+Please advise to how to troubleshoot such situation.
+
+NB I might later try similarish cifs mount of our local HPC which I believe might expose it similarly.
+"""]]

work around git segfault
Work around bug in git 2.37 that causes a segfault when when
core.untrackedCache is set, and broke git-annex init.
Depending on when git gets fixed and how widely the buggy versions are
used, this could be reverted quite soon, or need to linger for a long time.
It only makes git-annex init a tiny bit slower in a new repo.
Sponsored-by: Max Thoursie on Patreon
diff --git a/Annex/Branch.hs b/Annex/Branch.hs
index 61e6012c2e..b227adb32c 100644
--- a/Annex/Branch.hs
+++ b/Annex/Branch.hs
@@ -133,6 +133,11 @@ getBranch = maybe (hasOrigin >>= go >>= use) return =<< branchsha
 		fromMaybe (error $ "failed to create " ++ fromRef name)
 			<$> branchsha
 	go False = withIndex' True $ do
+		-- Create the index file. This is not necessary,
+		-- except to avoid a bug in git that causes
+		-- git write-tree to segfault when the index file does not
+		-- exist.
+		inRepo $ flip Git.UpdateIndex.streamUpdateIndex []
 		cmode <- annexCommitMode <$> Annex.getGitConfig
 		cmessage <- createMessage
 		inRepo $ Git.Branch.commitAlways cmode cmessage fullname []
diff --git a/CHANGELOG b/CHANGELOG
index b62c1d81b5..05989b1804 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -11,6 +11,8 @@ git-annex (10.20220725) UNRELEASED; urgency=medium
   * Allow find --branch to be used in a bare repository, the same as
     the deprecated findref can be.
   * add --dry-run: New option. 
+  * Work around bug in git 2.37 that causes a segfault
+    when when core.untrackedCache is set, and broke git-annex init.
 
  -- Joey Hess <id@joeyh.name>  Mon, 25 Jul 2022 15:35:45 -0400
 
diff --git a/doc/bugs/Incompatibility_with_git_2.37/comment_6_3bb6424838d4f8a971f3dce6d1b8dbfb._comment b/doc/bugs/Incompatibility_with_git_2.37/comment_6_3bb6424838d4f8a971f3dce6d1b8dbfb._comment
new file mode 100644
index 0000000000..787d17a4ce
--- /dev/null
+++ b/doc/bugs/Incompatibility_with_git_2.37/comment_6_3bb6424838d4f8a971f3dce6d1b8dbfb._comment
@@ -0,0 +1,16 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 6"""
+ date="2022-08-04T17:46:32Z"
+ content="""
+Now 2 weeks since the segfault in git has been known, and they have not
+fixed it.
+
+Now feeling that it's might be worth git-annex init avoiding the
+segfault, by making sure to do something that creates the index file before
+write-tree. So I don't have to worry about when this gets fixed in git,
+or the chances that a buggy release will start being widely used for a long
+time.
+
+Yeah, done so.
+"""]]

explain why this happens and close
diff --git a/doc/bugs/GIN_is_not_recognized_as_a_git-annex_enabled_repos.mdwn b/doc/bugs/GIN_is_not_recognized_as_a_git-annex_enabled_repos.mdwn
index 2326cf9398..c882dbe2d1 100644
--- a/doc/bugs/GIN_is_not_recognized_as_a_git-annex_enabled_repos.mdwn
+++ b/doc/bugs/GIN_is_not_recognized_as_a_git-annex_enabled_repos.mdwn
@@ -12,3 +12,5 @@ If there are any mistakes in my understanding please let me know.
 
 sincerely yours,  
 Rino Mizuguchi
+
+> [[notabug|done]] --[[Joey]]
diff --git a/doc/bugs/GIN_is_not_recognized_as_a_git-annex_enabled_repos/comment_1_8a27545e11b3d9e4e45aea4c9a5c9af4._comment b/doc/bugs/GIN_is_not_recognized_as_a_git-annex_enabled_repos/comment_1_8a27545e11b3d9e4e45aea4c9a5c9af4._comment
new file mode 100644
index 0000000000..6112e946e2
--- /dev/null
+++ b/doc/bugs/GIN_is_not_recognized_as_a_git-annex_enabled_repos/comment_1_8a27545e11b3d9e4e45aea4c9a5c9af4._comment
@@ -0,0 +1,42 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2022-08-04T16:22:09Z"
+ content="""
+If you're using GIN, perhaps you're also using Datalad. Have you read 
+[their documentation](http://handbook.datalad.org/en/0.13_a/basics/101-139-gin.html)
+on using it with git-annex?
+
+Part of that documentation that seems likely to be especially
+relevant is [here](http://handbook.datalad.org/en/0.13_a/basics/101-139-gin.html#access):
+
+> Important: Take the URL in the browser, not the copy-paste URL
+> Please note that you need to use the browser URL of the repository,
+> not the copy-paste URL on the upper right hand side of the repository if you want
+> to get anonymous HTTPS access! The two URLs differ only by a .git extension:
+> 
+>    Brower bar: `https://gin.g-node.org/<user>/<repo>`
+> 
+>    Copy-paste “HTTPS clone”: `https://gin.g-node.org/<user>/<repo>.git`
+> 
+> A dataset cloned from `https://gin.g-node.org/<user>/<repoy>.git`, however, can not retrieve annexed files!
+
+The reason is that git-annex needs to construct urls to download
+files from the repo, starting with git's `config` file.
+Looking at the sample repo <https://gin.g-node.org/adswa/DataLad-101>,
+an url based on that works <https://gin.g-node.org/adswa/DataLad-101/config>,
+but its web page suggests cloning the url 
+<https://gin.g-node.org/adswa/DataLad-101.git>, and
+<https://gin.g-node.org/adswa/DataLad-101.git/config> does not work.
+
+How does git manage to clone the latter url then? Well,
+the http server is speaking the git smart http protocol.
+So git makes requests like `https://gin.g-node.org/adswa/DataLad-101.git/info/refs?service=git-upload-pack`
+which do work. But that protocol is not useful for git-annex, so it
+needs the url where the actual files in the repository can be downloaded,
+not the url where the smart http protocol is spoken.
+
+There is not generally a way to discover one url from the other url
+(removing ".git" might work in this case, but not in other cases).
+So unfortunately you will need to remember to use the right url.
+"""]]

Revert "fix link"
This reverts commit 2f671f1d1bd71ef26c6a648b2321b25e6689f227.
Didn't work
diff --git a/doc/bugs/Resolver_lts-19.16_still_causes_trouble_with_Win32/comment_3_79cafc76eb23e54ff70c72c2f528e724._comment b/doc/bugs/Resolver_lts-19.16_still_causes_trouble_with_Win32/comment_3_79cafc76eb23e54ff70c72c2f528e724._comment
index ec8a051089..98083e6238 100644
--- a/doc/bugs/Resolver_lts-19.16_still_causes_trouble_with_Win32/comment_3_79cafc76eb23e54ff70c72c2f528e724._comment
+++ b/doc/bugs/Resolver_lts-19.16_still_causes_trouble_with_Win32/comment_3_79cafc76eb23e54ff70c72c2f528e724._comment
@@ -13,6 +13,6 @@ on linux. But I don't like putting it in there regardless, and needing
 to downgrade the other dependencies for it is also suboptimal.
 
 I'll revert the stack.yaml change again, and it seems we'll need to wait for
-[[todo/windows:_prepare_for_Win32_not_export_c_entities]]
+[[todo/windows__58___prepare_for_Win32_not_export_c__95___entities]]
 to be fixed before updating it.
 """]]

fix link
diff --git a/doc/bugs/Resolver_lts-19.16_still_causes_trouble_with_Win32/comment_3_79cafc76eb23e54ff70c72c2f528e724._comment b/doc/bugs/Resolver_lts-19.16_still_causes_trouble_with_Win32/comment_3_79cafc76eb23e54ff70c72c2f528e724._comment
index 98083e6238..ec8a051089 100644
--- a/doc/bugs/Resolver_lts-19.16_still_causes_trouble_with_Win32/comment_3_79cafc76eb23e54ff70c72c2f528e724._comment
+++ b/doc/bugs/Resolver_lts-19.16_still_causes_trouble_with_Win32/comment_3_79cafc76eb23e54ff70c72c2f528e724._comment
@@ -13,6 +13,6 @@ on linux. But I don't like putting it in there regardless, and needing
 to downgrade the other dependencies for it is also suboptimal.
 
 I'll revert the stack.yaml change again, and it seems we'll need to wait for
-[[todo/windows__58___prepare_for_Win32_not_export_c__95___entities]]
+[[todo/windows:_prepare_for_Win32_not_export_c_entities]]
 to be fixed before updating it.
 """]]

fix case of Win32
diff --git a/Utility/LockFile/Windows.hs b/Utility/LockFile/Windows.hs
index 9ec34c9a79..6985f408cf 100644
--- a/Utility/LockFile/Windows.hs
+++ b/Utility/LockFile/Windows.hs
@@ -61,7 +61,7 @@ lockExclusive = openLock fILE_SHARE_NONE
 openLock :: ShareMode -> LockFile -> IO (Maybe LockHandle)
 openLock sharemode f = do
 	f' <- convertToNativeNamespace f
-#if MIN_VERSION_win32(2,13,3)
+#if MIN_VERSION_Win32(2,13,3)
 	r <- tryNonAsync $ createFile_NoRetry f' gENERIC_READ sharemode 
 		security_attributes oPEN_ALWAYS fILE_ATTRIBUTE_NORMAL
 		(maybePtr Nothing)
diff --git a/doc/todo/windows__58___prepare_for_Win32_not_export_c__95___entities/comment_7_91c17601eed0936bab17cdf9ec5f3ecb._comment b/doc/todo/windows__58___prepare_for_Win32_not_export_c__95___entities/comment_7_91c17601eed0936bab17cdf9ec5f3ecb._comment
new file mode 100644
index 0000000000..24bf69ed23
--- /dev/null
+++ b/doc/todo/windows__58___prepare_for_Win32_not_export_c__95___entities/comment_7_91c17601eed0936bab17cdf9ec5f3ecb._comment
@@ -0,0 +1,7 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 7"""
+ date="2022-08-04T16:16:59Z"
+ content="""
+Ah yes, case-sensativity urk. Thanks, fixed.
+"""]]

diff --git a/doc/bugs/GIN_is_not_recognized_as_a_git-annex_enabled_repos.mdwn b/doc/bugs/GIN_is_not_recognized_as_a_git-annex_enabled_repos.mdwn
index 4eb0067d35..2326cf9398 100644
--- a/doc/bugs/GIN_is_not_recognized_as_a_git-annex_enabled_repos.mdwn
+++ b/doc/bugs/GIN_is_not_recognized_as_a_git-annex_enabled_repos.mdwn
@@ -7,6 +7,7 @@ I checked the .git/config file and it says annex-ignore=true.
 
 ![image](https://user-images.githubusercontent.com/91708725/182578704-c04fdb60-5b6a-4faf-8869-04914723c27f.png)<br>
 Because of this, git annex copy --to [GIN remote repository] is not possible with HTTPS protocol.  
+Is git-annex capable of copying content over the HTTPS protocol?  
 If there are any mistakes in my understanding please let me know.
 
 sincerely yours,  

diff --git a/doc/bugs/GIN_is_not_recognized_as_a_git-annex_enabled_repos.mdwn b/doc/bugs/GIN_is_not_recognized_as_a_git-annex_enabled_repos.mdwn
index c569d3c283..4eb0067d35 100644
--- a/doc/bugs/GIN_is_not_recognized_as_a_git-annex_enabled_repos.mdwn
+++ b/doc/bugs/GIN_is_not_recognized_as_a_git-annex_enabled_repos.mdwn
@@ -1,14 +1,13 @@
 Hi, git-annex Team.
 
 I want to ask you this issue.
-GIN is not recognized as a git-annex enabled repository when using the HTTPS protocol.
-
-I cloned a GIN repository with HTTPS protocol and then did `git annex init` on the cloned local repository, but it is not recognized as a git annex-enabled remote. 
+GIN is not recognized as a git-annex enabled repository when using the HTTPS protocol.  
+I cloned a GIN repository with HTTPS protocol and then did `git annex init` on the cloned local repository, but it is not recognized as a git annex-enabled remote.   
 I checked the .git/config file and it says annex-ignore=true. 
-![image](https://user-images.githubusercontent.com/91708725/182578704-c04fdb60-5b6a-4faf-8869-04914723c27f.png)
-Because of this, git annex copy --to [GIN remote repository] is not possible with HTTPS protocol.
 
+![image](https://user-images.githubusercontent.com/91708725/182578704-c04fdb60-5b6a-4faf-8869-04914723c27f.png)<br>
+Because of this, git annex copy --to [GIN remote repository] is not possible with HTTPS protocol.  
 If there are any mistakes in my understanding please let me know.
 
-sincerely yours,
+sincerely yours,  
 Rino Mizuguchi

diff --git a/doc/bugs/GIN_is_not_recognized_as_a_git-annex_enabled_repos.mdwn b/doc/bugs/GIN_is_not_recognized_as_a_git-annex_enabled_repos.mdwn
new file mode 100644
index 0000000000..c569d3c283
--- /dev/null
+++ b/doc/bugs/GIN_is_not_recognized_as_a_git-annex_enabled_repos.mdwn
@@ -0,0 +1,14 @@
+Hi, git-annex Team.
+
+I want to ask you this issue.
+GIN is not recognized as a git-annex enabled repository when using the HTTPS protocol.
+
+I cloned a GIN repository with HTTPS protocol and then did `git annex init` on the cloned local repository, but it is not recognized as a git annex-enabled remote. 
+I checked the .git/config file and it says annex-ignore=true. 
+![image](https://user-images.githubusercontent.com/91708725/182578704-c04fdb60-5b6a-4faf-8869-04914723c27f.png)
+Because of this, git annex copy --to [GIN remote repository] is not possible with HTTPS protocol.
+
+If there are any mistakes in my understanding please let me know.
+
+sincerely yours,
+Rino Mizuguchi

Added a comment: typo in Utility/LockFile/Windows.hs
diff --git a/doc/todo/windows__58___prepare_for_Win32_not_export_c__95___entities/comment_6_a623b2e131dd85f50e04483d262abc9a._comment b/doc/todo/windows__58___prepare_for_Win32_not_export_c__95___entities/comment_6_a623b2e131dd85f50e04483d262abc9a._comment
new file mode 100644
index 0000000000..59f1c522a8
--- /dev/null
+++ b/doc/todo/windows__58___prepare_for_Win32_not_export_c__95___entities/comment_6_a623b2e131dd85f50e04483d262abc9a._comment
@@ -0,0 +1,26 @@
+[[!comment format=mdwn
+ username="jkniiv"
+ avatar="http://cdn.libravatar.org/avatar/05fd8b33af7183342153e8013aa3713d"
+ subject="typo in Utility/LockFile/Windows.hs"
+ date="2022-08-03T20:46:14Z"
+ content="""
+It seems there was a tiny typo in commit [[!commit 472f5c142b063053828358a3031a2ca09a373127]], hence
+the following simple correction is needed for the build to complete:
+
+[[!format diff \"\"\"
+diff --git a/Utility/LockFile/Windows.hs b/Utility/LockFile/Windows.hs
+index 9ec34c9a7..6985f408c 100644
+--- a/Utility/LockFile/Windows.hs
++++ b/Utility/LockFile/Windows.hs
+@@ -61,7 +61,7 @@ lockExclusive = openLock fILE_SHARE_NONE
+ openLock :: ShareMode -> LockFile -> IO (Maybe LockHandle)
+ openLock sharemode f = do
+        f' <- convertToNativeNamespace f
+-#if MIN_VERSION_win32(2,13,3)
++#if MIN_VERSION_Win32(2,13,3)
+        r <- tryNonAsync $ createFile_NoRetry f' gENERIC_READ sharemode
+                security_attributes oPEN_ALWAYS fILE_ATTRIBUTE_NORMAL
+                (maybePtr Nothing)
+\"\"\"]]
+
+"""]]

Added a comment
diff --git a/doc/bugs/Resolver_lts-19.16_still_causes_trouble_with_Win32/comment_4_07f1b2eacf7e9e58809ee44fc1d6b574._comment b/doc/bugs/Resolver_lts-19.16_still_causes_trouble_with_Win32/comment_4_07f1b2eacf7e9e58809ee44fc1d6b574._comment
new file mode 100644
index 0000000000..cfe2026977
--- /dev/null
+++ b/doc/bugs/Resolver_lts-19.16_still_causes_trouble_with_Win32/comment_4_07f1b2eacf7e9e58809ee44fc1d6b574._comment
@@ -0,0 +1,17 @@
+[[!comment format=mdwn
+ username="jkniiv"
+ avatar="http://cdn.libravatar.org/avatar/05fd8b33af7183342153e8013aa3713d"
+ subject="comment 4"
+ date="2022-08-03T15:47:07Z"
+ content="""
+@joey: No problem. Most of my git-annex use is rather vanilla (apart from annexing huge files) so I
+don't usually need the very latest in git-annex so I can always fall back to an earlier release/build.
+It's just that I like to keep track of git-annex's development and make sure it works on Windows most
+of the time which means I feel a need to build fresh versions and then kind of dogfood them as soon
+as possible. As a non-developer being able to report build errors and other bugs is my way of taking
+part in this project and hopefully in the process help make things smoother for the Windows user constituent
+that I represent.
+
+PS. Ikiwiki broke that link you made to my related todo. What's with that? The backlink appears in the todo,
+however.
+"""]]

add --dry-run: New option
This is intended for users who want to see what it would output in order to
eg, check if a file would be added to git or the annex. It is not intended
as a way for scripts to get information.
Sponsored-by: Dartmouth College's Datalad project
diff --git a/CHANGELOG b/CHANGELOG
index 0d2953328a..b62c1d81b5 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -10,6 +10,7 @@ git-annex (10.20220725) UNRELEASED; urgency=medium
   * Added new matching options --want-get-by and --want-drop-by.
   * Allow find --branch to be used in a bare repository, the same as
     the deprecated findref can be.
+  * add --dry-run: New option. 
 
  -- Joey Hess <id@joeyh.name>  Mon, 25 Jul 2022 15:35:45 -0400
 
diff --git a/CmdLine/GitAnnex/Options.hs b/CmdLine/GitAnnex/Options.hs
index 48d7a3daf4..df24b7f1f9 100644
--- a/CmdLine/GitAnnex/Options.hs
+++ b/CmdLine/GitAnnex/Options.hs
@@ -128,6 +128,12 @@ parseUUIDOption :: String -> DeferredParse UUID
 parseUUIDOption = DeferredParse
 	. (Remote.nameToUUID)
 
+parseDryRunOption :: Parser DryRun
+parseDryRunOption = DryRun <$> switch
+	( long "dry-run"
+	<> help "don't make changes, but show what would be done"
+	)
+
 -- | From or To a remote.
 data FromToOptions
 	= FromRemote (DeferredParse Remote)
diff --git a/Command.hs b/Command.hs
index bc418fdc3d..21607e4962 100644
--- a/Command.hs
+++ b/Command.hs
@@ -106,6 +106,12 @@ stop = return Nothing
 stopUnless :: Annex Bool -> Annex (Maybe a) -> Annex (Maybe a)
 stopUnless c a = ifM c ( a , stop )
 
+{- When doing a dry run, avoid actually performing the action, but pretend
+ - that it succeeded. -}
+skipWhenDryRun :: DryRun -> CommandPerform -> CommandPerform
+skipWhenDryRun (DryRun False) a = a
+skipWhenDryRun (DryRun True) _ = next $ return True
+
 {- When acting on a failed transfer, stops unless it was in the specified
  - direction. -}
 checkFailedTransferDirection :: ActionItem -> Direction -> Annex (Maybe a) -> Annex (Maybe a)
diff --git a/Command/Add.hs b/Command/Add.hs
index a777178afb..cf3e5f5534 100644
--- a/Command/Add.hs
+++ b/Command/Add.hs
@@ -52,6 +52,7 @@ data AddOptions = AddOptions
 	, updateOnly :: Bool
 	, largeFilesOverride :: Maybe Bool
 	, checkGitIgnoreOption :: CheckGitIgnore
+	, dryRunOption :: DryRun
 	}
 
 optParser :: CmdParamsDesc -> Parser AddOptions
@@ -65,6 +66,7 @@ optParser desc = AddOptions
 		)
 	<*> (parseforcelarge <|> parseforcesmall)
 	<*> checkGitIgnoreSwitch
+	<*> parseDryRunOption
   where
 	parseforcelarge = flag Nothing (Just True)
 		( long "force-large"
@@ -91,16 +93,16 @@ seek o = startConcurrency commandStages $ do
 			ifM (pure (annexdotfiles || not (dotfile file))
 				<&&> (checkFileMatcher largematcher file 
 				<||> Annex.getRead Annex.force))
-				( start si file addunlockedmatcher
+				( start dr si file addunlockedmatcher
 				, if includingsmall
 					then ifM (annexAddSmallFiles <$> Annex.getGitConfig)
-						( startSmall si file s
+						( startSmall dr si file s
 						, stop
 						)
 					else stop
 				)
-		Just True -> start si file addunlockedmatcher
-		Just False -> startSmallOverridden si file
+		Just True -> start dr si file addunlockedmatcher
+		Just False -> startSmallOverridden dr si file
 	case batchOption o of
 		Batch fmt
 			| updateOnly o ->
@@ -126,25 +128,26 @@ seek o = startConcurrency commandStages $ do
 			-- same as a modified unlocked file would get
 			-- locked when added.
 			go False withUnmodifiedUnlockedPointers
+  where
+	dr = dryRunOption o
 
 {- Pass file off to git-add. -}
-startSmall :: SeekInput -> RawFilePath -> FileStatus -> CommandStart
-startSmall si file s =
+startSmall :: DryRun -> SeekInput -> RawFilePath -> FileStatus -> CommandStart
+startSmall dr si file s =
 	starting "add" (ActionItemTreeFile file) si $
-		next $ addSmall file s
+		addSmall dr file s
 
-addSmall :: RawFilePath -> FileStatus -> Annex Bool
-addSmall file s = do
+addSmall :: DryRun -> RawFilePath -> FileStatus -> CommandPerform
+addSmall dr file s = do
 	showNote "non-large file; adding content to git repository"
-	addFile Small file s
+	skipWhenDryRun dr $ next $ addFile Small file s
 
-startSmallOverridden :: SeekInput -> RawFilePath -> CommandStart
-startSmallOverridden si file = 
+startSmallOverridden :: DryRun -> SeekInput -> RawFilePath -> CommandStart
+startSmallOverridden dr si file = 
 	liftIO (catchMaybeIO $ R.getSymbolicLinkStatus file) >>= \case
-		Just s -> starting "add" (ActionItemTreeFile file) si $ next $ do
-			
+		Just s -> starting "add" (ActionItemTreeFile file) si $ do
 			showNote "adding content to git repository"
-			addFile Small file s
+			skipWhenDryRun dr $ next $ addFile Small file s
 		Nothing -> stop
 
 data SmallOrLarge = Small | Large
@@ -188,8 +191,8 @@ addFile smallorlarge file s = do
 		isRegularFile a /= isRegularFile b ||
 		isSymbolicLink a /= isSymbolicLink b
 
-start :: SeekInput -> RawFilePath -> AddUnlockedMatcher -> CommandStart
-start si file addunlockedmatcher = 
+start :: DryRun -> SeekInput -> RawFilePath -> AddUnlockedMatcher -> CommandStart
+start dr si file addunlockedmatcher = 
 	liftIO (catchMaybeIO $ R.getSymbolicLinkStatus file) >>= \case
 		Nothing -> stop
 		Just s
@@ -200,16 +203,17 @@ start si file addunlockedmatcher =
   where
 	go s = ifAnnexed file (addpresent s) (add s)
 	add s = starting "add" (ActionItemTreeFile file) si $
-		if isSymbolicLink s
-			then next $ addFile Small file s
-			else perform file addunlockedmatcher
+		skipWhenDryRun dr $
+			if isSymbolicLink s
+				then next $ addFile Small file s
+				else perform file addunlockedmatcher
 	addpresent s key
 		| isSymbolicLink s = fixuplink key
 		| otherwise = add s
 	fixuplink key = 
 		starting "add" (ActionItemTreeFile file) si $
 			addingExistingLink file key $
-				withOtherTmp $ \tmp -> do
+				skipWhenDryRun dr $ withOtherTmp $ \tmp -> do
 					let tmpf = tmp P.</> P.takeFileName file
 					liftIO $ moveFile file tmpf
 					ifM (isSymbolicLink <$> liftIO (R.getSymbolicLinkStatus tmpf))
@@ -223,9 +227,10 @@ start si file addunlockedmatcher =
 						)
 	fixuppointer s key =
 		starting "add" (ActionItemTreeFile file) si $
-			addingExistingLink file key $ do
-				Database.Keys.addAssociatedFile key =<< inRepo (toTopFilePath file)
-				next $ addFile Large file s
+			addingExistingLink file key $
+				skipWhenDryRun dr $ do
+					Database.Keys.addAssociatedFile key =<< inRepo (toTopFilePath file)
+					next $ addFile Large file s
 
 perform :: RawFilePath -> AddUnlockedMatcher -> CommandPerform
 perform file addunlockedmatcher = withOtherTmp $ \tmpdir -> do
diff --git a/Command/AddUrl.hs b/Command/AddUrl.hs
index 4bfa5767a4..805e72a0e7 100644
--- a/Command/AddUrl.hs
+++ b/Command/AddUrl.hs
@@ -476,7 +476,7 @@ addWorkTree _ addunlockedmatcher u url file key mtmp = case mtmp of
 					(fromRawFilePath file)
 					(fromRawFilePath tmp)
 				go
-			else void $ Command.Add.addSmall file s
+			else void $ Command.Add.addSmall (DryRun False) file s
   where
 	go = do
 		maybeShowJSON $ JSONChunk [("key", serializeKey key)]
diff --git a/Command/Import.hs b/Command/Import.hs
index 692b621c5f..b24bbcfd5f 100644
--- a/Command/Import.hs
+++ b/Command/Import.hs
@@ -248,7 +248,7 @@ startLocal o addunlockedmatcher largematcher mode (srcfile, destfile) =
 				>>= maybe
 					stop
 					(\addedk -> next $ Command.Add.cleanup addedk True)
-			, next $ Command.Add.addSmall destfile s
+			, Command.Add.addSmall (DryRun False) destfile s
 			)
 	notoverwriting why = do
 		warning $ "not overwriting existing " ++ fromRawFilePath destfile ++ " " ++ why
diff --git a/Types/Command.hs b/Types/Command.hs
index 94e10dfb16..4f3a2b8632 100644

(Diff truncated)
Added a comment
diff --git a/doc/todo/windows__58___prepare_for_Win32_not_export_c__95___entities/comment_5_43603d84801cfe0ecfcdc408db97ae22._comment b/doc/todo/windows__58___prepare_for_Win32_not_export_c__95___entities/comment_5_43603d84801cfe0ecfcdc408db97ae22._comment
new file mode 100644
index 0000000000..8021baf121
--- /dev/null
+++ b/doc/todo/windows__58___prepare_for_Win32_not_export_c__95___entities/comment_5_43603d84801cfe0ecfcdc408db97ae22._comment
@@ -0,0 +1,11 @@
+[[!comment format=mdwn
+ username="jkniiv"
+ avatar="http://cdn.libravatar.org/avatar/05fd8b33af7183342153e8013aa3713d"
+ subject="comment 5"
+ date="2022-08-03T15:14:22Z"
+ content="""
+Thanks, Joey, for making the pull request in Win32 with the necessary changes to support git-annex's
+use case. I will be on the lookout for its next release and then as soon as possible try building
+git-annex with LTS 19 via stack. I'll then report my findings here if you have not already done
+something to that effect before me.
+"""]]

typo fix
diff --git a/doc/git-annex-calckey.mdwn b/doc/git-annex-calckey.mdwn
index 616e6aa662..92ab65443e 100644
--- a/doc/git-annex-calckey.mdwn
+++ b/doc/git-annex-calckey.mdwn
@@ -1,6 +1,6 @@
 # NAME
 
-git-annex calckey - calulate key for a file
+git-annex calckey - calculate key for a file
 
 # SYNOPSIS
 

comment
diff --git a/doc/todo/add_--dry-run/comment_1_4daf51eec7db67a89bec8f81b742a094._comment b/doc/todo/add_--dry-run/comment_1_4daf51eec7db67a89bec8f81b742a094._comment
new file mode 100644
index 0000000000..1709202877
--- /dev/null
+++ b/doc/todo/add_--dry-run/comment_1_4daf51eec7db67a89bec8f81b742a094._comment
@@ -0,0 +1,31 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2022-08-03T13:54:44Z"
+ content="""
+That old todo was about adding --dry-run to all git-annex commands.
+That would be infeasible as discussed there. I'm willing to consider adding
+it to specific commands like `git-annex add` or maybe `git-annex drop`.
+
+It's certianly possible to use `git-annex matchexpression` to check if a
+file matches an annex.largefiles or annex.addunlocked expression. But I think
+you're probably not looking for a machine-parseable way to do it.
+(It would not be appropriate for `--dry-run` output to be machine-parseable
+either.)
+
+While `git-annex add` does report when it adds a file to git rather than
+the annex, it does not currently have any output difference at all for
+locked vs unlocked adds. I don't think I would want to change that
+either. If add does not do what the user wants WRT locked/unlocked, they
+can just use `git-annex lock` or `git-annex unlock` to get to the desired
+state.
+
+> > And like git add, you can certianly undo the effects of git annex add.
+> 
+> well -- unless there was a version staged already you don't want to loose etc.
+
+That does not make sense. Why would --dry-run help you avoid such a mistake?
+It's not going to tell you that you have a previous staged version
+that would be overwritten. If you're concerned about that happening, commit
+first.
+"""]]

initial report on wanting --dry-run
diff --git a/doc/todo/add_--dry-run.mdwn b/doc/todo/add_--dry-run.mdwn
new file mode 100644
index 0000000000..7eab779ccc
--- /dev/null
+++ b/doc/todo/add_--dry-run.mdwn
@@ -0,0 +1,24 @@
+Previous discussion which touched upon it was [7 years ago](https://git-annex.branchable.com/todo/wishlist__58___--dry-run_option_for_all_commands/) (unless I missed some) where part of the response was 
+
+> I don't see the benefit to justify this work. git annex add is entirely predictable; it's very similar to git add. Which itself lacks a dry-run option. 
+
+Oh well:
+
+```
+$> git add --help | grep -e '-n, --dry' -A1
+       -n, --dry-run
+           Don’t actually add the file(s), just show if they exist and/or will be ignored.
+
+```
+and users [submit requests against DataLad](https://github.com/datalad/datalad/issues/6909) to be able to discover what file would go to git and which to git-annex. Also would be useful to know if to git-annex -- would it be locked or unlocked?  Someone else might even want to discover what would be the annex key if it would go into annex, but so far I do not think it is within our desired use-case and it might be too lengthy to compute the key checksum etc.
+
+As for 
+
+> And like git add, you can certianly undo the effects of git annex add.
+
+
+well -- unless there was a version staged already you don't want to loose etc.
+
+[[!meta author=yoh]]
+[[!tag projects/datalad]]
+ 

Use createFile_NoRetry from win32 2.13.3.1
Sponsored-by: Tobias Ammann on Patreon
diff --git a/Utility/LockFile/Windows.hs b/Utility/LockFile/Windows.hs
index 08f5e80930..9ec34c9a79 100644
--- a/Utility/LockFile/Windows.hs
+++ b/Utility/LockFile/Windows.hs
@@ -1,11 +1,11 @@
 {- Windows lock files
  -
- - Copyright 2014,2021 Joey Hess <id@joeyh.name>
+ - Copyright 2014,2022 Joey Hess <id@joeyh.name>
  -
  - License: BSD-2-clause
  -}
 
-{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE OverloadedStrings, CPP #-}
 
 module Utility.LockFile.Windows (
 	lockShared,
@@ -61,12 +61,21 @@ lockExclusive = openLock fILE_SHARE_NONE
 openLock :: ShareMode -> LockFile -> IO (Maybe LockHandle)
 openLock sharemode f = do
 	f' <- convertToNativeNamespace f
+#if MIN_VERSION_win32(2,13,3)
+	r <- tryNonAsync $ createFile_NoRetry f' gENERIC_READ sharemode 
+		security_attributes oPEN_ALWAYS fILE_ATTRIBUTE_NORMAL
+		(maybePtr Nothing)
+	return $ case r of
+		Left _ -> Nothing
+		Right h -> Just h
+#else
 	h <- withTString (fromRawFilePath f') $ \c_f ->
 		c_CreateFile c_f gENERIC_READ sharemode security_attributes
 			oPEN_ALWAYS fILE_ATTRIBUTE_NORMAL (maybePtr Nothing)
 	return $ if h == iNVALID_HANDLE_VALUE
 		then Nothing
 		else Just h
+#endif
   where
 	security_attributes = maybePtr Nothing
 
diff --git a/doc/todo/windows__58___prepare_for_Win32_not_export_c__95___entities.mdwn b/doc/todo/windows__58___prepare_for_Win32_not_export_c__95___entities.mdwn
index 73b2b454b3..9442fa50ac 100644
--- a/doc/todo/windows__58___prepare_for_Win32_not_export_c__95___entities.mdwn
+++ b/doc/todo/windows__58___prepare_for_Win32_not_export_c__95___entities.mdwn
@@ -53,3 +53,5 @@ using Windows LockFileEx, for instance the one by my compatriot: <https://hackag
 
 [[!meta title="windows: prepare for System.Win32.File not exporting c_ entities"]]
 [[!meta author=jkniiv]]
+
+> [[fixed|done]] --[[Joey]]
diff --git a/doc/todo/windows__58___prepare_for_Win32_not_export_c__95___entities/comment_4_28e5593e0a58fb7d7a2a297fa63e8208._comment b/doc/todo/windows__58___prepare_for_Win32_not_export_c__95___entities/comment_4_28e5593e0a58fb7d7a2a297fa63e8208._comment
new file mode 100644
index 0000000000..5365531c7f
--- /dev/null
+++ b/doc/todo/windows__58___prepare_for_Win32_not_export_c__95___entities/comment_4_28e5593e0a58fb7d7a2a297fa63e8208._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 4"""
+ date="2022-08-02T14:43:47Z"
+ content="""
+The necessary change will be in win32 2.13.3.1, which should be released
+in due course. And I've made a (so far untested) change to git-annex to
+support that version.
+"""]]
diff --git a/git-annex.cabal b/git-annex.cabal
index d27c0c4b62..261de5f638 100644
--- a/git-annex.cabal
+++ b/git-annex.cabal
@@ -402,7 +402,7 @@ Executable git-annex
 
   if (os(windows))
     Build-Depends:
-      Win32 (>= 2.6.1.0 && < 2.12.0.0),
+      Win32 ((>= 2.6.1.0 && < 2.12.0.0) || >= 2.13.3.1),
       setenv,
       process (>= 1.6.2.0),
       silently (>= 1.2.5.1)

fix link to git-annex-initremote
diff --git a/doc/git-annex-filter-branch.mdwn b/doc/git-annex-filter-branch.mdwn
index 14e6bf85a6..df391945b5 100644
--- a/doc/git-annex-filter-branch.mdwn
+++ b/doc/git-annex-filter-branch.mdwn
@@ -18,7 +18,7 @@ without publishing the whole thing.
 Other ways to avoid publishing information from a git-annex branch,
 or remove information from it include [[git-annex-forget]](1), the 
 `annex.private` git config, and the `--private` option to
-[[git-annex-initremote](1). Those are much easier to use, but this
+[[git-annex-initremote]](1). Those are much easier to use, but this
 provides full control for those who need it.
 
 With no options, no information at all will be included from the git-annex

fix links
diff --git a/doc/devblog/day_590__toward_importing_from_externals.mdwn b/doc/devblog/day_590__toward_importing_from_externals.mdwn
index 414038c274..bd1de81d24 100644
--- a/doc/devblog/day_590__toward_importing_from_externals.mdwn
+++ b/doc/devblog/day_590__toward_importing_from_externals.mdwn
@@ -1,6 +1,6 @@
 I've added an
-[[external_special_remote_protocol/export_and_import_appendix]]
-to the [[external_special_remote_protocol]] which documents how
+[[design/external_special_remote_protocol/export_and_import_appendix]]
+to the [[design/external_special_remote_protocol]] which documents how
 the protocol might be extended to allow for importing from external special
 remotes.
 

Added a comment
diff --git a/doc/bugs/performance_regression__63___init_takes_times_more/comment_11_847e04bbe9c59700249136b7fef4d0b7._comment b/doc/bugs/performance_regression__63___init_takes_times_more/comment_11_847e04bbe9c59700249136b7fef4d0b7._comment
new file mode 100644
index 0000000000..5a3c443721
--- /dev/null
+++ b/doc/bugs/performance_regression__63___init_takes_times_more/comment_11_847e04bbe9c59700249136b7fef4d0b7._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="yarikoptic"
+ avatar="http://cdn.libravatar.org/avatar/f11e9c84cb18d26a1748c33b48c924b4"
+ subject="comment 11"
+ date="2022-08-01T18:55:38Z"
+ content="""
+figured out some what to lookup on github
+- go to Actions for the entire repo
+- [filter only for pull requests:](https://github.com/datalad/git-annex/actions?query=event%3Apull_request)
+- select [most recent one for that PR and architecture](https://github.com/datalad/git-annex/actions/runs/2672648689)
+- build artifacts are at the bottom of that page
+"""]]

Added a comment
diff --git a/doc/bugs/performance_regression__63___init_takes_times_more/comment_10_7aed761c4843217ea4c90491897224c1._comment b/doc/bugs/performance_regression__63___init_takes_times_more/comment_10_7aed761c4843217ea4c90491897224c1._comment
new file mode 100644
index 0000000000..0412582bdc
--- /dev/null
+++ b/doc/bugs/performance_regression__63___init_takes_times_more/comment_10_7aed761c4843217ea4c90491897224c1._comment
@@ -0,0 +1,19 @@
+[[!comment format=mdwn
+ username="yarikoptic"
+ avatar="http://cdn.libravatar.org/avatar/f11e9c84cb18d26a1748c33b48c924b4"
+ subject="comment 10"
+ date="2022-08-01T18:51:59Z"
+ content="""
+didn't have time yet to look at that :-/ as for \"where\"
+
+- don't even know myself now how to lookup for those older github actions runs on github interface;
+
+- they all are fetched to smaug within con/tinuous archive of build logs/artifacts. So for this PR:
+
+```
+(git)smaug:/mnt/datasets/datalad/ci/git-annex/builds/2022/07[master]
+$> /usr/bin/find pr-128/build-ubuntu.yaml-7* -iname *deb
+pr-128/build-ubuntu.yaml-761-ebf2f1b0-failed/git-annex-debianstandalone-packages_10.20220624+git120-gc3df38dd1_amd64/git-annex-standalone_10.20220624+git120-gc3df38dd1-1~ndall+1_amd64.deb
+
+```
+"""]]

Revert "stack.yaml: Updated to lts-19.16"
This reverts commit b5dc04099efd8b1bd2dbfa09a288518eabf8ceec.
Broke windows build, because the new lts updates Win32 to a version that
lacks a function that git-annex needs. git-annex.cabal depends on an
older Win32, and so stack build fails.
Will need to wait to update stack.yaml until this is fixed
https://github.com/haskell/win32/issues/208
and is in a new LTS release.
diff --git a/doc/bugs/Resolver_lts-19.16_still_causes_trouble_with_Win32.mdwn b/doc/bugs/Resolver_lts-19.16_still_causes_trouble_with_Win32.mdwn
index 0830314264..90821b161d 100644
--- a/doc/bugs/Resolver_lts-19.16_still_causes_trouble_with_Win32.mdwn
+++ b/doc/bugs/Resolver_lts-19.16_still_causes_trouble_with_Win32.mdwn
@@ -90,3 +90,5 @@ Git Annex is great. I use it several times a week with my multigigabyte backups,
 
 [[!meta author=jkniiv]]
 [[!meta title="windows: Resolver lts-19.16 still causes trouble with Win32 for stack builds"]]
+
+> reverted, [[done]] --[[Joey]]
diff --git a/doc/bugs/Resolver_lts-19.16_still_causes_trouble_with_Win32/comment_3_79cafc76eb23e54ff70c72c2f528e724._comment b/doc/bugs/Resolver_lts-19.16_still_causes_trouble_with_Win32/comment_3_79cafc76eb23e54ff70c72c2f528e724._comment
new file mode 100644
index 0000000000..98083e6238
--- /dev/null
+++ b/doc/bugs/Resolver_lts-19.16_still_causes_trouble_with_Win32/comment_3_79cafc76eb23e54ff70c72c2f528e724._comment
@@ -0,0 +1,18 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 3"""
+ date="2022-08-01T17:13:22Z"
+ content="""
+Hey, thanks and sorry for inflicting that stack change on you a second
+time. I hypothesized that the toolchain installation, that failed before,
+might have been a transient problem, and it seems it was, but now these other
+problems surface..
+
+Surprisingly, putting Win32 in the stack file does not break stack build
+on linux. But I don't like putting it in there regardless, and needing
+to downgrade the other dependencies for it is also suboptimal.
+
+I'll revert the stack.yaml change again, and it seems we'll need to wait for
+[[todo/windows__58___prepare_for_Win32_not_export_c__95___entities]]
+to be fixed before updating it.
+"""]]
diff --git a/stack.yaml b/stack.yaml
index 789a8ad2c2..0da838187a 100644
--- a/stack.yaml
+++ b/stack.yaml
@@ -12,13 +12,17 @@ flags:
     gitlfs: true
 packages:
 - '.'
-resolver: lts-19.16
+resolver: lts-18.13
 extra-deps:
 - IfElse-0.85
-- aws-0.22.1
+- aws-0.22
 - bloomfilter-2.0.1.0
 - git-lfs-1.2.0
-- http-client-restricted-0.0.5
+- http-client-restricted-0.0.4
 - network-multicast-0.3.2
 - sandi-0.5
 - torrent-10000.1.1
+- base16-bytestring-0.1.1.7
+- base64-bytestring-1.0.0.3
+- bencode-0.6.1.1
+- http-client-0.7.9

comment
diff --git a/doc/bugs/performance_regression__63___init_takes_times_more/comment_9_d4ba8c726e8b74d4692caf0d4afd214c._comment b/doc/bugs/performance_regression__63___init_takes_times_more/comment_9_d4ba8c726e8b74d4692caf0d4afd214c._comment
new file mode 100644
index 0000000000..7b054cacda
--- /dev/null
+++ b/doc/bugs/performance_regression__63___init_takes_times_more/comment_9_d4ba8c726e8b74d4692caf0d4afd214c._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 9"""
+ date="2022-08-01T17:06:50Z"
+ content="""
+Looks like that PR build did succeed later. I don't know where the 
+resulting artifact would have ended up.
+"""]]

comment
diff --git a/doc/todo/annex.addunlocked_in_gitattributes/comment_9_02866c504617c2914eff01d3529d5cc7._comment b/doc/todo/annex.addunlocked_in_gitattributes/comment_9_02866c504617c2914eff01d3529d5cc7._comment
new file mode 100644
index 0000000000..ea7d96fc27
--- /dev/null
+++ b/doc/todo/annex.addunlocked_in_gitattributes/comment_9_02866c504617c2914eff01d3529d5cc7._comment
@@ -0,0 +1,13 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 9"""
+ date="2022-08-01T16:39:40Z"
+ content="""
+I also think that the thinking in this comment is worth considering:
+<https://github.com/datalad/datalad/issues/5383#issuecomment-770108778>
+
+Those are valid reasons to prefer to be able to set things like this
+in gitattributes rather than the global config. Those kinds of
+considerations are why the global config always has a local way to override
+it. Sometimes that is necessarily .git/config, not .gitattributes though.
+"""]]

comment
diff --git a/doc/todo/annex.addunlocked_in_gitattributes/comment_8_73a402df13f30b279dfd2914adec5f35._comment b/doc/todo/annex.addunlocked_in_gitattributes/comment_8_73a402df13f30b279dfd2914adec5f35._comment
new file mode 100644
index 0000000000..a688bb6937
--- /dev/null
+++ b/doc/todo/annex.addunlocked_in_gitattributes/comment_8_73a402df13f30b279dfd2914adec5f35._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 8"""
+ date="2022-08-01T16:37:20Z"
+ content="""
+I would support adding annex.backend to `git-annex config` using the
+current simple value though. There is benefit to doing it for consistencty,
+surely. If a more complicated syntax is needed someone
+can still use gitattributes or git-annex could be changed later.
+
+Please open a new todo if this would be useful to you..
+"""]]

response
diff --git a/doc/todo/annex.addunlocked_in_gitattributes/comment_7_d06e3412f07d98c784b420d82d2d8d49._comment b/doc/todo/annex.addunlocked_in_gitattributes/comment_7_d06e3412f07d98c784b420d82d2d8d49._comment
new file mode 100644
index 0000000000..dc4eea27e7
--- /dev/null
+++ b/doc/todo/annex.addunlocked_in_gitattributes/comment_7_d06e3412f07d98c784b420d82d2d8d49._comment
@@ -0,0 +1,34 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 7"""
+ date="2022-08-01T16:10:31Z"
+ content="""
+Well, moving your annex.largefiles settings from gitattributes to `git-annex
+config` won't speed up queries for it, because the gitattribute overrides
+the `git-annex config` setting. And so git-annex still has to do the work
+of querying for the gitattribute anyway, even when it's not set. 
+
+In [[!commit 4acbb40112aa73dcde63841d8d8c04c433f6a806]] I benchmarked that 
+as making `git-annex add` 2% slower than it would be otherwise (excluding
+hashing). We will just have to live with that, unless the gitattribute
+can eventually somehow be deprecated.
+That is a good lesson about the risks of adding more gitattributes. 
+
+annex.backend is not currently configurable by `git-annex config`.
+It would be listed in its man page if it were.
+
+I'd support adding that, but annex.backend is currently the name of a
+single backend, so this would not allow setting the backend differently for
+different filenames. Which is something that gitattributes can do. So it
+would need annex.backend to be expanded, so it can specify different
+backends for different filenames or other properties. I don't know how that
+syntax would look; the syntax git-annex currently uses for annex.largefiles
+etc is not suitable here. It would certianly be an added complication.
+
+Also, it seems that the reasoning that made the annex.largefiles 
+gitattributes override `git-annex config` would also make sense for
+annex.backend, and if so there would be no performance benefit to moving
+it. I'm not sure what that reasoning was. Possibly that there
+might be cases where the desired value depends on the branch that's checked
+out.
+"""]]

created my user page
diff --git a/doc/users/jkniiv.mdwn b/doc/users/jkniiv.mdwn
new file mode 100644
index 0000000000..6e401e56ed
--- /dev/null
+++ b/doc/users/jkniiv.mdwn
@@ -0,0 +1,10 @@
+This is the git-annex wiki page for the user jkniiv aka. Jarkko Kniivilä.
+
+I'm a gen-X Windows/Linux geek from Hämeenlinna, Finland (the EU), who has been using git-annex on and off
+for a few years now but only since late 2019 or so in earnest. I finally found a use case with managing the
+relatively huge files that are the backup images of my laptops. I also tend to add whole external hdds into
+their respective annexes (with an annex.largefiles setting at 1 megabytes) then cloning those to my laptops
+secondary drive E: (on an ssd) without getting the annex objects and thus keeping a rudimentary catalog of my
+offline files always at hand.
+
+In a past life I used to be a systems specialist (Linux servers and FOSS) for an internet consultancy.

Added a comment
diff --git a/doc/bugs/Resolver_lts-19.16_still_causes_trouble_with_Win32/comment_2_0b96112c5d57886add62d79e7bf6044e._comment b/doc/bugs/Resolver_lts-19.16_still_causes_trouble_with_Win32/comment_2_0b96112c5d57886add62d79e7bf6044e._comment
new file mode 100644
index 0000000000..e62aa2a009
--- /dev/null
+++ b/doc/bugs/Resolver_lts-19.16_still_causes_trouble_with_Win32/comment_2_0b96112c5d57886add62d79e7bf6044e._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="jkniiv"
+ avatar="http://cdn.libravatar.org/avatar/05fd8b33af7183342153e8013aa3713d"
+ subject="comment 2"
+ date="2022-07-31T18:00:59Z"
+ content="""
+@Ilya: Yes, the change took place in commit [[!commit b5dc04099efd8b1bd2dbfa09a288518eabf8ceec]] which was some 24 hours after
+release 10.20220724. :)
+"""]]

Added a comment: lts version
diff --git a/doc/bugs/Resolver_lts-19.16_still_causes_trouble_with_Win32/comment_1_7fc0ffa7787353cf40fff0bc8da43c1d._comment b/doc/bugs/Resolver_lts-19.16_still_causes_trouble_with_Win32/comment_1_7fc0ffa7787353cf40fff0bc8da43c1d._comment
new file mode 100644
index 0000000000..31ef6d2c9f
--- /dev/null
+++ b/doc/bugs/Resolver_lts-19.16_still_causes_trouble_with_Win32/comment_1_7fc0ffa7787353cf40fff0bc8da43c1d._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="Ilya_Shlyakhter"
+ avatar="http://cdn.libravatar.org/avatar/1647044369aa7747829c38b9dcc84df0"
+ subject="lts version"
+ date="2022-07-31T17:25:27Z"
+ content="""
+Did the resolver change to lts-19.16? [`stack.yaml` on hackage](https://hackage.haskell.org/package/git-annex-10.20220724/src/stack.yaml) still seems to say lts-18.
+
+
+"""]]

lts-19.16 causes an issue on Windows
diff --git a/doc/bugs/Resolver_lts-19.16_still_causes_trouble_with_Win32.mdwn b/doc/bugs/Resolver_lts-19.16_still_causes_trouble_with_Win32.mdwn
new file mode 100644
index 0000000000..0830314264
--- /dev/null
+++ b/doc/bugs/Resolver_lts-19.16_still_causes_trouble_with_Win32.mdwn
@@ -0,0 +1,92 @@
+### Please describe the problem.
+
+The change of resolver to LTS 19 (lts-19.16) still causes stack builds to fail on Windows
+with a plan construction problem. Pinning Win32 as `Win32-2.11.1.0` in extra-deps as
+suggested by stack is not enough to resolve the issue -- one has to go further and
+pin Win32 as `Win32-2.9.0.0` and do similarly with a few other GHC boot packages
+including `Cabal`. This setup then builds and tests just fine. I'm aware this needs to
+be probably addressed in the cabal file instead but as a user the patch below is my
+local fix for the issue.
+
+### What steps will reproduce the problem?
+
+`stack setup && stack build`. Observe the following output:
+
+[[!format sh """
+Warning: C:\Projektit\git-annex.branchable.com\git-annex--BUILD-220730-b5dc04099\stack.yaml: Unrecognized field in ProjectAndConfigMonoid: explicit-setup-deps
+
+Error: While constructing the build plan, the following exceptions were encountered:
+
+In the dependencies for git-annex-10.20220724(+assistant
++benchmark
+-dbus
+-debuglocks
++gitlfs
+-magicmime
++pairing
++production
++torrentparser
++webapp):
+    Win32-2.12.0.1 from stack configuration does not match (>=2.6.1.0 && <2.12.0.0)  (latest
+                   matching version is 2.11.1.0)
+needed since git-annex is a build target.
+
+Some different approaches to resolving this:
+
+  * Set 'allow-newer: true'
+    in C:\hs-stack\config.yaml to ignore all version constraints and build anyway.
+
+  * Recommended action: try adding the following to your extra-deps
+    in C:\Projektit\git-annex.branchable.com\git-annex--BUILD-220730-b5dc04099\stack.yaml:
+
+- Win32-2.11.1.0@sha256:f503acb4ea2e7da6433549d5ff7d0851da54f226df032b40ae51559c7914d62f,4387
+
+Plan construction failed.
+# End of transcript or log.
+"""]]
+
+### What version of git-annex are you using? On what operating system?
+
+[[!format sh """
+git-annex version: 10.20220725-gb5dc04099
+build flags: Assistant Webapp Pairing TorrentParser Feeds Testsuite S3 WebDAV
+dependency versions: aws-0.22.1 bloomfilter-2.0.1.0 cryptonite-0.29 DAV-1.3.4 feed-1.3.2.1 ghc-9.0.2 http-client-0.7.11 persistent-sqlite-2.13.1.0 torrent-10000.1.1 uuid-1.3.15 yesod-1.6.2
+key/value backends: SHA256E SHA256 SHA512E SHA512 SHA224E SHA224 SHA384E SHA384 SHA3_256E SHA3_256 SHA3_512E SHA3_512 SHA3_224E SHA3_224 SHA3_384E SHA3_384 SKEIN256E SKEIN256 SKEIN512E SKEIN512 BLAKE2B256E BLAKE2B256 BLAKE2B512E BLAKE2B512 BLAKE2B160E BLAKE2B160 BLAKE2B224E BLAKE2B224 BLAKE2B384E BLAKE2B384 BLAKE2BP512E BLAKE2BP512 BLAKE2S256E BLAKE2S256 BLAKE2S160E BLAKE2S160 BLAKE2S224E BLAKE2S224 BLAKE2SP256E BLAKE2SP256 BLAKE2SP224E BLAKE2SP224 SHA1E SHA1 MD5E MD5 WORM URL X*
+remote types: git gcrypt p2p S3 bup directory rsync web bittorrent webdav adb tahoe glacier ddar git-lfs httpalso borg hook external
+operating system: mingw32 x86_64
+supported repository versions: 8 9 10
+upgrade supported from repository versions: 2 3 4 5 6 7 8 9 10
+"""]]
+
+A successful build that passes the testsuite is achieved with the patch to `stack.yaml` below.
+
+Windows 10 version 21H2 (build 19044.1826), 64 bit.
+
+### Please provide any additional information below.
+
+Apply the following patch to build on Windows:
+
+[[!format diff """
+diff --git a/stack.yaml b/stack.yaml
+index 8ca5d7383..94b724fe2 100644
+--- a/stack.yaml
++++ b/stack.yaml
+@@ -22,5 +22,10 @@ extra-deps:
+ - network-multicast-0.3.2
+ - sandi-0.5
+ - torrent-10000.1.1
++- Win32-2.9.0.0
++- Cabal-3.6.3.0
++- directory-1.3.7.1
++- process-1.6.14.0
++- time-1.11.1.2
+ explicit-setup-deps:
+   git-annex: true
+"""]]
+
+### Have you had any luck using git-annex before? (Sometimes we get tired of reading bug reports all day and a lil' positive end note does wonders)
+
+Git Annex is great. I use it several times a week with my multigigabyte backups, where it gives structure to my image-based backup routines, so you could say I'm a believer. :)
+
+[[!meta author=jkniiv]]
+[[!meta title="windows: Resolver lts-19.16 still causes trouble with Win32 for stack builds"]]

Added a comment
diff --git a/doc/git-annex-find/comment_15_7124135eced9d6516141bb9be8bb345e._comment b/doc/git-annex-find/comment_15_7124135eced9d6516141bb9be8bb345e._comment
new file mode 100644
index 0000000000..e191413b0e
--- /dev/null
+++ b/doc/git-annex-find/comment_15_7124135eced9d6516141bb9be8bb345e._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="Atemu"
+ avatar="http://cdn.libravatar.org/avatar/d1f0f4275931c552403f4c6707bead7a"
+ subject="comment 15"
+ date="2022-07-30T15:30:31Z"
+ content="""
+How about a `git annex find --keys` option? That way it's crystal clear you're searching among keys rather than files.
+"""]]

Added a comment
diff --git a/doc/git-annex-find/comment_14_2acf9c8a2d261ee69f3649b05581be4d._comment b/doc/git-annex-find/comment_14_2acf9c8a2d261ee69f3649b05581be4d._comment
new file mode 100644
index 0000000000..8cbea4da96
--- /dev/null
+++ b/doc/git-annex-find/comment_14_2acf9c8a2d261ee69f3649b05581be4d._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="Dan"
+ avatar="http://cdn.libravatar.org/avatar/986de9e060699ae70ff7c31342393adc"
+ subject="comment 14"
+ date="2022-07-29T22:02:56Z"
+ content="""
+Ah, I hadn't considered the parallel to the standard `find` command, but now that you mention that I understand where you're coming from and can appreciate why `whereis` is free of this association.
+Still, I would think that a user who, after looking at the docs for `git annex find`, specified `--all` because they wanted to operate on keys would not be surprised.
+
+I notice that the man page for `git annex find` already has a \"SEE ALSO\" reference to `git annex whereis`. 
+Could this be expanded so that it more clearly and prominently advises the reader who is looking to query against all known keys to check out the `--all` argument to `git annex whereis` as well as its `--format=` option if \"whereis\" information is not actually of interest?
+"""]]

remove explicit-setup-deps
This has not been needed since stack <1.4.0, and even the i386ancent
build uses stack 2.1.1.
Stack 2.7.5 seems to have forgotten about this old config and warns
about it, so this avoids that warning.
The libtinfo-dev was added to the docs at the same time, I assume it is
also not necessary.
diff --git a/doc/install/fromsource.mdwn b/doc/install/fromsource.mdwn
index 33b8fabac4..062aa6430b 100644
--- a/doc/install/fromsource.mdwn
+++ b/doc/install/fromsource.mdwn
@@ -41,7 +41,7 @@ and avoids build failures due to fast-changing haskell libraries.
 First, [install stack](https://github.com/commercialhaskell/stack/blob/master/doc/install_and_upgrade.md)
 On Debian:
 
-	sudo apt-get install haskell-stack zlib1g-dev libtinfo-dev
+	sudo apt-get install haskell-stack zlib1g-dev
 
 Get the git-annex source code, and inside the source tree run:
 
diff --git a/stack.yaml b/stack.yaml
index 8ca5d73830..789a8ad2c2 100644
--- a/stack.yaml
+++ b/stack.yaml
@@ -22,5 +22,3 @@ extra-deps:
 - network-multicast-0.3.2
 - sandi-0.5
 - torrent-10000.1.1
-explicit-setup-deps:
-  git-annex: true

fix pagespec
diff --git a/doc/projects/datalad.mdwn b/doc/projects/datalad.mdwn
index 751bf45887..c569d6ec9d 100644
--- a/doc/projects/datalad.mdwn
+++ b/doc/projects/datalad.mdwn
@@ -17,7 +17,7 @@ My bugs
 =======
 
 [[!inline pages="bugs/* and !bugs/done and !link(bugs/done) and
-(author(mih) or author(ben) or or author(kyle) or tagged(projects/datalad))" sort=mtime feeds=no actions=yes archive=yes show=0  template=buglist template=buglist]]
+(author(mih) or author(ben) or author(kyle) or tagged(projects/datalad))" sort=mtime feeds=no actions=yes archive=yes show=0  template=buglist template=buglist]]
 
 
 

comment
diff --git a/doc/git-annex-find/comment_13_19556ecddc220a9739d8b061744dc065._comment b/doc/git-annex-find/comment_13_19556ecddc220a9739d8b061744dc065._comment
new file mode 100644
index 0000000000..2975e82a01
--- /dev/null
+++ b/doc/git-annex-find/comment_13_19556ecddc220a9739d8b061744dc065._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 13"""
+ date="2022-07-29T16:34:56Z"
+ content="""
+The reason I think that `git-annex find` is limited to operating on files
+is because it is analagous to the `find` command. It would violate least
+surprise to some extent for it to operate on keys. `git-annex whereis` has
+no such expectation.
+"""]]

find does not support --batch-keys
It was added to the man page in error.
diff --git a/doc/git-annex-find.mdwn b/doc/git-annex-find.mdwn
index e8b5feead2..2decd932b8 100644
--- a/doc/git-annex-find.mdwn
+++ b/doc/git-annex-find.mdwn
@@ -72,10 +72,6 @@ finds files in the current directory and its subdirectories.
   or otherwise doesn't meet the matching options, an empty line
   will be output instead.
 
-* `--batch-keys`
-
-  This is like `--batch` but the lines read from stdin are parsed as keys.
-
 * `-z`
 
   Makes the `--batch` input be delimited by nulls instead of the usual

comment
diff --git a/doc/todo/wishlist__58___--dry-run_option_for_all_commands/comment_6_cd430ea90286759eb5311ef376f63929._comment b/doc/todo/wishlist__58___--dry-run_option_for_all_commands/comment_6_cd430ea90286759eb5311ef376f63929._comment
new file mode 100644
index 0000000000..0d21988e6d
--- /dev/null
+++ b/doc/todo/wishlist__58___--dry-run_option_for_all_commands/comment_6_cd430ea90286759eb5311ef376f63929._comment
@@ -0,0 +1,7 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 6"""
+ date="2022-07-28T16:39:58Z"
+ content="""
+Thanks for the bump. I've implemented both.
+"""]]

Added a comment
diff --git a/doc/bugs/Android_unable_to_use_external_special_remote/comment_2_c235675c07faaecf8e7df2d77fdac3ea._comment b/doc/bugs/Android_unable_to_use_external_special_remote/comment_2_c235675c07faaecf8e7df2d77fdac3ea._comment
new file mode 100644
index 0000000000..a08ac0a617
--- /dev/null
+++ b/doc/bugs/Android_unable_to_use_external_special_remote/comment_2_c235675c07faaecf8e7df2d77fdac3ea._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="ceramic_glass"
+ avatar="http://cdn.libravatar.org/avatar/adc8ffa8bf5b777008b1fb2083df1cf0"
+ subject="comment 2"
+ date="2022-07-29T08:08:32Z"
+ content="""
+No luck with that I'm afraid, still getting the same error. I figured out the `runshell` bit, but I can run `proot git-annex-remote-rclone` with no problems, so I don't think that's the issue.
+"""]]

Added a comment: Re: Confirming all annexed files exist elsewhere?
diff --git a/doc/git-annex-find/comment_12_cb599679d6b5e19867253175e2174c31._comment b/doc/git-annex-find/comment_12_cb599679d6b5e19867253175e2174c31._comment
new file mode 100644
index 0000000000..7821e77ec3
--- /dev/null
+++ b/doc/git-annex-find/comment_12_cb599679d6b5e19867253175e2174c31._comment
@@ -0,0 +1,26 @@
+[[!comment format=mdwn
+ username="Dan"
+ avatar="http://cdn.libravatar.org/avatar/986de9e060699ae70ff7c31342393adc"
+ subject="Re: Confirming all annexed files exist elsewhere?"
+ date="2022-07-28T23:20:03Z"
+ content="""
+Thanks Joey and Ilya for the nigh simultaneous untrust then fsck suggestion. 
+I was able to get everything squared away using the `whereis` approach as a sort of poor man's dry run, then running the copy command I described, and then using my `whereis` again to convince myself that nothing was left behind, although I imagine I'm not the first one to be retiring a repo and so hopefully these comments will be of use to future users.
+
+While my particular problem is solved, I just wanted to add some additional input RE adding `--all` to find.
+I appreciate that Joey thinks that `find` is about \"listing files, not keys\" (and if anyone's opinion here is authoritative, it should be his), but this was not my expectation as a user (although I would agree it was called `findfiles` or something like that), so I just wanted to share my experience trying to accomplish this task.
+
+Given what I understand of `git-annex`, my instinct was to reach for a command that would let me use the powerful matching options against all known keys, so I looked over the list of commands to try to identify something that would do this.
+Right away, `find` leapt out as the natural candidate, but I couldn't get it to work how I wanted, so the next obvious choice was `list`, but that also didn't work.
+It was only when I looked at the this wiki page for `find` and saw discussion of adding support for `--all` that I started searching for commands that *did* accept `--all`, and I stumbled upon `whereis`, but this required a fair deal of detective work on my part.
+
+FWIW, `whereis` is, IMHO, just as much about listing files at particular paths as `find` is (the documentation for both describes the argument as `[path ...]`; it only typically talks about keys when `--all` is passed, and so `whereis` taking `--all` when `find` does not seems unbalanced given that `whereis` seems like a tool that would be built on top of `find`.
+I think there's a similar asymmetry with `list` since it's described as being \"similar to `git annex whereis` but a more compact display.\"
+
+Now that the `--all` genie is somewhat out of the bottle it might be too late for this, but I wonder if a `findkeys` command would help fill this need while obviating the need for `--all` being passed to most other commands.
+It would be unequivocally about finding keys and not files, and its output could be say a list of keys delimited by newlines (or perhaps optionally null's to make it play nice with commands that accept `-z`).
+If the user wanted to know more about the keys that matched their query, the output of this command could then be piped to `whereis`, `examinekey`, and other commands that support the `--batch` and/or `-z` option.
+Of course, instead of defining a new command, this functionality could be absorbed into `find --all`.
+
+I realize that I can accomplish precisely what I describe above with e.g., `git annex whereis --all --format='${key}\n'`, which is great now that I know it's possible under `whereis`, but as a new user I would expect to find this functionality in `find` (which helpfully already supports `--format=`)  before I thought to check `whereis`.
+"""]]

Added a comment: Re: "Confirming all annexed files exist elsewhere?"
diff --git a/doc/git-annex-find/comment_10_085277234c93261701b8c5bb9f1758d3._comment b/doc/git-annex-find/comment_10_085277234c93261701b8c5bb9f1758d3._comment
new file mode 100644
index 0000000000..ed08251182
--- /dev/null
+++ b/doc/git-annex-find/comment_10_085277234c93261701b8c5bb9f1758d3._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="Ilya_Shlyakhter"
+ avatar="http://cdn.libravatar.org/avatar/1647044369aa7747829c38b9dcc84df0"
+ subject="Re: &quot;Confirming all annexed files exist elsewhere?&quot;"
+ date="2022-07-28T17:40:19Z"
+ content="""
+Could you [[`git-annex-untrust`|git-annex-untrust]] the laptop repo, do a [[`git-annex-sync`|git-annex-sync]], then [[`git-annex-fsck`|git-annex-fsck]] to check that the files have enough trusted copies (as set in your `numcopies` setting)?
+
+"""]]

new matching options --want-get-by and --want-drop-by
Sponsored-by: Graham Spencer on Patreon
diff --git a/Annex/Wanted.hs b/Annex/Wanted.hs
index cb2a8e3401..87fdbdae49 100644
--- a/Annex/Wanted.hs
+++ b/Annex/Wanted.hs
@@ -22,8 +22,8 @@ wantGet :: Bool -> Maybe Key -> AssociatedFile -> Annex Bool
 wantGet d key file = isPreferredContent Nothing S.empty key file d
 
 {- Check if a file is preferred content for a repository. -}
-wantSend :: Bool -> Maybe Key -> AssociatedFile -> UUID -> Annex Bool
-wantSend d key file to = isPreferredContent (Just to) S.empty key file d
+wantGetBy :: Bool -> Maybe Key -> AssociatedFile -> UUID -> Annex Bool
+wantGetBy d key file to = isPreferredContent (Just to) S.empty key file d
 
 {- Check if a file is not preferred or required content, and can be
  - dropped. When a UUID is provided, checks for that repository.
diff --git a/Assistant/Threads/TransferScanner.hs b/Assistant/Threads/TransferScanner.hs
index b771e9f8e9..970516a380 100644
--- a/Assistant/Threads/TransferScanner.hs
+++ b/Assistant/Threads/TransferScanner.hs
@@ -171,7 +171,7 @@ expensiveScan urlrenderer rs = batch <~> do
 			"expensive scan found too many copies of object"
 			present key af (SeekInput []) [] callCommandAction
 		ts <- if present
-			then liftAnnex . filterM (wantSend True (Just key) af . Remote.uuid . fst)
+			then liftAnnex . filterM (wantGetBy True (Just key) af . Remote.uuid . fst)
 				=<< use syncDataRemotes (genTransfer Upload False)
 			else ifM (liftAnnex $ wantGet True (Just key) af)
 				( use downloadRemotes (genTransfer Download True) , return [] )
diff --git a/Assistant/TransferQueue.hs b/Assistant/TransferQueue.hs
index c852615ed1..ec5f0ab318 100644
--- a/Assistant/TransferQueue.hs
+++ b/Assistant/TransferQueue.hs
@@ -88,7 +88,7 @@ queueTransfersMatching matching reason schedule k f direction
 		 - already have it. -}
 		| otherwise = do
 			s <- locs
-			filterM (wantSend True (Just k) f . Remote.uuid) $
+			filterM (wantGetBy True (Just k) f . Remote.uuid) $
 				filter (\r -> not (inset s r || Remote.readonly r))
 					(syncDataRemotes st)
 	  where
diff --git a/Assistant/TransferSlots.hs b/Assistant/TransferSlots.hs
index f49a995ac4..0ea91ab00e 100644
--- a/Assistant/TransferSlots.hs
+++ b/Assistant/TransferSlots.hs
@@ -212,7 +212,7 @@ shouldTransfer t info
 	| transferDirection t == Upload = case transferRemote info of
 		Nothing -> return False
 		Just r -> notinremote r
-			<&&> wantSend True (Just key) file (Remote.uuid r)
+			<&&> wantGetBy True (Just key) file (Remote.uuid r)
 	| otherwise = return False
   where
 	key = transferKey t
diff --git a/CHANGELOG b/CHANGELOG
index f336a3c5fc..13a00e5c32 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -7,6 +7,7 @@ git-annex (10.20220725) UNRELEASED; urgency=medium
   * Avoid starting an unncessary number of git hash-object processes when 
     concurrency is enabled.
   * stack.yaml: Updated to lts-19.16
+  * Added new matching options --want-get-by and --want-drop-by.
 
  -- Joey Hess <id@joeyh.name>  Mon, 25 Jul 2022 15:35:45 -0400
 
diff --git a/CmdLine/GitAnnex/Options.hs b/CmdLine/GitAnnex/Options.hs
index 96d0b1872d..48d7a3daf4 100644
--- a/CmdLine/GitAnnex/Options.hs
+++ b/CmdLine/GitAnnex/Options.hs
@@ -288,12 +288,23 @@ keyMatchingOptions' =
 		)
 	, annexFlag (setAnnexState Limit.Wanted.addWantGet)
 		( long "want-get"
-		<> help "match files the repository wants to get"
+		<> help "match files the local repository wants to get"
 		<> hidden
 		)
+	, annexOption (setAnnexState . Limit.Wanted.addWantGetBy) $ strOption
+		( long "want-get-by" <> metavar paramRemote
+		<> help "match files the specified repository wants to get"
+		<> hidden
+		<> completeRemotes
+		)
 	, annexFlag (setAnnexState Limit.Wanted.addWantDrop)
 		( long "want-drop"
-		<> help "match files the repository wants to drop"
+		<> help "match files the local repository wants to drop"
+		<> hidden
+		)
+	, annexOption (setAnnexState . Limit.Wanted.addWantDropBy) $ strOption
+		( long "want-drop-by" <> metavar paramRemote
+		<> help "match files the specified repository wants to drop"
 		<> hidden
 		)
 	, annexOption (setAnnexState . Limit.addAccessedWithin) $
diff --git a/Command/Copy.hs b/Command/Copy.hs
index bc386894d4..267fa71d3d 100644
--- a/Command/Copy.hs
+++ b/Command/Copy.hs
@@ -82,5 +82,5 @@ start o si file key = stopUnless shouldCopy $
 		Right (FromRemote _) -> checkwantget
 		Left ToHere -> checkwantget
 			
-	checkwantsend = wantSend False (Just key) (AssociatedFile (Just file))
+	checkwantsend = wantGetBy False (Just key) (AssociatedFile (Just file))
 	checkwantget = wantGet False (Just key) (AssociatedFile (Just file))
diff --git a/Command/Sync.hs b/Command/Sync.hs
index bad311ed3a..167ea08b7a 100644
--- a/Command/Sync.hs
+++ b/Command/Sync.hs
@@ -855,7 +855,7 @@ syncFile ebloom rs af k = do
 	wantput r
 		| Remote.readonly r || remoteAnnexReadOnly (Remote.gitconfig r) = return False
 		| isThirdPartyPopulated r = return False
-		| otherwise = wantSend True (Just k) af (Remote.uuid r)
+		| otherwise = wantGetBy True (Just k) af (Remote.uuid r)
 	handleput lack inhere
 		| inhere = catMaybes <$>
 			( forM lack $ \r ->
diff --git a/Limit/Wanted.hs b/Limit/Wanted.hs
index 9188594b90..7eb8df7ad4 100644
--- a/Limit/Wanted.hs
+++ b/Limit/Wanted.hs
@@ -12,14 +12,27 @@ import Annex.Wanted
 import Limit
 import Types.FileMatcher
 import Logs.PreferredContent
+import qualified Remote
 
 addWantGet :: Annex ()
 addWantGet = addPreferredContentLimit $
 	checkWant $ wantGet False Nothing
 
+addWantGetBy :: String -> Annex ()
+addWantGetBy name = do
+	u <- Remote.nameToUUID name
+	addPreferredContentLimit $ checkWant $ \af ->
+		wantGetBy False Nothing af u
+
 addWantDrop :: Annex ()
-addWantDrop = addPreferredContentLimit $
-	checkWant $ \af -> wantDrop False Nothing Nothing af (Just [])
+addWantDrop = addPreferredContentLimit $ checkWant $ \af ->
+	wantDrop False Nothing Nothing af (Just [])
+
+addWantDropBy :: String -> Annex ()
+addWantDropBy name = do
+	u <- Remote.nameToUUID name
+	addPreferredContentLimit $ checkWant $ \af ->
+		wantDrop False (Just u) Nothing af (Just [])
 
 addPreferredContentLimit :: (MatchInfo -> Annex Bool) -> Annex ()
 addPreferredContentLimit a = do
diff --git a/doc/git-annex-matching-options.mdwn b/doc/git-annex-matching-options.mdwn
index 93172165ca..199063a154 100644
--- a/doc/git-annex-matching-options.mdwn
+++ b/doc/git-annex-matching-options.mdwn
@@ -153,21 +153,43 @@ in either of two repositories.
 
 * `--want-get`
 
-  Matches only when the preferred content settings for the repository
+  Matches only when the preferred content settings for the local repository
   make it want to get content. Note that this will match even when
-  the content is already present, unless limited with e.g., `--not --in .`
+  the content is already present, unless limited with e.g., `--not --in=here`
 
 * `--want-drop`
 
-  Matches only when the preferred content settings for the repository
+  Matches only when the preferred content settings for the local repository
   make it want to drop content. Note that this will match even when
-  the content is not present, unless limited with e.g., `--in .`
+  the content is not present, unless limited with e.g., `--not --in=here`
 
   Things that this matches will not necessarily be dropped by
   `git-annex drop --auto`. This does not check that there are enough copies
   to drop. Also the same content may be used by a file that is not wanted
   to be dropped.
 
+* `--want-get-by=repository`
+
+  Matches only when the preferred content settings for the specified 
+  repository make it want to get content. Note that this will match even when
+  the content is already present in that repository, unless limited with e.g.,
+  `--not --in=repository`
+
+  The repository should be specified using the name of a configured remote,
+  or the UUID or description of a repository. `--want-get-by=here`
+  is the same as `--want-get`.
+
+* `--want-drop-by=repository`
+
+  Matches only when the preferred content settings for the specificed
+  repository make it want to drop content. Note that this will match
+  even when the content is not present, unless limited with e.g., 
+  `--not --in=repository`
+ 
+  The repository should be specified using the name of a configured remote,

(Diff truncated)
comment
diff --git a/doc/git-annex-find/comment_10_b1c3f781b573d56f1b9572a9bf9f269b._comment b/doc/git-annex-find/comment_10_b1c3f781b573d56f1b9572a9bf9f269b._comment
new file mode 100644
index 0000000000..60d8740881
--- /dev/null
+++ b/doc/git-annex-find/comment_10_b1c3f781b573d56f1b9572a9bf9f269b._comment
@@ -0,0 +1,19 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""Re: Confirming all annexed files exist elsewhere?"""
+ date="2022-07-28T16:10:17Z"
+ content="""
+@Dan `findref` never supported listing all keys either.
+
+Yours is the best argument I've seen so far for wanting `find --all`.
+But the fact that this command is about listing files, not keys, still
+makes that seem out of scope for it.
+
+Using `whereis` would certainly do what you want. Another option would
+be to `untrust` the repository that you are going to be deleting, and then
+run `fsck --all`. Although that would report potentially other problems
+besides files that are only present in that repository.
+
+Finally, there's the bare metal option, which is also the fastest:
+`find .git/annex/objects -type f`
+"""]]

comment
diff --git a/doc/bugs/Android_unable_to_use_external_special_remote/comment_1_17b13329db6fb4788240428ed1e2b212._comment b/doc/bugs/Android_unable_to_use_external_special_remote/comment_1_17b13329db6fb4788240428ed1e2b212._comment
new file mode 100644
index 0000000000..aaaa2524b7
--- /dev/null
+++ b/doc/bugs/Android_unable_to_use_external_special_remote/comment_1_17b13329db6fb4788240428ed1e2b212._comment
@@ -0,0 +1,13 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2022-07-28T16:03:32Z"
+ content="""
+Does Android have a /bin/bash, which is in the shebang of that script? 
+You might want to try running `termux-fix-shebang` on 
+git-annex-remote-rclone, or otherwise modify it to use a shell that is
+available.
+
+You can modify git-annex.linux/runshell to change how it runs proot. The
+call to proot is right down at the end of it.
+"""]]

diff --git a/doc/bugs/Android_unable_to_use_external_special_remote.mdwn b/doc/bugs/Android_unable_to_use_external_special_remote.mdwn
new file mode 100644
index 0000000000..0a40642f4e
--- /dev/null
+++ b/doc/bugs/Android_unable_to_use_external_special_remote.mdwn
@@ -0,0 +1,34 @@
+### Please describe the problem.
+
+I'm trying to set up the rclone special remote from [here](https://github.com/Craeckie/git-annex-remote-rclone) (a fork of the recommended that works with newer versions of rclone), for syncing across my laptop and tablet. So far, I've managed to sync everything from my laptop to the remote perfectly well, and I'm now trying to get it to work in Termux.
+
+Having added `git-annex-remote-rclone` to my `$PATH` in Termux, and having installed git-annex itself (which seems to work fine), I tried running `git annex initremote mega type=external externaltype=rclone target=mega-encrypted prefix=git-annex chunk=1MiB encryption=none rclone_layout=lower`, and was greeted (among several linker errors, which are said to be harmless) with the following:
+
+```
+Cannot run /data/data/com.termux/files/home/.git-annex/git-annex.linux/bin/git-annex-remote-rclone -- Make sure it's executable and that its dependencies are installed.
+```
+
+This is after trying to put the `git-annex-remote-rclone` shell script into a git annex internal binaries folder, though it works nowhere else in my $PATH either. I suspect this is an issue with `proot` not copying in my `$PATH` correctly, though I'm not sure how I would fix this, seeing as I can't find any documentation on how to moify the PRoot flags `git-annex` uses.
+
+### What steps will reproduce the problem?
+
+1. Download `git-annex` into Termux on Android as documented [here](https://git-annex.branchable.com/Android).
+2. Download the `git-annex-remote-rclone` folder from [here]() and place it anywhere in your `$PATH`.
+3. Run `git init && git annex init` in some directory.
+4. Run `git annex initremote test type=external externaltype=rclone target=thisdoesnotexist prefix=git-annex chunk=1MiB encryption=none rclone_layout=lower`. This should print an rclone-related error, but it prints a `git-annex` error as above.
+
+### What version of git-annex are you using? On what operating system?
+10.20220121-g0bcb94487 on Android 12 on a Samsung Galaxy Tab S6.
+
+### Please provide any additional information below.
+
+[[!format sh """
+# If you can, paste a complete transcript of the problem occurring here.
+# If the problem is with the git-annex assistant, paste in .git/anne
+
+# End of transcript or log.
+"""]]
+
+### Have you had any luck using git-annex before? (Sometimes we get tired of reading bug reports all day and a lil' positive end note does wonders)
+
+I'm very new to the program, but so far I've found it excellently effective on my laptop! Thanks for a great tool!

update comment about updating comments :)
diff --git a/doc/contribute/comment_3_e7219514f52207fcfb97aeec03241e8d._comment b/doc/contribute/comment_3_e7219514f52207fcfb97aeec03241e8d._comment
index 513f6e5ae5..4e1087a768 100644
--- a/doc/contribute/comment_3_e7219514f52207fcfb97aeec03241e8d._comment
+++ b/doc/contribute/comment_3_e7219514f52207fcfb97aeec03241e8d._comment
@@ -7,4 +7,6 @@
 Is it possible to edit comments on the branchable wiki? I realized there was a sentence I failed to finish when posting [this comment](https://git-annex.branchable.com/todo/sync_--branches__to_sync_only_specified_branches___40__e.g._git-annex__41__/#comment-19feab1afb2e0b33315a8368a7cdebf7) and I'd love to go back and finish the thought. The \"Edit\" button at the top of the page lets me edit the content of the page, but not any of the comments.
 
 I tried cloning the wiki, editing the file corresponding to my comment, and then pushing, but the push was rejected (the changes were in doc tree so I expected it to be accepted, but perhaps comments are more locked down).
+
+Update: It seems I am able to edit comments by cloning the wiki, editing (comments are located in a folder with the same name as the associated page), committing, and then pushing. Yay!
 """]]

fix up comment
diff --git a/doc/git-annex-find/comment_9_d7ea718f3a898bf9f3e1514802b99fec._comment b/doc/git-annex-find/comment_9_d7ea718f3a898bf9f3e1514802b99fec._comment
index d6d82fb0a3..4dd9262e52 100644
--- a/doc/git-annex-find/comment_9_d7ea718f3a898bf9f3e1514802b99fec._comment
+++ b/doc/git-annex-find/comment_9_d7ea718f3a898bf9f3e1514802b99fec._comment
@@ -10,14 +10,17 @@ At first glance, it seems like the appropriate way to do this is with `git annex
 Since I have recently `git annex sync`-ed, this doesn't turn up anything.
 
 However, if I understand everything correctly, this *only* checks files that are reachable from my current working tree.
-Thus, if there are a bunch of files in my (not currently checked out) `dev` branch that are *not* in my corktree, then this query will not discover them.
+Thus, if there are a bunch of files in my (not currently checked out) `dev` branch that are *not* in my worktree, then this query will not discover them.
 I can get them to be considered with `git annex find --in here --not --copies=2 --branch dev`.
-I could manually (or script) a loop over all of my branches and repeat `git annex find --in here --not --copies=2 --branch ${branch}` to check all of my branches.
+I could manually (or via script) loop over all of my branches and repeat `git annex find --in here --not --copies=2 --branch ${branch}` to check all of my branches.
 However, this will only check the tips.
 Suppose there's a file that previously existed (solely) in my master branch, but at some point it was `git rm`-ed. Then unless I specify using `--branch` a TREEISH that has that file, it will not be considered.
 
-As a result, it seems like the safest thing for me to do is to instead run `git annex whereis --all --in here --not --copies=2` in order to identify keys corresponding to files that are (a) locally available but where (b) the number of copies is not 2 or greater (i.e., it is here and only here). 
+So, I need to use some sort of query tool that supports both the `--all` flag as well as all of the matching options.
+The only thing I was able to find was `whereis`, so I can run `git annex whereis --all --in here --not --copies=2` in order to identify keys corresponding to files that are (a) locally available but where (b) the number of copies is not 2 or greater (i.e., it is here and only here).
 I suppose I could also just plunge ahead with `git annex copy --to ${remote} --all --in here --not --copies=2`, but it's reassuring to be able to run the query and see what would need to get moved (as well as to see the query come back empty before I wipe the hard drive).
 
-Is this an appropriate use of `git annex whereis`, or is there a way that I can use `git annex find` to accomplish this? I see discussion above regarding the lack of `--all` support for `git annex find` Perhaps this is all a roundabout way of asking that `--all` be supported in `git annex find`
+Is this an appropriate use of `git annex whereis`, or is there a way that I can use `git annex find` to accomplish this, or perhaps some other query tool?
+In essence, I just want a way of querying "all" of the objects that git annex has ever known about using all of the standard matching options.
+I see discussion above regarding the lack of `--all` support for `git annex find`, which at the time suggested using `findref` instead but it seems like that has been deprecated in favor of `find`.
 """]]

Added a comment: Confirming all annexed files exist elsewhere?
diff --git a/doc/git-annex-find/comment_9_d7ea718f3a898bf9f3e1514802b99fec._comment b/doc/git-annex-find/comment_9_d7ea718f3a898bf9f3e1514802b99fec._comment
new file mode 100644
index 0000000000..d6d82fb0a3
--- /dev/null
+++ b/doc/git-annex-find/comment_9_d7ea718f3a898bf9f3e1514802b99fec._comment
@@ -0,0 +1,23 @@
+[[!comment format=mdwn
+ username="Dan"
+ avatar="http://cdn.libravatar.org/avatar/986de9e060699ae70ff7c31342393adc"
+ subject="Confirming all annexed files exist elsewhere?"
+ date="2022-07-27T16:35:21Z"
+ content="""
+I'm preparing to recycle an aging laptop that has a few git-annex repos on it. I'd like to confirm that anything in its annex(es) exist in at least one other place and want to confirm what I'm doing to check this makes sense. 
+
+At first glance, it seems like the appropriate way to do this is with `git annex find --in here --not --copies=2` (where the latter predicate should be equal to testing for copies strictly less than 2).
+Since I have recently `git annex sync`-ed, this doesn't turn up anything.
+
+However, if I understand everything correctly, this *only* checks files that are reachable from my current working tree.
+Thus, if there are a bunch of files in my (not currently checked out) `dev` branch that are *not* in my corktree, then this query will not discover them.
+I can get them to be considered with `git annex find --in here --not --copies=2 --branch dev`.
+I could manually (or script) a loop over all of my branches and repeat `git annex find --in here --not --copies=2 --branch ${branch}` to check all of my branches.
+However, this will only check the tips.
+Suppose there's a file that previously existed (solely) in my master branch, but at some point it was `git rm`-ed. Then unless I specify using `--branch` a TREEISH that has that file, it will not be considered.
+
+As a result, it seems like the safest thing for me to do is to instead run `git annex whereis --all --in here --not --copies=2` in order to identify keys corresponding to files that are (a) locally available but where (b) the number of copies is not 2 or greater (i.e., it is here and only here). 
+I suppose I could also just plunge ahead with `git annex copy --to ${remote} --all --in here --not --copies=2`, but it's reassuring to be able to run the query and see what would need to get moved (as well as to see the query come back empty before I wipe the hard drive).
+
+Is this an appropriate use of `git annex whereis`, or is there a way that I can use `git annex find` to accomplish this? I see discussion above regarding the lack of `--all` support for `git annex find` Perhaps this is all a roundabout way of asking that `--all` be supported in `git annex find`
+"""]]

Added a comment: Bump for --want-get/drop-by
diff --git a/doc/todo/wishlist__58___--dry-run_option_for_all_commands/comment_5_e139434d88638d05c84b721abdbb406c._comment b/doc/todo/wishlist__58___--dry-run_option_for_all_commands/comment_5_e139434d88638d05c84b721abdbb406c._comment
new file mode 100644
index 0000000000..9f2dc9aee4
--- /dev/null
+++ b/doc/todo/wishlist__58___--dry-run_option_for_all_commands/comment_5_e139434d88638d05c84b721abdbb406c._comment
@@ -0,0 +1,17 @@
+[[!comment format=mdwn
+ username="kdm9"
+ avatar="http://cdn.libravatar.org/avatar/b7b736335a0e9944a8169a582eb4c43d"
+ subject="Bump for --want-get/drop-by"
+ date="2022-07-26T18:19:36Z"
+ content="""
+Hi Joey,
+
+A million thanks for a fantastic tool.
+
+I came across the need today for the aforementioned  --want-get-by/ --want-drop-by REMOTE options. Is this something that has since been developed/worked around, or is it still in the infinite TODO?
+
+In the mean time, some more explicit documentation that --want-get/want-drop only ever applies to . would be good. I'll see if I can make a PR for this since I can write docs (but alas Haskell not so much).
+
+best,
+Kevin
+"""]]

use ResourcePool for hash-object handles
Avoid starting an unncessary number of git hash-object processes when
concurrency is enabled.
Sponsored-by: Dartmouth College's DANDI project
diff --git a/Annex.hs b/Annex.hs
index 81ecb1a833..293e323eb2 100644
--- a/Annex.hs
+++ b/Annex.hs
@@ -175,7 +175,7 @@ data AnnexState = AnnexState
 	, branchstate :: BranchState
 	, repoqueue :: Maybe (Git.Queue.Queue Annex)
 	, catfilehandles :: CatFileHandles
-	, hashobjecthandle :: Maybe HashObjectHandle
+	, hashobjecthandle :: Maybe (ResourcePool HashObjectHandle)
 	, checkattrhandle :: Maybe (ResourcePool CheckAttrHandle)
 	, checkignorehandle :: Maybe (ResourcePool CheckIgnoreHandle)
 	, globalnumcopies :: Maybe NumCopies
diff --git a/Annex/Branch.hs b/Annex/Branch.hs
index e98ce12167..61e6012c2e 100644
--- a/Annex/Branch.hs
+++ b/Annex/Branch.hs
@@ -631,9 +631,9 @@ genIndex g = Git.UpdateIndex.streamUpdateIndex g
 mergeIndex :: JournalLocked -> [Git.Ref] -> Annex ()
 mergeIndex jl branches = do
 	prepareModifyIndex jl
-	hashhandle <- hashObjectHandle
-	withCatFileHandle $ \ch ->
-		inRepo $ \g -> Git.UnionMerge.mergeIndex hashhandle ch g branches
+	withHashObjectHandle $ \hashhandle ->
+		withCatFileHandle $ \ch ->
+			inRepo $ \g -> Git.UnionMerge.mergeIndex hashhandle ch g branches
 
 {- Removes any stale git lock file, to avoid git falling over when
  - updating the index.
@@ -709,10 +709,10 @@ stageJournal jl commitindex = withIndex $ withOtherTmp $ \tmpdir -> do
 	g <- gitRepo
 	let dir = gitAnnexJournalDir g
 	(jlogf, jlogh) <- openjlog (fromRawFilePath tmpdir)
-	h <- hashObjectHandle
-	withJournalHandle gitAnnexJournalDir $ \jh ->
-		Git.UpdateIndex.streamUpdateIndex g
-			[genstream dir h jh jlogh]
+	withHashObjectHandle $ \h ->
+		withJournalHandle gitAnnexJournalDir $ \jh ->
+			Git.UpdateIndex.streamUpdateIndex g
+				[genstream dir h jh jlogh]
 	commitindex
 	liftIO $ cleanup (fromRawFilePath dir) jlogh jlogf
   where
diff --git a/Annex/Concurrent.hs b/Annex/Concurrent.hs
index b4451f823b..72ea40318f 100644
--- a/Annex/Concurrent.hs
+++ b/Annex/Concurrent.hs
@@ -1,6 +1,6 @@
 {- git-annex concurrent state
  -
- - Copyright 2015-2021 Joey Hess <id@joeyh.name>
+ - Copyright 2015-2022 Joey Hess <id@joeyh.name>
  -
  - Licensed under the GNU AGPL version 3 or higher.
  -}
@@ -18,6 +18,7 @@ import Types.Concurrency
 import Types.CatFileHandles
 import Annex.CatFile
 import Annex.CheckAttr
+import Annex.HashObject
 import Annex.CheckIgnore
 
 import qualified Data.Map as M
@@ -47,14 +48,17 @@ setConcurrency' c f = do
 	fromnonconcurrent = do
 		catFileStop
 		checkAttrStop
+		hashObjectStop
 		checkIgnoreStop
 		cfh <- liftIO catFileHandlesPool
 		cah <- mkConcurrentCheckAttrHandle c
+		hoh <- mkConcurrentHashObjectHandle c
 		cih <- mkConcurrentCheckIgnoreHandle c
 		Annex.changeState $ \s -> s
 			{ Annex.concurrency = newc
 			, Annex.catfilehandles = cfh
 			, Annex.checkattrhandle = Just cah
+			, Annex.hashobjecthandle = Just hoh
 			, Annex.checkignorehandle = Just cih
 			}
 
diff --git a/Annex/HashObject.hs b/Annex/HashObject.hs
index b529176e72..4a0ea187ed 100644
--- a/Annex/HashObject.hs
+++ b/Annex/HashObject.hs
@@ -1,6 +1,6 @@
-{- git hash-object interface, with handle automatically stored in the Annex monad
+{- git hash-object interface
  -
- - Copyright 2016 Joey Hess <id@joeyh.name>
+ - Copyright 2016-2022 Joey Hess <id@joeyh.name>
  -
  - Licensed under the GNU AGPL version 3 or higher.
  -}
@@ -8,40 +8,59 @@
 module Annex.HashObject (
 	hashFile,
 	hashBlob,
-	hashObjectHandle,
 	hashObjectStop,
+	mkConcurrentHashObjectHandle,
+	withHashObjectHandle,
 ) where
 
 import Annex.Common
 import qualified Git.HashObject
 import qualified Annex
 import Git.Types
-
-hashObjectHandle :: Annex Git.HashObject.HashObjectHandle
-hashObjectHandle = maybe startup return =<< Annex.getState Annex.hashobjecthandle
-  where
-	startup = do
-		h <- inRepo $ Git.HashObject.hashObjectStart True
-		Annex.changeState $ \s -> s { Annex.hashobjecthandle = Just h }
-		return h
+import Utility.ResourcePool
+import Types.Concurrency
+import Annex.Concurrent.Utility
 
 hashObjectStop :: Annex ()
 hashObjectStop = maybe noop stop =<< Annex.getState Annex.hashobjecthandle
   where
-	stop h = do
-		liftIO $ Git.HashObject.hashObjectStop h
+	stop p = do
+		liftIO $ freeResourcePool p Git.HashObject.hashObjectStop
 		Annex.changeState $ \s -> s { Annex.hashobjecthandle = Nothing }
-		return ()
 
 hashFile :: RawFilePath -> Annex Sha
-hashFile f = do
-	h <- hashObjectHandle
+hashFile f = withHashObjectHandle $ \h -> 
 	liftIO $ Git.HashObject.hashFile h f
 
 {- Note that the content will be written to a temp file.
  - So it may be faster to use Git.HashObject.hashObject for large
  - blob contents. -}
 hashBlob :: Git.HashObject.HashableBlob b => b -> Annex Sha
-hashBlob content = do
-	h <- hashObjectHandle
+hashBlob content = withHashObjectHandle $ \h ->
 	liftIO $ Git.HashObject.hashBlob h content
+
+withHashObjectHandle :: (Git.HashObject.HashObjectHandle -> Annex a) -> Annex a
+withHashObjectHandle a =
+	maybe mkpool go =<< Annex.getState Annex.hashobjecthandle
+  where
+	go p = withResourcePool p start a
+	start = inRepo $ Git.HashObject.hashObjectStart True
+	mkpool = do
+		-- This only runs in non-concurrent code paths;
+		-- a concurrent pool is set up earlier when needed.
+		p <- mkResourcePoolNonConcurrent start
+		Annex.changeState $ \s -> s { Annex.hashobjecthandle = Just p }
+		go p
+
+mkConcurrentHashObjectHandle :: Concurrency -> Annex (ResourcePool Git.HashObject.HashObjectHandle)
+mkConcurrentHashObjectHandle c =
+        Annex.getState Annex.hashobjecthandle >>= \case
+                Just p@(ResourcePool {}) -> return p
+                _ -> mkResourcePool =<< liftIO (maxHashObjects c)
+
+{- git hash-object is typically CPU bound, and is not likely to be the main
+ - bottleneck for any command. So limit to the number of CPU cores, maximum,
+ - while respecting the -Jn value.
+ -}
+maxHashObjects :: Concurrency -> IO Int
+maxHashObjects = concurrencyUpToCpus
diff --git a/CHANGELOG b/CHANGELOG
index 5def79db9f..2c07433317 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -4,6 +4,8 @@ git-annex (10.20220725) UNRELEASED; urgency=medium
     automatically upgrade to v10 in a year's time.
     To avoid this upgrade, you can set annex.autoupgraderepository to false.
   * Use v10 by default for new repositories.
+  * Avoid starting an unncessary number of git hash-object processes when 
+    concurrency is enabled.
 
  -- Joey Hess <id@joeyh.name>  Mon, 25 Jul 2022 15:35:45 -0400
 
diff --git a/Utility/ResourcePool.hs b/Utility/ResourcePool.hs
index 79a5a3a05c..48feb4bf16 100644
--- a/Utility/ResourcePool.hs
+++ b/Utility/ResourcePool.hs
@@ -34,7 +34,7 @@ mkResourcePool maxsz = liftIO $
 		<*> newTVarIO []
 
 {- When there will not be multiple threads that may 
- - may concurrently try to use it, using this is more
+ - concurrently try to use it, using this is more
  - efficient than mkResourcePool.
  -}
 mkResourcePoolNonConcurrent :: (MonadMask m, MonadIO m) => m r -> m (ResourcePool r)
diff --git a/doc/bugs/many___40__2x_jobs__63____41___sleeping__hash-object__processes__63__.mdwn b/doc/bugs/many___40__2x_jobs__63____41___sleeping__hash-object__processes__63__.mdwn
index 2296f7891e..2b2fe673ca 100644

(Diff truncated)
analysis
diff --git a/doc/bugs/many___40__2x_jobs__63____41___sleeping__hash-object__processes__63__/comment_1_c01d8d2e4aa2cb0d064ab223e615a75c._comment b/doc/bugs/many___40__2x_jobs__63____41___sleeping__hash-object__processes__63__/comment_1_c01d8d2e4aa2cb0d064ab223e615a75c._comment
new file mode 100644
index 0000000000..bd3256f989
--- /dev/null
+++ b/doc/bugs/many___40__2x_jobs__63____41___sleeping__hash-object__processes__63__/comment_1_c01d8d2e4aa2cb0d064ab223e615a75c._comment
@@ -0,0 +1,16 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2022-07-25T20:37:55Z"
+ content="""
+I was able to reproduce this by feeding 10 urls into git-annex addurl
+-J5 and got 7 hash-object processes running.
+
+filter.annex.process has nothing to do with this. I reproduced the behavior
+without it set.
+
+Seems like a simple concurrency issue, where each thread potentially starts
+its own hash-object handle, and there can be around 2x as many threads
+started as the -J number due to job stages. Annex.Concurrent sets up pools of
+handles for other similar git processes, but not hash-object.
+"""]]

comment and fix my incorrect earlier comment
diff --git a/doc/todo/git_smudge_clean_interface_suboptiomal/comment_12_bb2bf0e82985bf2045741205c4682813._comment b/doc/todo/git_smudge_clean_interface_suboptiomal/comment_12_bb2bf0e82985bf2045741205c4682813._comment
new file mode 100644
index 0000000000..ae3ba11005
--- /dev/null
+++ b/doc/todo/git_smudge_clean_interface_suboptiomal/comment_12_bb2bf0e82985bf2045741205c4682813._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 12"""
+ date="2022-07-25T20:29:11Z"
+ content="""
+v10 only differs in a locking mechanic, anyway I'm using it myself so.
+
+`git-annex upgrade` will go from v8 to v9, no --version needed.
+"""]]
diff --git a/doc/todo/git_smudge_clean_interface_suboptiomal/comment_8_e99ecb0ac561dd670f3ea7b2915de872._comment b/doc/todo/git_smudge_clean_interface_suboptiomal/comment_8_e99ecb0ac561dd670f3ea7b2915de872._comment
index eedccd8276..c5ed1cec56 100644
--- a/doc/todo/git_smudge_clean_interface_suboptiomal/comment_8_e99ecb0ac561dd670f3ea7b2915de872._comment
+++ b/doc/todo/git_smudge_clean_interface_suboptiomal/comment_8_e99ecb0ac561dd670f3ea7b2915de872._comment
@@ -12,5 +12,5 @@ But, it seems likely that `git add` would not be slow if you upgraded
 the repository version to v9 instead. Most scenarios where it is slow
 have been fixed in that version.
 
-	git-annex upgrade --version=9
+	git-annex upgrade
 """]]

v8 repositories automatically upgrade to v9
(And v9 later on to v10.)
When v9/v10 were added, making v8 automatically upgrade was deferred
"for a few months" to prevent interoperability problems if users also
have an old version of git-annex. Of course that could still be the
case, but there has been a good amount of time and this can't be put off
forever.
Allow setting annex.autoupgraderepository to false to avoid this upgrade.
Previously, that only prevented upgrades from no longer supported git-annex
versions, but v8 is still supported, and users may want to keep on v8 to
interoperate with an old git-annex version.
Sponsored-by: Boyd Stephen Smith Jr. on Patreon
diff --git a/Annex/Version.hs b/Annex/Version.hs
index 958e52a834..c3504cfd93 100644
--- a/Annex/Version.hs
+++ b/Annex/Version.hs
@@ -19,7 +19,7 @@ import qualified Annex
 import qualified Data.Map as M
 
 defaultVersion :: RepoVersion
-defaultVersion = RepoVersion 8
+defaultVersion = RepoVersion 10
 
 latestVersion :: RepoVersion
 latestVersion = RepoVersion 10
@@ -42,7 +42,7 @@ autoUpgradeableVersions = M.fromList
 	, (RepoVersion 6, defaultVersion)
 	, (RepoVersion 7, defaultVersion)
 	, (RepoVersion 8, defaultVersion)
-	, (RepoVersion 9, latestVersion)
+	, (RepoVersion 9, defaultVersion)
 	]
 
 versionField :: ConfigKey
diff --git a/CHANGELOG b/CHANGELOG
index aefdd7b49b..5def79db9f 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,12 @@
+git-annex (10.20220725) UNRELEASED; urgency=medium
+
+  * v8 repositories automatically upgrade to v9, which will in turn
+    automatically upgrade to v10 in a year's time.
+    To avoid this upgrade, you can set annex.autoupgraderepository to false.
+  * Use v10 by default for new repositories.
+
+ -- Joey Hess <id@joeyh.name>  Mon, 25 Jul 2022 15:35:45 -0400
+
 git-annex (10.20220724) upstream; urgency=medium
 
   * filter-process: Fix a bug involving handling of empty files,
diff --git a/Upgrade.hs b/Upgrade.hs
index 01daa3a327..2073b1bec0 100644
--- a/Upgrade.hs
+++ b/Upgrade.hs
@@ -39,7 +39,12 @@ checkUpgrade = maybe noop giveup <=< needsUpgrade
 
 needsUpgrade :: RepoVersion -> Annex (Maybe String)
 needsUpgrade v
-	| v `elem` supportedVersions = ok
+	| v `elem` supportedVersions = case M.lookup v autoUpgradeableVersions of
+		Just newv | newv /= v -> ifM (annexAutoUpgradeRepository <$> Annex.getGitConfig)
+			( runupgrade newv
+			, ok
+			)
+		_ -> ok
 	| otherwise = case M.lookup v autoUpgradeableVersions of
 		Nothing
 			| v `elem` upgradeableVersions ->
@@ -47,10 +52,7 @@ needsUpgrade v
 			| otherwise ->
 				err "Upgrade git-annex."
 		Just newv -> ifM (annexAutoUpgradeRepository <$> Annex.getGitConfig)
-			( tryNonAsync (upgrade True newv) >>= \case
-				Right True -> ok
-				Right False -> err "Automatic upgrade failed!"
-				Left ex -> err $ "Automatic upgrade exception! " ++ show ex
+			( runupgrade newv
 			, err "Automatic upgrade is disabled by annex.autoupgraderepository configuration. To upgrade this repository: git-annex upgrade"
 			)
   where
@@ -63,8 +65,14 @@ needsUpgrade v
 			, show (fromRepoVersion v) ++ "."
 			, msg
 			]
+	
 	ok = return Nothing
 
+	runupgrade newv = tryNonAsync (upgrade True newv) >>= \case
+		Right True -> ok
+		Right False -> err "Automatic upgrade failed!"
+		Left ex -> err $ "Automatic upgrade exception! " ++ show ex
+
 upgrade :: Bool -> RepoVersion -> Annex Bool
 upgrade automatic destversion = do
 	startversion <- getVersion
diff --git a/doc/git-annex.mdwn b/doc/git-annex.mdwn
index 34c3ba7f60..a53f7bf7eb 100644
--- a/doc/git-annex.mdwn
+++ b/doc/git-annex.mdwn
@@ -1181,13 +1181,18 @@ repository, using [[git-annex-config]]. See its man page for a list.)
 
 * `annex.autoupgraderepository`
 
-  When an old git-annex repository version has become deprecated,
+  When an old git-annex repository version is no longer supported,
   git-annex will normally automatically upgrade the repository to
-  the new version.
+  the new version. It may also sometimes upgrade from an old repository
+  version that is still supported but that is not as good as a later
+  version.
 
   If this is set to false, git-annex won't automatically upgrade the
-  repository. Instead it will exit with an error message. You can run
-  `git annex upgrade` yourself when you are ready to upgrade the
+  repository. If the repository version is not supported, git-annex
+  will instead exit with an error message. If it is still supported,
+  git-annex will continue to work.
+
+  You can run `git annex upgrade` yourself when you are ready to upgrade the
   repository.
 
 * `annex.crippledfilesystem`
diff --git a/doc/upgrades.mdwn b/doc/upgrades.mdwn
index 836f922b85..7d48547d82 100644
--- a/doc/upgrades.mdwn
+++ b/doc/upgrades.mdwn
@@ -61,12 +61,15 @@ it very unlikely that such a process is still running.
 
 ## v8 -> v9 (git-annex version 10.x)
 
-v8 repositories are not yet automatically upgraded to v9.
+v8 repositories are automatically upgraded to v9.
 
 v9 is a stepping stone to the v10 upgrade. By adding this intermediate
 version, old versions of git-annex that only support v8 will not be able to
 start new processes in the repository after the v9 upgrade.
 
+v9 also enables using `git-annex filter-process`. This can significantly
+speed up git operations involving unlocked files.
+
 ## v7 -> v8 (git-annex version 8.x)
 
 v7 repositories are automatically upgraded to v8.
@@ -95,7 +98,7 @@ dotfiles to git by default, unless annex.dotfiles is set to true.
 v6 repositories are automatically upgraded to v7.
 
 The only difference between v6 and v7 is that some additional git hooks
-were added in v7. See below for details about what's new in v6/v7.
+were added in v7.
 
 ## v5 -> v6 (git-annex version 6.x)
 

initial report on hash-object's
diff --git a/doc/bugs/many___40__2x_jobs__63____41___sleeping__hash-object__processes__63__.mdwn b/doc/bugs/many___40__2x_jobs__63____41___sleeping__hash-object__processes__63__.mdwn
new file mode 100644
index 0000000000..2296f7891e
--- /dev/null
+++ b/doc/bugs/many___40__2x_jobs__63____41___sleeping__hash-object__processes__63__.mdwn
@@ -0,0 +1,45 @@
+### Please describe the problem.
+
+May be not a problem per se, but decided to check if expected. Following [this advise](http://git-annex.branchable.com/todo/git_smudge_clean_interface_suboptiomal/#comment-65f848510d8684bf65c6698f68b700dd) I have `git config filter.annex.process "git-annex filter-process"` in that git-annex repo and now observe following tree (in htop) of processes:
+
+```
+3799768 dandi      20   0 1025G  191M 40616 S  6.6  0.3  0:31.87 │                 │     ├─ git-annex addurl --batch --with-files --jobs 5 --json --json-error-messages --json-progress --raw
+3799796 dandi      20   0  191M  5088  4680 S  0.0  0.0  0:00.01 │                 │     │  ├─ git --git-dir=.git --work-tree=. --literal-pathspecs cat-file --batch
+3805272 dandi      20   0  6892  3420  2992 S  0.0  0.0  0:00.27 │                 │     │  ├─ /bin/bash /usr/bin/git-annex-remote-rclone
+3805640 dandi      20   0 20432 13032  4024 S  0.0  0.0  0:02.82 │                 │     │  ├─ git --git-dir=.git --work-tree=. check-ignore -z --stdin --verbose --non-matching
+3805646 dandi      20   0 20432 13044  4036 S  0.0  0.0  0:00.00 │                 │     │  ├─ git --git-dir=.git --work-tree=. --literal-pathspecs check-attr -z --stdin annex.backend annex.largefiles annex.numcopies annex.mincopies --
+3805650 dandi      20   0 31900  4064  3816 S  0.0  0.0  0:00.00 │                 │     │  ├─ git --git-dir=.git --work-tree=. --literal-pathspecs hash-object -w --stdin-paths --no-filters
+3805685 dandi      20   0 30144  4000  3752 S  0.0  0.0  0:00.00 │                 │     │  ├─ git --git-dir=.git --work-tree=. --literal-pathspecs hash-object -w --stdin-paths --no-filters
+3805704 dandi      20   0 30144 16076 15792 S  0.0  0.0  0:00.01 │                 │     │  ├─ git --git-dir=.git --work-tree=. --literal-pathspecs hash-object -w --stdin-paths --no-filters
+3805705 dandi      20   0 30144  3976  3728 S  0.0  0.0  0:00.00 │                 │     │  ├─ git --git-dir=.git --work-tree=. --literal-pathspecs hash-object -w --stdin-paths --no-filters
+3805717 dandi      20   0 30144 15968 15680 S  0.0  0.0  0:00.01 │                 │     │  ├─ git --git-dir=.git --work-tree=. --literal-pathspecs hash-object -w --stdin-paths --no-filters
+3805781 dandi      20   0 30144  3980  3724 S  0.0  0.0  0:00.00 │                 │     │  ├─ git --git-dir=.git --work-tree=. --literal-pathspecs hash-object -w --stdin-paths --no-filters
+3805786 dandi      20   0 30144  4068  3820 S  0.0  0.0  0:00.00 │                 │     │  ├─ git --git-dir=.git --work-tree=. --literal-pathspecs hash-object -w --stdin-paths --no-filters
+3805807 dandi      20   0 30144 16028 15744 S  0.0  0.0  0:00.02 │                 │     │  ├─ git --git-dir=.git --work-tree=. --literal-pathspecs hash-object -w --stdin-paths --no-filters
+3805808 dandi      20   0 30144  3884  3636 S  0.0  0.0  0:00.00 │                 │     │  ├─ git --git-dir=.git --work-tree=. --literal-pathspecs hash-object -w --stdin-paths --no-filters
+3805828 dandi      20   0 30144  4008  3764 S  0.0  0.0  0:00.00 │                 │     │  ├─ git --git-dir=.git --work-tree=. --literal-pathspecs hash-object -w --stdin-paths --no-filters
+3805848 dandi      20   0 20432 13104  4092 S  0.0  0.0  0:00.04 │                 │     │  ├─ git --git-dir=.git --work-tree=. check-ignore -z --stdin --verbose --non-matching
+3805852 dandi      20   0 20432 12948  3940 S  0.0  0.0  0:00.02 │                 │     │  ├─ git --git-dir=.git --work-tree=. check-ignore -z --stdin --verbose --non-matching
+3805865 dandi      20   0 20432 13032  4024 S  0.0  0.0  0:00.02 │                 │     │  ├─ git --git-dir=.git --work-tree=. --literal-pathspecs check-attr -z --stdin annex.backend annex.largefiles annex.numcopies annex.mincopies --
+3806054 dandi      20   0 30144  4004  3752 S  0.0  0.0  0:00.00 │                 │     │  ├─ git --git-dir=.git --work-tree=. --literal-pathspecs hash-object -w --stdin-paths --no-filters
+3806066 dandi      20   0 45216  5108  4700 S  0.0  0.0  0:00.00 │                 │     │  ├─ git --git-dir=.git --work-tree=. --literal-pathspecs cat-file --batch
+3806067 dandi      20   0 30144  3888  3640 S  0.0  0.0  0:00.00 │                 │     │  ├─ git --git-dir=.git --work-tree=. --literal-pathspecs hash-object -w --stdin-paths --no-filters
+3806068 dandi      20   0 30144 16032 15748 S  0.0  0.0  0:00.01 │                 │     │  ├─ git --git-dir=.git --work-tree=. --literal-pathspecs hash-object -w --stdin-paths --no-filters
+3806095 dandi      20   0 30144  4060  3816 S  0.0  0.0  0:00.00 │                 │     │  ├─ git --git-dir=.git --work-tree=. --literal-pathspecs hash-object -w --stdin-paths --no-filters
+3806104 dandi      20   0 20432 12928  3916 S  0.0  0.0  0:00.06 │                 │     │  ├─ git --git-dir=.git --work-tree=. --literal-pathspecs check-attr -z --stdin annex.backend annex.largefiles annex.numcopies annex.mincopies --
+3806110 dandi      20   0 30144 15944 15660 S  0.0  0.0  0:00.02 │                 │     │  └─ git --git-dir=.git --work-tree=. --literal-pathspecs hash-object -w --stdin-paths --no-filters
+3804258 dandi      20   0 1024G 44336 37772 S  0.0  0.1  0:00.04 │                 │     ├─ git-annex addurl --batch --with-files --jobs 5 --json --json-error-messages --json-progress --raw
+3804277 dandi      20   0 40844  5124  4740 S  0.0  0.0  0:00.00 │                 │     │  └─ git --git-dir=.git --work-tree=. --literal-pathspecs cat-file --batch
+3805399 dandi      20   0 1024G 23508 20844 S  0.0  0.0  0:00.61 │                 │     ├─ git-annex examinekey --batch --migrate-to-backend=SHA256E
+3805493 dandi      20   0 1024G 36516 26184 S  0.0  0.1  0:01.51 │                 │     ├─ git-annex fromkey --force --batch --json --json-error-messages
+3805503 dandi      20   0 25788  5120  4712 S  0.0  0.0  0:00.00 │                 │     │  ├─ git --git-dir=.git --work-tree=. --literal-pathspecs cat-file --batch
+3805510 dandi      20   0 12472  3984  3732 S  0.0  0.0  0:00.05 │                 │     │  └─ git --git-dir=.git --work-tree=. --literal-pathspecs hash-object -w --stdin-paths --no-filters
+```
+
+which might be ok but still wonder why they are just sleeping there in more than one per `--jobs` number quantities. git annex 10.20220624-g769be12
+
+
+[[!meta author=yoh]]
+[[!tag projects/dandi]]
+
+

Added a comment
diff --git a/doc/todo/git_smudge_clean_interface_suboptiomal/comment_11_39e671908522b79b8054ed9ddcaf918c._comment b/doc/todo/git_smudge_clean_interface_suboptiomal/comment_11_39e671908522b79b8054ed9ddcaf918c._comment
new file mode 100644
index 0000000000..a5fc406717
--- /dev/null
+++ b/doc/todo/git_smudge_clean_interface_suboptiomal/comment_11_39e671908522b79b8054ed9ddcaf918c._comment
@@ -0,0 +1,16 @@
+[[!comment format=mdwn
+ username="yarikoptic"
+ avatar="http://cdn.libravatar.org/avatar/f11e9c84cb18d26a1748c33b48c924b4"
+ subject="comment 11"
+ date="2022-07-25T19:03:42Z"
+ content="""
+What about v10? ;-)  FWIW, [I added a test run for DataLad](https://github.com/datalad/datalad/pull/6881) to operate on v10 by default --  remains green.
+
+> `git-annex upgrade --version=9`
+
+FWIW 10.20220624-g769be12 seems to not have `--version` for `upgrade` and I see nothing
+
+> `git config filter.annex.process \"git-annex filter-process\"`
+
+cool -- seems to work (as commit took only 3m on that slow box).  I will go this route for now.
+"""]]

add news item for git-annex 10.20220724
diff --git a/doc/news/version_10.20220222.mdwn b/doc/news/version_10.20220222.mdwn
deleted file mode 100644
index 6114abd9b9..0000000000
--- a/doc/news/version_10.20220222.mdwn
+++ /dev/null
@@ -1,15 +0,0 @@
-git-annex 10.20220222 released with [[!toggle text="these changes"]]
-[[!toggleable text="""  * annex.skipunknown now defaults to false, so commands like
-    `git annex get foo*` will not silently skip over files/dirs that are
-    not checked into git.
-  * info: Allow using matching options in more situations. File matching
-    options like --include will be rejected in situations where there is
-    no filename to match against.
-  * adb: Avoid find failing with "Argument list too long"
-  * Fix git-annex forget propagation between repositories.
-    (reversion introduced in version 7.20190122)
-  * registerurl, unregisterurl: Improved output when reading from stdin
-    to be more like other batch commands.
-  * registerurl, unregisterurl: Added --json and --json-error-messages options.
-  * Avoid git status taking a long time after git-annex unlock of many files.
-  * Pass --no-textconv when running git diff internally."""]]
\ No newline at end of file
diff --git a/doc/news/version_10.20220724.mdwn b/doc/news/version_10.20220724.mdwn
new file mode 100644
index 0000000000..6781822296
--- /dev/null
+++ b/doc/news/version_10.20220724.mdwn
@@ -0,0 +1,23 @@
+git-annex 10.20220724 released with [[!toggle text="these changes"]]
+[[!toggleable text="""  * filter-process: Fix a bug involving handling of empty files,
+    that caused git to kill git-annex filter-process.
+  * add: Fix reversion when adding an annex link that has been moved to
+    another directory. (Introduced in version 10.20220624)
+  * Added annex.alwayscompact setting which can be unset to speed up
+    writes to the git-annex branch in some cases. See its documentation
+    for important notes on when it's appropariate to use.
+  * adb: Added configuration setting oldandroid=true to avoid using
+    find -printf, which was first supported in Android around 2019-2020.
+    This may need to be enabled for old android devices that used to work
+    without it being set, since version 10.20220222 started using
+    find -printf.
+  * --backend is no longer a global option, and is only accepted by
+    commands that actually need it.
+  * Improve handling of parallelization with -J when copying content
+    from/to a git remote that is a local path.
+  * S3: Avoid writing or checking the uuid file in the S3 bucket when
+    importtree=yes or exporttree=yes.
+  * Fix a reversion that prevented --batch commands (and the assistant)
+    from noticing data written to the journal by other commands.
+  * Fix building with the Assistant build flag disabled but the Webapp
+    build flag enabled."""]]
\ No newline at end of file

comment
diff --git a/doc/forum/git_status_is_slow_twice__44___then_fast/comment_2_1aba5ad6deb4634fca187ecc69a6adf9._comment b/doc/forum/git_status_is_slow_twice__44___then_fast/comment_2_1aba5ad6deb4634fca187ecc69a6adf9._comment
new file mode 100644
index 0000000000..735edec5b4
--- /dev/null
+++ b/doc/forum/git_status_is_slow_twice__44___then_fast/comment_2_1aba5ad6deb4634fca187ecc69a6adf9._comment
@@ -0,0 +1,11 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 2"""
+ date="2022-07-25T16:53:34Z"
+ content="""
+I don't know why git would re-run the slow operation twice before caching
+the result for the third time.
+
+But, yes, smudging is slow in repository v8. If you upgrade to v9 it should
+be significantly faster.
+"""]]

comment
diff --git a/doc/todo/record_ETag_when_using_addurl_--fast/comment_1_cf15e943ba9405240aecc3dc83b4ef08._comment b/doc/todo/record_ETag_when_using_addurl_--fast/comment_1_cf15e943ba9405240aecc3dc83b4ef08._comment
new file mode 100644
index 0000000000..e00c59fb35
--- /dev/null
+++ b/doc/todo/record_ETag_when_using_addurl_--fast/comment_1_cf15e943ba9405240aecc3dc83b4ef08._comment
@@ -0,0 +1,14 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2022-07-25T16:40:50Z"
+ content="""
+Etags are intended to help http clients with caching. It would
+not be considered much of a problem if a web server only returned the same
+Etag for a little while and then generated a new one later, since clients
+only cache so long anyway. But then git-annex would treat the file as no
+longer present on the website.
+
+Apache uses the inode, size, and mtime for its Etag generation. So just
+moving a website to a different drive would change the Etag.
+"""]]

comment
diff --git a/doc/todo/git_smudge_clean_interface_suboptiomal/comment_10_2247cea7e7ca09389073fb32e98394e7._comment b/doc/todo/git_smudge_clean_interface_suboptiomal/comment_10_2247cea7e7ca09389073fb32e98394e7._comment
new file mode 100644
index 0000000000..fd0e9e44fb
--- /dev/null
+++ b/doc/todo/git_smudge_clean_interface_suboptiomal/comment_10_2247cea7e7ca09389073fb32e98394e7._comment
@@ -0,0 +1,18 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 10"""
+ date="2022-07-25T16:27:36Z"
+ content="""
+Well, there has been one bug noticed in v9 so far, it happens to be fixed
+in the upcoming release, and it only affected an edge case involving empty
+files.
+
+I'm not waiting to make v9 the default because of a lack of testing.
+There were some complaints that v8 became the default too
+quickly and caused problems when a mixture of git-annex versions was in
+use, and so it made sense to slow down the upgrade speed.
+
+Anyway, you can enable the speedup in v8 repositories:
+
+	git config filter.annex.process "git-annex filter-process"
+"""]]

Added a comment
diff --git a/doc/forum/fatal__58___export-tree_object_is_unavailable/comment_1_e101855120be3639fce9f3725737b189._comment b/doc/forum/fatal__58___export-tree_object_is_unavailable/comment_1_e101855120be3639fce9f3725737b189._comment
new file mode 100644
index 0000000000..1d72ee2f57
--- /dev/null
+++ b/doc/forum/fatal__58___export-tree_object_is_unavailable/comment_1_e101855120be3639fce9f3725737b189._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="arnaud@c1d1cc612a3921dc06a417301be08a3e125478c4"
+ nickname="arnaud"
+ avatar="http://cdn.libravatar.org/avatar/c0defbf54541c499f6c0464588fc2ad0"
+ subject="comment 1"
+ date="2022-07-25T07:52:39Z"
+ content="""
+So I managed to find a copy of the missing tree in a packfile somewhere and saved my repo. I still wish I knew of an alternative solution. 
+"""]]

removed
diff --git a/doc/forum/fatal__58___export-tree_object_is_unavailable/comment_1_b76071f8c6c14d3485c030e6a30e7412._comment b/doc/forum/fatal__58___export-tree_object_is_unavailable/comment_1_b76071f8c6c14d3485c030e6a30e7412._comment
deleted file mode 100644
index 5b4d7402b8..0000000000
--- a/doc/forum/fatal__58___export-tree_object_is_unavailable/comment_1_b76071f8c6c14d3485c030e6a30e7412._comment
+++ /dev/null
@@ -1,9 +0,0 @@
-[[!comment format=mdwn
- username="arnaud@c1d1cc612a3921dc06a417301be08a3e125478c4"
- nickname="arnaud"
- avatar="http://cdn.libravatar.org/avatar/c0defbf54541c499f6c0464588fc2ad0"
- subject="comment 1"
- date="2022-07-24T16:16:35Z"
- content="""
-I just tried using `git write-tree` to write a random tree, then renamed it to match the missing objects name... and my annex is now syncing. I thought git would complain about having a file with the sha1 not matching the contents, but so far so good. I'm pretty sure `git fsck` is not going to likei it. Hopefully I've not broken anything.
-"""]]

Added a comment
diff --git a/doc/todo/git_smudge_clean_interface_suboptiomal/comment_9_ccea12d55706ab2fc1b0ba46818354a3._comment b/doc/todo/git_smudge_clean_interface_suboptiomal/comment_9_ccea12d55706ab2fc1b0ba46818354a3._comment
new file mode 100644
index 0000000000..e7abebedee
--- /dev/null
+++ b/doc/todo/git_smudge_clean_interface_suboptiomal/comment_9_ccea12d55706ab2fc1b0ba46818354a3._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="yarikoptic"
+ avatar="http://cdn.libravatar.org/avatar/f11e9c84cb18d26a1748c33b48c924b4"
+ subject="comment 9"
+ date="2022-07-24T16:52:33Z"
+ content="""
+FWIW, [in dandisets/000026](https://github.com/dandi/dandisets/issues/229#issuecomment-1192971292) I provide provide some timings on committing files renames. Overall rough: pure git (no git-annex) - 1 sec, v8 - 1500 minutes, v9 - 1 minute.  The question is, since v9 is not default, how well was it tested/used in real life?  
+"""]]

Added a comment
diff --git a/doc/forum/fatal__58___export-tree_object_is_unavailable/comment_1_b76071f8c6c14d3485c030e6a30e7412._comment b/doc/forum/fatal__58___export-tree_object_is_unavailable/comment_1_b76071f8c6c14d3485c030e6a30e7412._comment
new file mode 100644
index 0000000000..5b4d7402b8
--- /dev/null
+++ b/doc/forum/fatal__58___export-tree_object_is_unavailable/comment_1_b76071f8c6c14d3485c030e6a30e7412._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="arnaud@c1d1cc612a3921dc06a417301be08a3e125478c4"
+ nickname="arnaud"
+ avatar="http://cdn.libravatar.org/avatar/c0defbf54541c499f6c0464588fc2ad0"
+ subject="comment 1"
+ date="2022-07-24T16:16:35Z"
+ content="""
+I just tried using `git write-tree` to write a random tree, then renamed it to match the missing objects name... and my annex is now syncing. I thought git would complain about having a file with the sha1 not matching the contents, but so far so good. I'm pretty sure `git fsck` is not going to likei it. Hopefully I've not broken anything.
+"""]]

diff --git a/doc/forum/fatal__58___export-tree_object_is_unavailable.mdwn b/doc/forum/fatal__58___export-tree_object_is_unavailable.mdwn
new file mode 100644
index 0000000000..cacfb23dcf
--- /dev/null
+++ b/doc/forum/fatal__58___export-tree_object_is_unavailable.mdwn
@@ -0,0 +1,15 @@
+Hello !
+
+I'm having a little issue with one of my annexes. Not sure how I got to this point, I might have reset the master branch in one of the repositories to undo changes at some point.
+
+```
+❯ git annex sync
+(merging origin/synced/git-annex into git-annex...)
+(recording state in git...)
+fatal: entry 'export.tree' object 92ab3e13460c6c7a6e9f19484d1808f22eab0077 is unavailable
+git-annex: fd:17: hClose: resource vanished (Broken pipe)
+```
+
+There is indeed an entry in git-annex:export.log with that checksum. I don't really care about the export, since its to a remote I don't use anymore. But I'm not sure how to make my annex usable again. Marking the remote as dead does not help. I've considered editing all the git-annex:export.log in all the repositories to remove the offending line, but that's quite some work and I'm not sure if that's enough or if I might do more damage.
+
+Any ideas ?