Repository: borgbackup/borg

Issue:
`borg recreate` fails with `KeyError: 'sparse'` when using `fixed` chunker
<!--
Thank you for reporting an issue.

*IMPORTANT* -  *before* creating a new issue please look around:
 - Borgbackup documentation: http://borgbackup.readthedocs.io/en/stable/index.html
 - FAQ: https://borgbackup.readthedocs.io/en/stable/faq.html
 and
 - open issues in Github tracker: https://github.com/borgbackup/borg/issues
  
If you cannot find a similar problem, then create a new issue.

Please fill in as much of the template as possible.
-->

## Have you checked borgbackup docs, FAQ, and open Github issues?

Yes

## Is this a BUG / ISSUE report or a QUESTION?

BUG

## System information. For client/server mode post info for both machines.

#### Your borg version (borg -V).
`borg 1.2.2`

#### Operating system (distribution) and version.
Up-to-date Arch Linux

#### Filesystems used.
ext4 and tmpfs

#### How much data is handled by borg?
Any amount

#### Full borg commandline that lead to the problem (leave away excludes and passwords)
```
borg recreate --chunker-params=fixed,4096 ./borg
```

## Describe the problem you're observing.
`borg recreate` fails with `KeyError: 'sparse'`

#### Can you reproduce the problem? If so, describe how. If not, describe troubleshooting steps you took before opening the issue.
```
borg init --encryption none ./borg
echo testing | borg create ./borg::data -
borg --debug recreate --chunker-params=fixed,4096 ./borg
```

#### Include any warning/errors/backtraces from the system logs

```
using builtin fallback logging configuration
33 self tests completed in 0.10 seconds
Verified integrity of /tmp/borg/index.5
TAM-verified manifest
security: read previous location '/tmp/borg'
security: read manifest timestamp '2022-09-26T21:24:52.146884'
security: determined newest manifest timestamp as 2022-09-26T21:24:52.146884
security: repository checks ok, allowing access
Verified integrity of /home/cat/.cache/borg/aafd5e0ed92a7d5fe9df2f810d49ce6713b4e4c0704179cbedeaa97616d9ca61/chunks
security: read previous location '/tmp/borg'
security: read manifest timestamp '2022-09-26T21:24:52.146884'
security: determined newest manifest timestamp as 2022-09-26T21:24:52.146884
security: repository checks ok, allowing access
Rechunking archives to ('fixed', 4096, 0)
Processing data
Rechunking archive from ('buzhash', 19, 23, 21, 4095) to ('fixed', 4096, 0)
Local Exception
Traceback (most recent call last):
  File "/usr/lib/python3.10/site-packages/borg/archiver.py", line 5159, in main
    exit_code = archiver.run(args)
  File "/usr/lib/python3.10/site-packages/borg/archiver.py", line 5090, in run
    return set_ec(func(args))
  File "/usr/lib/python3.10/site-packages/borg/archiver.py", line 181, in wrapper
    return method(self, args, repository=repository, cache=cache_, **kwargs)
  File "/usr/lib/python3.10/site-packages/borg/archiver.py", line 1712, in do_recreate
    if not recreater.recreate(name, args.comment):
  File "/usr/lib/python3.10/site-packages/borg/archive.py", line 2121, in recreate
    target = self.create_target(archive, target_name)
  File "/usr/lib/python3.10/site-packages/borg/archive.py", line 2312, in create_target
    target.chunker = get_chunker(*target.chunker_params, seed=self.key.chunk_seed)
  File "src/borg/chunker.pyx", line 288, in borg.chunker.get_chunker
KeyError: 'sparse'

Platform: Linux deskcat 5.19.10-arch1-1 #1 SMP PREEMPT_DYNAMIC Tue, 20 Sep 2022 15:17:59 +0000 x86_64
Linux: Unknown Linux
Borg: 1.2.2  Python: CPython 3.10.7 msgpack: 1.0.4 fuse: llfuse 1.4.2 [pyfuse3,llfuse]
PID: 26890  CWD: /tmp
sys.argv: ['/usr/bin/borg', '--debug', 'recreate', '--chunker-params=fixed,4096', './borg']
SSH_ORIGINAL_COMMAND: None
```
<!--

If this complaint relates to borg performance, please include CRUD benchmark
results and any steps you took to troubleshoot.
How to run benchmark: http://borgbackup.readthedocs.io/en/stable/usage/benchmark.html

*IMPORTANT* - Please mark logs and text output from terminal commands 
or else Github will not display them correctly. 
An example is provided below.

Example:
```
this is an example how log text should be marked (wrap it with ```)
```
-->


Discussion:

Patch:
diff --git a/src/borg/archive.py b/src/borg/archive.py
index 8cd261ad..5d9d9707 100644
--- a/src/borg/archive.py
+++ b/src/borg/archive.py
@@ -349,7 +349,7 @@ def __init__(self, key, chunker_params=ITEMS_CHUNKER_PARAMS):
         self.packer = msgpack.Packer()
         self.chunks = []
         self.key = key
-        self.chunker = get_chunker(*chunker_params, seed=self.key.chunk_seed)
+        self.chunker = get_chunker(*chunker_params, seed=self.key.chunk_seed, sparse=False)
 
     def add(self, item):
         self.buffer.write(self.packer.pack(item.as_dict()))
@@ -2313,7 +2313,7 @@ def create_target(self, archive, target_name=None):
             cache=self.cache, key=self.key,
             add_item=target.add_item, write_checkpoint=target.write_checkpoint,
             checkpoint_interval=self.checkpoint_interval, rechunkify=target.recreate_rechunkify).process_file_chunks
-        target.chunker = get_chunker(*target.chunker_params, seed=self.key.chunk_seed)
+        target.chunker = get_chunker(*target.chunker_params, seed=self.key.chunk_seed, sparse=False)
         return target
 
     def create_target_archive(self, name):


Test patch:
diff --git a/src/borg/testsuite/archiver.py b/src/borg/testsuite/archiver.py
index 0e475266..161469b8 100644
--- a/src/borg/testsuite/archiver.py
+++ b/src/borg/testsuite/archiver.py
@@ -2992,6 +2992,21 @@ def test_recreate_rechunkify(self):
         assert not int(self.cmd('list', self.repository_location + '::test1', 'input/large_file',
                                 '--format', '{unique_chunks}'))
 
+    def test_recreate_fixed_rechunkify(self):
+        with open(os.path.join(self.input_path, 'file'), 'wb') as fd:
+            fd.write(b'a' * 8192)
+        self.cmd('init', '--encryption=repokey', self.repository_location)
+        self.cmd('create', '--chunker-params', '7,9,8,128', self.repository_location + '::test', 'input')
+        output = self.cmd('list', self.repository_location + '::test', 'input/file',
+                          '--format', '{num_chunks}')
+        num_chunks = int(output)
+        assert num_chunks > 2
+        self.cmd('recreate', self.repository_location, '--chunker-params', 'fixed,4096')
+        output = self.cmd('list', self.repository_location + '::test', 'input/file',
+                          '--format', '{num_chunks}')
+        num_chunks = int(output)
+        assert num_chunks == 2
+
     def test_recreate_recompress(self):
         self.create_regular_file('compressible', size=10000)
         self.cmd('init', '--encryption=repokey', self.repository_location)