syntax = "proto3";

package config;

import "lib/config/foldertype.proto";
import "lib/config/size.proto";
import "lib/config/pullorder.proto";
import "lib/config/versioningconfiguration.proto";
import "lib/config/blockpullorder.proto";

import "lib/fs/types.proto";
import "lib/fs/copyrangemethod.proto";

import "ext.proto";

message FolderDeviceConfiguration {
    bytes  device_id           = 1 [(ext.goname) = "DeviceID", (ext.xml) = "id,attr", (ext.json) = "deviceID", (ext.device_id) = true];
    bytes  introduced_by       = 2 [(ext.xml) = "introducedBy,attr", (ext.device_id) = true];
    string encryption_password = 3;
}

message FolderConfiguration {
    string                             id                         = 1 [(ext.goname) = "ID", (ext.xml) = "id,attr", (ext.nodefault) = true];
    string                             label                      = 2 [(ext.xml) = "label,attr", (ext.restart) = false];
    fs.FilesystemType                  filesystem_type            = 3;
    string                             path                       = 4 [(ext.xml) = "path,attr", (ext.default) = "~"];
    FolderType                         type                       = 5 [(ext.xml) = "type,attr"];
    repeated FolderDeviceConfiguration devices                    = 6;
    int32                              rescan_interval_s          = 7 [(ext.xml) = "rescanIntervalS,attr", (ext.default) = "3600"];
    bool                               fs_watcher_enabled         = 8 [(ext.goname) = "FSWatcherEnabled", (ext.xml) = "fsWatcherEnabled,attr", (ext.default) = "true"];
    double                             fs_watcher_delay_s         = 9 [(ext.goname) = "FSWatcherDelayS", (ext.xml) = "fsWatcherDelayS,attr", (ext.default) = "10"];
    double                             fs_watcher_timeout_s       = 40 [(ext.goname) = "FSWatcherTimeoutS", (ext.xml) = "fsWatcherTimeoutS,attr"];
    bool                               ignore_perms               = 10 [(ext.xml) = "ignorePerms,attr"];
    bool                               auto_normalize             = 11 [(ext.xml) = "autoNormalize,attr", (ext.default) = "true"];
    Size                               min_disk_free              = 12 [(ext.default) = "1 %"];
    VersioningConfiguration            versioning                 = 13;
    int32                              copiers                    = 14;
    int32                              puller_max_pending_kib     = 15 [(ext.goname) = "PullerMaxPendingKiB", (ext.xml) = "pullerMaxPendingKiB", (ext.json) = "pullerMaxPendingKiB"];
    int32                              hashers                    = 16;
    PullOrder                          order                      = 17;
    bool                               ignore_delete              = 18;
    int32                              scan_progress_interval_s   = 19;
    int32                              puller_pause_s             = 20;
    int32                              max_conflicts              = 21 [(ext.default) = "10"];
    bool                               disable_sparse_files       = 22;
    bool                               disable_temp_indexes       = 23;
    bool                               paused                     = 24;
    int32                              weak_hash_threshold_pct    = 25;
    string                             marker_name                = 26;
    bool                               copy_ownership_from_parent = 27;
    int32                              mod_time_window_s          = 28 [(ext.goname) = "RawModTimeWindowS"];
    int32                              max_concurrent_writes      = 29 [(ext.default) = "2"];
    bool                               disable_fsync              = 30;
    BlockPullOrder                     block_pull_order           = 31;
    fs.CopyRangeMethod                 copy_range_method          = 32 [(ext.default) = "standard"];
    bool                               case_sensitive_fs          = 33 [(ext.goname) = "CaseSensitiveFS", (ext.xml) = "caseSensitiveFS", (ext.json) = "caseSensitiveFS"];
    bool                               follow_junctions           = 34 [(ext.goname) = "JunctionsAsDirs", (ext.xml) = "junctionsAsDirs", (ext.json) = "junctionsAsDirs"];
    bool                               sync_ownership             = 35;
    bool                               send_ownership             = 36;
    bool                               sync_xattrs                = 37;
    bool                               send_xattrs                = 38;
    XattrFilter                        xattr_filter               = 39;

    // Legacy deprecated
    bool   read_only         = 9000 [deprecated=true, (ext.xml) = "ro,attr,omitempty"];
    double min_disk_free_pct = 9001 [deprecated=true];
    int32  pullers           = 9002 [deprecated=true];
    bool   scan_ownership    = 9003 [deprecated=true];
}

// Extended attribute filter. This is a list of patterns to match (glob
// style), each with an action (permit or deny). First match is used. If the
// filter is empty, all strings are permitted. If the filter is non-empty,
// the default action becomes deny. To counter this, you can use the "*"
// pattern to match all strings at the end of the filter. There are also
// limits on the size of accepted attributes.
message XattrFilter {
    repeated XattrFilterEntry entries               = 1 [(ext.xml) = "entry"];
    int32                     max_single_entry_size = 2 [(ext.xml) = "maxSingleEntrySize", (ext.default) = "1024"];
    int32                     max_total_size        = 3 [(ext.xml) = "maxTotalSize", (ext.default) = "4096"];
}

message XattrFilterEntry {
    string match  = 1 [(ext.xml) = "match,attr"];
    bool   permit = 2 [(ext.xml) = "permit,attr"];
}
