Repository: borgbackup/borg

Issue:
TypeError when trying to pad {flags} in borg list --format
## 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.1.17

#### Operating system (distribution) and version.

Fedora release 33 (Thirty Three)

#### Hardware / network configuration, and filesystems used.

network: N/A, filesystem: ext4

#### How much data is handled by borg?

1024 bytes (this is a toy example)

#### Full borg commandline that lead to the problem (leave away excludes and passwords)
```sh
~/.local/bin/borg list --format "{flags:10}{NL}" /path/to/repo::ArchiveFoo
```

## Describe the problem you're observing.
`borg list` crashes with a traceback. The error message is not helpful in troubleshooting.

#### Can you reproduce the problem? If so, describe how. If not, describe troubleshooting steps you took before opening the issue.
1. Create a borg repo
2. Create a borg archive
3. Print a list of files in the archive using the "{flags:10}{NL}" format

#### Include any warning/errors/backtraces from the system logs
```
Local Exception
Traceback (most recent call last):
  File "/home/user/.local/pipx/venvs/borgbackup/lib64/python3.9/site-packages/borg/archiver.py", line 4703, in main
    exit_code = archiver.run(args)
  File "/home/user/.local/pipx/venvs/borgbackup/lib64/python3.9/site-packages/borg/archiver.py", line 4635, in run
    return set_ec(func(args))
  File "/home/user/.local/pipx/venvs/borgbackup/lib64/python3.9/site-packages/borg/archiver.py", line 177, in wrapper
    return method(self, args, repository=repository, **kwargs)
  File "/home/user/.local/pipx/venvs/borgbackup/lib64/python3.9/site-packages/borg/archiver.py", line 1460, in do_list
    return self._list_archive(args, repository, manifest, key)
  File "/home/user/.local/pipx/venvs/borgbackup/lib64/python3.9/site-packages/borg/archiver.py", line 1489, in _list_archive
    _list_inner(cache=None)
  File "/home/user/.local/pipx/venvs/borgbackup/lib64/python3.9/site-packages/borg/archiver.py", line 1482, in _list_inner
    sys.stdout.write(formatter.format_item(item))
  File "/home/user/.local/pipx/venvs/borgbackup/lib64/python3.9/site-packages/borg/helpers.py", line 1763, in format_item
    return self.format.format_map(self.get_item_data(item))
TypeError: unsupported format string passed to NoneType.__format__

Platform: Linux borg 5.4.156-1.fc25.qubes.x86_64 #1 SMP Fri Oct 29 02:51:34 CEST 2021 x86_64
Linux: Unknown Linux  
Borg: 1.1.17  Python: CPython 3.9.9 msgpack: 0.5.6.+borg1
PID: 3969  CWD: /home/user
sys.argv: ['/home/user/.local/bin/borg', 'list', '--format', '{flags:10}{NL}', '/path/to/repo::ArchiveFoo']
SSH_ORIGINAL_COMMAND: None
```


Discussion:
This might be a python bug:
```py
>>> '{:10}'.format(None)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported format string passed to NoneType.__format__
```
Have a look why it tries to work with None.
```
        item_data['flags'] = item.get('bsdflags')
```

The problem was that this put a `None` value into `item_data` and that can't be formatted.

When not trying to align it into some given width cell, I guess somehow `__repr__` was used so this resulted in just a `"None"` str usually.

But the type of the bsdflags value is `int` and specifically `0` means there shall not be any flags set (or we do not know about any flags that shall be set), so I'll fix this like:
```
        item_data['flags'] = item.get('bsdflags', 0)
```

@hexagonrecursion have a look ^^^.


Resolving patch:
diff --git a/src/borg/helpers.py b/src/borg/helpers.py
--- a/src/borg/helpers.py
+++ b/src/borg/helpers.py
@@ -2051,7 +2051,7 @@ def get_item_data(self, item):
             item_data['health'] = 'broken' if 'chunks_healthy' in item else 'healthy'
         item_data['source'] = source
         item_data['linktarget'] = source
-        item_data['flags'] = item.get('bsdflags')
+        item_data['flags'] = item.get('bsdflags', 0)
         for key in self.used_call_keys:
             item_data[key] = self.call_keys[key](item)
         return item_data


Test patch: