Repository: borgbackup/borg

Issue:
2.0.0b3: AttributeError: 'borg.item.Item' object has no attribute '_dict'
<!--
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).

In command name.

#### Operating system (distribution) and version.

Debian 11 on Qubes OS 4.1

#### Hardware / network configuration, and filesystems used.

Notebook, local repo, BTRFS

#### How much data is handled by borg?

106 GiB

#### Full borg commandline that lead to the problem (leave away excludes and passwords)

```
user@tmp-borg:~$ borg-1.2.2 check --verify stella

user@tmp-borg:~$ borg-2.0.0b3 rcreate -e repokey-blake2-chacha20-poly1305 --other-repo stella --repo stella_new

IMPORTANT: you will need both KEY AND PASSPHRASE to access this repo!
If you used a repokey mode, the key is stored in the repo, but you should back it up separately.
Use "borg key export" to export the key, optionally in printable format.
Write down the passphrase. Store both at safe place(s).

user@tmp-borg:~$ borg-2.0.0b3 transfer --other-repo stella --repo stella_new --upgrader=From12To20
vm:debian-11:root:1650914346-back: copying archive to destination repo...
Local Exception
Traceback (most recent call last):
  File "borg/archiver/__init__.py", line 594, in main
  File "borg/archiver/__init__.py", line 522, in run
  File "borg/archiver/_common.py", line 223, in wrapper
  File "borg/archiver/_common.py", line 155, in wrapper
  File "borg/archiver/transfer_cmd.py", line 100, in do_transfer
  File "borg/upgrade.py", line 80, in upgrade_item
AttributeError: 'borg.item.Item' object has no attribute '_dict'

Platform: Linux tmp-borg 5.19.9-1.fc32.qubes.x86_64 #1 SMP PREEMPT_DYNAMIC Fri Sep 16 14:54:56 CEST 2022 x86_64
Linux: Unknown Linux  
Borg: 2.0.0b3  Python: CPython 3.9.14 msgpack: 1.0.4 fuse: llfuse 1.4.2 [pyfuse3,llfuse]
PID: 2844  CWD: /home/user
sys.argv: ['borg-2.0.0b3', 'transfer', '--other-repo', 'stella', '--repo', 'stella_new', '--upgrader=From12To20']
SSH_ORIGINAL_COMMAND: None
```

This still worked with v2.0.0b2:

```
user@tmp-borg:~$ borg-2.0.0b2 rcreate -e repokey-blake2-chacha20-poly1305 --other-repo stella --repo stella_new

IMPORTANT: you will need both KEY AND PASSPHRASE to access this repo!
If you used a repokey mode, the key is stored in the repo, but you should back it up separately.
Use "borg key export" to export the key, optionally in printable format.
Write down the passphrase. Store both at safe place(s).

user@tmp-borg:~$ borg-2.0.0b2 transfer --other-repo stella --repo stella_new --upgrader=From12To20
vm:debian-11:root:1650914346-back: copying archive to destination repo...
vm:debian-11:root:1650914346-back: finished. transfer_size: 7.27 GB present_size: 3.47 GB
…
```


Discussion:
there is no command `rcreate`, right name is `recreate `
@infectormp, there will be in Borg 2 with some other r(epository) commands.

https://borgbackup.readthedocs.io/en/2.0.0b3/usage/rcreate.html
eh, sorry I overlooked version.
maybe related to https://github.com/borgbackup/borg/issues/7072
I can reproduce, this was caused by the cython code refactor / cleanup, #7063, which made `._dict` inaccessible from python.

Resolving patch:
diff --git a/src/borg/upgrade.py b/src/borg/upgrade.py
--- a/src/borg/upgrade.py
+++ b/src/borg/upgrade.py
@@ -77,18 +77,18 @@ def upgrade_item(self, *, item):
         }
 
         if self.hlm.borg1_hardlink_master(item):
-            item._dict["hlid"] = hlid = self.hlm.hardlink_id_from_path(item._dict["path"])
-            self.hlm.remember(id=hlid, info=(item._dict.get("chunks"), item._dict.get("chunks_healthy")))
+            item.hlid = hlid = self.hlm.hardlink_id_from_path(item.path)
+            self.hlm.remember(id=hlid, info=(item.get("chunks"), item.get("chunks_healthy")))
         elif self.hlm.borg1_hardlink_slave(item):
-            item._dict["hlid"] = hlid = self.hlm.hardlink_id_from_path(item._dict["source"])
+            item.hlid = hlid = self.hlm.hardlink_id_from_path(item.source)
             chunks, chunks_healthy = self.hlm.retrieve(id=hlid, default=(None, None))
             if chunks is not None:
-                item._dict["chunks"] = chunks
+                item.chunks = chunks
                 for chunk_id, _ in chunks:
                     self.cache.chunk_incref(chunk_id, self.archive.stats)
             if chunks_healthy is not None:
-                item._dict["chunks_healthy"] = chunks
-            item._dict.pop("source")  # not used for hardlinks any more, replaced by hlid
+                item.chunks_healthy = chunks
+            del item.source  # not used for hardlinks any more, replaced by hlid
         # make sure we only have desired stuff in the new item. specifically, make sure to get rid of:
         # - 'acl' remnants of bug in attic <= 0.13
         # - 'hardlink_master' (superseded by hlid)


Test patch: