Files
Kenneth Skovhede 243cb62975 Improve license flexibility
This changes the way license usage is calculated. Previously the licenses would prohibit enumerating more than what was licensed. This had the benefit that the backup engine was unaware that more items exists.

However, this also prevented filtering items, as the enumeration happens before the filters are applied.

With the new approach, enumeration is applied without imposing limitations, but actually reading the items are limited. This allows filtering unwanted items, and they will not count towards usage.

The downside of this approach is that the backup will contain empty "folders" that could, at a glance, appear to contain everything, but are in fact just empty folders.

To mitigate this, the warning message now explictly mentions that some folders may be empty.
2026-06-12 13:34:04 +02:00

54 lines
2.3 KiB
C#

// Copyright (c) 2026 Duplicati Inc. All rights reserved.
using Duplicati.Library.Common.IO;
using Duplicati.Library.Interface;
using Google.Apis.Drive.v3;
using System.Runtime.CompilerServices;
namespace Duplicati.Proprietary.GoogleWorkspace.SourceItems;
internal class SharedDrivesSourceEntry(SourceProvider provider, string parentPath, string? userId, DriveService driveService)
: MetaEntryBase(Util.AppendDirSeparator(SystemIO.IO_OS.PathCombine(parentPath, "Shared Drives")), null, null)
{
public override IAsyncEnumerable<ISourceProviderEntry> Enumerate(CancellationToken cancellationToken)
=> EnumerateSharedDrives(provider, this.Path, userId, driveService, cancellationToken);
public static async IAsyncEnumerable<ISourceProviderEntry> EnumerateSharedDrives(SourceProvider provider, string path, string? userId, DriveService driveService, [EnumeratorCancellation] CancellationToken cancellationToken)
{
var request = driveService.Drives.List();
string? nextPageToken = null;
do
{
if (cancellationToken.IsCancellationRequested) yield break;
request.PageToken = nextPageToken;
var drives = await request.ExecuteAsync(cancellationToken);
if (drives.Drives != null)
{
foreach (var drive in drives.Drives)
{
if (cancellationToken.IsCancellationRequested) yield break;
if (provider.LicenseApprovedForEntry(path, GoogleRootType.SharedDrives, drive.Id, false))
yield return new SharedDriveSourceEntry(provider, path, userId!, drive, driveService);
}
}
nextPageToken = drives.NextPageToken;
} while (!string.IsNullOrEmpty(nextPageToken));
}
public override Task<Dictionary<string, string?>> GetMinorMetadata(CancellationToken cancellationToken)
{
return Task.FromResult(new Dictionary<string, string?>
{
{ "gsuite:v", "1" },
{ "gsuite:Type", SourceItemType.SharedDrives.ToString() },
{ "gsuite:Name", "Shared Drives" },
{ "gsuite:Id", "Shared Drives" }
}
.Where(kv => !string.IsNullOrEmpty(kv.Value))
.ToDictionary(kv => kv.Key, kv => kv.Value));
}
}