mirror of
https://github.com/nextcloud/desktop.git
synced 2024-10-27 06:45:49 +03:00
Vfs: Distinguish availability error kinds #7143
Previously "no-availability" meant db-error and querying the availability of a nonexistant path returned AllHydrated. Now, the availability has a DbError and a NoSuchItem error case.
This commit is contained in:
parent
1e5ae77994
commit
7774b8049e
5 changed files with 45 additions and 28 deletions
|
@ -79,13 +79,13 @@ Optional<PinState> Vfs::pinStateInDb(const QString &folderPath)
|
|||
return _setupParams.journal->internalPinStates().effectiveForPath(folderPath.toUtf8());
|
||||
}
|
||||
|
||||
Optional<VfsItemAvailability> Vfs::availabilityInDb(const QString &folderPath, const QString &pinPath)
|
||||
Vfs::AvailabilityResult Vfs::availabilityInDb(const QString &folderPath, const QString &pinPath)
|
||||
{
|
||||
auto pin = _setupParams.journal->internalPinStates().effectiveForPathRecursive(pinPath.toUtf8());
|
||||
// not being able to retrieve the pin state isn't too bad
|
||||
auto hydrationStatus = _setupParams.journal->hasHydratedOrDehydratedFiles(folderPath.toUtf8());
|
||||
if (!hydrationStatus)
|
||||
return {};
|
||||
return AvailabilityError::DbError;
|
||||
|
||||
if (hydrationStatus->hasDehydrated) {
|
||||
if (hydrationStatus->hasHydrated)
|
||||
|
@ -94,12 +94,13 @@ Optional<VfsItemAvailability> Vfs::availabilityInDb(const QString &folderPath, c
|
|||
return VfsItemAvailability::OnlineOnly;
|
||||
else
|
||||
return VfsItemAvailability::AllDehydrated;
|
||||
} else {
|
||||
} else if (hydrationStatus->hasHydrated) {
|
||||
if (pin && *pin == PinState::AlwaysLocal)
|
||||
return VfsItemAvailability::AlwaysLocal;
|
||||
else
|
||||
return VfsItemAvailability::AllHydrated;
|
||||
}
|
||||
return AvailabilityError::NoSuchItem;
|
||||
}
|
||||
|
||||
VfsOff::VfsOff(QObject *parent)
|
||||
|
|
|
@ -99,6 +99,15 @@ public:
|
|||
static QString modeToString(Mode mode);
|
||||
static Optional<Mode> modeFromString(const QString &str);
|
||||
|
||||
enum class AvailabilityError
|
||||
{
|
||||
// Availability can't be retrieved due to db error
|
||||
DbError,
|
||||
// Availability not available since the item doesn't exist
|
||||
NoSuchItem,
|
||||
};
|
||||
using AvailabilityResult = Result<VfsItemAvailability, AvailabilityError>;
|
||||
|
||||
public:
|
||||
explicit Vfs(QObject* parent = nullptr);
|
||||
virtual ~Vfs();
|
||||
|
@ -204,6 +213,8 @@ public:
|
|||
* plugins will override it to retrieve the state from elsewhere.
|
||||
*
|
||||
* folderPath is relative to the sync folder. Can be "" for root folder.
|
||||
*
|
||||
* Returns none on retrieval error.
|
||||
*/
|
||||
virtual Optional<PinState> pinState(const QString &folderPath) = 0;
|
||||
|
||||
|
@ -214,7 +225,7 @@ public:
|
|||
*
|
||||
* folderPath is relative to the sync folder. Can be "" for root folder.
|
||||
*/
|
||||
virtual Optional<VfsItemAvailability> availability(const QString &folderPath) = 0;
|
||||
virtual AvailabilityResult availability(const QString &folderPath) = 0;
|
||||
|
||||
public slots:
|
||||
/** Update in-sync state based on SyncFileStatusTracker signal.
|
||||
|
@ -247,7 +258,7 @@ protected:
|
|||
bool setPinStateInDb(const QString &folderPath, PinState state);
|
||||
Optional<PinState> pinStateInDb(const QString &folderPath);
|
||||
// sadly for virtual files the path in the metadata table can differ from path in 'flags'
|
||||
Optional<VfsItemAvailability> availabilityInDb(const QString &folderPath, const QString &pinPath);
|
||||
AvailabilityResult availabilityInDb(const QString &folderPath, const QString &pinPath);
|
||||
|
||||
// the parameters passed to start()
|
||||
VfsSetupParams _setupParams;
|
||||
|
@ -282,7 +293,7 @@ public:
|
|||
|
||||
bool setPinState(const QString &, PinState) override { return true; }
|
||||
Optional<PinState> pinState(const QString &) override { return PinState::AlwaysLocal; }
|
||||
Optional<VfsItemAvailability> availability(const QString &) override { return VfsItemAvailability::AlwaysLocal; }
|
||||
AvailabilityResult availability(const QString &) override { return VfsItemAvailability::AlwaysLocal; }
|
||||
|
||||
public slots:
|
||||
void fileStatusChanged(const QString &, SyncFileStatus) override {}
|
||||
|
|
|
@ -1049,26 +1049,29 @@ void SocketApi::command_GET_MENU_ITEMS(const QString &argument, OCC::SocketListe
|
|||
auto merge = [](VfsItemAvailability lhs, VfsItemAvailability rhs) {
|
||||
if (lhs == rhs)
|
||||
return lhs;
|
||||
auto l = int(lhs) < int(rhs) ? lhs : rhs; // reduce cases by sorting
|
||||
auto r = int(lhs) < int(rhs) ? rhs : lhs;
|
||||
if (l == VfsItemAvailability::AlwaysLocal && r == VfsItemAvailability::AllHydrated)
|
||||
if (int(lhs) > int(rhs))
|
||||
std::swap(lhs, rhs); // reduce cases ensuring lhs < rhs
|
||||
if (lhs == VfsItemAvailability::AlwaysLocal && rhs == VfsItemAvailability::AllHydrated)
|
||||
return VfsItemAvailability::AllHydrated;
|
||||
if (l == VfsItemAvailability::AllDehydrated && r == VfsItemAvailability::OnlineOnly)
|
||||
if (lhs == VfsItemAvailability::AllDehydrated && rhs == VfsItemAvailability::OnlineOnly)
|
||||
return VfsItemAvailability::AllDehydrated;
|
||||
return VfsItemAvailability::Mixed;
|
||||
};
|
||||
for (const auto &file : files) {
|
||||
auto fileData = FileData::get(file);
|
||||
auto availability = syncFolder->vfs().availability(fileData.folderRelativePath);
|
||||
if (!availability)
|
||||
availability = VfsItemAvailability::Mixed; // db error
|
||||
if (!availability) {
|
||||
if (availability.error() == Vfs::AvailabilityError::DbError)
|
||||
availability = VfsItemAvailability::Mixed;
|
||||
if (availability.error() == Vfs::AvailabilityError::NoSuchItem)
|
||||
continue;
|
||||
}
|
||||
if (!combined) {
|
||||
combined = availability;
|
||||
combined = *availability;
|
||||
} else {
|
||||
combined = merge(*combined, *availability);
|
||||
}
|
||||
}
|
||||
ENFORCE(combined);
|
||||
|
||||
// TODO: Should be a submenu, should use icons
|
||||
auto makePinContextMenu = [&](bool makeAvailableLocally, bool freeSpace) {
|
||||
|
@ -1082,18 +1085,20 @@ void SocketApi::command_GET_MENU_ITEMS(const QString &argument, OCC::SocketListe
|
|||
+ Utility::vfsFreeSpaceActionText());
|
||||
};
|
||||
|
||||
switch (*combined) {
|
||||
case VfsItemAvailability::AlwaysLocal:
|
||||
makePinContextMenu(false, true);
|
||||
break;
|
||||
case VfsItemAvailability::AllHydrated:
|
||||
case VfsItemAvailability::Mixed:
|
||||
makePinContextMenu(true, true);
|
||||
break;
|
||||
case VfsItemAvailability::AllDehydrated:
|
||||
case VfsItemAvailability::OnlineOnly:
|
||||
makePinContextMenu(true, false);
|
||||
break;
|
||||
if (combined) {
|
||||
switch (*combined) {
|
||||
case VfsItemAvailability::AlwaysLocal:
|
||||
makePinContextMenu(false, true);
|
||||
break;
|
||||
case VfsItemAvailability::AllHydrated:
|
||||
case VfsItemAvailability::Mixed:
|
||||
makePinContextMenu(true, true);
|
||||
break;
|
||||
case VfsItemAvailability::AllDehydrated:
|
||||
case VfsItemAvailability::OnlineOnly:
|
||||
makePinContextMenu(true, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -105,7 +105,7 @@ bool VfsSuffix::statTypeVirtualFile(csync_file_stat_t *stat, void *)
|
|||
return false;
|
||||
}
|
||||
|
||||
Optional<VfsItemAvailability> VfsSuffix::availability(const QString &folderPath)
|
||||
Vfs::AvailabilityResult VfsSuffix::availability(const QString &folderPath)
|
||||
{
|
||||
const auto suffix = fileSuffix();
|
||||
QString pinPath = folderPath;
|
||||
|
|
|
@ -51,7 +51,7 @@ public:
|
|||
{ return setPinStateInDb(folderPath, state); }
|
||||
Optional<PinState> pinState(const QString &folderPath) override
|
||||
{ return pinStateInDb(folderPath); }
|
||||
Optional<VfsItemAvailability> availability(const QString &folderPath) override;
|
||||
AvailabilityResult availability(const QString &folderPath) override;
|
||||
|
||||
public slots:
|
||||
void fileStatusChanged(const QString &, SyncFileStatus) override {}
|
||||
|
|
Loading…
Reference in a new issue